[
  {
    "path": ".bowerrc",
    "content": "{\"directory\":\"resources/assets/vendor\",\"analytics\":false}\n"
  },
  {
    "path": ".editorconfig",
    "content": "# editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.php]\nindent_size = 4\n\n[**.blade.php]\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n*.css linguist-vendored\n*.less linguist-vendored\n"
  },
  {
    "path": ".gitignore",
    "content": ".env\n.idea\n.DS_Store\n.phpstorm*\n_ide_helper*\ndredd.*\ngit_*\nHomestead.*\nnode_modules\nnpm-debug.log\n/public/css\n/public/js\n/resources/assets/css\n/resources/assets/vendor\n/tests/database.sqlite\n/vendor"
  },
  {
    "path": ".travis.yml",
    "content": "language: php\n\nphp:\n  - 5.6\n  - 7.0\n\nsudo: false\n\ninstall:\n  - composer self-update\n  - travis_retry composer install --no-interaction --no-scripts --prefer-source --dev\n\nbefore_script:\n  - cp .env.example .env\n  - touch tests/database.sqlite\n  - php artisan key:generate\n  - php artisan clear-compiled\n  - php artisan optimize\n  - php artisan cache:clear\n  - php artisan migrate --env=\"testing\" --database=\"sqlite\" --force\n  - php artisan db:seed --env=\"testing\" --database=\"sqlite\" --force\n\nscript: vendor/bin/phpunit\n\nmatrix:\n  fast_finish: true"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribution Guide\n\n이 강좌에 여러가지 방법으로 기여할 수 있습니다. \n\n-   강좌 오류 수정\n-   코드 오류 수정\n-   ...\n\n기여자 분들은 기여의 형태에 따라 [Contributors / Sponsors](https://github.com/appkr/l5essential#contributors--sponsors) 또는 [Contributor List](https://github.com/appkr/l5essential/graphs/contributors) 에 등록됩니다. 이 강좌는 독자 및 기여자 여러분들과 같이 만들어 가는 것입니다. 여러 분들의 기여 활동은 이 강좌를 접하는 많은 분들에게 도움이 될 것입니다. \n\n## Pull Request\n\n-   코드는 [PSR-2 코딩 컨벤션](http://www.php-fig.org/psr/psr-2/) 을 지켜 주세요.\n-   수정 내용을 설명해 주세요.\n-   Fork 한후 Topic Branch 를 만들어서 PR 을 보내 주세요.\n-   PR 전에 최신 코드인 지를 확인해 주세요. (`$ git pull && git merge master`)\n-   단순 오류 수정이 아니라, 동작을 변경하는 코드라면 Test 를 포함해 주세요.\n\n## Test\n\n이 강좌의 코드는 Integration Test 를 포함하고 있습니다. 코드를 수정했다면 PR 전에 테스트를 실행해 주세요. PR 을 하시면 Travis CI 가 테스트를 한번 더 수행합니다.\n\n```sh\n$ phpunit\n```\n\n감사합니다.\n\nappkr.\n   \n   \n"
  },
  {
    "path": "Envoy.blade.php",
    "content": "#--------------------------------------------------------------------------\n# List of tasks, that you can run...\n# e.g. envoy run hello\n#--------------------------------------------------------------------------\n#\n# hello     Check ssh connection\n# release   Publish new release\n# list      Show list of releases\n# checkout  Checkout to the given release (must provide --release=/path/to/release)\n# prune     Purge old releases (must provide --keep=n, where n is a number)\n#\n\n\n@servers(['web' => 'aws-seoul-deploy'])\n\n\n@setup\n  $path = [\n    'base' => '/home/deployer/www',\n    'docroot' => '/home/deployer/www/l5.appkr.kr',\n    'shared' => '/home/deployer/www/shared',\n    'release' => '/home/deployer/www/releases',\n  ];\n\n  $required_dirs = [\n    $path['base'],\n    $path['shared'],\n    $path['release'],\n  ];\n\n  $shared_item = [\n    '/home/deployer/www/shared/.env' => '.env',\n    '/home/deployer/www/shared/storage' => 'storage',\n    '/home/deployer/www/shared/cache' => 'bootstrap/cache',\n    '/home/deployer/www/shared/attachments' => 'public/attachments',\n  ];\n\n  $distribution = [\n    'name' => 'release_' . date('YmdHis'),\n  ];\n\n  $git = [\n    'repo' => 'git@github.com:appkr/l5essential.git',\n  ];\n@endsetup\n\n\n@task('hello', ['on' => ['web']])\n  HOSTNAME=$(hostname);\n  echo \"Hello Envoy! Responding from $HOSTNAME\";\n@endtask\n\n\n@task('release', ['on' => ['web']])\n  {{--Create directories if not exists--}}\n  @foreach ($required_dirs as $dir)\n    if [ ! -d {{ $dir }} ]; then\n      mkdir {{ $dir }};\n      chgrp -h -R www-data {{ $dir }};\n    fi;\n  @endforeach\n\n  {{--Download book keeping officer--}}\n  if [ ! -f {{ $path['base'] }}/officer.php ]; then\n    wget https://raw.githubusercontent.com/appkr/envoy/master/scripts/officer.php -O {{ $path['base'] }}/officer.php;\n  fi;\n\n  {{--Fetch code from git--}}\n  cd {{ $path['release'] }};\n  git clone -b master {{ $git['repo'] }} {{ $distribution['name'] }};\n\n  {{--Symlink shared directory to current release.--}}\n  {{--e.g. storage, .env, user uploaded file storage, ...--}}\n  cd {{ $path['release'] }}/{{ $distribution['name'] }};\n  @foreach($shared_item as $global => $local)\n    [ -f {{ $local }} ] && rm {{ $local }};\n    [ -d {{ $local }} ] && rm -rf {{ $local }};\n    ln -nfs {{ $global }} {{ $local }};\n    chgrp -h -R www-data {{ $local }};\n  @endforeach\n\n  {{--Run composer install--}}\n  composer install --prefer-dist --no-scripts;\n  php artisan clear-compiled;\n  php artisan optimize;\n  php artisan cache:clear;\n  php artisan my:update-lesson;\n\n  {{--Symlink current release to service directory.--}}\n  ln -nfs {{ $path['release'] }}/{{ $distribution['name'] }} {{ $path['docroot'] }};\n  chgrp -h -R www-data {{ $path['docroot'] }};\n\n  {{--Set permission and change owner. Do one final more for safety.--}}\n  chgrp -h -R www-data {{ $path['release'] }}/{{ $distribution['name'] }};\n\n  {{--Book keeping--}}\n  php {{ $path['base'] }}/officer.php deploy {{ $path['release'] }}/{{ $distribution['name'] }};\n\n  {{--Restart web server.--}}\n  sudo service nginx restart;\n  sudo service php5-fpm restart;\n@endtask\n\n\n@task('prune', ['on' => 'web'])\n  if [ ! -f {{ $path['base'] }}/officer.php ]; then\n    echo '\"officer.php\" script not found.';\n    echo '\\$ envoy run hire_officer';\n    exit 1;\n  fi;\n\n  @if (isset($keep) and $keep > 0)\n    php {{ $path['base'] }}/officer.php prune {{ $keep }};\n  @else\n    echo 'Must provide --keep=n, where n is a number.';\n  @endif\n@endtask\n\n\n@task('hire_officer', ['on' => 'web'])\n  {{--Download \"officer.php\" to the server--}}\n  wget https://raw.githubusercontent.com/appkr/envoy/master/scripts/officer.php -O {{ $path['base'] }}/officer.php;\n  echo '\"officer.php\" is ready!';\n@endtask\n\n\n@task('list', ['on' => 'web'])\n  {{--Show the list of release--}}\n  if [ ! -f {{ $path['base'] }}/officer.php ]; then\n    echo '\"officer.php\" script not found.';\n    echo '\\$ envoy run hire_officer';\n    exit 1;\n  fi;\n\n  php {{ $path['base'] }}/officer.php list;\n@endtask\n\n\n@task('checkout', ['on' => 'web'])\n  {{--Checkout to the given release path--}}\n  if [ ! -f {{ $path['base'] }}/officer.php ]; then\n    echo '\"officer.php\" script not found.';\n    echo '\\$ envoy run hire_officer';\n    exit 1;\n  fi;\n\n  @if (isset($release))\n    cd {{ $release }};\n\n    {{--Symlink shared directory to the given release.--}}\n    @foreach($shared_item as $global => $local)\n      [ -f {{ $local }} ] && rm {{ $local }};\n      [ -d {{ $local }} ] && rm -rf {{ $local }};\n      ln -nfs {{ $global }} {{ $local }};\n      chgrp -h -R www-data {{ $local }};\n    @endforeach\n\n    {{--Symlink the given release to service directory.--}}\n    ln -nfs {{ $release }} {{ $path['docroot'] }};\n    chgrp -h -R www-data {{ $path['docroot'] }};\n\n    {{--Book keeping--}}\n    php {{ $path['base'] }}/officer.php checkout {{ $release }};\n\n    {{--Restart web server.--}}\n    sudo service nginx restart;\n    sudo service php5-fpm restart;\n  @else\n    echo 'Must provide --release=/full/path/to/release.';\n  @endif\n@endtask"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Appkr <juwonkim@me.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 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."
  },
  {
    "path": "Vagrantfile",
    "content": "require 'json'\nrequire 'yaml'\n\nVAGRANTFILE_API_VERSION ||= \"2\"\nconfDir = $confDir ||= File.expand_path(\"vendor/laravel/homestead\", File.dirname(__FILE__))\n\nhomesteadYamlPath = \"Homestead.yaml\"\nhomesteadJsonPath = \"Homestead.json\"\nafterScriptPath = \"after.sh\"\naliasesPath = \"aliases\"\n\nrequire File.expand_path(confDir + '/scripts/homestead.rb')\n\nVagrant.configure(VAGRANTFILE_API_VERSION) do |config|\n    if File.exists? aliasesPath then\n        config.vm.provision \"file\", source: aliasesPath, destination: \"~/.bash_aliases\"\n    end\n\n    if File.exists? homesteadYamlPath then\n        Homestead.configure(config, YAML::load(File.read(homesteadYamlPath)))\n    elsif File.exists? homesteadJsonPath then\n        Homestead.configure(config, JSON.parse(File.read(homesteadJsonPath)))\n    end\n\n    if File.exists? afterScriptPath then\n        config.vm.provision \"shell\", path: afterScriptPath\n    end\nend\n"
  },
  {
    "path": "apiary.apib",
    "content": "FORMAT: 1A\nHOST: http://api.appkr.kr\n\n# Welcome to the myProject Api\n\nmyProject Api 에 오신 것을 환영합니다.\n\nmyProject 에서는 포럼 <sup>Forum</sup> Api 를 제공합니다. 포럼을 사용하는 사용자를 식별하고 권한을 제어하기 위해 사용자 등록 및 로그인 <sup>Authentication</sup> 기능도 제공합니다.\n\n## Base URL\n\n모든 Api 요청은 아래 Base URL 을 이용합니다.\n\n```http\nhttp://api.appkr.kr\n```\n\n## Current Version\n\n현재 버전은 v1 입니다. [Authentication](#authentication) 을 제외하고 모든 Api 요청에 `/v1` 이 포함되어야 합니다.\n\n```http\nGET /v1 HTTP/1.1\nHost: api.appkr.kr\n```\n\n## Request 101\n\nREST 원칙을 따릅니다.\n\n### Reqeust Headers\n\n#### Accept (Content Negotiation)\n\nv1 에서는 JSON 응답만 지원합니다.\n\n```http\nGET /v1 HTTP/1.1\nHost: api.appkr.kr\nAccept: application/json\n```\n\n#### Accept-Language (Language Negoation)\n\nv1 에서는 ko_KR 만 지원합니다.\n\n```http\nGET /v1 HTTP/1.1\nHost: api.appkr.kr\nAccept-Language: ko-KR\n```\n\n### Request Payload\n\n`multipart/form-data`, `application/x-www-form-urlencoded`, `application/json` 을 모두 지원합니다. `application/json` 사용을 권장합니다.\n\n```http\nPOST /v1/articles HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\n\n{\"field\": \"value\"}\n```\n\n## Response 101\n\n### Collection Response\n\nCollection 에 해당하는 리소스를 요청하면 Pagination 이 포함된 응답을 받습니다. `data` 키 아래에 포함된 내용이 Collection 입니다.\n\n```http\nGET /v1/articles HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\n```\n\n```json\nHTTP/1.1 200 OK\n\n{\n    \"data\": [\n        {\"key\": \"value\"},\n        {\"key\": \"value\"},\n        {\"key\": \"value\"},\n        {\"key\": \"value\"},\n        {\"key\": \"value\"}\n    ],\n    \"meta\": {\n        \"pagination\": {\n            \"total\": 20,\n            \"count\": 5,\n            \"per_page\": 5,\n            \"current_page\": 1,\n            \"total_pages\": 4,\n            \"links\": {\n                \"next\": \"/v1/articles?page=2\"\n            }\n        }\n    }\n}\n```\n\n### Instance Response\n\nInstance 에 해당하는 리소스를 요청하면 요청한 Instance 하나에 대한 응답을 받습니다. 이 응답은 JSON 키가 없습니다.\n\n```http\nGET /v1/articles/95280986 HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\n```\n\n```json\nHTTP/1.1 200 OK\n\n{\n    \"id\": 95280986,\n    \"title\": \"example title\"\n}\n```\n\n### Successful Response\n\n리소스 생성, 수정, 삭제 등의 요청을 성공하면 성공 응답을 받습니다.\n\n```http\nPUT /v1/articles/95280986 HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\nAuthorization: Bearer header.payload.signagure\n\n{\"title\": \"modified title\"}\n```\n\n```javascript\nHTTP/1.1 200 OK\n\n{\n    \"success\": {\n        \"code\": 200,\n        \"message\": \"Updated\"\n    }\n}\n```\n\n성공 응답 목록은 아래와 같고, HTTP 응답 코드와 동일한 코드를 JSON 본문에도 포함합니다.\n\nResponse Code|Description\n---|---\n200|성공\n201|새로운 리소스가 성공적으로 생성되었습니다.\n204|요청한 리소스가 삭제되었습니다.\n\n### Error Response\n\n에러가 발생했을 때는 아래와 같은 응답을 받습니다.\n\n```http\nPUT /v1/articles/95280986 HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\nAuthorization: Bearer header.payload.signagure\n\n{\"title\": \"modified title\"}\n```\n\n```javascript\nHTTP/1.1 403 Forbidden\n\n{\n    \"error\": {\n        \"code\": 403,\n        \"message\": \"Forbidden\"\n    }\n}\n```\n\n오류 응답 목록은 아래와 같고, HTTP 응답 코드와 동일한 코드를 JSON 본문에도 포함합니다.\n\nResponse Code|Description\n---|---\n400|요청에 오류가 있습니다.\n401|인증 오류입니다. Authorization 헤더를 확인해 주세요.\n403|권한이 없습니다. Authorization 헤더로 넘긴 토큰에 해당하는 사용자가 요청하신 Action 을 수행할 권한이 없습니다.\n404|요청한 리소스가 없습니다.\n405|잘못된 HTTP 메소드를 사용했습니다.\n422|유효성 검사 오류입니다. 요청 본문에 데이터가 형식에 맞는지 확인하세요.\n429|Rate Limit 를 초과했습니다. 잠시 후 다시 시도하세요.\n500|서버에 오류가 있습니다. [관리자](mailto:junwonkim@me.com) 에게 신고해 주세요.\n503|서버에 트래픽이 폭주했거나, 서버 유지보수 작업 중입니다.\n\n## Rate Limit\n\n[Authentication](#authentication) 요청은 1 분에 10 회 까지, 리소스 요청은 1분에 60 회까지 허용합니다.\n\n```http\nGET /v1/articles/95280986 HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\n```\n\n```http\nHTTP/1.1 429 Too Many Requests\nRetry-After: 60\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 0\n```\n\n## Caching\n\nGET 동사를 이용한 요청은 `Etag` 헤더를 응답합니다.\n\n> 대부분의 HTTP 클라이언트 라이브러리가 자동으로 모든 처리를 해 줍니다.<br/><br/>\n> 다만, 여러분의 클라이언트가 `Etag` 기능을 지원하지 않는데, 캐싱의 이득을 보려면, 응답 받은 Etag 헤더를 파싱하여 요청 URL 과 응답 본문을 저장하고, 다음 요청시 `If-None-Match: Etag` 헤더를 전송해야 합니다.\n\n아래 그림은 `Etag` 를 이용한 클라이언트-서버간 캐싱 동작 시퀀스 다이어그램입니다.\n\n![](https://camo.githubusercontent.com/f5c800863972804dd7af6ef6a55343df3fb55b53/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d4f6a3674794f74386167302f565934456b5878324f5a492f41414141414141414145492f37554a6e43503459384f452f733634302f65746167732e706e67)\n\n### First Request & Response\n\n처음으로 `Etag` 값을 받습니다. 클라이언트 저장소에 받은 `Etag` 값을 키로 요청 URL 과 응답 본문을 저장해 놓습니다. *(대부분의 클라이언트 라이브러리가 자동으로 처리해 줍니다.)*\n\n```http\nGET /v1/articles/95280986 HTTP/1.1\nHost: api.appkr.kr\n```\n\n```http\nHTTP/1.1 200 OK\nEtag: CtXS0QQlWJKY2dXe\n```\n\n### Second-on Request & Response - **No change in server resources**\n\n요청 URL 에 해당하는 `Etag` 값을 `If-None-Match` 헤더에 달아서 보냅니다.\n\n응답을 보니 리소스의 내용이 변경되지 않았으므로, 클라이언트 저장소에 저장된 지난 번 응답 본문을 그대로 사용합니다. *(대부분의 클라이언트 라이브러리가 자동으로 처리해 줍니다.)*\n\n```http\nGET /v1/articles/95280986 HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\nIf-None-Match: CtXS0QQlWJKY2dXe\n```\n\n```http\nHTTP/1.1 304 Not Modified\n```\n\n### Second-on Request & Response - **Server resource changed**\n\n서버의 리소스가 변경되었습니다. 새로 받은 `Etag` 값과 응답 본문을 클라이언트 저장소에 저장합니다. *(대부분의 클라이언트 라이브러리가 자동으로 처리해 줍니다.)*\n\n```http\nGET /v1/articles/95280986 HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\nIf-Non-Match: CtXS0QQlWJKY2dXe\n```\n\n```http\nHTTP/1.1 200 OK\nEtag: F8tG872adeIC3zlf\n```\n\n**`WHY`** 모바일 환경에서 응답속도 개선 및 사용자 요금 절감을 위해 꼭 필요합니다.\n\n## Sub Resource Inclusion\n\n### Signature\n\n`include` 쿼리스트링을 이용하면, 현재 요청하는 리소스의 자식 리소스의 Collection 또는 Instance 를 응답에 포함할 수 있습니다.\n\n문법은 아래와 같습니다.\n\n```http\nGET /v1/parent?include=child_resource:limit(limit|offset):sort(sort|order) HTTP/1.1\n\n# 여러 개의 자식 리소스를 포함할 때는 array 필드나 콤마 (,) 를 이용할 수 있습니다.\nGET /v1/parent?include[]=child_resource_1&include[]=child_resource_2 HTTP/1.1\n# --or--\nGET /v1/parent?include[]=child_resource_1,child_resource_2 HTTP/1.1\n```\n\nKeyword|Description\n---|---\n`child_resource`|자식 리소스의 이름입니다. (Article 부모 리소스에 대해서는 `comments`, `author`, `tags`, `attachments` 자식 리소스가 가용합니다.)\n`:`|파라미터를 구분하는 구분자입니다.\n`limit`|예약어 입니다. `comments`, `author`, `tags`, `attachments` 등 Collection 형태의 리소스에만 적용 가능합니다.\n`limit(offset\\\\limit)`|`limit` 반환 받을 Collection 개수 입니다. `offset` 건너뛸 Collection 개수입니다. **(기본값 `limit(3\\\\0)`)**\n`sort`|예약어 입니다. Collection 형태의 리소스에만 적용 가능합니다.\n`sort(sort\\\\order)`|`sort` 정렬 기준 필드로 현재는 `created`, `view_count` 두 개만 지원합니다. `order` 정렬 방향으로 `asc`, `desc` 를 쓸 수 있습니다. **(기본값 `sort(created\\\\desc)`)**\n\n**`알림`** 위 표에서 `\\\\` 는 Apiary 의 마크다운 컴파일 에러를 방지하기 위해 `|` 대신 넣은 문자입니다.\n\n### Example\n\n아래는 Article 리소스의 자식 리소스인 comments 와 authors 를 포함하는 예제 입니다.\n\n```http\nGET /v1/articles/95280986?include=comments:limit(1|0):sort('created'|'asc') HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\n```\n\n```javascript\nHTTP/1.1 200 OK\n\n{\n    \"id\": 95280986,\n    \"title\": \"example title\",\n    \"content_raw\": \"example content\",\n    \"content_html\": \"<p>example content</p>\",\n    \"created\": \"2015-12-19T10:37:42+0000\",\n    \"view_count\": 1,\n    \"link\": {\n        \"rel\": \"self\",\n        \"href\": \"/v1/articles/95280986\"\n    },\n    \"comments\": {\n        \"data\": [\n            {\n                \"id\": 95280986,\n                \"content_raw\": \"example comment\",\n                \"content_html\": \"<p>example comment</p>\",\n                \"created\": \"2015-12-19T10:37:42+0000\",\n                \"vote\": {\n                    \"up\": 1,\n                    \"down\": 1\n                },\n                \"link\": {\n                    \"rel\": \"self\",\n                    \"href\": \"/v1/comments/95280986\"\n                },\n                \"author\": {\n                    \"name\": \"John Doe\",\n                    \"email\": \"john@example.com\",\n                    \"avatar\": \"http://www.gravatar.com/d4c74594d841139328695756648b6bd6\"\n                }\n            }\n        ]\n    },\n    \"author\": {\n        \"name\": \"John Doe\",\n        \"email\": \"john@example.com\",\n        \"avatar\": \"http://www.gravatar.com/d4c74594d841139328695756648b6bd6\"\n    },\n    \"tags\": [\n        \"laravel\",\n        \"eloquent\"\n    ],\n    \"attachments\": 1\n}\n```\n\n## Partial Response\n\n### Against Parent Resource\n\n`fields` 쿼리스트링을 이용하면, 응답 필드를 골라서 받을 수 있습니다. 필드는 콤마 (`,`) 로 구분하고, 필드간에 공백이 없도록 주의하십시오.\n\n```http\nGET /v1/articles/95280986?fields=id,title,content_raw,author HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\n```\n\n```javascript\nHTTP/1.1 200 OK\n\n{\n    \"id\": 95280986,\n    \"title\": \"example title\",\n    \"content_raw\": \"example content\",\n    \"author\": {\n      \"name\": \"John Doe\",\n      \"email\": \"john@example.com\",\n      \"avatar\": \"http://www.gravatar.com/d4c74594d841139328695756648b6bd6\"\n    }\n}\n```\n\n### Against Sub Resource\n\n역시 `fields` 쿼리스트링을 이용해서 자식 리소스의 응답 필드를 골라 받을 수 있습니다. 부모 리소스에서와 달리, 필드 구분에 파이프 문자 (`|`) 를 이용합니다. 필드 사이에 공백이 없도록 주의하십시오.\n\n```http\nGET /v1/articles/95280986?fields=id,title,content_raw,author&include=comments:fields(id|created|vote) HTTP/1.1\nHost: api.appkr.kr\nContent-type: application/json\n```\n\n```javascript\nHTTP/1.1 200 OK\n\n{\n    \"id\": 95280986,\n    \"title\": \"example title\",\n    \"content_raw\": \"example content\",\n    \"author\": {\n      \"name\": \"John Doe\",\n      \"email\": \"john@example.com\",\n      \"avatar\": \"http://www.gravatar.com/d4c74594d841139328695756648b6bd6\"\n    },\n    \"comments\": {\n        \"data\": [\n            {\n                \"id\": 95280986,\n                \"created\": \"2015-12-19T10:37:42+0000\",\n                \"vote\": {\n                    \"up\": 1,\n                    \"down\": 1\n                }\n            }\n        ]\n    },\n}\n```\n\n# group Welcome to myProject Api v1\n\nmyProject Api v1 에 오신 것을 환영합니다.\n\n## Welcoming the Api v1 [/v1]\n\n### Hello myProject Api v1 [GET]\n\n-   request\n\n    -   headers\n\n            Accept: application/json\n\n-   response 200 (application/json)\n\n        {\n            \"name\": \"myProject Api\",\n            \"message\": \"Welcome to myProject Api. This is a base endpoint of version 1.\",\n            \"version\": \"v1\",\n            \"links\": [\n                {\n                    \"rel\": \"self\",\n                    \"href\": \"/v1\"\n                },\n                {\n                    \"rel\": \"api.users.store\",\n                    \"href\": \"/auth/register\"\n                },\n                {\n                    \"rel\": \"api.sessions.store\",\n                    \"href\": \"/auth/login\"\n                },\n                {\n                    \"rel\": \"api.v1.docs\",\n                    \"href\": \"/v1/docs\"\n                }\n            ]\n        }\n\n# group Authentication\n<a name=\"authentication\"></a>\n\n사용자 등록 및 인증을 위한 Api 입니다. myProject Api 는 사용자 인증을 위해 JWT <sup>Json Web Token</sup> 을 이용합니다.\n\n## `token` 의 발급 및 사용\n\n사용자 등록 및 로그인을 통해 생성된 `token` 은 myProject 서버에 새로운 리소스를 생성, 기존 리소스 수정 또는 삭제를 위한 Api 요청을 할 때 꼭 필요합니다. 전술한 Api 요청을 할 때 `token` 을 HTTP Authorization Header 에 붙여서 사용합니다. (e.g. `Authorization: Bearer token`) `token` 이 없으면 401 Unauthorized 응답을 받습니다. 한번 발급된 `token` 은 120 분 동안 유효하며, 유효한 기간 동안은 로그인 없이 Api 요청을 할 수 있습니다. 그래서, Api 클라이언트는 사용자 등록 및 로그인에서 받은 토큰을 로컬 저장소에 저장하고 있어야 합니다.\n\n## `token` 의 만료 및 갱신\n\n`token` 이 만료되면 서버는 401 Unauthorized 응답 코드와 함께 `token_expired` 메시지를 응답합니다. `token` 을 사용하지 않은지 총 2 주일이 지나지 않았다면, 기존 `token` 을 이용하여 새로운 토큰을 받을 수 있습니다. 2 주가 지나 더 이상 갱신이 불가한 상태가 되면, 서버로 부터 401 응답을 받게 되며 이때는 사용자에게 로그인 UI 를 표출하여 로그인을 하도록 유도하여 `token` 을 발급 받아야 합니다.\n\n## User Registration [/auth/register]\n\n새로운 사용자를 등록합니다.\n\n### User Registration [POST]\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n\n    -   body\n\n            {\n                \"name\": \"New User\",\n                \"email\": \"new_user@example.org\",\n                \"password\": \"password\",\n                \"password_confirmation\": \"password\"\n            }\n\n-   response 201 (application/json)\n\n    -   Attributes\n\n        -   success (object)\n            -   code: `201` (number) - Http Status Equivalent Message Code\n            -   message: `Created` (string) - Message\n        -   meta (object)\n            -   token: `header.payload.signature` (string) - Json Web Token\n\n-   request Invalid Data\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n\n    -   body\n\n            {\"email\": \"invalid-email-address\"}\n\n-   response 422 (application/json)\n\n    -   Attributes\n\n        -   error (object)\n            -   code: `422` (number) - Http Status Equivalent Message Code\n            -   message (array)\n                -   `name 은(는) 필수 입력 항목 입니다.`\n                -   `email 은(는) 유효한 이메일 주소가 아닙니다.`\n                -   `password 은(는) 필수 입력 항목 입니다.`\n\n-   request Duplicate User\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n\n    -   body\n\n            {\n                \"name\": \"John Doe\",\n                \"email\": \"john@example.com\",\n                \"password\": \"password\",\n                \"password_confirmation\": \"password\"\n            }\n\n-   response 422 (application/json)\n\n    -   Attributes\n\n        -   error (object)\n            -   code: `422` (number) - Http Status Equivalent Message Code\n            -   message (array)\n                -   `email 은(는) 이미 사용 중입니다.`\n\n## User Login [/auth/login]\n\n로그인을 하고 `token` 을 얻습니다.\n\n### User Login [POST]\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n\n    -   body\n\n            {\n                \"email\": \"john@example.com\",\n                \"password\": \"password\"\n            }\n\n-   response 201 (application/json)\n\n    -   Attributes\n\n        -   success (object)\n            -   code: `201` (number) - Http Status Equivalent Message Code\n            -   message: `Created` (string) - Message\n        -   meta (object)\n            -   token: `header.payload.signature` (string) - Json Web Token\n\n-   request Invalid Credential\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n\n    -   body\n\n            {\n                \"email\": \"john@example.com\",\n                \"password\": \"wrong-password\"\n            }\n\n-   response 401 (application/json)\n\n    -   Attributes\n\n        -   error (object)\n            -   code: `401` (number) - Http Status Equivalent Message Code\n            -   message: `invalid_credentials` (string) - Message\n\n-   request Invalid Data\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n\n    -   body\n\n            {\n                \"email\": \"invalid-email-address\",\n                \"password\": \"password\"\n            }\n            email: invalid-email-address\n\n-   response 422 (application/json)\n\n    -   Attributes\n\n        -   error (object)\n            -   code: `422` (number) - Http Status Equivalent Message Code\n            -   message (array)\n                -   `email 은(는) 유효한 이메일 주소가 아닙니다.` (string)\n\n## Token Refresh [/auth/refresh]\n\n만료된 `token` 을 갱신합니다.\n\n### Token Refresh [POST]\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n            Authorization: Bearer header.payload.signagure\n\n-   response 201 (application/json)\n\n    -   Attributes\n\n        -   success (object)\n            -   code: `201` (number) - Http Status Equivalent Message Code\n            -   message: `Created` (string) - Message\n        -   meta (object)\n            -   token: `header.payload.signature` (string) - Json Web Token\n\n# group Forum\n\nForum Api 는 HTTP 요청을 통해 여러분의 Api 클라이언트가 서버에 저장된 게시글 <sup>`Article`</sup> 과 댓글 <sup>`Comment`</sup> 리소스를 이용할 수 있도록 해 줍니다.\n\n**`참고`** 댓글에 대한 생성, 수정, 삭제 Api 는 현재 구현되어 있지 않습니다.\n\n## Articles Collection [/v1/articles]\n\n### List All Articles [GET]\n\n`Article` Collection 을 요청합니다. 사용할 수 있는 쿼리스트링은 다음과 같습니다.\n\n<a name=\"available_querystrings\"></a>\n####   Available Querystrings\n\n-   `filter` - 필터 (선택, `no_comment`|`not_solved`)\n\n    ```http\n    GET /v1/articles?filter=no_comment\n    ```\n\n-   `limit` - 응답 받을 게시물 수 (선택, `1`~`10`, 기본값 `5`)\n\n    ```http\n    GET /v1/articles?limit=3\n    ```\n\n-   `sort` - 정렬에 사용할 필드 (선택, `created`|`view_count`, 기본값 `created`)\n\n    ```http\n    GET /v1/articles?sort=view_count\n    ```\n\n-   `order` - 정렬 방향 (선택, `asc`|`desc`, 기본값 `desc`)\n\n    ```http\n    GET /v1/articles?sort=view_count&order=asc\n    ```\n\n-   `q` - 풀 텍스트 서치 키워드 (선택)\n\n    ```http\n    GET /v1/articles?q=hello%20api\n    ```\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n\n-   response 200 (application/json)\n\n    -   headers\n\n            Etag: aK08i2L8jQRdjBcd\n\n    -   attributes\n\n        -   data (array[Article])\n        -   meta (Pagination)\n\n-   request Not Modified\n\n    -   headers\n\n            Accept: application/json\n            If-None-Match: etag\n\n-   response 304 (application/json)\n\n### Not-allowed Querystrings [GET /v1/articles?filter=not_existing_filter]\n\n-   request Not-existing Querystrings\n\n    -   headers\n\n            Accept: application/json\n\n-   response 422 (application/json)\n\n    -   Attributes\n\n        -   error (object)\n            -   code: `422` (number) - Http Status Equivalent Message Code\n            -   message (object)\n                -   filter (array)\n                    -   `filter 은(는) 유효하지 않습니다.` (string)\n\n### Create New Article [POST]\n\n새로운 `Article` 리소스를 생성합니다.\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n            Authorization: Bearer header.payload.signagure\n\n    -   body\n\n            {\n                \"title\": \"some title\",\n                \"content\": \"some content\",\n                \"tags[]\": 1,\n                \"tags[]\": 2\n            }\n\n-   response 201 (application/json)\n\n    -   attributes\n\n        -   success (object)\n            -   code: `201` (number) - Http Status Equivalent Message Code\n            -   message: `Created` (string) - Message\n\n-   request Token Not Provided\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n\n-   response 400 (application/json)\n\n    -   attributes\n\n        -   error (object)\n            -   code: `400` (number) - Http Status Equivalent Message Code\n            -   message: `token_not_provided` (string) - Message\n\n-   request Token Invalid\n\n    -   headers\n\n            Accept: application/json\n            Authorization: Bearer invalid.token.signature\n\n-   response 400 (application/json)\n\n    -   attributes\n\n        -   error (object)\n            -   code: `400` (number) - Http Status Equivalent Message Code\n            -   message: `token_invalid` (string) - Message\n\n-   request Token Expired\n\n    -   headers\n\n            Authorization: Bearer expired.token.signagure\n            Content-type: application/json\n\n-   response 401 (application/json)\n\n    -   attributes\n\n        -   error (object)\n            -   code: `400` (number) - Http Status Equivalent Message Code\n            -   message: `token_expired` (string) - Message\n\n## Articles Instance [/v1/articles/{id}]\n\n-   parameters\n\n    -   id: `95280986` (required, number)\n\n### Fetch Article Instance [GET]\n\n`id` 로 지정된 `Article` 리소스의 상세정보를 요청합니다.\n\n`Article Collection` 과 동일한 [Available Querystrings](#available_querystrings) 을 사용할 수 있습니다.\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n\n-   response 200 (application/json)\n\n    -   headers\n\n            Etag: 31Ba8Uuo29Za4s2v\n\n    -   body\n\n            {\n                \"id\": 95280986,\n                \"title\": \"example title\",\n                \"content_raw\": \"example content\",\n                \"content_html\": \"<p>example content</p>\",\n                \"created\": \"2015-12-19T10:37:42+0000\",\n                \"view_count\": 1,\n                \"link\": {\n                    \"rel\": \"self\",\n                    \"href\": \"/v1/articles/95280986\"\n                },\n                \"comments\": 1,\n                \"author\": {\n                    \"name\": \"John Doe\",\n                    \"email\": \"john@example.com\",\n                    \"avatar\": \"http://www.gravatar.com/d4c74594d841139328695756648b6bd6\"\n                },\n                \"tags\": [\n                    \"laravel\",\n                    \"eloquent\"\n                ],\n                \"attachments\": 1\n            }\n\n-   request Not Modified\n\n    -   headers\n\n            Accept: application/json\n            If-None-Match: 31Ba8Uuo29Za4s2v\n\n-   response 304 (application/json)\n\n### Fetch Not-existing Article Instance [GET /v1/articles/{id}]\n\n없는 `id` 이면 404 Not Found 응답을 받습니다.\n\n-   parameters\n\n    -   id: `00000000` (required, number)\n\n-   request Not-existing Resource\n\n    -   headers\n\n            Accept: application/json\n\n-   response 404 (application/json)\n\n    -   Attributes\n\n        -   error (object)\n            -   code: `404` (number) - Http Status Equivalent Message Code\n            -   message: `No query results for model [App\\\\Article].` (string) - Message\n\n### Update Article Instance [PUT]\n\n`id` 로 지정된 `Article` 의 내용을 수정합니다. 수정은 리소스의 소유자 또는 관리자에게만 허용되며, 이 조건이 충족되지 않을 경우에는 403 Forbidden 응답을 받습니다.\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n            Authorization: Bearer header.payload.signagure\n\n    -   body\n\n            {\n                \"title\": \"updated title\",\n                \"content\": \"updated content\",\n                \"tags[]\": \"3\"\n            }\n\n-   response 200 (application/json)\n\n    -   attributes\n\n        -   success (object)\n            -   code: `200` (number) - Http Status Equivalent Message Code\n            -   message: `Updated` (string) - Message\n\n-   request Forbidden\n\n    -   headers\n\n            Accept: application/json\n            Content-type: application/json\n            Authorization: Bearer not.owner.signagure\n\n-   response 403 (application/json)\n\n    -   attributes\n\n        -   error (object)\n            -   code: `403` (number) - Http Status Equivalent Message Code\n            -   message: `Forbidden` (string) - Message\n\n\n### Delete Article Instance [DELETE]\n\n`id` 로 지정된 `Article` 을 삭제합니다. 삭제는 리소스의 소유자 또는 관리자에게만 허용되며, 이 조건이 충족되지 않을 경우에는 403 Forbidden 응답을 받습니다.\n\n-   request OK\n\n    -   headers\n\n            Accept: application/json\n            Authorization: Bearer header.payload.signagure\n\n-   response 204 (application/json)\n\n-   request Forbidden\n\n    -   headers\n\n            Accept: application/json\n            Authorization: Bearer not.owner.signagure\n\n-   response 403 (application/json)\n\n    -   attributes\n\n        -   error (object)\n            -   code: `403` (number) - Http Status Equivalent Message Code\n            -   message: `Forbidden` (string) - Message\n\n\n\n\n\n# data structures\n\n## Article (object)\n\n-   id: `95280986` (number) - 고유 키\n-   title: `example title` (string) - 제목\n-   content_raw: `example content` (string) - 본문 (Markdown 형식)\n-   content_html: `<p>example content</p>` (string) - 본문 (HTML 컴파일)\n-   created: `2015-12-19T10:37:42+0000` (string) - 생성일\n-   view_count: 1 (number) - 조회 수\n-   link (object)\n    -   rel: `self`\n    -   href: `/v1/articles/95280986` (string) - 상세 내용 요청을 위한 Api Endpoint\n-   comments: `1` (number) - 댓글 개수\n-   author (object)\n    -   name: `John Doe` (string) - 작성자 이름\n    -   email: `john@example.com` (string) - 작성자 이메일\n    -   avatar: `http://www.gravatar.com/d4c74594d841139328695756648b6bd6` (string) - 작성자 아바타 URL\n-   tags (array)\n    -   laravel\n    -   eloquent\n-   attachments: `1` (number) - 첨부파일 개수\n\n## User (object)\n\n-   id: `95280986` (number) - 고유 키\n-   name: `John Doe` (string) - 사용자 이름\n-   email: `john@example.com` (string) - 사용자 이메일\n-   avatar: `http://www.gravatar.com/d4c74594d841139328695756648b6bd6` (string) - 사용자 아바타 URL\n-   signup: `2016-01-12T06:18:10+0000` - 가입일\n-   link (object)\n    -   rel: `self`\n    -   href: `/users/95280986` (string) - 상세 내용 요청을 위한 Api Endpoint\n-   articles: `1` (number) - 포럼 게시글 개수\n-   comments: `1` (number) - 작성한 댓글 개수\n\n## Comment (object)\n\n-   id: `95280986` (number) - 고유 키\n-   content_raw: `example content` (string) - 본문 (Markdown 형식)\n-   content_html: `<p>example content</p>` (string) - 본문 (HTML 컴파일)\n-   created: `2015-12-19T10:37:42+0000` (string) - 생성일\n-   vote (object)\n    -   up: `1` (number) - 좋아요 투표 수\n    -   down: `1` (number) - 싫어요 투표 수\n-   link (object)\n    -   rel: `self`\n    -   href: `/v1/comments/95280986` (string) - 상세 내용 요청을 위한 Api Endpoint\n-   author (object)\n    -   name: `John Doe` (string) - 작성자 이름\n    -   email: `john@example.com` (string) - 작성자 이메일\n    -   avatar: `http://www.gravatar.com/d4c74594d841139328695756648b6bd6` (string) - 작성자 아바타 URL\n\n## Tag (object)\n\n-   id: `95280986` (number) - 고유 키\n-   slug: `laravel` (string) - Slug\n-   created: `2015-12-19T10:37:42+0000` (string) - 생성일\n-   link (object)\n    -   rel: `self`\n    -   href: `/v1/tags/laravel/articles` (string) - 상세 내용 요청을 위한 Api Endpoint\n-   articles: 1 (number) - 태그에 해당하는 게시글 개수\n\n## Attachment (object)\n\n-   id: `95280986` (number) - 고유 키\n-   name: `kEvzc4qBPwEze1mi.jpg`\n-   created: `2015-12-19T10:37:42+0000` (string) - 생성일\n-   link (object)\n    -   rel: `self`\n    -   href: `http://myproject.dev:8000/attachments/kEvzc4qBPwEze1mi.jpg` (string) - 첨부파일 다운로드 URL\n\n## Pagination\n\n-   pagination (object)\n    -   total: `20` (number) - 전체 게시글 개수\n    -   count: `5` (number) - 현재 응답의 게시글 개수\n    -   per_page: `5` (number) - 요청당 응답할 게시글 개수\n    -   current_page: `2` (number) - 현재 페이지 번호\n    -   total_pages: `4` (number) - 총 페이지 수\n    -   links (object)\n        -   previous: `/v1/articles?page=1` (string) - 이전 페이지 URL\n        -   next: `/v1/articles?page=3` (string) - 다음 페이지 URL"
  },
  {
    "path": "app/Article.php",
    "content": "<?php\n\nnamespace App;\n\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\n\nclass Article extends Model\n{\n    use SoftDeletes;\n    use AuthorTrait;\n\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array\n     */\n    protected $fillable = [\n        'author_id',\n        'title',\n        'content',\n        'notification',\n        'solution_id',\n        'pin',\n    ];\n\n    /**\n     * The attributes that should be hidden for arrays.\n     *\n     * @var array\n     */\n    protected $hidden = [\n        'author_id',\n        'solution_id',\n        'notification',\n        'deleted_at',\n        'pin',\n    ];\n\n    /**\n     * The relations to eager load on every query.\n     *\n     * @var array\n     */\n    protected $with = [\n        'author',\n    ];\n\n    /**\n     * The attributes that should be mutated to dates.\n     *\n     * @var array\n     */\n    protected $dates = [\n        'deleted_at'\n    ];\n\n    /* Relationships */\n\n    public function author()\n    {\n        return $this->belongsTo(User::class, 'author_id');\n    }\n\n    public function tags()\n    {\n        return $this->belongsToMany(Tag::class)->withTimestamps();\n    }\n\n    public function comments()\n    {\n        return $this->morphMany(Comment::class, 'commentable');\n    }\n\n    public function solution()\n    {\n        return $this->hasOne(Comment::class, 'id', 'solution_id');\n    }\n\n    public function attachments()\n    {\n        return $this->hasMany(Attachment::class);\n    }\n\n    /* Query Scope */\n\n    public function scopeNoComment($query)\n    {\n        return $query->has('comments', '<', 1);\n    }\n\n    public function scopeNotSolved($query)\n    {\n        return $query->whereNull('solution_id');\n    }\n\n    /* Helpers */\n\n    public function isNotice()\n    {\n        return $this->pin ? true : false;\n    }\n\n    public function etag($cacheKey = null)\n    {\n        $etag = $this->getTable() . $this->getKey();\n\n        if ($this->usesTimestamps()) {\n            $etag .= $this->updated_at->timestamp;\n        }\n\n        return md5($etag.$cacheKey);\n    }\n}\n"
  },
  {
    "path": "app/Attachment.php",
    "content": "<?php\n\nnamespace App;\n\nclass Attachment extends Model\n{\n    protected $fillable = [\n        'name'\n    ];\n\n    protected $hidden = [\n        'article_id'\n    ];\n\n    /* Relationships */\n\n    public function article()\n    {\n        return $this->belongsTo(Article::class);\n    }\n}\n"
  },
  {
    "path": "app/AuthorTrait.php",
    "content": "<?php\n\nnamespace App;\n\ntrait AuthorTrait\n{\n    /**\n     * Determine if the current instance was authored by the current user.\n     *\n     * @return bool\n     */\n    public function isAuthor()\n    {\n        return $this->author->id == auth()->user()->id;\n    }\n}"
  },
  {
    "path": "app/Comment.php",
    "content": "<?php\n\nnamespace App;\n\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\n\nclass Comment extends Model\n{\n    use SoftDeletes;\n    use AuthorTrait;\n\n    protected $fillable = [\n        'commentable_type',\n        'commentable_id',\n        'author_id',\n        'parent_id',\n        'title',\n        'content'\n    ];\n\n    protected $hidden = [\n        'author_id',\n        'commentable_type',\n        'commentable_id',\n        'parent_id',\n        'deleted_at',\n    ];\n\n    protected $dates = [\n        'deleted_at'\n    ];\n\n    protected $with = [\n        'author',\n        'votes',\n    ];\n\n    protected $appends = [\n        'up_count',\n        'down_count'\n    ];\n\n    /* Accessors */\n\n    public function getUpCountAttribute()\n    {\n        return (int) static::votes()->sum('up');\n    }\n\n    public function getDownCountAttribute()\n    {\n        return (int) static::votes()->sum('down');\n    }\n\n    /* Relationships */\n\n    public function author()\n    {\n        return $this->belongsTo(User::class, 'author_id');\n    }\n\n    public function commentable()\n    {\n        return $this->morphTo();\n    }\n\n    public function replies()\n    {\n        return $this->hasMany(Comment::class, 'parent_id')->latest();\n    }\n\n    public function parent()\n    {\n        return $this->belongsTo(Comment::class, 'parent_id', 'id');\n    }\n\n    public function votes()\n    {\n        return $this->hasMany(Vote::class);\n    }\n}\n"
  },
  {
    "path": "app/Console/Commands/BackupDb.php",
    "content": "<?php\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\n\nclass BackupDb extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'my:backup-db\n        {user : User name for database login.}\n        {pass : Password for database login.}\n        {--S|db=myProject : Database name to backup.}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Execute database backup.';\n\n    /**\n     * Create a new command instance.\n     *\n     * @return void\n     */\n    public function __construct()\n    {\n        parent::__construct();\n    }\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $dir = storage_path('backup');\n\n        if (! \\File::isDirectory($dir)) {\n            \\File::makeDirectory($dir);\n        }\n\n        $command = sprintf(\n            'mysqldump %s > %s -u%s -p%s',\n            $this->option('db'),\n            storage_path(\"backup/{$this->option('db')}.sql\"),\n            $this->argument('user'),\n            $this->argument('pass')\n        );\n\n        system($command);\n\n        $now = \\Carbon\\Carbon::now()->toDateTimeString();\n        $result = \"{$this->getName()} command done at {$now}\";\n        \\Log::info($result);\n\n        return $this->info($result);\n    }\n}\n"
  },
  {
    "path": "app/Console/Commands/ClearLog.php",
    "content": "<?php\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\n\nclass ClearLog extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'my:clear-log';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Clear Laravel log.';\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $path = storage_path('logs/laravel.log');\n        system('cat /dev/null > ' . $path);\n\n        $now = \\Carbon\\Carbon::now()->toDateTimeString();\n        $result = \"{$this->getName()} command done at {$now}\";\n        \\Log::info($result);\n\n        return $this->info($result);\n    }\n}\n"
  },
  {
    "path": "app/Console/Commands/Inspire.php",
    "content": "<?php\n\nnamespace App\\Console\\Commands;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Foundation\\Inspiring;\n\nclass Inspire extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'inspire';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Display an inspiring quote';\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $this->comment(PHP_EOL.Inspiring::quote().PHP_EOL);\n    }\n}\n"
  },
  {
    "path": "app/Console/Commands/PruneRelease.php",
    "content": "<?php\n\nnamespace App\\Console\\Commands;\n\nuse File;\nuse Illuminate\\Console\\Command;\n\nclass PruneRelease extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'my:prune-release\n        {path : Releases path.}\n        {--K|keep=3 : Number of recent releases to keep.}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Prune old releases.';\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $path = $this->argument('path');\n\n        $dirs = collect(File::directories($path))->sortByDesc(function($dir) {\n            return File::lastModified($dir);\n        });\n\n        $dirs->values()->splice($this->option($keep))->map(function($dir) {\n            File::deleteDirectory($dir);\n            $this->info(sprintf('%s removed.', $dir));\n        });\n\n        $now = \\Carbon\\Carbon::now()->toDateTimeString();\n        $result = sprintf(\n            '%s command done at %s. %d %s removed',\n            $this->getName(),\n            $now,\n            $dirs->count(),\n            str_plural('release', $dirs->count())\n        );\n        \\Log::info($result . ': ' . $dirs->toJson());\n\n        return $this->warn($result);\n    }\n}\n"
  },
  {
    "path": "app/Console/Commands/UpdateLessonsTable.php",
    "content": "<?php\n\nnamespace App\\Console\\Commands;\n\nuse App\\DocumentRepository;\nuse Illuminate\\Console\\Command;\n\nclass UpdateLessonsTable extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'my:update-lessons {--A|all=true : If true, all lesson files be processed}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Update the content of the lessons table.';\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $lessons = \\App\\Lesson::all();\n\n        foreach($lessons as $lesson) {\n            $path = base_path(\\App\\Lesson::$path . DIRECTORY_SEPARATOR . $lesson->name);\n            $lesson->content = \\File::get($path);\n            $lesson->save();\n            $lesson->touch();\n\n            $this->info(sprintf('Success updating %d: %s', $lesson->id, $lesson->name));\n        }\n\n        return $this->warn('Finished.');\n    }\n}\n"
  },
  {
    "path": "app/Console/Kernel.php",
    "content": "<?php\n\nnamespace App\\Console;\n\nuse Illuminate\\Console\\Scheduling\\Schedule;\nuse Illuminate\\Foundation\\Console\\Kernel as ConsoleKernel;\n\nclass Kernel extends ConsoleKernel\n{\n    /**\n     * The Artisan commands provided by your application.\n     *\n     * @var array\n     */\n    protected $commands = [\n        \\App\\Console\\Commands\\Inspire::class,\n        \\App\\Console\\Commands\\UpdateLessonsTable::class,\n        \\App\\Console\\Commands\\BackupDb::class,\n        \\App\\Console\\Commands\\ClearLog::class,\n        \\App\\Console\\Commands\\PruneRelease::class,\n    ];\n\n    /**\n     * Define the application's command schedule.\n     *\n     * @param  \\Illuminate\\Console\\Scheduling\\Schedule  $schedule\n     * @return void\n     */\n    protected function schedule(Schedule $schedule)\n    {\n        $schedule->command('inspire')->hourly();\n        $schedule->command('my:clear-log')->monthly();\n        $schedule->command(sprintf(\n                'my:backup-db %s %s',\n                env('DB_USERNAME'),\n                env('DB_PASSWORD')\n            ))->dailyAt('03:00');\n    }\n}\n"
  },
  {
    "path": "app/Events/ArticleConsumed.php",
    "content": "<?php\n\nnamespace App\\Events;\n\nuse Illuminate\\Queue\\SerializesModels;\n\nclass ArticleConsumed extends Event\n{\n    use SerializesModels;\n\n    /**\n     * @var \\App\\Article\n     */\n    public $article;\n\n    /**\n     * Create a new event instance.\n     *\n     * @param \\App\\Article $article\n     */\n    public function __construct(\\App\\Article $article)\n    {\n        $this->article = $article;\n    }\n}\n"
  },
  {
    "path": "app/Events/Event.php",
    "content": "<?php\n\nnamespace App\\Events;\n\nabstract class Event\n{\n    //\n}\n"
  },
  {
    "path": "app/Events/ModelChanged.php",
    "content": "<?php\n\nnamespace App\\Events;\n\nuse Illuminate\\Queue\\SerializesModels;\n\nclass ModelChanged extends Event\n{\n    use SerializesModels;\n\n    /**\n     * @var string|array\n     */\n    public $cacheTags;\n\n    /**\n     * Create a new event instance.\n     *\n     * @param string $cacheTags\n     */\n    public function __construct($cacheTags)\n    {\n        $this->cacheTags = $cacheTags;\n    }\n}\n"
  },
  {
    "path": "app/Exceptions/Handler.php",
    "content": "<?php\n\nnamespace App\\Exceptions;\n\nuse Exception;\nuse Illuminate\\Auth\\Access\\AuthorizationException;\nuse Illuminate\\Database\\Eloquent\\ModelNotFoundException;\nuse Illuminate\\Foundation\\Exceptions\\Handler as ExceptionHandler;\nuse Illuminate\\Foundation\\Validation\\ValidationException;\nuse Illuminate\\Http\\Exception\\HttpResponseException;\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\nuse Symfony\\Component\\HttpKernel\\Exception\\MethodNotAllowedHttpException;\nuse Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException;\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenExpiredException;\nuse Tymon\\JWTAuth\\Exceptions\\TokenInvalidException;\n\nclass Handler extends ExceptionHandler\n{\n    /**\n     * A list of the exception types that should not be reported.\n     *\n     * @var array\n     */\n    protected $dontReport = [\n        AuthorizationException::class,\n        HttpException::class,\n        ModelNotFoundException::class,\n        NotFoundHttpException::class,\n        ValidationException::class,\n        TokenExpiredException::class,\n        TokenInvalidException::class,\n        JWTException::class,\n    ];\n\n    /**\n     * Report or log an exception.\n     *\n     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.\n     *\n     * @param  \\Exception  $e\n     * @return void\n     */\n    public function report(Exception $e)\n    {\n        if ($this->shouldReport($e) and app()->environment('production')) {\n            app(\\App\\Reporters\\ErrorReport::class, [$e])->send();\n        }\n\n        return parent::report($e);\n    }\n\n    /**\n     * Render an exception into an HTTP response.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Exception  $e\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function render($request, Exception $e)\n    {\n        if (app()->environment('production')) {\n            $title = 'Error';\n            $description = 'Unknown error occurred :(';\n            $statusCode = 400;\n\n            if ($e instanceof ModelNotFoundException or $e instanceof NotFoundHttpException) {\n                $title = trans('errors.not_found');\n                $description = trans('errors.not_found_description');\n                $statusCode = 404;\n            }\n\n            return response(view('errors.notice', [\n                'title'       => $title,\n                'description' => $description\n            ]), $e->getCode() ?: $statusCode);\n        }\n\n        if (is_api_request()) {\n            $statusCode = method_exists($e, 'getStatusCode')\n                ? $e->getStatusCode()\n                : $e->getCode();\n\n            if ($e instanceof TokenExpiredException) {\n                $message = 'token_expired';\n            } elseif ($e instanceof TokenInvalidException) {\n                $message = 'token_invalid';\n            } elseif ($e instanceof JWTException) {\n                $message = $e->getMessage() ?: 'could_not_create_token';\n            } elseif ($e instanceof NotFoundHttpException or $e instanceof ModelNotFoundException) {\n                $statusCode = 404;\n                $message = $e->getMessage() ?: 'not_found';\n            } elseif ($e instanceof MethodNotAllowedHttpException) {\n                $message = $e->getMessage() ?: 'not_allowed';\n            } elseif ($e instanceof HttpResponseException){\n                 return $e->getResponse();\n            } elseif ($e instanceof Exception){\n                $message = $e->getMessage() ?: 'Whoops~ Tell me what you did :(';\n            }\n\n            return json()->setStatusCode($statusCode ?: 400)->error($message);\n        }\n\n        return parent::render($request, $e);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/PasswordsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\PasswordsController as ParentController;\n\nclass PasswordsController extends ParentController\n{\n    public function __construct()\n    {\n        // Kill middleware defined by ParentController.\n        // $this->middleware = [];\n        $this->middleware('throttle.api:10,1');\n\n        parent::__construct();\n    }\n\n    /**\n     * Make an error response.\n     *\n     * @param     $message\n     * @param int $statusCode\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondError($message, $statusCode = 400)\n    {\n        return json()->setStatusCode($statusCode)->error('not_found');\n    }\n\n    /**\n     * Make a success response.\n     *\n     * @param $message\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function respondSuccess($message)\n    {\n        return json()->success();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/SessionsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\SessionsController as ParentController;\nuse Illuminate\\Contracts\\Validation\\Validator;\n\nclass SessionsController extends ParentController\n{\n    public function __construct()\n    {\n        // Kill middleware defined by ParentController.\n        // $this->middleware = [];\n        $this->middleware('throttle.api:10,1');\n        $this->middleware('jwt.refresh', ['only' => 'refresh']);\n\n        parent::__construct();\n    }\n\n    /**\n     * Blank method for token refresh.\n     *\n     * @return bool\n     */\n    public function refresh()\n    {\n        return true;\n    }\n\n    /**\n     * Make validation error response.\n     *\n     * @param \\Illuminate\\Contracts\\Validation\\Validator $validator\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondValidationError(Validator $validator)\n    {\n        return json()->unprocessableError($validator->errors()->all());\n    }\n\n    /**\n     * Make login failed response.\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondLoginFailed()\n    {\n        return json()->unauthorizedError('invalid_credentials');\n    }\n\n    /**\n     * Make a success response.\n     *\n     * @param string $return\n     * @param string $token\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondCreated($return = '', $token = '')\n    {\n        return json()->setMeta(['token' => $token])->created();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/UsersController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\UsersController as ParentController;\nuse App\\User;\nuse Illuminate\\Contracts\\Validation\\Validator;\n\nclass UsersController extends ParentController\n{\n    public function __construct()\n    {\n        // Kill middleware defined by ParentController.\n        // $this->middleware = [];\n        $this->middleware('throttle.api:10,1');\n\n        parent::__construct();\n    }\n\n    /**\n     * Display the specified resource.\n     *\n     * @param  int $id\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function show($id)\n    {\n        return json()->withItem(\n            \\App\\User::with('articles', 'comments')->findOrFail($id),\n            new \\App\\Transformers\\UserTransformer\n        );\n    }\n\n    /**\n     * Make validation error response.\n     *\n     * @param \\Illuminate\\Contracts\\Validation\\Validator $validator\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondValidationError(Validator $validator)\n    {\n        return json()->unprocessableError($validator->errors()->all());\n    }\n\n    /**\n     * Make a success response.\n     *\n     * @param \\App\\User $user\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondCreated(User $user)\n    {\n        return json()->setMeta(['token' => \\JWTAuth::fromUser($user)])->created();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ArticlesController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Article;\nuse App\\Transformers\\ArticleTransformer;\nuse App\\Http\\Controllers\\ArticlesController as ParentController;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\n\nclass ArticlesController extends ParentController\n{\n    public function __construct()\n    {\n        $this->middleware('jwt.auth', ['except' => ['index', 'show']]);\n        $this->middleware('throttle.api:60,1');\n        $this->middleware('obfuscate:article');\n\n        parent::__construct();\n    }\n\n    /**\n     * Respond Article collection in JSON.\n     *\n     * @param \\Illuminate\\Pagination\\LengthAwarePaginator $articles\n     * @param string|null                                 $cacheKey\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondCollection(LengthAwarePaginator $articles, $cacheKey = null)\n    {\n        $reqEtag = request()->getETags();\n        $genEtag = $this->etags($articles, $cacheKey);\n\n        if (config('project.cache') === true and isset($reqEtag[0]) and $reqEtag[0] === $genEtag) {\n            return $this->respondNotModified();\n        }\n\n        return json()->setHeaders(['Etag' => $genEtag])->withPagination(\n            $articles,\n            new ArticleTransformer\n        );\n    }\n\n    /**\n     * Respond 201 in JSON.\n     *\n     * @param \\App\\Article $article\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondCreated(Article $article)\n    {\n        return json()->created();\n    }\n\n    /**\n     * Respond single Article item in JSON.\n     *\n     * @param \\App\\Article                                  $article\n     * @param \\Illuminate\\Database\\Eloquent\\Collection|null $commentsCollection\n     * @param string|null                                   $cacheKey\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondItem(Article $article, Collection $commentsCollection = null, $cacheKey = null)\n    {\n        $reqEtag = request()->getETags();\n        $genEtag = $article->etag($cacheKey);\n\n        if (config('project.cache') === true and isset($reqEtag[0]) and $reqEtag[0] === $genEtag) {\n            return $this->respondNotModified();\n        }\n\n        return json()->setHeaders(['Etag' => $genEtag])->withItem($article, new ArticleTransformer);\n    }\n\n    /**\n     * Respond Updated in JSON.\n     *\n     * @param \\App\\Article $article\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondUpdated(Article $article)\n    {\n        return json()->success('Updated');\n    }\n\n    /**\n     * Respond 204 Deleted.\n     *\n     * @param \\App\\Article $article\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    protected function respondDeleted(Article $article)\n    {\n        return json()->noContent();\n    }\n\n    /**\n     * Respond Not Modified;\n     *\n     * @return \\Illuminate\\Contracts\\Http\\Response\n     */\n    protected function respondNotModified()\n    {\n        return json()->notModified();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/V1/CommentsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Transformers\\CommentTransformer;\n\nclass CommentsController extends Controller\n{\n    public function __construct()\n    {\n//        $this->middleware('jwt.auth');\n\n        parent::__construct();\n    }\n\n    /**\n     * Display a listing of the resource.\n     */\n    public function index()\n    {\n        return json()->withPagination(\n            \\App\\Comment::paginate(5),\n            new CommentTransformer\n        );\n    }\n\n    /**\n     * Display the specified resource.\n     *\n     * @param  int $id\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function show($id)\n    {\n        $article = \\App\\Comment::findOrFail($id);\n\n        return json()->withItem(\n            $article,\n            new CommentTransformer\n        );\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/V1/WelcomeController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Controllers\\Controller;\n\nclass WelcomeController extends Controller\n{\n    /**\n     * Get the index page\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function index()\n    {\n        return json([\n            'name'    => 'myProject Api',\n            'message' => 'Welcome to myProject Api. This is a base endpoint of version 1.',\n            'version' => 'v1',\n            'links'   => [\n                [\n                    'rel'  => 'self',\n                    'href' => route(\\Route::currentRouteName())\n                ],\n                [\n                    'rel'  => 'api.users.store',\n                    'href' => route('api.users.store')\n                ],\n                [\n                    'rel'  => 'api.sessions.store',\n                    'href' => route('api.sessions.store')\n                ],\n                [\n                    'rel'  => 'api.v1.docs',\n                    'href' => 'http://docs.forumv1.apiary.io/'\n                ],\n            ],\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Api/WelcomeController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\Controller;\n\nclass WelcomeController extends Controller\n{\n    /**\n     * Get the index page\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function index()\n    {\n        return json([\n            'name'    => 'myProject Api',\n            'message' => 'Welcome to myProject Api. This is a base endpoint.',\n            'version' => 'n/a',\n            'links'   => [\n                [\n                    'rel'  => 'self',\n                    'href' => route(\\Route::currentRouteName())\n                ],\n                [\n                    'rel'  => 'api.users.store',\n                    'href' => route('api.users.store')\n                ],\n                [\n                    'rel'  => 'api.sessions.store',\n                    'href' => route('api.sessions.store')\n                ],\n                [\n                    'rel'  => 'api.v1.index',\n                    'href' => route('api.v1.index')\n                ],\n                [\n                    'rel'  => 'api.v1.docs',\n                    'href' => 'http://docs.forumv1.apiary.io/'\n                ],\n            ],\n        ]);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/ArticlesController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Article;\nuse App\\Events\\ArticleConsumed;\nuse App\\Events\\ModelChanged;\nuse App\\Http\\Requests\\ArticlesRequest;\nuse App\\Http\\Requests\\FilterArticlesRequest;\nuse App\\Tag;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\n\nclass ArticlesController extends Controller implements Cacheable\n{\n    public function __construct()\n    {\n        $this->middleware('author:article', ['only' => ['update', 'destroy', 'pickBest']]);\n\n        if (! is_api_request()) {\n            $this->middleware('auth', ['except' => ['index', 'show']]);\n\n            $allTags = \\Cache::remember('tags', 30, function() {\n                return Tag::with('articles')->get();\n            });\n\n            view()->share('allTags', $allTags);\n        }\n\n        parent::__construct();\n    }\n\n    public function cacheKeys()\n    {\n        return 'articles';\n    }\n\n    /**\n     * Display a listing of the resource.\n     *\n     * @param \\App\\Http\\Requests\\FilterArticlesRequest $request\n     * @param string|null                              $slug\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function index(FilterArticlesRequest $request, $slug = null)\n    {\n        $query = $slug\n            ? Tag::whereSlug($slug)->firstOrFail()->articles()\n            : new Article;\n\n        $cacheKey = cache_key('articles.index');\n\n        $query = $this->filter($query->orderBy('pin', 'desc'));\n        $args = $request->input(config('project.params.limit'), 5);\n\n        $articles = $this->cache($cacheKey, 5, $query, 'paginate', $args);\n\n        return $this->respondCollection($articles, $cacheKey);\n    }\n\n    /**\n     * Show the form for creating a new resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function create()\n    {\n        $article = new Article;\n\n        return view('articles.create', compact('article'));\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param \\App\\Http\\Requests\\ArticlesRequest $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(ArticlesRequest $request)\n    {\n        $payload = array_merge($request->except('_token'), [\n            'notification' => $request->has('notification'),\n        ]);\n\n        $article = $request->user()->articles()->create($payload);\n        $article->tags()->sync($request->input('tags'));\n\n        if ($request->has('attachments')) {\n            $attachments = \\App\\Attachment::whereIn('id', $request->input('attachments'))->get();\n            $attachments->each(function ($attachment) use ($article) {\n                $attachment->article()->associate($article);\n                $attachment->save();\n            });\n        }\n\n        event(new ModelChanged(['articles', 'tags']));\n\n        return $this->respondCreated($article);\n    }\n\n    /**\n     * Display the specified resource.\n     *\n     * @param  int $id\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function show($id)\n    {\n        $cacheKey = cache_key(\"articles.show.{$id}\");\n        $secondKey = cache_key(\"articles.show.{$id}.comments\");\n\n        $query = Article::with('comments', 'tags', 'attachments', 'solution')->findOrFail($id);\n        $article = $this->cache($cacheKey, 5, $query, 'findOrFail', $id);\n\n\n        $secondQuery = $article->comments()->with('replies')->withTrashed()->whereNull('parent_id')->latest();\n        $commentsCollection = $this->cache($secondKey, 5, $secondQuery, 'get');\n\n        if (! is_api_request()) {\n            event(new ArticleConsumed($article));\n        }\n\n        return $this->respondItem($article, $commentsCollection, $cacheKey.$secondKey);\n    }\n\n    /**\n     * Show the form for editing the specified resource.\n     *\n     * @param  int $id\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function edit($id)\n    {\n        $article = Article::findOrFail($id);\n\n        return view('articles.edit', compact('article'));\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param \\App\\Http\\Requests\\ArticlesRequest $request\n     * @param  int                               $id\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(ArticlesRequest $request, $id)\n    {\n        $payload = array_merge($request->except('_token'), [\n            'notification' => $request->has('notification'),\n        ]);\n\n        $article = Article::findOrFail($id);\n        $article->update($payload);\n\n        if ($request->has('tags')) {\n            $article->tags()->sync($request->input('tags'));\n        }\n\n        event(new ModelChanged(['articles', 'tags']));\n\n        return $this->respondUpdated($article);\n    }\n\n    public function pickBest(Request $request, $id)\n    {\n        $this->validate($request, [\n            'solution_id' => 'required|numeric|exists:comments,id',\n        ]);\n\n        Article::findOrFail($id)->update([\n            'solution_id' => $request->input('solution_id'),\n        ]);\n\n\n        return json()->noContent();\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param  int                     $id\n     * @return \\Illuminate\\Http\\Response\n     * @throws \\Exception\n     */\n    public function destroy(Request $request, $id)\n    {\n        $article = Article::with('attachments', 'comments')->findOrFail($id);\n\n        foreach ($article->attachments as $attachment) {\n            \\File::delete(attachment_path($attachment->name));\n        }\n\n        $article->attachments()->delete();\n        $article->comments->each(function ($comment) use ($request) {\n            app(\\App\\Http\\Controllers\\CommentsController::class)->destroy($request, $comment->id);\n        });\n        $article->delete();\n\n        event(new ModelChanged('articles'));\n\n        if ($request->ajax()) {\n            return response()->json('', 204);\n        }\n\n        return $this->respondDeleted($article);\n    }\n\n    /**\n     * Respond Article Collection.\n     *\n     * @param \\Illuminate\\Pagination\\LengthAwarePaginator $articles\n     * @param string|null                                 $cacheKey\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    protected function respondCollection(LengthAwarePaginator $articles, $cacheKey = null)\n    {\n        return view('articles.index', compact('articles'));\n    }\n\n    /**\n     * Respond Created.\n     *\n     * @param \\App\\Article $article\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function respondCreated(Article $article)\n    {\n        flash()->success(trans('common.created'));\n\n        return redirect(route('articles.index'));\n    }\n\n    /**\n     * Respond single Article item with a corresponding Comment collection.\n     *\n     * @param \\App\\Article                                  $article\n     * @param \\Illuminate\\Database\\Eloquent\\Collection|null $commentsCollection\n     * @param string|null                                    $cacheKey\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    protected function respondItem(Article $article, Collection $commentsCollection = null, $cacheKey = null)\n    {\n        return view('articles.show', [\n            'article'         => $article,\n            'comments'        => $commentsCollection,\n            'commentableType' => Article::class,\n            'commentableId'   => $article->id,\n        ]);\n    }\n\n    /**\n     * Respond Updated.\n     *\n     * @param \\App\\Article $article\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function respondUpdated(Article $article)\n    {\n        flash()->success(trans('common.updated'));\n\n        return redirect(route('articles.show', $article->id));\n    }\n\n    /**\n     * Respond Deleted.\n     *\n     * @param \\App\\Article $article\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function respondDeleted(Article $article)\n    {\n        flash()->success(trans('common.deleted'));\n\n        return redirect(route('articles.index'));\n    }\n\n    /**\n     * Respond Not Modified.\n     *\n     * @return \\Illuminate\\Contracts\\Routing\\ResponseFactory|\\Symfony\\Component\\HttpFoundation\\Response\n     */\n    protected function respondNotModified()\n    {\n        return response('', 304);\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/AttachmentsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Events\\ModelChanged;\nuse Illuminate\\Http\\Request;\nuse App\\Http\\Requests;\n\nclass AttachmentsController extends Controller\n{\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Request $request)\n    {\n        if (! $request->hasFile('file')) {\n            return response()->json('File not passed !', 422);\n        }\n\n        // Save file\n        $file = $request->file('file');\n        $name = time() . '_' . str_replace(' ', '_', $file->getClientOriginalName());\n        $file->move(attachment_path(), $name);\n\n        $articleId = $request->input('articleId');\n\n        // Persist Attachment model\n        $attachment = $articleId\n            ? \\App\\Article::findOrFail($articleId)->attachments()->create(['name' => $name])\n            : \\App\\Attachment::create(['name' => $name]);\n\n        event(new ModelChanged('attachments'));\n\n        return response()->json([\n            'id'   => $attachment->id,\n            'name' => $name,\n            'type' => $file->getClientMimeType(),\n            'url'  => sprintf(\"/attachments/%s\", $name),\n        ]);\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param  int                     $id\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Request $request, $id)\n    {\n        $attachment = \\App\\Attachment::findOrFail($id);\n\n        $path = attachment_path($attachment->name);\n        if (\\File::exists($path)) {\n            \\File::delete($path);\n        }\n\n        $attachment->delete();\n        event(new ModelChanged('attachments'));\n\n        if ($request->ajax()) {\n            return response()->json('', 204);\n        }\n\n        flash()->success(trans('common.deleted'));\n\n        return back();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Cacheable.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\ninterface Cacheable\n{\n    /**\n     * Specify the tags for caching.\n     * @see https://laravel.com/docs/cache#cache-tags\n     *\n     * @return string\n     */\n    public function cacheKeys();\n}"
  },
  {
    "path": "app/Http/Controllers/CommentsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Comment;\nuse App\\Vote;\nuse App\\Events\\ModelChanged;\nuse Illuminate\\Http\\Request;\n\nclass CommentsController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth');\n        $this->middleware('author:comment', ['except' => ['store', 'vote']]);\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Request $request)\n    {\n        $this->validate($request, [\n            'commentable_type' => 'required|in:App\\Article,App\\Lesson',\n            'commentable_id'   => 'required|numeric',\n            'parent_id'        => 'numeric|exists:comments,id',\n            'content'          => 'required',\n        ]);\n\n        $parentModel = \"\\\\\" . $request->input('commentable_type');\n        $comment = $parentModel::find($request->input('commentable_id'))\n            ->comments()->create([\n                'author_id' => \\Auth::user()->id,\n                'parent_id' => $request->input('parent_id', null),\n                'content'   => $request->input('content')\n            ]);\n\n        event('comments.created', [$comment]);\n        event(new ModelChanged('articles', 'comments'));\n        flash()->success(trans('forum.comment_add'));\n\n        return back();\n    }\n\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  int  $id\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update(Request $request, $id)\n    {\n        $this->validate($request, ['content' => 'required']);\n\n        $comment = Comment::findOrFail($id);\n        $comment->update($request->only('content'));\n\n        event('comments.updated', [$comment]);\n        event(new ModelChanged('articles', 'comments'));\n        flash()->success(trans('forum.comment_edit'));\n\n        return back();\n    }\n\n    /**\n     * Vote up or down for the given comment.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param                          $id\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function vote(Request $request, $id)\n    {\n        $this->validate($request, [\n            'vote' => 'required|in:up,down',\n        ]);\n\n        if(Vote::whereCommentId($id)->whereUserId($request->user()->id)->exists()) {\n            return response()->json(['errors' => 'Already voted!'], 409);\n        }\n\n        $comment = Comment::findOrFail($id);\n\n        $up = $request->input('vote') == 'up' ? true : false;\n\n        $comment->votes()->create([\n            'user_id'  => $request->user()->id,\n            'up'       => $up ? 1 : null,\n            'down'     => $up ? null : 1,\n            'voted_at' => \\Carbon\\Carbon::now()->toDateTimeString(),\n        ]);\n\n        return response()->json([\n            'voted' => $request->input('vote'),\n            'value' => $comment->votes()->sum($request->input('vote'))\n        ]);\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param  int                     $id\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy(Request $request, $id)\n    {\n        $comment = Comment::with('replies')->find($id);\n\n        // Do not recursively destroy children comments.\n        // Because 1. Soft delete feature was adopted,\n        // and 2. it's not just pleasant for authors of children comments to being deleted by the parent author.\n        if ($comment->replies->count() > 0) {\n            $comment->delete();\n        } else {\n            if ($comment->votes->count()) {\n                $this->deleteVote($comment->votes);\n            }\n\n            $comment->forceDelete();\n        }\n\n        // $this->recursiveDestroy($comment);\n\n        event(new ModelChanged('articles', 'comments'));\n\n        if ($request->ajax()) {\n            return response()->json('', 204);\n        }\n\n        flash()->success(trans('common.deleted'));\n\n        return back();\n    }\n\n    /**\n     * Delete given votes collection.\n     *\n     * @param $votes\n     */\n    protected function deleteVote($votes)\n    {\n        foreach($votes as $vote) {\n            $vote->delete();\n        }\n    }\n\n    /**\n     * Delete comment recursively\n     *\n     * @param \\App\\Comment $comment\n     * @return bool|null\n     */\n    public function recursiveDestroy(Comment $comment)\n    {\n        if ($comment->replies->count()) {\n            $comment->replies->each(function($reply) {\n                if ($reply->replies->count()) {\n                    $this->recursiveDestroy($reply);\n                } else {\n                    $reply->delete();\n                }\n            });\n        }\n\n        return $comment->delete();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/Controller.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Foundation\\Bus\\DispatchesJobs;\nuse Illuminate\\Routing\\Controller as BaseController;\nuse Illuminate\\Foundation\\Validation\\ValidatesRequests;\nuse Illuminate\\Foundation\\Auth\\Access\\AuthorizesRequests;\n\nclass Controller extends BaseController\n{\n    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;\n\n    /**\n     * @var \\Illuminate\\Cache\\CacheManager\n     */\n    protected $cache;\n\n    /**\n     * Constructor\n     */\n    public function __construct() {\n        if (! is_api_request()) {\n            $this->setSharedVariables();\n        }\n\n        $this->cache = app('cache');\n\n        if ((new \\ReflectionClass($this))->implementsInterface(\\App\\Http\\Controllers\\Cacheable::class) and taggable()) {\n            $this->cache = app('cache')->tags($this->cacheKeys());\n        }\n    }\n\n    /**\n     * Share common view variables\n     */\n    protected function setSharedVariables() {\n        view()->share('currentLocale', app()->getLocale());\n        view()->share('currentUser', auth()->user());\n        view()->share('currentRouteName', \\Route::currentRouteName());\n        view()->share('currentUrl', current_url());\n        view()->share('isLandingPage', in_array(\\Route::currentRouteName(), ['home', 'index']));\n    }\n\n    /**\n     * Do the filter, search, and sorting job\n     *\n     * @param $query\n     * @return mixed\n     */\n    protected function filter($query)\n    {\n        $params = config('project.params');\n\n        if ($filter = request()->input($params['filter'])) {\n            $query = $query->{camel_case($filter)}();\n        }\n\n        if ($keyword = request()->input($params['search'])) {\n            $raw = 'MATCH(title,content) AGAINST(? IN BOOLEAN MODE)';\n            $query = $query->whereRaw($raw, [$keyword]);\n        }\n\n        $sort = request()->input($params['sort'], 'created_at');\n        $direction = request()->input($params['order'], 'desc');\n\n        if ($sort == 'created') {\n            // We transformed field name of 'created_at' to 'created'.\n            // Applicable only to api request. But this code laid here\n            // to suppress QueryException of not existing column in web request.\n            $sort = 'created_at';\n        }\n\n        return $query->orderBy($sort, $direction);\n    }\n\n    /**\n     * Create etag against collection of resources.\n     *\n     * @param \\Illuminate\\Database\\Eloquent\\Collection|\\Illuminate\\Contracts\\Pagination\\Paginator| $collection\n     * @param string|null $cacheKey\n     * @return string\n     */\n    protected function etags($collection, $cacheKey = null)\n    {\n        $etag = '';\n\n        foreach($collection as $instance) {\n            $etag .= $instance->etag();\n        }\n\n        return md5($etag.$cacheKey);\n    }\n\n    /**\n     * Execute caching against database query.\n     *\n     * @see config/project.php's cache section.\n     *\n     * @param string $key\n     * @param int $minutes\n     * @param \\App\\Model|\\Illuminate\\Database\\Eloquent\\Builder|\\Illuminate\\Database\\Query\\Builder\n     *        |\\Illuminate\\Database\\Eloquent\\Relations\\Relation $query\n     * @param string $method\n     * @param mixed ...$args\n     * @return mixed\n     */\n    protected function cache($key, $minutes, $query, $method, ...$args)\n    {\n        $args = (! empty($args)) ? implode(',', $args) : null;\n\n        if (config('project.cache') === false) {\n            return $query->{$method}($args);\n        }\n\n        return $this->cache->remember($key, $minutes, function() use($query, $method, $args){\n            return $query->{$method}($args);\n        });\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/LessonsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Document;\nuse App\\Repositories\\LessonRepository;\nuse Request;\n\nclass LessonsController extends Controller\n{\n    /**\n     * @var \\App\\Repositories\\LessonRepository\n     */\n    protected $repo;\n\n    /**\n     * Constructor.\n     *\n     * @param \\App\\Repositories\\LessonRepository $repo\n     */\n    public function __construct(LessonRepository $repo)\n    {\n        $this->repo = $repo;\n\n        parent::__construct();\n    }\n\n    /**\n     * Show document page in response to the given $file.\n     *\n     * @param string $file\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function show($file = '01-welcome.md')\n    {\n        $lesson = $this->repo->find($file);\n\n        $commentsCollection = $lesson->comments()->with('replies')\n            ->withTrashed()->whereNull('parent_id')->latest()->get();\n\n        return view('lessons.show', [\n            'index'           => $this->repo->index(),\n            'lesson'          => $lesson,\n            'prev'            => $this->repo->prev($file),\n            'next'            => $this->repo->next($file),\n            'comments'        => $commentsCollection,\n            'commentableType' => $this->repo->model(),\n            'commentableId'   => $lesson->id,\n        ]);\n    }\n\n    /**\n     * Make image response.\n     *\n     * @param $file\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function image($file)\n    {\n        $image = $this->repo->image($file);\n        $reqEtag = Request::getEtags();\n        $genEtag = $this->repo->etag($file);\n\n        if (isset($reqEtag[0])) {\n            if ($reqEtag[0] === $genEtag) {\n                return response('', 304);\n            }\n        }\n\n        return response($image->encode('png'), 200, [\n            'Content-Type'  => 'image/png',\n            'Cache-Control' => 'public, max-age=0',\n            'Etag'          => $genEtag,\n        ]);\n    }\n\n    /**\n     * Leave off unnecessary string from the given path.\n     *\n     * @param $path\n     * @return mixed\n     */\n    protected function sanitizePath($path)\n    {\n        return starts_with($path, ['/lessons/', 'lessons/'])\n            ? pathinfo($path, PATHINFO_BASENAME)\n            : $path;\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/PasswordsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\User;\nuse Illuminate\\Http\\Request;\nuse Password;\n\nclass PasswordsController extends Controller\n{\n    /**\n     * Create new password controller instance.\n     */\n    public function __construct()\n    {\n        $this->middleware('guest');\n\n        parent::__construct();\n    }\n\n    /**\n     * Display the form to request a password reset link.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function getRemind()\n    {\n        return view('passwords.remind');\n    }\n\n    /**\n     * Send a reset link to the given user.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @return $this|\\Illuminate\\Http\\RedirectResponse\n     */\n    public function postRemind(Request $request)\n    {\n        $this->validate($request, ['email' => 'required|email']);\n\n        if (User::whereEmail($request->input('email'))->noPassword()->first()) {\n            // Notify the user if he/she is a social login user.\n            $message = sprintf(\"%s %s\", trans('auth.social_olny'), trans('auth.no_password'));\n\n            return $this->respondError($message, 400);\n        }\n\n        $response = Password::sendResetLink($request->only('email'), function ($m) {\n            $m->subject(trans('auth.email_password_reset_title'));\n        });\n\n        switch ($response) {\n            case Password::RESET_LINK_SENT:\n                return $this->respondSuccess(trans($response));\n\n            case Password::INVALID_USER:\n                return $this->respondError(trans($response), 404);\n        }\n    }\n\n    /**\n     * Display the password reset view for the given token.\n     *\n     * @param null $token\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function getReset($token = null)\n    {\n        if (is_null($token) or strlen($token) != 64) {\n            throw new \\Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException;\n        }\n\n        return view('passwords.reset', compact('token'));\n    }\n\n    /**\n     * Reset the given user's password.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    public function postReset(Request $request)\n    {\n        $this->validate($request, [\n            'token'    => 'required',\n            'email'    => 'required|email',\n            'password' => 'required|confirmed',\n        ]);\n\n        $credentials = $request->only(\n            'email',\n            'password',\n            'password_confirmation',\n            'token'\n        );\n\n        $response = Password::reset($credentials, function ($user, $password) {\n            $user->password = bcrypt($password);\n            $user->save();\n            \\Auth::login($user);\n        });\n\n        switch ($response) {\n            case Password::PASSWORD_RESET:\n                flash(sprintf(\n                    \"%s %s\",\n                    trans($response),\n                    trans('auth.welcome', ['name' => \\Auth::user()->name])\n                ));\n                return redirect(route('home'));\n\n            default:\n                flash()->error(trans($response));\n                return back()\n                    ->withInput($request->only('email'));\n        }\n    }\n\n    /**\n     * Make an error response.\n     *\n     * @param     $message\n     * @param int $statusCode\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function respondError($message, $statusCode = 400)\n    {\n        flash()->error($message);\n\n        return back()->withInput();\n    }\n\n    /**\n     * Make a success response.\n     *\n     * @param $message\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function respondSuccess($message)\n    {\n        flash($message);\n\n        return back();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/SessionsController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse Auth;\nuse Illuminate\\Contracts\\Validation\\Validator;\nuse Illuminate\\Http\\Request;\n\nclass SessionsController extends Controller\n{\n    /**\n     * Create a new session controller instance.\n     */\n    public function __construct()\n    {\n        $this->middleware('guest', ['except' => 'destroy']);\n\n        parent::__construct();\n    }\n\n    /**\n     * Show the application login form.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function create()\n    {\n        return view('sessions.create');\n    }\n\n    /**\n     * Handle login request to the application.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    public function store(Request $request)\n    {\n        $validator = \\Validator::make($request->all(), [\n            'email'    => 'required|email',\n            'password' => 'required|min:6',\n        ]);\n\n        if ($validator->fails()) {\n            return $this->respondValidationError($validator);\n        }\n\n        $token = is_api_request()\n            ? \\JWTAuth::attempt($request->only('email', 'password'))\n            : Auth::attempt($request->only('email', 'password'), $request->has('remember'));\n\n        if (! $token) {\n            return $this->respondLoginFailed();\n        }\n\n        event('users.login', [Auth::user()]);\n\n        return $this->respondCreated($request->input('return'), $token);\n    }\n\n    /**\n     * Log the user out of the application.\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    public function destroy()\n    {\n        Auth::logout();\n        flash(trans('auth.goodbye'));\n\n        return redirect(route('index'));\n    }\n\n    /**\n     * Make validation error response.\n     *\n     * @param \\Illuminate\\Contracts\\Validation\\Validator $validator\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function respondValidationError(Validator $validator)\n    {\n        return back()->withInput()->withErrors($validator);\n    }\n\n    /**\n     * Make login failed response.\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function respondLoginFailed()\n    {\n        flash()->error(trans('auth.failed'));\n\n        return back()->withInput();\n    }\n\n    /**\n     * Make a success response.\n     *\n     * @param string $return\n     * @param string $token\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function respondCreated($return = '', $token = '')\n    {\n        flash(trans('auth.welcome', ['name' => Auth::user()->name]));\n\n        return ($return)\n            ? redirect(urldecode($return))\n            : redirect()->intended();\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/SocialController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\User;\nuse Illuminate\\Http\\Request;\nuse Laravel\\Socialite\\Contracts\\Factory as Socialite;\n\nclass SocialController extends Controller\n{\n    /**\n     * @var Factory\n     */\n    private $socialite;\n\n    /**\n     * Create social login controller instance.\n     *\n     * @param Socialite $socialite\n     */\n    public function __construct(Socialite $socialite)\n    {\n        $this->middleware('guest', ['only' => 'execute']);\n\n        $this->socialite = $socialite;\n\n        parent::__construct();\n    }\n\n    /**\n     * Handle social login process.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param string                   $provider\n     * @return \\App\\Http\\Controllers\\Response\n     */\n    public function execute(Request $request, $provider)\n    {\n        if (! $request->has('code')) {\n            return $this->redirectToProvider($provider);\n        }\n\n        return $this->handleProviderCallback($provider);\n    }\n\n    /**\n     * Redirect the user to the Social Login Provider's authentication page.\n     *\n     * @param string $provider\n     * @return \\Symfony\\Component\\HttpFoundation\\RedirectResponse\n     */\n    protected function redirectToProvider($provider)\n    {\n        return $this->socialite->driver($provider)->redirect();\n    }\n\n    /**\n     * Obtain the user information from the Social Login Provider.\n     *\n     * @param string $provider\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function handleProviderCallback($provider)\n    {\n        $user = $this->socialite->driver($provider)->user();\n\n        $user = (User::whereEmail($user->getEmail())->first())\n            ?: User::create([\n                'name'  => $user->getName() ?: 'unknown',\n                'email' => $user->getEmail(),\n            ]);\n\n        \\Auth::login($user, true);\n        event('users.login', [$user]);\n        flash(trans('auth.welcome', ['name' => $user->name]));\n\n        return redirect(route('home'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/UsersController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\User;\nuse Illuminate\\Contracts\\Validation\\Validator;\nuse Illuminate\\Http\\Request;\n\nclass UsersController extends Controller\n{\n    /**\n     * Create user controller instance.\n     */\n    public function __construct()\n    {\n        $this->middleware('guest');\n\n        parent::__construct();\n    }\n\n    /**\n     * Show the application registration form.\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function create()\n    {\n        return view('users.create');\n    }\n\n    /**\n     * Handle a registration request for the application.\n     *\n     * @param  \\Illuminate\\Http\\Request $request\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function store(Request $request)\n    {\n        if ($user = User::whereEmail($request->input('email'))->noPassword()->first()) {\n            // Filter through the User model to find whether there is a social account\n            // that has the same email address with the current request\n            return $this->syncAccountInfo($request, $user);\n        }\n\n        return $this->createAccount($request);\n    }\n\n    /**\n     * A user logged into the application with social account first,\n     * and then, when s/he tries to register an application's native account,\n     * update his/her name and password as given\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\App\\User                $user\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function syncAccountInfo(Request $request, User $user)\n    {\n        $validator = \\Validator::make($request->except('_token'), [\n            'name'     => 'required|max:255',\n            'email'    => 'required|email|max:255',\n            'password' => 'required|confirmed|min:6',\n        ]);\n\n        if ($validator->fails()) {\n            return $this->respondValidationError($validator);\n        }\n\n        $user->update([\n            'name'     => $request->input('name'),\n            'password' => bcrypt($request->input('password')),\n        ]);\n\n        $this->addMemberRole($user);\n\n        return $this->respondCreated($user);\n    }\n\n    /**\n     * A user tries to register a native account.\n     * S/he haven't logged in to the application with a social account before.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function createAccount(Request $request)\n    {\n        $validator = \\Validator::make($request->except('_token'), [\n            'name'     => 'required|max:255',\n            'email'    => 'required|email|max:255|unique:users',\n            'password' => 'required|confirmed|min:6',\n        ]);\n\n        if ($validator->fails()) {\n            return $this->respondValidationError($validator);\n        }\n\n        $user = User::create([\n            'name'     => $request->input('name'),\n            'email'    => $request->input('email'),\n            'password' => bcrypt($request->input('password')),\n        ]);\n        $this->addMemberRole($user);\n\n        return $this->respondCreated($user);\n    }\n\n    /**\n     * Attach Role to the user\n     *\n     * @param \\App\\User $user\n     * @return array\n     */\n    protected function addMemberRole(User $user)\n    {\n        // 1 is admin, 2 is member\n        return $user->roles()->sync([2]);\n    }\n\n    /**\n     * Make validation error response.\n     *\n     * @param $validator\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function respondValidationError(Validator $validator)\n    {\n        return back()->withInput()->withErrors($validator);\n    }\n\n    /**\n     * Make a success response.\n     *\n     * @param \\App\\User $user\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function respondCreated(User $user)\n    {\n        \\Auth::login($user);\n        flash(trans('auth.welcome', ['name' => $user->name]));\n\n        return redirect(route('home'));\n    }\n}\n"
  },
  {
    "path": "app/Http/Controllers/WelcomeController.php",
    "content": "<?php\n\nnamespace App\\Http\\Controllers;\n\nclass WelcomeController extends Controller\n{\n    /**\n     * Constructor.\n     */\n    public function __construct()\n    {\n        $this->middleware('auth', ['only' => ['home']]);\n\n        parent::__construct();\n    }\n\n    /**\n     * Get the index page\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory\n     */\n    public function index()\n    {\n        return view('home');\n    }\n\n    /**\n     * Get the home page\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory\n     */\n    public function home()\n    {\n        return view('home');\n    }\n\n    /**\n     * Set locale preference of a user\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    public function locale()\n    {\n        $cookie = cookie()->forever('locale__myProject', request('locale'));\n\n        cookie()->queue($cookie);\n\n        return ($return = request('return'))\n            ? redirect(urldecode($return))->withCookie($cookie)\n            : redirect(\\Auth::check() ? route('home') : route('index'))->withCookie($cookie);\n    }\n}\n"
  },
  {
    "path": "app/Http/Kernel.php",
    "content": "<?php\n\nnamespace App\\Http;\n\nuse Illuminate\\Foundation\\Http\\Kernel as HttpKernel;\n\nclass Kernel extends HttpKernel\n{\n    /**\n     * The application's global HTTP middleware stack.\n     *\n     * @var array\n     */\n    protected $middleware = [\n        \\Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode::class,\n        \\App\\Http\\Middleware\\EncryptCookies::class,\n        \\Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse::class,\n        \\Illuminate\\Session\\Middleware\\StartSession::class,\n        \\Illuminate\\View\\Middleware\\ShareErrorsFromSession::class,\n        \\App\\Http\\Middleware\\VerifyCsrfToken::class,\n\n//        Laravel 5.2 Global middlewares, but will not be used for this project\n//        'web' => [\n//            \\App\\Http\\Middleware\\EncryptCookies::class,\n//            \\Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse::class,\n//            \\Illuminate\\Session\\Middleware\\StartSession::class,\n//            \\Illuminate\\View\\Middleware\\ShareErrorsFromSession::class,\n//            \\App\\Http\\Middleware\\VerifyCsrfToken::class,\n//        ],\n//\n//        'api' => [\n//            'throttle:60,1',\n//        ],\n    ];\n\n    /**\n     * The application's route middleware.\n     *\n     * @var array\n     */\n    protected $routeMiddleware = [\n        'auth'        => \\App\\Http\\Middleware\\Authenticate::class,\n        'auth.basic'  => \\Illuminate\\Auth\\Middleware\\AuthenticateWithBasicAuth::class,\n        'guest'       => \\App\\Http\\Middleware\\RedirectIfAuthenticated::class,\n        'throttle'    => \\Illuminate\\Routing\\Middleware\\ThrottleRequests::class,\n        'throttle.api'=> \\App\\Http\\Middleware\\ThrottleApiRequests::class,\n        'role'        => \\Bican\\Roles\\Middleware\\VerifyRole::class,\n        'author'      => \\App\\Http\\Middleware\\AuthorOnly::class,\n        'jwt.auth'    => \\App\\Http\\Middleware\\GetUserFromToken::class,\n        'jwt.refresh' => \\App\\Http\\Middleware\\RefreshToken::class,\n        'obfuscate'   => \\App\\Http\\Middleware\\ObfuscateId::class,\n    ];\n}\n"
  },
  {
    "path": "app/Http/Middleware/Authenticate.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Contracts\\Auth\\Guard;\n\nclass Authenticate\n{\n    /**\n     * The Guard implementation.\n     *\n     * @var Guard\n     */\n    protected $auth;\n\n    /**\n     * Create a new filter instance.\n     *\n     * @param  Guard  $auth\n     * @return void\n     */\n    public function __construct(Guard $auth)\n    {\n        $this->auth = $auth;\n    }\n\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        if ($this->auth->guest()) {\n            if ($request->ajax()) {\n                return response('Unauthorized.', 401);\n            } else {\n                return redirect()->guest(\n                    route('sessions.create', ['return' => $request->fullUrl()])\n                );\n            }\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/AuthorOnly.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\n\nclass AuthorOnly\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Closure                 $next\n     * @param string|null              $param\n     * @return mixed\n     */\n    public function handle(Request $request, Closure $next, $param = null)\n    {\n        $user = $request->user();\n        $model = '\\\\App\\\\' . ucfirst($param);\n        $modelId = $request->route($param ? str_plural($param) : 'id');\n\n        if (! $model::whereId($modelId)->whereAuthorId($user->id)->exists() and ! $user->isAdmin()) {\n            if (is_api_request()) {\n                return json()->forbiddenError();\n            }\n\n            flash()->error(trans('errors.forbidden') . ' : ' . trans('errors.forbidden_description'));\n\n            return back();\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/EncryptCookies.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Cookie\\Middleware\\EncryptCookies as BaseEncrypter;\n\nclass EncryptCookies extends BaseEncrypter\n{\n    /**\n     * The names of the cookies that should not be encrypted.\n     *\n     * @var array\n     */\n    protected $except = [\n        //\n    ];\n}\n"
  },
  {
    "path": "app/Http/Middleware/GetUserFromToken.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Middleware\\BaseMiddleware;\n\nclass GetUserFromToken extends BaseMiddleware\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request $request\n     * @param  \\Closure                 $next\n     *\n     * @return mixed\n     * @throws \\Exception\n     */\n    public function handle($request, \\Closure $next)\n    {\n        if (! $token = $this->auth->setRequest($request)->getToken()) {\n            throw new JWTException('token_not_provided', 400);\n        }\n\n        if (! $user = $this->auth->authenticate($token)) {\n            throw new JWTException('user_not_found', 404);\n        }\n\n        $this->events->fire('tymon.jwt.valid', $user);\n\n        return $next($request);\n    }\n}"
  },
  {
    "path": "app/Http/Middleware/ObfuscateId.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\n\nclass ObfuscateId\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Closure                 $next\n     * @param string|null              $param\n     * @return mixed\n     */\n    public function handle(Request $request, Closure $next, $param = null)\n    {\n        $routeParamName = $param ? str_plural($param) : 'id';\n\n        if ($routeParamValue = $request->route()->getParameter($routeParamName)) {\n            $request->route()->setParameter($routeParamName, optimus()->decode($routeParamValue));\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/RedirectIfAuthenticated.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Contracts\\Auth\\Guard;\n\nclass RedirectIfAuthenticated\n{\n    /**\n     * The Guard implementation.\n     *\n     * @var Guard\n     */\n    protected $auth;\n\n    /**\n     * Create a new filter instance.\n     *\n     * @param  Guard  $auth\n     * @return void\n     */\n    public function __construct(Guard $auth)\n    {\n        $this->auth = $auth;\n    }\n\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        if ($this->auth->check()) {\n            return redirect('/home');\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/RefreshToken.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Tymon\\JWTAuth\\Middleware\\BaseMiddleware;\n\nclass RefreshToken extends BaseMiddleware\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request $request\n     * @param  \\Closure                 $next\n     *\n     * @return mixed\n     */\n    public function handle($request, \\Closure $next)\n    {\n        $newToken = $this->auth->setRequest($request)->parseToken()->refresh();\n\n        return response()->json([\n            'code' => 201,\n            'message' => 'success',\n            'token' => $newToken,\n        ], 201, [\n            'Authorization' => \"Bearer {$newToken}\",\n        ]);\n    }\n}"
  },
  {
    "path": "app/Http/Middleware/ThrottleApiRequests.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Routing\\Middleware\\ThrottleRequests;\n\nclass ThrottleApiRequests extends ThrottleRequests\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @param  int  $maxAttempts\n     * @param  int  $decayMinutes\n     * @return mixed\n     */\n    public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)\n    {\n        $key = $this->resolveRequestSignature($request);\n\n        if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {\n            return json()->setHeaders([\n                'Retry-After' => $this->limiter->availableIn($key),\n                'X-RateLimit-Limit' => $maxAttempts,\n                'X-RateLimit-Remaining' => 0,\n            ])->tooManyRequestsError();\n        }\n\n        $this->limiter->hit($key, $decayMinutes);\n\n        $response = $next($request);\n\n        $response->headers->add([\n            'X-RateLimit-Limit' => $maxAttempts,\n            'X-RateLimit-Remaining' => $maxAttempts - $this->limiter->attempts($key) + 1,\n        ]);\n\n        return $response;\n    }\n}\n"
  },
  {
    "path": "app/Http/Middleware/VerifyCsrfToken.php",
    "content": "<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken as BaseVerifier;\n\nclass VerifyCsrfToken extends BaseVerifier\n{\n    /**\n     * The URIs that should be excluded from CSRF verification.\n     *\n     * @var array\n     */\n    protected $except = [];\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handle($request, Closure $next)\n    {\n        if (is_api_request()) {\n            return $next($request);\n        }\n\n        return parent::handle($request, $next);\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/ArticlesRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nclass ArticlesRequest extends Request\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        $rules = [];\n\n        if ($this->isDelete()) {\n            $rules = [];\n        } elseif ($this->isUpdate()) {\n            $rules = ['tags' => ['array']];\n        } else {\n            $rules = [\n                'title'   => 'required',\n                'content' => 'required',\n                'tags'    => 'required|array'\n            ];\n        }\n\n        return $rules;\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/FilterArticlesRequest.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nclass FilterArticlesRequest extends Request\n{\n    /**\n     * Determine if the user is authorized to make this request.\n     *\n     * @return bool\n     */\n    public function authorize()\n    {\n        return true;\n    }\n\n    /**\n     * Get the validation rules that apply to the request.\n     *\n     * @return array\n     */\n    public function rules()\n    {\n        $params = config('project.params');\n        $filters = implode(',', array_keys(config('project.filters.article')));\n\n        return [\n            $params['filter'] => \"in:{$filters}\",                      // Query scope filter\n            $params['limit']  => 'size:1,10',                          // PerPage\n            $params['sort']   => 'in:created_at,view_count,created',   // Sort: Age(created_at), View(view_count)\n            $params['order']  => 'in:asc,desc',                        // Direction: Ascending or Descending\n            $params['search'] => 'alpha_dash',                         // Search query\n            $params['page']   => '',                                   // Page number\n        ];\n    }\n}\n"
  },
  {
    "path": "app/Http/Requests/Request.php",
    "content": "<?php\n\nnamespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nabstract class Request extends FormRequest\n{\n    /**\n     * Determine if the request is update\n     *\n     * @return bool\n     */\n    protected function isUpdate()\n    {\n        $needle = ['put', 'patch'];\n\n        return in_array(strtolower($this->input('_method')), $needle)\n            or in_array(strtolower($this->header('x-http-method-override')), $needle)\n            or in_array(strtolower($this->method()), $needle);\n    }\n\n    /**\n     * Determine if the request is delete\n     *\n     * @return bool\n     */\n    protected function isDelete()\n    {\n        $needle = ['delete'];\n\n        return in_array(strtolower($this->input('_method')), $needle)\n            or in_array(strtolower($this->header('x-http-method-override')), $needle)\n            or in_array(strtolower($this->method()), $needle);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function response(array $errors)\n    {\n        if (is_api_request()) {\n            return json()->unprocessableError($errors);\n        }\n\n        if ($this->ajax() || $this->wantsJson()) {\n            return new JsonResponse($errors, 422);\n        }\n\n        return $this->redirector->to($this->getRedirectUrl())\n            ->withInput($this->except($this->dontFlash))\n            ->withErrors($errors, $this->errorBag);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function forbiddenResponse()\n    {\n        if (is_api_request()) {\n            return json()->forbiddenError();\n        }\n\n        return response('Forbidden', 403);\n    }\n}\n"
  },
  {
    "path": "app/Http/routes.php",
    "content": "<?php\n\nRoute::group(['domain' => config('project.api_domain'), 'as' => 'api.', 'namespace' => 'Api', 'middleware' => 'cors'], function() {\n    /* Landing page */\n    Route::get('/', [\n        'as'   => 'index',\n        'uses' => 'WelcomeController@index'\n    ]);\n\n    /* User Registration */\n    Route::post('auth/register', [\n        'as'   => 'users.store',\n        'uses' => 'UsersController@store'\n    ]);\n\n    /* Session.\n     * In API, logout path is not required. Because,\n     * when token is expired, any API request will not be validated.\n     */\n    Route::post('auth/login', [\n        'as'   => 'sessions.store',\n        'uses' => 'SessionsController@store'\n    ]);\n\n    Route::post('auth/refresh', [\n        'as'   => 'sessions.refresh',\n        'uses' => 'SessionsController@refresh'\n    ]);\n\n    /* Social Login\n     * In API, social login is not provided.\n     * Each client has to integrate an Oauth library, and\n     * call 'POST auth/register' route in a onOauthLoginSuccessCallback.\n     */\n\n    /* Password Reminder.\n     * Password reset is possible only through the web page.\n     * For api client, this endpoint will accept user's email address\n     * and send the user email which contains password reset token.\n     */\n    Route::post('auth/remind', [\n        'as'   => 'remind.store',\n        'uses' => 'PasswordsController@postRemind',\n    ]);\n\n    /* User */\n    Route::resource('users', 'UsersController', ['only' => ['show']]);\n\n    /* api.v1 */\n    Route::group(['prefix' => 'v1', 'namespace' => 'V1'], function() {\n        /* Landing page */\n        Route::get('/', [\n            'as'   => 'v1.index',\n            'uses' => 'WelcomeController@index'\n        ]);\n\n        /* Forum */\n        Route::get('tags/{slug}/articles', [\n            'as'   => 'v1.tags.articles.index',\n            'uses' => 'ArticlesController@index'\n        ]);\n        Route::resource('articles', 'ArticlesController', ['except' => ['create', 'edit']]);\n        Route::resource('comments', 'CommentsController', ['except' => ['create', 'edit']]);\n    });\n});\n\nRoute::group(['domain' => config('project.app_domain')], function() {\n    /* Landing page */\n    Route::get('/', [\n        'as'   => 'index',\n        'uses' => 'WelcomeController@index',\n    ]);\n\n    Route::get('home', [\n        'as'   => 'home',\n        'uses' => 'WelcomeController@home',\n    ]);\n\n    Route::get('locale', [\n        'as'   => 'locale',\n        'uses' => 'WelcomeController@locale',\n    ]);\n\n    /* Mailing list */\n    //Route::post('mail-list/subscribe', [\n    //    'as'   => 'mail-list.subscribe',\n    //    'uses' => 'MailListController@subscribe',\n    //]);\n    //\n    //Route::delete('mail-list/unsubscribe', [\n    //    'as'   => 'mail-list.unsubscribe',\n    //    'uses' => 'MailListController@unsubscribe',\n    //]);\n\n    /* Documents */\n    Route::get('lessons/{image}', [\n        'as'   => 'lessons.image',\n        'uses' => 'LessonsController@image',\n    ]);\n\n    Route::get('lessons/{file?}', [\n        'as'   => 'lessons.show',\n        'uses' => 'LessonsController@show',\n    ]);\n\n    /* Forum */\n    Route::get('tags/{slug}/articles', [\n        'as'   => 'tags.articles.index',\n        'uses' => 'ArticlesController@index'\n    ]);\n    Route::put('articles/{articles}/pick', [\n        'as'   => 'articles.pick-best-comment',\n        'uses' => 'ArticlesController@pickBest'\n    ]);\n    Route::resource('articles', 'ArticlesController');\n\n    /* Attachments */\n    Route::resource('files', 'AttachmentsController', ['only' => ['store', 'destroy']]);\n\n    /* Comments */\n    Route::post('comments/{id}/vote', 'CommentsController@vote');\n    Route::resource('comments', 'CommentsController', ['only' => ['store', 'update', 'destroy']]);\n\n    /* User Registration */\n    Route::get('auth/register', [\n        'as'   => 'users.create',\n        'uses' => 'UsersController@create'\n    ]);\n    Route::post('auth/register', [\n        'as'   => 'users.store',\n        'uses' => 'UsersController@store'\n    ]);\n\n    /* Social Login */\n    Route::get('social/{provider}', [\n        'as'   => 'social.login',\n        'uses' => 'SocialController@execute',\n    ]);\n\n    /* Session */\n    Route::get('auth/login', [\n        'as'   => 'sessions.create',\n        'uses' => 'SessionsController@create'\n    ]);\n    Route::post('auth/login', [\n        'as'   => 'sessions.store',\n        'uses' => 'SessionsController@store'\n    ]);\n    Route::get('auth/logout', [\n        'as'   => 'sessions.destroy',\n        'uses' => 'SessionsController@destroy'\n    ]);\n\n    /* Password Reminder */\n    Route::get('auth/remind', [\n        'as'   => 'remind.create',\n        'uses' => 'PasswordsController@getRemind',\n    ]);\n    Route::post('auth/remind', [\n        'as'   => 'remind.store',\n        'uses' => 'PasswordsController@postRemind',\n    ]);\n    Route::get('auth/reset/{token}', [\n        'as'   => 'reset.create',\n        'uses' => 'PasswordsController@getReset',\n    ]);\n    Route::post('auth/reset', [\n        'as'   => 'reset.store',\n        'uses' => 'PasswordsController@postReset',\n    ]);\n});\n\n/* From Laravel 5.2 all built-in events are fired in the form of Object */\n//DB::listen(function($event){\n//    var_dump($event->sql/*, $event->bindings, $event->time*/);\n//});"
  },
  {
    "path": "app/Jobs/Job.php",
    "content": "<?php\n\nnamespace App\\Jobs;\n\nuse Illuminate\\Bus\\Queueable;\n\nabstract class Job\n{\n    /*\n    |--------------------------------------------------------------------------\n    | Queueable Jobs\n    |--------------------------------------------------------------------------\n    |\n    | This job base class provides a central location to place any logic that\n    | is shared across all of your jobs. The trait included with the class\n    | provides access to the \"onQueue\" and \"delay\" queue helper methods.\n    |\n    */\n\n    use Queueable;\n}\n"
  },
  {
    "path": "app/Lesson.php",
    "content": "<?php\n\nnamespace App;\n\nclass Lesson extends Model\n{\n    use AuthorTrait;\n\n    // Directory name that holds markdown files\n    // that is corresponding to this Eloquent model.\n    // This should be relative to project root. e.g. docs/version1\n    public static $path = 'lessons';\n\n    // List of files that should not be included\n    // when generating index of files.\n    public static $excepts = [\n        'INDEX.md',\n        'SUMMARY.md',\n        'GLOSSARY.md',\n        // 'README.md',\n    ];\n\n    protected $fillable = [\n        'author_id',\n        'name',\n        'content',\n    ];\n\n    /* Relationships */\n\n    public function author()\n    {\n        return $this->belongsTo(User::class, 'author_id');\n    }\n\n    public function comments()\n    {\n        return $this->morphMany(Comment::class, 'commentable');\n    }\n}\n"
  },
  {
    "path": "app/Listeners/.gitkeep",
    "content": ""
  },
  {
    "path": "app/Listeners/CacheHandler.php",
    "content": "<?php\n\nnamespace App\\Listeners;\n\nuse App\\Events\\ModelChanged;\n\nclass CacheHandler\n{\n    /**\n     * Handle the event.\n     *\n     * @param \\App\\Events\\ModelChanged $event\n     */\n    public function handle(ModelChanged $event)\n    {\n        if (! taggable()) {\n            // Remove all cache store\n            return \\Cache::flush();\n        }\n\n        // Remove only cache that has the given tag(s)\n        return \\Cache::tags($event->cacheTags)->flush();\n    }\n}\n"
  },
  {
    "path": "app/Listeners/CommentsHandler.php",
    "content": "<?php\n\nnamespace App\\Listeners;\n\nuse App\\Comment;\n\nclass CommentsHandler\n{\n    protected $to = [];\n\n    /**\n     * Handle the event.\n     *\n     * @param \\App\\Comment $comment\n     */\n    public function handle(Comment $comment)\n    {\n        if ($comment->commentable->notification) {\n            // get the Article author's email and append to the recipients array.\n            $this->to[] = $comment->commentable->author->email;\n        }\n\n        // get email address lists from the comments and append to the recipients array.\n        $this->findEmail($comment);\n\n        // Remove duplicate email address.\n        $to = array_unique($this->to);\n        $subject = 'New comment';\n\n        return \\Mail::send('emails.new-comment', compact('comment'), function($m) use($to, $subject) {\n            return $m->to($to)->subject($subject);\n        });\n    }\n\n    /**\n     * Recursively find email address from the comments and push them to recipients list.\n     *\n     * @param \\App\\Comment $comment\n     */\n    protected function findEmail(Comment $comment)\n    {\n        if ($comment->parent) {\n            $this->to[] = $comment->parent->author->email;\n\n            return $this->findEmail($comment->parent);\n        }\n\n        return;\n    }\n}\n"
  },
  {
    "path": "app/Listeners/UserEventsHandler.php",
    "content": "<?php\n\nnamespace App\\Listeners;\n\nuse App\\User;\nuse Illuminate\\Contracts\\Events\\Dispatcher;\n\nclass UserEventsHandler\n{\n    /**\n     * Map events and handlers\n     *\n     * @param Dispatcher $events\n     */\n    public function subscribe(Dispatcher $events) {\n        $events->listen(\n            'users.login',\n            __CLASS__ . '@onUserLogin'\n        );\n    }\n\n    /**\n     * User login event handler\n     *\n     * @param \\App\\User $user\n     */\n    public function onUserLogin(User $user)\n    {\n        // Update last_login field\n        $user->last_login = \\Carbon\\Carbon::now()->toDateTimeString();\n        $user->save();\n    }\n}\n"
  },
  {
    "path": "app/Listeners/ViewCountHandler.php",
    "content": "<?php\n\nnamespace App\\Listeners;\n\nuse App\\Events\\ArticleConsumed;\n\nclass ViewCountHandler\n{\n    /**\n     * Handle the event.\n     *\n     * @param  ArticleConsumed  $event\n     * @return void\n     */\n    public function handle(ArticleConsumed $event)\n    {\n        // Increase view count\n        $event->article->view_count ++;\n        $event->article->save();\n    }\n}\n"
  },
  {
    "path": "app/Model.php",
    "content": "<?php\n\nnamespace App;\n\nuse Illuminate\\Database\\Eloquent\\Model as Eloquent;\n\nabstract class Model extends Eloquent\n{\n\n}"
  },
  {
    "path": "app/Policies/.gitkeep",
    "content": ""
  },
  {
    "path": "app/Providers/AppServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    /**\n     * Bootstrap any application services.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        if ($locale = request()->cookie('locale__myProject')) {\n            app()->setLocale(\\Crypt::decrypt($locale));\n        }\n\n        \\Carbon\\Carbon::setLocale(app()->getLocale());\n    }\n\n    /**\n     * Register any application services.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->app->singleton(\\Jenssegers\\Optimus\\Optimus::class, function () {\n            return new \\Jenssegers\\Optimus\\Optimus(132961291, 1484265379, 37817169);\n        });\n\n        if ($this->app->environment('local')) {\n            $this->app->register(\\Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider::class);\n        }\n    }\n}\n"
  },
  {
    "path": "app/Providers/AuthServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Contracts\\Auth\\Access\\Gate as GateContract;\nuse Illuminate\\Foundation\\Support\\Providers\\AuthServiceProvider as ServiceProvider;\n\nclass AuthServiceProvider extends ServiceProvider\n{\n    /**\n     * The policy mappings for the application.\n     *\n     * @var array\n     */\n    protected $policies = [\n        'App\\Model' => 'App\\Policies\\ModelPolicy',\n    ];\n\n    /**\n     * Register any application authentication / authorization services.\n     *\n     * @param  \\Illuminate\\Contracts\\Auth\\Access\\Gate  $gate\n     * @return void\n     */\n    public function boot(GateContract $gate)\n    {\n        $this->registerPolicies($gate);\n\n        //\n    }\n}\n"
  },
  {
    "path": "app/Providers/EventServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Contracts\\Events\\Dispatcher as DispatcherContract;\nuse Illuminate\\Foundation\\Support\\Providers\\EventServiceProvider as ServiceProvider;\n\nclass EventServiceProvider extends ServiceProvider\n{\n    /**\n     * The event listener mappings for the application.\n     *\n     * @var array\n     */\n    protected $listen = [\n        \\App\\Events\\ModelChanged::class => [\n            \\App\\Listeners\\CacheHandler::class\n        ],\n        \\App\\Events\\ArticleConsumed::class => [\n            \\App\\Listeners\\ViewCountHandler::class\n        ]\n    ];\n\n    /**\n     * Register any other events for your application.\n     *\n     * @param  \\Illuminate\\Contracts\\Events\\Dispatcher  $events\n     * @return void\n     */\n    public function boot(DispatcherContract $events)\n    {\n        parent::boot($events);\n\n        $events->listen('comments.*', \\App\\Listeners\\CommentsHandler::class);\n        $events->subscribe(\\App\\Listeners\\UserEventsHandler::class);\n    }\n}\n"
  },
  {
    "path": "app/Providers/RouteServiceProvider.php",
    "content": "<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Routing\\Router;\nuse Illuminate\\Foundation\\Support\\Providers\\RouteServiceProvider as ServiceProvider;\n\nclass RouteServiceProvider extends ServiceProvider\n{\n    /**\n     * This namespace is applied to the controller routes in your routes file.\n     *\n     * In addition, it is set as the URL generator's root namespace.\n     *\n     * @var string\n     */\n    protected $namespace = 'App\\Http\\Controllers';\n\n    /**\n     * Define your route model bindings, pattern filters, etc.\n     *\n     * @param  \\Illuminate\\Routing\\Router  $router\n     * @return void\n     */\n    public function boot(Router $router)\n    {\n        $router->pattern('id', '[0-9]+');\n        // Should handle 32n33-sss-img-dd.png exception\n        $router->pattern('image', 'images/(?P<parent>[0-9n]{2,5}-[\\pL-\\pN\\._-]+)-(?P<suffix>img-[0-9]{2}.png)');\n\n        parent::boot($router);\n    }\n\n    /**\n     * Define the routes for the application.\n     *\n     * @param  \\Illuminate\\Routing\\Router  $router\n     * @return void\n     */\n    public function map(Router $router)\n    {\n        $router->group(['namespace' => $this->namespace], function ($router) {\n            require app_path('Http/routes.php');\n        });\n    }\n}\n"
  },
  {
    "path": "app/Reporters/ErrorReport.php",
    "content": "<?php\n\nnamespace App\\Reporters;\n\nuse Carbon\\Carbon;\nuse Maknz\\Slack\\Attachment;\nuse Maknz\\Slack\\AttachmentField;\nuse Maknz\\Slack\\Client;\nuse Request;\nuse Route;\n\nclass ErrorReport\n{\n    /**\n     * @var \\Maknz\\Slack\\Client\n     */\n    private $client;\n\n    /**\n     * @var \\Exception\n     */\n    private $primitive;\n\n    /**\n     * @param \\Exception $e\n     * @param string     $webhook\n     * @param array      $settings\n     */\n    public function __construct(\\Exception $e, $webhook = '', $settings = [])\n    {\n        $this->primitive = $e;\n        $webhook = $webhook ?: env('SLACK_WEBHOOK');\n        $this->client = $this->createClient($webhook, $settings);\n    }\n\n    /**\n     * Send slack report.\n     *\n     * @return mixed\n     */\n    public function send()\n    {\n        return $this->client->createMessage()->attach($this->buildPayload())->send();\n    }\n\n    /**\n     * Build Slack Attachment array based on given Exception object.\n     *\n     * @see https://api.slack.com/docs/attachments\n     *\n     * @return array\n     */\n    protected function buildPayload()\n    {\n        return new Attachment([\n            'fallback' => 'Error Report',\n            'text'     => $this->primitive->getMessage() ?: \"Something broken :(\",\n            'color'    => 'danger',\n            'fields'   => [\n                new AttachmentField([\n                    'title' => 'localtime',\n                    'value' => Carbon::now('Asia/Seoul')->toDateTimeString(),\n                ]),\n                new AttachmentField([\n                    'title' => 'username',\n                    'value' => (auth()->check() ? auth()->user()->email : 'Unknown')\n                        . sprintf(' (%s)', Request::ip()),\n                ]),\n                new AttachmentField([\n                    'title' => 'route',\n                    'value' => Route::currentRouteName()\n                        . sprintf(\n                            ' (%s %s)',\n                            Request::method(),\n                            Request::fullUrl()\n                        ),\n                ]),\n                new AttachmentField([\n                    'title' => 'description',\n                    'value' => sprintf(\n                        '%s in %s line %d',\n                        get_class($this->primitive),\n                        pathinfo($this->primitive->getFile(), PATHINFO_BASENAME),\n                        $this->primitive->getLine()\n                    ),\n                ]),\n                new AttachmentField([\n                    'title' => 'trace',\n                    'value' => $this->primitive->getTraceAsString(),\n                ]),\n            ],\n        ]);\n    }\n\n    /**\n     * Factory - Create HTTP API Client for Slack\n     *\n     * @param array $overrides\n     * @return \\Maknz\\Slack\\Client\n     */\n    protected function createClient($webhook, $overrides = [])\n    {\n        $settings = array_merge([\n            'channel'                 => '#l5essential',\n            'username'                => 'aws-demo',\n            'link_names'              => true,\n            'unfurl_links'            => true,\n            'markdown_in_attachments' => ['title', 'text', 'fields'],\n        ], $overrides);\n\n        return new Client($webhook, $settings);\n    }\n}"
  },
  {
    "path": "app/Reporters/MonologSlackReport.php",
    "content": "<?php\n\nnamespace App\\Reporters;\n\nclass MonologSlackReport\n{\n    /**\n     * @var \\Monolog\\Logger\n     */\n    protected $logger;\n\n    public function __construct()\n    {\n        $this->createLogger();\n    }\n\n    /**\n     * Send slack report.\n     *\n     * @param \\Exception $e\n     * @return mixed\n     */\n    public function send(\\Exception $e)\n    {\n        return $this->logger->error(\n            $e->getMessage() ?: \"Something broken :(\",\n            $this->buildPayload($e)\n        );\n    }\n\n    /**\n     * Build payload array based on given Exception object.\n     *\n     * @param \\Exception $e\n     * @return array\n     */\n    protected function buildPayload(\\Exception $e)\n    {\n        return [\n            'username'  => auth()->check() ? auth()->user()->email : 'Unknown',\n            'route'     => \\Route::currentRouteName(),\n            'localtime' => \\Carbon\\Carbon::now('Asia/Seoul')->toDateTimeString(),\n            'exception' => [\n                'class'   => get_class($e),\n                'file'    => $e->getFile(),\n                'line'    => $e->getLine(),\n                'message' => $e->getMessage(),\n                'code'    => $e->getCode(),\n                'trace'   => $e->getTraceAsString(),\n                'ip'      => \\Request::ip(),\n                'method'  => \\Request::method(),\n                'url'     => \\Request::fullUrl(),\n                'content' => \\Request::instance()->getContent()\n                    ?: json_encode(\\Request::all()),\n                'headers' => \\Request::header(),\n            ],\n        ];\n    }\n\n    /**\n     * Factory - Create Monolog instance which has a Slack handler.\n     */\n    protected function createLogger()\n    {\n        $logger = \\Log::getMonolog();\n\n        $logger->pushHandler(\n            (new \\Monolog\\Handler\\SlackHandler(env('SLACK_TOKEN'), '#l5essential', 'aws-demo'))\n                ->setLevel(\\Monolog\\Logger::ERROR)\n        );\n\n        return $this->logger = $logger;\n    }\n}"
  },
  {
    "path": "app/Repositories/LessonRepository.php",
    "content": "<?php\n\nnamespace App\\Repositories;\n\nclass LessonRepository extends MarkdownRepository\n{\n    /**\n     * Get the index of documents.\n     *\n     * @return mixed\n     */\n    public function index()\n    {\n        return $this->find('INDEX.md');\n    }\n\n    /**\n     * Specify an Eloquent Model's class name.\n     *\n     * @return string\n     */\n    public function model()\n    {\n        return \\App\\Lesson::class;\n    }\n}"
  },
  {
    "path": "app/Repositories/MarkdownRepository.php",
    "content": "<?php\n\nnamespace App\\Repositories;\n\nuse Cache;\nuse Exception;\nuse File;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Image;\n\nabstract class MarkdownRepository implements RepositoryInterface\n{\n    /**\n     * @var \\Illuminate\\Database\\Eloquent\\Model\n     */\n    protected $model;\n\n    /**\n     * @var string Directory name, that houses the markdown files.\n     */\n    protected $path;\n\n    /**\n     * @var array Table of markdown files.\n     */\n    protected $toc;\n\n    /**\n     * @var string Currently selected markdown file.\n     */\n    protected $current;\n\n    /**\n     * Create DocumentRepository instance.\n     */\n    public function __construct()\n    {\n        $this->initialize();\n    }\n\n    /**\n     * Specify an Eloquent Model's class name.\n     *\n     * @return string\n     */\n    public abstract function model();\n\n    /**\n     * Factory - new up the model and set the required properties.\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Model\n     * @throws \\Exception\n     */\n    protected function initialize()\n    {\n        $model = app()->make($this->model());\n\n        if (! $model instanceof Model) {\n            throw new Exception(\n                'model() method must return a string name of an Eloquent Model. Or the provided model cannot be instantiable.'\n            );\n        }\n\n        if (! property_exists($this->model(), 'path')) {\n            throw new Exception(\n                \"{$this->model()} should have a property named 'path'\"\n            );\n        }\n\n        $path  = base_path($model::$path);\n\n        if (! File::isDirectory($path)) {\n            throw new Exception(\n                \"Something went wrong with the path property of {$this->model()} model.\"\n            );\n        }\n\n        $this->model = $model;\n        $this->path  = $path;\n\n        if (! $this->toc) {\n            // Todo Expensive job. Should apply cache..\n            $this->toc = Cache::remember('lessons.index', 120, function() use($model) {\n                $all = glob(base_path($model::$path . DIRECTORY_SEPARATOR . '*.md'));\n                $excepts = [];\n\n                if (property_exists($this->model(), 'excepts')) {\n                    foreach ($model::$excepts as $except) {\n                        $excepts[] = base_path($model::$path . DIRECTORY_SEPARATOR . $except);\n                    }\n                }\n\n                $files  = array_diff($all, $excepts);\n\n                return array_map(function($file) {\n                    return pathinfo($file, PATHINFO_BASENAME);\n                }, $files);\n            });\n        }\n\n        return;\n    }\n\n    /**\n     * Get the collection of model.\n     *\n     * @param array $columns\n     * @return \\Illuminate\\Database\\Eloquent\\Collection\n     */\n    public function all($columns = ['*'])\n    {\n        return $this->model->get($columns);\n    }\n\n    /**\n     * Get the table of contents.\n     *\n     * @return array\n     */\n    public function toc()\n    {\n        return $this->toc;\n    }\n\n    /**\n     * Get the currently selected markdown's filename.\n     *\n     * @return string\n     */\n    public function current()\n    {\n        return $this->current;\n    }\n\n    /**\n     * Calculate previous entry.\n     *\n     * @param $current\n     * @return bool\n     */\n    public function prev($current) {\n        $prev = array_search($current, $this->toc) - 1;\n\n        return array_key_exists($prev, $this->toc)\n            ? $this->toc[$prev]\n            : false;\n    }\n\n    /**\n     * Calculate next entry.\n     *\n     * @param $current\n     * @return mixed\n     */\n    public function next($current) {\n        $next = array_search($current, $this->toc) + 1;\n\n        return array_key_exists($next, $this->toc)\n            ? $this->toc[$next]\n            : false;\n    }\n\n    /**\n     * Get the model instance.\n     *\n     * @param mixed $id filename\n     * @param array $columns\n     * @return \\Illuminate\\Database\\Eloquent\\Model\n     */\n    public function find($id, $columns = ['*'])\n    {\n        $this->current = $id;\n\n        return $this->model->whereName($id)->first()\n            ?: $this->model->create([\n                'author_id' => 1, // Bad!! Avoid hard code, b.c, admin may change.\n                'name'      => $id,\n                'content'   => File::get($this->getPath($id)),\n            ]);\n    }\n\n    /**\n     * Calculate and respond image path.\n     *\n     * @param string $file\n     * @return \\Intervention\\Image\\Image\n     */\n    public function image($file)\n    {\n        return Image::make($this->getPath($file));\n    }\n\n    /**\n     * Create etag value\n     *\n     * @param string $file\n     * @return string\n     */\n    public function etag($file)\n    {\n        return md5($file . '/' . File::lastModified($this->getPath($file)));\n    }\n\n    /**\n     * Calculate full path to the given file.\n     *\n     * @param string $file\n     * @return string\n     */\n    protected function getPath($file)\n    {\n        $path = $this->path . DIRECTORY_SEPARATOR . $file;\n\n        if (!File::exists($path)) {\n            abort(404, 'File not exist');\n        }\n\n        return $path;\n    }\n}\n"
  },
  {
    "path": "app/Repositories/RepositoryInterface.php",
    "content": "<?php\n\nnamespace App\\Repositories;\n\ninterface RepositoryInterface\n{\n    /**\n     * Get the model instance.\n     *\n     * @param mixed $id\n     * @param array $columns\n     * @return \\Illuminate\\Database\\Eloquent\\Model\n     */\n    public function find($id, $columns = ['*']);\n\n    /**\n     * Get the collection of model.\n     *\n     * @param array $columns\n     * @return \\Illuminate\\Database\\Eloquent\\Collection\n     */\n    public function all($columns = ['*']);\n}"
  },
  {
    "path": "app/Services/Markdown.php",
    "content": "<?php\n\nnamespace App\\Services;\n\nuse ParsedownExtra;\n\nclass Markdown extends ParsedownExtra {\n\n    // Pattern to search for 'article#000, ArTicle#00, A#0, a#00, ...' mention\n    const PATTERN_ARTICLE = '/(article|a)(\\#|\\@|\\:\\:)(?P<id>\\d+)/i';\n\n    const PATTERN_REMOVE = '/<!--\\s?@start\\s?-->[\\w\\W\\d\\D]+<!--\\s?@end\\s?-->/';\n\n    const PATTERN_FRONT_FORMATTER = '/---[\\w\\W\\d\\D]+extends[\\w\\W\\d\\D]+---/';\n\n    /**\n     * Add link to another articles\n     *\n     * @param $text\n     * @return mixed|string\n     */\n    public function text($text) {\n        if (preg_match(self::PATTERN_ARTICLE, $text, $matches) > 0) {\n            $text = preg_replace_callback(self::PATTERN_ARTICLE, function ($matches) {\n                return sprintf(\n                    \"<a href='%s'>%s</a>\",\n                    route('articles.show', $matches['id']),\n                    $matches[0]\n                );\n            }, $text);\n        }\n\n        if (preg_match(self::PATTERN_REMOVE, $text, $matches) > 0) {\n            $text = preg_replace_callback(self::PATTERN_REMOVE, function ($matches) {\n                return '';\n            }, $text);\n        }\n\n        if (preg_match(self::PATTERN_FRONT_FORMATTER, $text, $matches) > 0) {\n            $text = preg_replace_callback(self::PATTERN_FRONT_FORMATTER, function ($matches) {\n                return '';\n            }, $text);\n        }\n\n        return parent::text($text);\n    }\n}"
  },
  {
    "path": "app/Tag.php",
    "content": "<?php\n\nnamespace App;\n\nclass Tag extends Model\n{\n    protected $fillable = [\n        'name',\n        'slug'\n    ];\n\n    /* Relationships */\n\n    public function articles()\n    {\n        return $this->belongsToMany(Article::class)->withTimestamps();\n    }\n}\n"
  },
  {
    "path": "app/Transformers/ArticleTransformer.php",
    "content": "<?php\n\nnamespace App\\Transformers;\n\nuse App\\Article;\nuse Appkr\\Api\\TransformerAbstract;\nuse League\\Fractal\\ParamBag;\n\nclass ArticleTransformer extends TransformerAbstract\n{\n    /**\n     * List of resources possible to include using url query string.\n     * e.g. collection case -> ?include=comments:limit(5|1):order(created_at|desc)\n     *      item case       -> ?include=author\n     *\n     * @var  array\n     */\n    protected $availableIncludes = ['comments', 'author', 'tags', 'attachments'];\n\n    /**\n     * Transform single resource.\n     *\n     * @param  \\App\\Article $article\n     * @return  array\n     */\n    public function transform(Article $article)\n    {\n        $id = optimus((int) $article->id);\n\n        $payload = [\n            'id'           => $id,\n            'title'        => $article->title,\n            'content_raw'  => strip_tags($article->content),\n            'content_html' => markdown($article->content),\n            'created'      => $article->created_at->toIso8601String(),\n            'view_count'   => (int) $article->view_count,\n            'link'         => [\n                'rel'  => 'self',\n                'href' => route('api.v1.articles.show', $id),\n            ],\n            'comments'     => (int) $article->comments->count(),\n            'author'       => [\n                'name'   => $article->author->name,\n                'email'  => $article->author->email,\n                'avatar' => 'http:' . gravatar_profile_url($article->author->email),\n            ],\n            'tags'         => $article->tags->pluck('slug'),\n            'attachments'  => (int) $article->attachments->count(),\n        ];\n\n        if ($fields = $this->getPartialFields()) {\n            $payload = array_only($payload, $fields);\n        }\n\n        return $payload;\n    }\n\n    /**\n     * Include comments.\n     *\n     * @param  \\App\\Article                  $article\n     * @param  \\League\\Fractal\\ParamBag|null $params\n     * @return  \\League\\Fractal\\Resource\\Collection\n     * @throws  \\Exception\n     */\n    public function includeComments(Article $article, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\CommentTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $comments = $article->comments()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($comments, $transformer);\n    }\n\n    /**\n     * Include author.\n     *\n     * @param  \\App\\Article                 $article\n     * @param \\League\\Fractal\\ParamBag|null $params\n     * @return \\League\\Fractal\\Resource\\Item\n     */\n    public function includeAuthor(Article $article, ParamBag $params = null)\n    {\n        return $this->item($article->author, new \\App\\Transformers\\UserTransformer($params));\n    }\n\n    /**\n     * Include tags.\n     *\n     * @param  \\App\\Article                  $article\n     * @param  \\League\\Fractal\\ParamBag|null $params\n     * @return  \\League\\Fractal\\Resource\\Collection\n     * @throws  \\Exception\n     */\n    public function includeTags(Article $article, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\TagTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $tags = $article->tags()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($tags, $transformer);\n    }\n\n    /**\n     * Include attachments.\n     *\n     * @param  \\App\\Article                  $article\n     * @param  \\League\\Fractal\\ParamBag|null $params\n     * @return  \\League\\Fractal\\Resource\\Collection\n     * @throws  \\Exception\n     */\n    public function includeAttachments(Article $article, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\AttachmentTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $attachments = $article->attachments()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($attachments, $transformer);\n    }\n}\n"
  },
  {
    "path": "app/Transformers/AttachmentTransformer.php",
    "content": "<?php\n\nnamespace App\\Transformers;\n\nuse App\\Attachment;\nuse Appkr\\Api\\TransformerAbstract;\nuse League\\Fractal\\ParamBag;\n\nclass AttachmentTransformer extends TransformerAbstract\n{\n    /**\n     * Transform single resource.\n     *\n     * @param  \\App\\Attachment $attachment\n     * @return  array\n     */\n    public function transform(Attachment $attachment)\n    {\n        $payload = [\n            'id'      => optimus((int) $attachment->id),\n            'name'    => $attachment->name,\n            'created' => $attachment->created_at->toIso8601String(),\n            'link'    => [\n                'rel'  => 'self',\n                'href' => url(sprintf('http://%s:8000/attachments/%s', config('project.app_domain'), $attachment->name)),\n            ],\n        ];\n\n        if ($fields = $this->getPartialFields()) {\n            $payload = array_only($payload, $fields);\n        }\n\n        return $payload;\n    }\n}\n"
  },
  {
    "path": "app/Transformers/CommentTransformer.php",
    "content": "<?php\n\nnamespace App\\Transformers;\n\nuse App\\Comment;\nuse Appkr\\Api\\TransformerAbstract;\n\n;\nuse League\\Fractal\\ParamBag;\n\nclass CommentTransformer extends TransformerAbstract\n{\n    /**\n     * List of resources possible to include using url query string.\n     * e.g. collection case -> ?include=comments:limit(5|1):order(created_at|desc)\n     *      item case       -> ?include=author\n     *\n     * @var  array\n     */\n    protected $availableIncludes = ['author'];\n\n    /**\n     * Transform single resource.\n     *\n     * @param  \\App\\Comment $comment\n     * @return  array\n     */\n    public function transform(Comment $comment)\n    {\n        $id = optimus((int) $comment->id);\n\n        $payload = [\n            'id'           => $id,\n            'content_raw'  => strip_tags($comment->content),\n            'content_html' => markdown($comment->content),\n            'created'      => $comment->created_at->toIso8601String(),\n            'vote'         => ['up' => (int) $comment->up_count, 'down' => (int) $comment->down_count],\n            'link'         => [\n                'rel'  => 'self',\n                'href' => route('api.v1.comments.show', $id),\n            ],\n            'author'       => [\n                'name'   => $comment->author->name,\n                'email'  => $comment->author->email,\n                'avatar' => 'http:' . gravatar_profile_url($comment->author->email),\n            ],\n        ];\n\n        if ($fields = $this->getPartialFields()) {\n            $payload = array_only($payload, $fields);\n        }\n\n        return $payload;\n    }\n\n    /**\n     * Include author.\n     *\n     * @param  \\App\\Comment                 $comment\n     * @param \\League\\Fractal\\ParamBag|null $params\n     * @return \\League\\Fractal\\Resource\\Item\n     */\n    public function includeAuthor(Comment $comment, ParamBag $params = null)\n    {\n        return $this->item($comment->author, new \\App\\Transformers\\UserTransformer($params));\n    }\n}\n"
  },
  {
    "path": "app/Transformers/TagTransformer.php",
    "content": "<?php\n\nnamespace App\\Transformers;\n\nuse App\\Tag;\nuse Appkr\\Api\\TransformerAbstract;\nuse League\\Fractal\\ParamBag;\n\nclass TagTransformer extends TransformerAbstract\n{\n    protected $availableIncludes = ['articles'];\n\n    /**\n     * Transform single resource.\n     *\n     * @param  \\App\\Tag $tag\n     * @return  array\n     */\n    public function transform(Tag $tag)\n    {\n        $payload = [\n            'id'       => optimus((int) $tag->id),\n            'slug'     => $tag->slug,\n            'created'  => $tag->created_at->toIso8601String(),\n            'link'     => [\n                'rel'  => 'self',\n                'href' => route('api.v1.tags.articles.index', $tag->slug),\n            ],\n            'articles' => (int) $tag->articles->count(),\n        ];\n\n        if ($fields = $this->getPartialFields()) {\n            $payload = array_only($payload, $fields);\n        }\n\n        return $payload;\n    }\n\n    /**\n     * Include articles.\n     *\n     * @param  \\App\\Tag                      $tag\n     * @param  \\League\\Fractal\\ParamBag|null $params\n     * @return  \\League\\Fractal\\Resource\\Collection\n     * @throws  \\Exception\n     */\n    public function includeArticles(Tag $tag, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\ArticleTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $articles = $tag->articles()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($articles, $transformer);\n    }\n}\n"
  },
  {
    "path": "app/Transformers/UserTransformer.php",
    "content": "<?php\n\nnamespace App\\Transformers;\n\nuse App\\User;\nuse Appkr\\Api\\TransformerAbstract;\nuse League\\Fractal\\ParamBag;\n\nclass UserTransformer extends TransformerAbstract\n{\n    /**\n     * List of resources possible to include using url query string.\n     * e.g. collection case -> ?include=comments:limit(5|1):order(created_at|desc)\n     *      item case       -> ?include=author\n     *\n     * @var  array\n     */\n    protected $availableIncludes = ['articles', 'comments'];\n\n    /**\n     * Transform single resource.\n     *\n     * @param  \\App\\User $user\n     * @return  array\n     */\n    public function transform(User $user)\n    {\n        $id = optimus((int) $user->id);\n\n        $payload = [\n            'id'       => $id,\n            'name'     => $user->name,\n            'email'    => $user->email,\n            'avatar'   => 'http:' . gravatar_profile_url($user->email),\n            'signup'   => $user->created_at->toIso8601String(),\n            'link'     => [\n                'rel'  => 'self',\n                'href' => route('api.users.show', $id),\n            ],\n            'articles' => (int) $user->articles->count(),\n            'comments' => (int) $user->comments->count(),\n        ];\n\n        if ($fields = $this->getPartialFields()) {\n            $payload = array_only($payload, $fields);\n        }\n\n        return $payload;\n    }\n\n    /**\n     * Include articles.\n     *\n     * @param  \\App\\User                     $user\n     * @param  \\League\\Fractal\\ParamBag|null $params\n     * @return  \\League\\Fractal\\Resource\\Collection\n     * @throws  \\Exception\n     */\n    public function includeArticles(User $user, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\ArticleTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $articles = $user->articles()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($articles, $transformer);\n    }\n\n    /**\n     * Include comments.\n     *\n     * @param  \\App\\User                     $user\n     * @param  \\League\\Fractal\\ParamBag|null $params\n     * @return  \\League\\Fractal\\Resource\\Collection\n     * @throws  \\Exception\n     */\n    public function includeComments(User $user, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\CommentTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $comments = $user->comments()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($comments, $transformer);\n    }\n}\n"
  },
  {
    "path": "app/User.php",
    "content": "<?php\n\nnamespace App;\n\nuse Illuminate\\Auth\\Authenticatable;\nuse Illuminate\\Auth\\Passwords\\CanResetPassword;\nuse Illuminate\\Contracts\\Auth\\Authenticatable as AuthenticatableContract;\nuse Illuminate\\Contracts\\Auth\\CanResetPassword as CanResetPasswordContract;\nuse Bican\\Roles\\Traits\\HasRoleAndPermission;\nuse Bican\\Roles\\Contracts\\HasRoleAndPermission as HasRoleAndPermissionContract;\n\nclass User extends Model implements AuthenticatableContract,\n                                    CanResetPasswordContract,\n                                    HasRoleAndPermissionContract\n{\n    use Authenticatable;\n    use CanResetPassword;\n    use HasRoleAndPermission;\n\n    /**\n     * The database table used by the model.\n     *\n     * @var string\n     */\n    protected $table = 'users';\n\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array\n     */\n    protected $fillable = ['name', 'email', 'password'];\n\n    /**\n     * The attributes excluded from the model's JSON form.\n     *\n     * @var array\n     */\n    protected $hidden = ['password', 'remember_token'];\n\n    protected $dates = ['last_login'];\n\n    /* Relationships */\n\n    public function articles()\n    {\n        return $this->hasMany(Article::class, 'author_id');\n    }\n\n    public function comments()\n    {\n        return $this->hasMany(Comment::class, 'author_id');\n    }\n\n    public function votes()\n    {\n        return $this->hasMany(Vote::class);\n    }\n\n    /* Query Scopes */\n    public function scopeNoPassword($query)\n    {\n        return $query->whereNull('password');\n    }\n\n    /* Helpers */\n    public function isAdmin()\n    {\n        return $this->roles()->whereSlug('admin')->exists();\n    }\n}\n"
  },
  {
    "path": "app/Vote.php",
    "content": "<?php\n\nnamespace App;\n\nclass Vote extends Model\n{\n    public $timestamps = false;\n\n    protected $fillable = [\n        'user_id',\n        'comment_id',\n        'up',\n        'down',\n        'voted_at',\n    ];\n\n    protected $dates = [\n        'voted_at',\n    ];\n\n    /* Relationships */\n\n    public function comment()\n    {\n        return $this->belongsTo(Comment::class);\n    }\n\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n}\n"
  },
  {
    "path": "app/helpers.php",
    "content": "<?php\n\nif (! function_exists('markdown')) {\n    /**\n     * Compile the given text to markdown document.\n     *\n     * @param string $text\n     * @return string\n     */\n    function markdown($text)\n    {\n        return app(App\\Services\\Markdown::class)->text($text);\n    }\n}\n\nif (! function_exists('icon')) {\n    /**\n     * Generate FontAwesome icon tag\n     *\n     * @param string $class    font-awesome class name\n     * @param string $addition additional class\n     * @param string $inline   inline style\n     * @return string\n     */\n    function icon($class, $addition = 'icon', $inline = null)\n    {\n        $icon = config('icons.' . $class);\n        $inline = $inline ? 'style=\"' . $inline . '\"' : null;\n\n        return sprintf('<i class=\"%s %s\" %s></i>', $icon, $addition, $inline);\n    }\n}\n\nif (! function_exists('attachment_path')) {\n    /**\n     * @param string $path\n     *\n     * @return string\n     */\n    function attachment_path($path = '')\n    {\n        return public_path($path ? 'attachments' . DIRECTORY_SEPARATOR . $path : 'attachments');\n    }\n}\n\nif (! function_exists('gravatar_profile_url')) {\n    /**\n     * Get gravatar profile page url\n     *\n     * @param  string $email\n     * @return string\n     */\n    function gravatar_profile_url($email)\n    {\n        return sprintf(\"//www.gravatar.com/%s\", md5($email));\n    }\n}\n\nif (! function_exists('gravatar_url')) {\n    /**\n     * Get gravatar image url\n     *\n     * @param  string  $email\n     * @param  integer $size\n     * @return string\n     */\n    function gravatar_url($email, $size = 48)\n    {\n        return sprintf(\"//www.gravatar.com/avatar/%s?s=%s\", md5($email), $size);\n    }\n}\n\nif (! function_exists('taggable')) {\n    /**\n     * Determine if the current cache driver has cacheTags() method\n     *\n     * @return bool\n     */\n    function taggable()\n    {\n        return ! in_array(config('cache.default'), ['file', 'database']);\n    }\n}\n\nif (! function_exists('link_for_sort')) {\n    /**\n     * Build HTML anchor tag for sorting\n     *\n     * @param string $column\n     * @param string $text\n     * @param array  $params\n     * @return string\n     */\n    function link_for_sort($column, $text, $params = [])\n    {\n        $config = config('project.params');\n\n        $direction = request()->input($config['order']);\n        $reverse = ($direction == 'asc') ? 'desc' : 'asc';\n\n        if (request()->input($config['sort']) == $column) {\n            // Update passed $text var, only if it is active sort\n            $text = sprintf(\n                \"%s %s\",\n                $direction == 'asc' ? icon('asc') : icon('desc'),\n                $text\n            );\n        }\n\n        $queryString = http_build_query(array_merge(\n            request()->except([$config['page'], $config['sort'], $config['order']]),\n            [$config['sort'] => $column, $config['order'] => $reverse],\n            $params\n        ));\n\n        return sprintf(\n            '<a href=\"%s?%s\">%s</a>',\n            urldecode(request()->url()),\n            $queryString,\n            $text\n        );\n    }\n}\n\nif (! function_exists('current_url')) {\n    /**\n     * Build current url string, without return param.\n     *\n     * @return string\n     */\n    function current_url()\n    {\n        if (! request()->has('return')) {\n            return request()->fullUrl();\n        }\n\n        return sprintf(\n            '%s?%s',\n            request()->url(),\n            http_build_query(request()->except('return'))\n        );\n    }\n}\n\nif (! function_exists('is_api_request')) {\n    /**\n     * Determine if the current request is for HTTP api.\n     *\n     * @return bool\n     */\n    function is_api_request()\n    {\n        return starts_with(request()->getHttpHost(), config('project.api_domain'));\n    }\n}\n\nif (! function_exists('optimus')) {\n    /**\n     * Create Optimus instance.\n     *\n     * @param int|null $id\n     * @return int|\\Jenssegers\\Optimus\\Optimus\n     */\n    function optimus($id = null)\n    {\n        $factory = app(\\Jenssegers\\Optimus\\Optimus::class);\n\n        if (func_num_args() === 0) {\n            return $factory;\n        }\n\n        return $factory->encode($id);\n    }\n}\n\nif (! function_exists('cache_key')) {\n    /**\n     * Generate key for caching.\n     *\n     * Note. Even though the request endpoints are the same,\n     *       the response body should be different because of the query string.\n     *\n     * @param $base\n     * @return string\n     */\n    function cache_key($base)\n    {\n        $key = ($uri = request()->fullUrl())\n            ? $base . '.' . urlencode($uri)\n            : $base;\n\n        return md5($key);\n    }\n}"
  },
  {
    "path": "artisan",
    "content": "#!/usr/bin/env php\n<?php\n\n/*\n|--------------------------------------------------------------------------\n| Register The Auto Loader\n|--------------------------------------------------------------------------\n|\n| Composer provides a convenient, automatically generated class loader\n| for our application. We just need to utilize it! We'll require it\n| into the script here so that we do not have to worry about the\n| loading of any our classes \"manually\". Feels great to relax.\n|\n*/\n\nrequire __DIR__.'/bootstrap/autoload.php';\n\n$app = require_once __DIR__.'/bootstrap/app.php';\n\n/*\n|--------------------------------------------------------------------------\n| Run The Artisan Application\n|--------------------------------------------------------------------------\n|\n| When we run the console application, the current CLI command will be\n| executed in this console and the response sent back to a terminal\n| or another output device for the developers. Here goes nothing!\n|\n*/\n\n$kernel = $app->make(Illuminate\\Contracts\\Console\\Kernel::class);\n\n$status = $kernel->handle(\n    $input = new Symfony\\Component\\Console\\Input\\ArgvInput,\n    new Symfony\\Component\\Console\\Output\\ConsoleOutput\n);\n\n/*\n|--------------------------------------------------------------------------\n| Shutdown The Application\n|--------------------------------------------------------------------------\n|\n| Once Artisan has finished running. We will fire off the shutdown events\n| so that any final work may be done by the application before we shut\n| down the process. This is the last thing to happen to the request.\n|\n*/\n\n$kernel->terminate($input, $status);\n\nexit($status);\n"
  },
  {
    "path": "bootstrap/app.php",
    "content": "<?php\n\n/*\n|--------------------------------------------------------------------------\n| Create The Application\n|--------------------------------------------------------------------------\n|\n| The first thing we will do is create a new Laravel application instance\n| which serves as the \"glue\" for all the components of Laravel, and is\n| the IoC container for the system binding all of the various parts.\n|\n*/\n\n$app = new Illuminate\\Foundation\\Application(\n    realpath(__DIR__.'/../')\n);\n\n/*\n|--------------------------------------------------------------------------\n| Bind Important Interfaces\n|--------------------------------------------------------------------------\n|\n| Next, we need to bind some important interfaces into the container so\n| we will be able to resolve them when needed. The kernels serve the\n| incoming requests to this application from both the web and CLI.\n|\n*/\n\n$app->singleton(\n    Illuminate\\Contracts\\Http\\Kernel::class,\n    App\\Http\\Kernel::class\n);\n\n$app->singleton(\n    Illuminate\\Contracts\\Console\\Kernel::class,\n    App\\Console\\Kernel::class\n);\n\n$app->singleton(\n    Illuminate\\Contracts\\Debug\\ExceptionHandler::class,\n    App\\Exceptions\\Handler::class\n);\n\n/*\n|--------------------------------------------------------------------------\n| Return The Application\n|--------------------------------------------------------------------------\n|\n| This script returns the application instance. The instance is given to\n| the calling script so we can separate the building of the instances\n| from the actual running of the application and sending responses.\n|\n*/\n\nreturn $app;\n"
  },
  {
    "path": "bootstrap/autoload.php",
    "content": "<?php\n\ndefine('LARAVEL_START', microtime(true));\n\n/*\n|--------------------------------------------------------------------------\n| Register The Composer Auto Loader\n|--------------------------------------------------------------------------\n|\n| Composer provides a convenient, automatically generated class loader\n| for our application. We just need to utilize it! We'll require it\n| into the script here so that we do not have to worry about the\n| loading of any our classes \"manually\". Feels great to relax.\n|\n*/\n\nrequire __DIR__.'/../vendor/autoload.php';\n\n/*\n|--------------------------------------------------------------------------\n| Include The Compiled Class File\n|--------------------------------------------------------------------------\n|\n| To dramatically increase your application's performance, you may use a\n| compiled class file which contains all of the classes commonly used\n| by a request. The Artisan \"optimize\" is used to create this file.\n|\n*/\n\n$compiledPath = __DIR__.'/cache/compiled.php';\n\nif (file_exists($compiledPath)) {\n    require $compiledPath;\n}\n"
  },
  {
    "path": "bootstrap/cache/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"myProject\",\n  \"devDependencies\": {\n    \"bootstrap-sass\": \"~3.3.5\",\n    \"font-awesome\": \"~4.4.0\",\n    \"dropzone\": \"~4.2.0\",\n    \"fastclick\": \"~1.0.6\",\n    \"tabby\": \"~0.13.1\",\n    \"autosize\": \"~3.0.14\",\n    \"marked\": \"~0.3.5\",\n    \"highlightjs\": \"~8.9.1\",\n    \"select2-bootstrap-theme\": \"~0.1.0-beta.4\",\n    \"select2\": \"~4.0.1\"\n  }\n}\n"
  },
  {
    "path": "composer.json",
    "content": "{\n  \"name\": \"appkr/l5essential\",\n  \"description\": \"Laravel 5 Essential\",\n  \"keywords\": [\n    \"laravel\",\n    \"how-to\",\n    \"lesson\",\n    \"beginners\"\n  ],\n  \"authors\": [\n    {\n      \"name\": \"appkr\",\n      \"email\": \"juwonkim@me.com\"\n    }\n  ],\n  \"license\": \"MIT\",\n  \"type\": \"project\",\n  \"require\": {\n    \"php\": \">=5.5.9\",\n    \"laravel/framework\": \"5.2.*\",\n    \"erusev/parsedown-extra\": \" 0.7.*\",\n    \"intervention/image\": \"2.3.*\",\n    \"laracasts/flash\": \"1.3.*\",\n    \"laravel/socialite\": \"2.0.*\",\n    \"bican/roles\": \" 2.1.*\",\n    \"maknz/slack\": \"1.*\",\n    \"tymon/jwt-auth\": \"0.5.*\",\n    \"appkr/api\": \"0.1.*\",\n    \"jenssegers/optimus\": \"^0.2.0\",\n    \"asm89/stack-cors\": \"dev-master as 0.2.2\",\n    \"barryvdh/laravel-cors\": \"^0.7.3\"\n  },\n  \"require-dev\": {\n    \"symfony/dom-crawler\": \"~3.0\",\n    \"symfony/css-selector\": \"~3.0\",\n    \"fzaninotto/faker\": \"~1.4\",\n    \"mockery/mockery\": \"0.9.*\",\n    \"phpunit/phpunit\": \"~4.0\",\n    \"phpspec/phpspec\": \"~2.1\",\n    \"barryvdh/laravel-ide-helper\": \"^2.1\"\n  },\n  \"autoload\": {\n    \"classmap\": [\n      \"database\"\n    ],\n    \"files\": [\n      \"app/helpers.php\"\n    ],\n    \"psr-4\": {\n      \"App\\\\\": \"app/\"\n    }\n  },\n  \"autoload-dev\": {\n    \"classmap\": [\n      \"tests/TestCase.php\"\n    ],\n    \"psr-4\": {\n      \"Test\\\\\": \"tests/integration/\"\n    }\n  },\n  \"scripts\": {\n    \"post-install-cmd\": [\n      \"php artisan clear-compiled\",\n      \"php artisan optimize\",\n      \"php artisan cache:clear\"\n    ],\n    \"pre-update-cmd\": [\n      \"php artisan clear-compiled\"\n    ],\n    \"post-update-cmd\": [\n      \"php artisan optimize\",\n      \"php artisan cache:clear\"\n    ],\n    \"post-root-package-install\": [\n      \"php -r \\\"copy('.env.example', '.env');\\\"\"\n    ],\n    \"post-create-project-cmd\": [\n      \"php artisan key:generate\"\n    ]\n  },\n  \"config\": {\n    \"preferred-install\": \"dist\"\n  }\n}\n"
  },
  {
    "path": "config/api.php",
    "content": "<?php\n\nreturn [\n    /*\n    |--------------------------------------------------------------------------\n    | Debug\n    |--------------------------------------------------------------------------\n    |\n    | If set to true, debug information will be include in api response.\n    | Must set to false for production.\n    |\n    */\n    'debug' => env('APP_DEBUG', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | API Endpoint pattern\n    |--------------------------------------------------------------------------\n    |\n    | Path 'pattern' used for is_api_request() Helper.\n    | Provide 'domain', if the api routes are distinguished by domain name.\n    |\n    */\n    'endpoint' => [\n        'pattern' => 'v1/*',\n        'domain'  => env('API_DOMAIN', 'api.myproject.dev'),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Include by query string.\n    |--------------------------------------------------------------------------\n    |\n    | If you defined 'availableInclude' property and includeXxx methods\n    | in a transformer, you can include sub resources using query string.\n    | e.g. /authors?include=books:limit(3|0):order(id|desc) means\n    | including 3 records of 'authors', which is reverse ordered by 'id' field,\n    | without any skipping(0).\n    |\n    | An API client can pass list of includes using array or csv string format.\n    | e.g. /authors?include[]=books:limit(2|0)&include[]=comments:order(id|asc)\n    |      /authors?include=books:limit(2|0),comments:order(id|asc)\n    |\n    | For sub-resource inclusion, client can use dot(.) notation.\n    | e.g. /books?include=author,publisher.somethingelse\n    |\n    */\n    'include' => [\n        'key' => 'include',\n        'params' => [ // available modifier params and their default value\n            'limit' => [3, 0], // [limit, offset]\n            'sort' => ['created_at', 'desc'], // [sortKey, sortDirection]\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Partial response\n    |--------------------------------------------------------------------------\n    |\n    | API clients are allowed to select the response format using query string.\n    | This will help saving network bandwidth..\n    | e.g. /author?fields=id,title,link&include=books:fields(id|title|published_at)\n    |\n    */\n    'partial' => [\n        'key' => 'fields',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Transformer directory and namespace.\n    |--------------------------------------------------------------------------\n    |\n    | Below config will be applied when we run 'make:transformer' artisan cmd.\n    | The generated class will be saved at 'dir', and namespaced as you set.\n    | Note that the 'dir' should be relative to the project root.\n    |\n    */\n    'transformer' => [\n        'dir' => 'app/Transformers',\n        'namespace' => 'App\\\\Transformers',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Fractal Serializer\n    |--------------------------------------------------------------------------\n    |\n    | Refer to\n    | http://fractal.thephpleague.com/serializers/\n    |\n    */\n    'serializer' => \\League\\Fractal\\Serializer\\ArraySerializer::class,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Response Headers\n    |--------------------------------------------------------------------------\n    |\n    | Default response headers that every resource/simple response should includes\n    |\n    */\n    'defaultHeaders' => ['X-Powered-By' => 'appkr/api'],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Suppress HTTP status code\n    |--------------------------------------------------------------------------\n    |\n    | If set to true, the status code will be fixed to 200.\n    |\n    */\n    'suppress_response_code' => false,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Success Response Format\n    |--------------------------------------------------------------------------\n    |\n    | The format will be used at the ApiResponse to respond with success message.\n    | respondNoContent(), respondSuccess(), respondCreated() consumes this format\n    |\n    */\n    'successFormat' => [\n        'success' => [\n            'code'    => ':code',\n            'message' => ':message',\n        ]\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Error Response Format\n    |--------------------------------------------------------------------------\n    |\n    | The format will be used at the ApiResponse to respond with error message.\n    | respondWithError(), respondForbidden()... consumes this format\n    |\n    */\n    'errorFormat' =>  [\n        'error' => [\n            'code'    => ':code',\n            'message' => ':message',\n        ]\n    ]\n\n];\n"
  },
  {
    "path": "config/app.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Environment\n    |--------------------------------------------------------------------------\n    |\n    | This value determines the \"environment\" your application is currently\n    | running in. This may determine how you prefer to configure various\n    | services your application utilizes. Set this in your \".env\" file.\n    |\n    */\n    'env' => env('APP_ENV', 'production'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Debug Mode\n    |--------------------------------------------------------------------------\n    |\n    | When your application is in debug mode, detailed error messages with\n    | stack traces will be shown on every error that occurs within your\n    | application. If disabled, a simple generic error page is shown.\n    |\n    */\n\n    'debug' => env('APP_DEBUG', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application URL\n    |--------------------------------------------------------------------------\n    |\n    | This URL is used by the console to properly generate URLs when using\n    | the Artisan command line tool. You should set this to the root of\n    | your application so that it is used when running Artisan tasks.\n    |\n    */\n\n    'url' => env('APP_URL', 'http://localhost:8000'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Timezone\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the default timezone for your application, which\n    | will be used by the PHP date and date-time functions. We have gone\n    | ahead and set this to a sensible default for you out of the box.\n    |\n    */\n\n    'timezone' => 'UTC',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Locale Configuration\n    |--------------------------------------------------------------------------\n    |\n    | The application locale determines the default locale that will be used\n    | by the translation service provider. You are free to set this value\n    | to any of the locales which will be supported by the application.\n    |\n    */\n\n    'locale' => 'ko',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Fallback Locale\n    |--------------------------------------------------------------------------\n    |\n    | The fallback locale determines the locale to use when the current one\n    | is not available. You may change the value to correspond to any of\n    | the language folders that are provided through your application.\n    |\n    */\n\n    'fallback_locale' => 'en',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Encryption Key\n    |--------------------------------------------------------------------------\n    |\n    | This key is used by the Illuminate encrypter service and should be set\n    | to a random, 32 character string, otherwise these encrypted strings\n    | will not be safe. Please do this before deploying an application!\n    |\n    */\n\n    'key' => env('APP_KEY', 'SomeRandomString'),\n\n    'cipher' => 'AES-256-CBC',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Logging Configuration\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the log settings for your application. Out of\n    | the box, Laravel uses the Monolog PHP logging library. This gives\n    | you a variety of powerful log handlers / formatters to utilize.\n    |\n    | Available Settings: \"single\", \"daily\", \"syslog\", \"errorlog\"\n    |\n    */\n\n    'log' => env('APP_LOG', 'single'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Autoloaded Service Providers\n    |--------------------------------------------------------------------------\n    |\n    | The service providers listed here will be automatically loaded on the\n    | request to your application. Feel free to add your own services to\n    | this array to grant expanded functionality to your applications.\n    |\n    */\n\n    'providers' => [\n\n        /*\n         * Laravel Framework Service Providers...\n         */\n        // Illuminate\\Foundation\\Providers\\ArtisanServiceProvider::class, // removed while migrating to 5.2\n        Illuminate\\Auth\\AuthServiceProvider::class,\n        Illuminate\\Broadcasting\\BroadcastServiceProvider::class,\n        Illuminate\\Bus\\BusServiceProvider::class,\n        Illuminate\\Cache\\CacheServiceProvider::class,\n        Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider::class,\n        // Illuminate\\Routing\\ControllerServiceProvider::class, // removed while migrating to 5.2\n        Illuminate\\Cookie\\CookieServiceProvider::class,\n        Illuminate\\Database\\DatabaseServiceProvider::class,\n        Illuminate\\Encryption\\EncryptionServiceProvider::class,\n        Illuminate\\Filesystem\\FilesystemServiceProvider::class,\n        Illuminate\\Foundation\\Providers\\FoundationServiceProvider::class,\n        Illuminate\\Hashing\\HashServiceProvider::class,\n        Illuminate\\Mail\\MailServiceProvider::class,\n        Illuminate\\Pagination\\PaginationServiceProvider::class,\n        Illuminate\\Pipeline\\PipelineServiceProvider::class,\n        Illuminate\\Queue\\QueueServiceProvider::class,\n        Illuminate\\Redis\\RedisServiceProvider::class,\n        Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider::class,\n        Illuminate\\Session\\SessionServiceProvider::class,\n        Illuminate\\Translation\\TranslationServiceProvider::class,\n        Illuminate\\Validation\\ValidationServiceProvider::class,\n        Illuminate\\View\\ViewServiceProvider::class,\n\n        /*\n         * Application Service Providers...\n         */\n        App\\Providers\\AppServiceProvider::class,\n        App\\Providers\\AuthServiceProvider::class,\n        App\\Providers\\EventServiceProvider::class,\n        App\\Providers\\RouteServiceProvider::class,\n\n        /*\n         * 3rd Party Service Providers\n         */\n        Intervention\\Image\\ImageServiceProvider::class,\n        Laracasts\\Flash\\FlashServiceProvider::class,\n        Laravel\\Socialite\\SocialiteServiceProvider::class,\n        Bican\\Roles\\RolesServiceProvider::class,\n        Maknz\\Slack\\SlackServiceProvider::class,\n        Tymon\\JWTAuth\\Providers\\JWTAuthServiceProvider::class,\n        Appkr\\Api\\ApiServiceProvider::class,\n        Barryvdh\\Cors\\ServiceProvider::class,\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Class Aliases\n    |--------------------------------------------------------------------------\n    |\n    | This array of class aliases will be registered when this application\n    | is started. However, feel free to register as many as you wish as\n    | the aliases are \"lazy\" loaded so they don't hinder performance.\n    |\n    */\n\n    'aliases' => [\n\n        'App'       => Illuminate\\Support\\Facades\\App::class,\n        'Artisan'   => Illuminate\\Support\\Facades\\Artisan::class,\n        'Auth'      => Illuminate\\Support\\Facades\\Auth::class,\n        'Blade'     => Illuminate\\Support\\Facades\\Blade::class,\n        'Bus'       => Illuminate\\Support\\Facades\\Bus::class,\n        'Cache'     => Illuminate\\Support\\Facades\\Cache::class,\n        'Config'    => Illuminate\\Support\\Facades\\Config::class,\n        'Cookie'    => Illuminate\\Support\\Facades\\Cookie::class,\n        'Crypt'     => Illuminate\\Support\\Facades\\Crypt::class,\n        'DB'        => Illuminate\\Support\\Facades\\DB::class,\n        'Eloquent'  => Illuminate\\Database\\Eloquent\\Model::class,\n        'Event'     => Illuminate\\Support\\Facades\\Event::class,\n        'File'      => Illuminate\\Support\\Facades\\File::class,\n        'Gate'      => Illuminate\\Support\\Facades\\Gate::class,\n        'Hash'      => Illuminate\\Support\\Facades\\Hash::class,\n        'Input'     => Illuminate\\Support\\Facades\\Input::class,\n        'Inspiring' => Illuminate\\Foundation\\Inspiring::class,\n        'Lang'      => Illuminate\\Support\\Facades\\Lang::class,\n        'Log'       => Illuminate\\Support\\Facades\\Log::class,\n        'Mail'      => Illuminate\\Support\\Facades\\Mail::class,\n        'Password'  => Illuminate\\Support\\Facades\\Password::class,\n        'Queue'     => Illuminate\\Support\\Facades\\Queue::class,\n        'Redirect'  => Illuminate\\Support\\Facades\\Redirect::class,\n        'Redis'     => Illuminate\\Support\\Facades\\Redis::class,\n        'Request'   => Illuminate\\Support\\Facades\\Request::class,\n        'Response'  => Illuminate\\Support\\Facades\\Response::class,\n        'Route'     => Illuminate\\Support\\Facades\\Route::class,\n        'Schema'    => Illuminate\\Support\\Facades\\Schema::class,\n        'Session'   => Illuminate\\Support\\Facades\\Session::class,\n        'Storage'   => Illuminate\\Support\\Facades\\Storage::class,\n        'URL'       => Illuminate\\Support\\Facades\\URL::class,\n        'Validator' => Illuminate\\Support\\Facades\\Validator::class,\n        'View'      => Illuminate\\Support\\Facades\\View::class,\n\n        /*\n         * 3rd Party Facade\n         */\n        'Image' => Intervention\\Image\\Facades\\Image::class,\n        'Flash' => Laracasts\\Flash\\Flash::class,\n        'Socialite' => Laravel\\Socialite\\Facades\\Socialite::class,\n        'Slack' => Maknz\\Slack\\Facades\\Slack::class,\n        'JWTAuth' => Tymon\\JWTAuth\\Facades\\JWTAuth::class,\n        'JWTFactory' => Tymon\\JWTAuth\\Facades\\JWTFactory::class,\n\n    ],\n\n];\n"
  },
  {
    "path": "config/auth.php",
    "content": "<?php\n\n// Copied from https://github.com/laravel/laravel/blob/master/config/auth.php\n// while migrating to Laravel 5.2\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Defaults\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default authentication \"guard\" and password\n    | reset options for your application. You may change these defaults\n    | as required, but they're a perfect start for most applications.\n    |\n    */\n\n    'defaults' => [\n        'guard' => 'web',\n        'passwords' => 'users',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Guards\n    |--------------------------------------------------------------------------\n    |\n    | Next, you may define every authentication guard for your application.\n    | Of course, a great default configuration has been defined for you\n    | here which uses session storage and the Eloquent user provider.\n    |\n    | All authentication drivers have a user provider. This defines how the\n    | users are actually retrieved out of your database or other storage\n    | mechanisms used by this application to persist your user's data.\n    |\n    | Supported: \"session\", \"token\"\n    |\n    */\n\n    'guards' => [\n        'web' => [\n            'driver' => 'session',\n            'provider' => 'users',\n        ],\n        'api' => [\n            'driver' => 'token',\n            'provider' => 'users',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | User Providers\n    |--------------------------------------------------------------------------\n    |\n    | All authentication drivers have a user provider. This defines how the\n    | users are actually retrieved out of your database or other storage\n    | mechanisms used by this application to persist your user's data.\n    |\n    | If you have multiple user tables or models you may configure multiple\n    | sources which represent each model / table. These sources may then\n    | be assigned to any extra authentication guards you have defined.\n    |\n    | Supported: \"database\", \"eloquent\"\n    |\n    */\n\n    'providers' => [\n        'users' => [\n            'driver' => 'eloquent',\n            'model' => App\\User::class,\n        ],\n        // 'users' => [\n        //     'driver' => 'database',\n        //     'table' => 'users',\n        // ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Resetting Passwords\n    |--------------------------------------------------------------------------\n    |\n    | Here you may set the options for resetting passwords including the view\n    | that is your password reset e-mail. You may also set the name of the\n    | table that maintains all of the reset tokens for your application.\n    |\n    | You may specify multiple password reset configurations if you have more\n    | than one user table or model in the application and you want to have\n    | separate password reset settings based on the specific user types.\n    |\n    | The expire time is the number of minutes that the reset token should be\n    | considered valid. This security feature keeps tokens short-lived so\n    | they have less time to be guessed. You may change this as needed.\n    |\n    */\n\n    'passwords' => [\n        'users' => [\n            'provider' => 'users',\n            'email' => 'emails.password',\n            'table' => 'password_resets',\n            'expire' => 60,\n        ],\n    ],\n\n];"
  },
  {
    "path": "config/broadcasting.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Broadcaster\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default broadcaster that will be used by the\n    | framework when an event needs to be broadcast. You may set this to\n    | any of the connections defined in the \"connections\" array below.\n    |\n    */\n\n    'default' => env('BROADCAST_DRIVER', 'pusher'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Broadcast Connections\n    |--------------------------------------------------------------------------\n    |\n    | Here you may define all of the broadcast connections that will be used\n    | to broadcast events to other systems or over websockets. Samples of\n    | each available type of connection are provided inside this array.\n    |\n    */\n\n    'connections' => [\n\n        'pusher' => [\n            'driver' => 'pusher',\n            'key' => env('PUSHER_KEY'),\n            'secret' => env('PUSHER_SECRET'),\n            'app_id' => env('PUSHER_APP_ID'),\n            'options' => [\n                //\n            ],\n        ],\n\n        'redis' => [\n            'driver' => 'redis',\n            'connection' => 'default',\n        ],\n\n        'log' => [\n            'driver' => 'log',\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "config/cache.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Cache Store\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default cache connection that gets used while\n    | using this caching library. This connection is used when another is\n    | not explicitly specified when executing a given caching function.\n    |\n    */\n\n    'default' => env('CACHE_DRIVER', 'file'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cache Stores\n    |--------------------------------------------------------------------------\n    |\n    | Here you may define all of the cache \"stores\" for your application as\n    | well as their drivers. You may even define multiple stores for the\n    | same cache driver to group types of items stored in your caches.\n    |\n    */\n\n    'stores' => [\n\n        'apc' => [\n            'driver' => 'apc',\n        ],\n\n        'array' => [\n            'driver' => 'array',\n        ],\n\n        'database' => [\n            'driver' => 'database',\n            'table'  => 'cache',\n            'connection' => null,\n        ],\n\n        'file' => [\n            'driver' => 'file',\n            'path'   => storage_path('framework/cache'),\n        ],\n\n        'memcached' => [\n            'driver'  => 'memcached',\n            'servers' => [\n                [\n                    'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100,\n                ],\n            ],\n        ],\n\n        'redis' => [\n            'driver' => 'redis',\n            'connection' => 'default',\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Cache Key Prefix\n    |--------------------------------------------------------------------------\n    |\n    | When utilizing a RAM based store such as APC or Memcached, there might\n    | be other applications utilizing the same cache. So, we'll specify a\n    | value to get prefixed to all our keys so we can avoid collisions.\n    |\n    */\n\n    'prefix' => 'laravel',\n\n];\n"
  },
  {
    "path": "config/compile.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Additional Compiled Classes\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify additional classes to include in the compiled file\n    | generated by the `artisan optimize` command. These should be classes\n    | that are included on basically every request into the application.\n    |\n    */\n\n    'files' => [\n        //\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Compiled File Providers\n    |--------------------------------------------------------------------------\n    |\n    | Here you may list service providers which define a \"compiles\" function\n    | that returns additional files that should be compiled, providing an\n    | easy way to get common files from any packages you are utilizing.\n    |\n    */\n\n    'providers' => [\n        //\n    ],\n\n];\n"
  },
  {
    "path": "config/cors.php",
    "content": "<?php\n\nreturn [\n    /*\n     |--------------------------------------------------------------------------\n     | Laravel CORS\n     |--------------------------------------------------------------------------\n     |\n\n     | allowedOrigins, allowedHeaders and allowedMethods can be set to array('*') \n     | to accept any value, the allowed methods however have to be explicitly listed.\n     |\n     */\n    'supportsCredentials' => false,\n    'allowedOrigins' => ['*'],\n    'allowedHeaders' => ['*'],\n    'allowedMethods' => ['GET', 'POST', 'PUT',  'DELETE'],\n    'exposedHeaders' => [],\n    'maxAge' => 0,\n    'hosts' => [],\n];\n\n"
  },
  {
    "path": "config/database.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | PDO Fetch Style\n    |--------------------------------------------------------------------------\n    |\n    | By default, database results will be returned as instances of the PHP\n    | stdClass object; however, you may desire to retrieve records in an\n    | array format for simplicity. Here you can tweak the fetch style.\n    |\n    */\n\n    'fetch' => PDO::FETCH_CLASS,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Database Connection Name\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify which of the database connections below you wish\n    | to use as your default connection for all database work. Of course\n    | you may use many connections at once using the Database library.\n    |\n    */\n\n    'default' => env('DB_CONNECTION', 'mysql'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Database Connections\n    |--------------------------------------------------------------------------\n    |\n    | Here are each of the database connections setup for your application.\n    | Of course, examples of configuring each database platform that is\n    | supported by Laravel is shown below to make development simple.\n    |\n    |\n    | All database work in Laravel is done through the PHP PDO facilities\n    | so make sure you have the driver for your particular database of\n    | choice installed on your machine before you begin development.\n    |\n    */\n\n    'connections' => [\n\n        'testing' => [\n            'driver' => 'sqlite',\n            'database' => ':memory:',\n        ],\n\n        'sqlite' => [\n            'driver'   => 'sqlite',\n            'database' => base_path('tests/database.sqlite'),\n            'prefix'   => '',\n        ],\n\n        'mysql' => [\n            'driver'    => 'mysql',\n            'host'      => env('DB_HOST', 'localhost'),\n            'database'  => env('DB_DATABASE', 'forge'),\n            'username'  => env('DB_USERNAME', 'forge'),\n            'password'  => env('DB_PASSWORD', ''),\n            'charset'   => 'utf8',\n            'collation' => 'utf8_unicode_ci',\n            'prefix'    => '',\n            'strict'    => false,\n        ],\n\n        'pgsql' => [\n            'driver'   => 'pgsql',\n            'host'     => env('DB_HOST', 'localhost'),\n            'database' => env('DB_DATABASE', 'forge'),\n            'username' => env('DB_USERNAME', 'forge'),\n            'password' => env('DB_PASSWORD', ''),\n            'charset'  => 'utf8',\n            'prefix'   => '',\n            'schema'   => 'public',\n        ],\n\n        'sqlsrv' => [\n            'driver'   => 'sqlsrv',\n            'host'     => env('DB_HOST', 'localhost'),\n            'database' => env('DB_DATABASE', 'forge'),\n            'username' => env('DB_USERNAME', 'forge'),\n            'password' => env('DB_PASSWORD', ''),\n            'charset'  => 'utf8',\n            'prefix'   => '',\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Migration Repository Table\n    |--------------------------------------------------------------------------\n    |\n    | This table keeps track of all the migrations that have already run for\n    | your application. Using this information, we can determine which of\n    | the migrations on disk haven't actually been run in the database.\n    |\n    */\n\n    'migrations' => 'migrations',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Redis Databases\n    |--------------------------------------------------------------------------\n    |\n    | Redis is an open source, fast, and advanced key-value store that also\n    | provides a richer set of commands than a typical key-value systems\n    | such as APC or Memcached. Laravel makes it easy to dig right in.\n    |\n    */\n\n    'redis' => [\n\n        'cluster' => false,\n\n        'default' => [\n            'host'     => '127.0.0.1',\n            'port'     => 6379,\n            'database' => 0,\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "config/filesystems.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Filesystem Disk\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the default filesystem disk that should be used\n    | by the framework. A \"local\" driver, as well as a variety of cloud\n    | based drivers are available for your choosing. Just store away!\n    |\n    | Supported: \"local\", \"ftp\", \"s3\", \"rackspace\"\n    |\n    */\n\n    'default' => 'local',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Cloud Filesystem Disk\n    |--------------------------------------------------------------------------\n    |\n    | Many applications store files both locally and in the cloud. For this\n    | reason, you may specify a default \"cloud\" driver here. This driver\n    | will be bound as the Cloud disk implementation in the container.\n    |\n    */\n\n    'cloud' => 's3',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Filesystem Disks\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure as many filesystem \"disks\" as you wish, and you\n    | may even configure multiple disks of the same driver. Defaults have\n    | been setup for each driver as an example of the required options.\n    |\n    */\n\n    'disks' => [\n\n        'local' => [\n            'driver' => 'local',\n            'root'   => storage_path('app'),\n        ],\n\n        'ftp' => [\n            'driver'   => 'ftp',\n            'host'     => 'ftp.example.com',\n            'username' => 'your-username',\n            'password' => 'your-password',\n\n            // Optional FTP Settings...\n            // 'port'     => 21,\n            // 'root'     => '',\n            // 'passive'  => true,\n            // 'ssl'      => true,\n            // 'timeout'  => 30,\n        ],\n\n        's3' => [\n            'driver' => 's3',\n            'key'    => 'your-key',\n            'secret' => 'your-secret',\n            'region' => 'your-region',\n            'bucket' => 'your-bucket',\n        ],\n\n        'rackspace' => [\n            'driver'    => 'rackspace',\n            'username'  => 'your-username',\n            'key'       => 'your-key',\n            'container' => 'your-container',\n            'endpoint'  => 'https://identity.api.rackspacecloud.com/v2.0/',\n            'region'    => 'IAD',\n            'url_type'  => 'publicURL',\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "config/icons.php",
    "content": "<?php\n\nreturn [\n\n    'login'       => 'fa fa-sign-in',\n    'github'      => 'fa fa-github',\n    'book'        => 'fa fa-book',\n    'locale'      => 'fa fa-language',\n    'certificate' => 'fa fa-certificate',\n    'forum'       => 'fa fa-weixin',\n    'logout'      => 'fa fa-sign-out',\n    'user'        => 'fa fa-user',\n    'plane'       => 'fa fa-paper-plane',\n    'check'       => 'fa fa-check',\n    'clock'       => 'fa fa-clock-o',\n    'tags'        => 'fa fa-tags',\n    'comments'    => 'fa fa-comments',\n    'reset'       => 'fa fa-refresh',\n    'pencil'      => 'fa fa-pencil',\n    'delete'      => 'fa fa-trash-o',\n    'clip'        => 'fa fa-paperclip',\n    'download'    => 'fa fa-cloud-download',\n    'dropdown'    => 'fa fa-chevron-down',\n    'update'      => 'fa fa-paragraph',\n    'reply'       => 'fa fa-reply',\n    'preview'     => 'fa fa-code',\n    'up'          => 'fa fa-chevron-up',\n    'down'        => 'fa fa-chevron-down',\n    'filter'      => 'fa fa-filter',\n    'view_count'  => 'fa fa-eye',\n    'sort'        => 'fa fa-sort',\n    'desc'        => 'fa fa-sort-alpha-desc',\n    'asc'         => 'fa fa-sort-alpha-asc',\n    'new'         => 'fa fa-plus-circle',\n    'notice'      => 'fa fa-bullhorn',\n    'pin'         => 'fa fa-thumb-tack',\n\n];\n"
  },
  {
    "path": "config/jwt.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | JWT Authentication Secret\n    |--------------------------------------------------------------------------\n    |\n    | Don't forget to set this, as it will be used to sign your tokens.\n    | A helper command is provided for this: `php artisan jwt:generate`\n    |\n    */\n\n    'secret' => env('JWT_SECRET', 'SomeRandomString'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | JWT time to live\n    |--------------------------------------------------------------------------\n    |\n    | Specify the length of time (in minutes) that the token will be valid for.\n    | Defaults to 1 hour\n    |\n    */\n\n    'ttl' => 120,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Refresh time to live\n    |--------------------------------------------------------------------------\n    |\n    | Specify the length of time (in minutes) that the token can be refreshed\n    | within. I.E. The user can refresh their token within a 2 week window of\n    | the original token being created until they must re-authenticate.\n    | Defaults to 2 weeks\n    |\n    */\n\n    'refresh_ttl' => 20160,\n\n    /*\n    |--------------------------------------------------------------------------\n    | JWT hashing algorithm\n    |--------------------------------------------------------------------------\n    |\n    | Specify the hashing algorithm that will be used to sign the token.\n    |\n    | See here: https://github.com/namshi/jose/tree/2.2.0/src/Namshi/JOSE/Signer\n    | for possible values\n    |\n    */\n\n    'algo' => 'HS256',\n\n    /*\n    |--------------------------------------------------------------------------\n    | User Model namespace\n    |--------------------------------------------------------------------------\n    |\n    | Specify the full namespace to your User model.\n    | e.g. 'Acme\\Entities\\User'\n    |\n    */\n\n    'user' => App\\User::class,\n\n    /*\n    |--------------------------------------------------------------------------\n    | User identifier\n    |--------------------------------------------------------------------------\n    |\n    | Specify a unique property of the user that will be added as the 'sub'\n    | claim of the token payload.\n    |\n    */\n\n    'identifier' => 'id',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Required Claims\n    |--------------------------------------------------------------------------\n    |\n    | Specify the required claims that must exist in any token.\n    | A TokenInvalidException will be thrown if any of these claims are not\n    | present in the payload.\n    |\n    */\n\n    'required_claims' => ['iss', 'iat', 'exp', 'nbf', 'sub', 'jti'],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Blacklist Enabled\n    |--------------------------------------------------------------------------\n    |\n    | In order to invalidate tokens, you must have the the blacklist enabled.\n    | If you do not want or need this functionality, then set this to false.\n    |\n    */\n\n    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Providers\n    |--------------------------------------------------------------------------\n    |\n    | Specify the various providers used throughout the package.\n    |\n    */\n\n    'providers' => [\n\n        /*\n        |--------------------------------------------------------------------------\n        | User Provider\n        |--------------------------------------------------------------------------\n        |\n        | Specify the provider that is used to find the user based\n        | on the subject claim\n        |\n        */\n\n        'user' => Tymon\\JWTAuth\\Providers\\User\\EloquentUserAdapter::class,\n\n        /*\n        |--------------------------------------------------------------------------\n        | JWT Provider\n        |--------------------------------------------------------------------------\n        |\n        | Specify the provider that is used to create and decode the tokens.\n        |\n        */\n\n        'jwt' => Tymon\\JWTAuth\\Providers\\JWT\\NamshiAdapter::class,\n\n        /*\n        |--------------------------------------------------------------------------\n        | Authentication Provider\n        |--------------------------------------------------------------------------\n        |\n        | Specify the provider that is used to authenticate users.\n        |\n        */\n\n        'auth' => function ($app) {\n            return new Tymon\\JWTAuth\\Providers\\Auth\\IlluminateAuthAdapter($app['auth']);\n        },\n\n        /*\n        |--------------------------------------------------------------------------\n        | Storage Provider\n        |--------------------------------------------------------------------------\n        |\n        | Specify the provider that is used to store tokens in the blacklist\n        |\n        */\n\n        'storage' => function ($app) {\n            return new Tymon\\JWTAuth\\Providers\\Storage\\IlluminateCacheAdapter($app['cache']);\n        }\n\n    ]\n\n];\n"
  },
  {
    "path": "config/mail.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Mail Driver\n    |--------------------------------------------------------------------------\n    |\n    | Laravel supports both SMTP and PHP's \"mail\" function as drivers for the\n    | sending of e-mail. You may specify which one you're using throughout\n    | your application here. By default, Laravel is setup for SMTP mail.\n    |\n    | Supported: \"smtp\", \"mail\", \"sendmail\", \"mailgun\", \"mandrill\", \"ses\", \"log\"\n    |\n    */\n\n    'driver' => env('MAIL_DRIVER', 'smtp'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | SMTP Host Address\n    |--------------------------------------------------------------------------\n    |\n    | Here you may provide the host address of the SMTP server used by your\n    | applications. A default option is provided that is compatible with\n    | the Mailgun mail service which will provide reliable deliveries.\n    |\n    */\n\n    'host' => env('MAIL_HOST', 'smtp.mailgun.org'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | SMTP Host Port\n    |--------------------------------------------------------------------------\n    |\n    | This is the SMTP port used by your application to deliver e-mails to\n    | users of the application. Like the host we have set this value to\n    | stay compatible with the Mailgun e-mail application by default.\n    |\n    */\n\n    'port' => env('MAIL_PORT', 587),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Global \"From\" Address\n    |--------------------------------------------------------------------------\n    |\n    | You may wish for all e-mails sent by your application to be sent from\n    | the same address. Here, you may specify a name and address that is\n    | used globally for all e-mails that are sent by your application.\n    |\n    */\n\n    'from' => ['address' => 'john@example.com', 'name' => 'John Doe'],\n\n    /*\n    |--------------------------------------------------------------------------\n    | E-Mail Encryption Protocol\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the encryption protocol that should be used when\n    | the application send e-mail messages. A sensible default using the\n    | transport layer security protocol should provide great security.\n    |\n    */\n\n    'encryption' => env('MAIL_ENCRYPTION', 'tls'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | SMTP Server Username\n    |--------------------------------------------------------------------------\n    |\n    | If your SMTP server requires a username for authentication, you should\n    | set it here. This will get used to authenticate with your server on\n    | connection. You may also set the \"password\" value below this one.\n    |\n    */\n\n    'username' => env('MAIL_USERNAME'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | SMTP Server Password\n    |--------------------------------------------------------------------------\n    |\n    | Here you may set the password required by your SMTP server to send out\n    | messages from your application. This will be given to the server on\n    | connection so that the application will be able to send messages.\n    |\n    */\n\n    'password' => env('MAIL_PASSWORD'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Sendmail System Path\n    |--------------------------------------------------------------------------\n    |\n    | When using the \"sendmail\" driver to send e-mails, we will need to know\n    | the path to where Sendmail lives on this server. A default path has\n    | been provided here, which will work well on most of your systems.\n    |\n    */\n\n    'sendmail' => '/usr/sbin/sendmail -bs',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Mail \"Pretend\"\n    |--------------------------------------------------------------------------\n    |\n    | When this option is enabled, e-mail will not actually be sent over the\n    | web and will instead be written to your application's logs files so\n    | you may inspect the message. This is great for local development.\n    |\n    */\n\n    'pretend' => env('MAIL_PRETEND', false),\n\n];\n"
  },
  {
    "path": "config/project.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Enable or disable site-wide caching\n    |--------------------------------------------------------------------------\n    |\n    | If set to false, site-wide cache and etag/304 feature will be disabled.\n    | For production, for performance this should be set to true.\n    |\n    */\n    'cache' => ! env('APP_DEBUG', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Project identification\n    |--------------------------------------------------------------------------\n    |\n    */\n    'name'        => 'l5essential',\n    'description' => 'Laravel 5 입문 및 실전 강좌',\n    'app_domain'  => env('APP_DOMAIN', 'myproject.dev'),\n    'api_domain'  => env('API_DOMAIN', 'api.myproject.dev'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | People & contacts\n    |--------------------------------------------------------------------------\n    |\n    */\n    'contacts'    => [\n        'author' => [\n            'name'         => 'appkr',\n            'email'        => 'juwonkim@me.com',\n            'url'          => '',\n            'organization' => 'Appkr Studio',\n        ],\n        'admin'  => [\n            // ...\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | SEO keys\n    |--------------------------------------------------------------------------\n    |\n    | @see https://www.google.com/webmasters/tools/home\n    |      Note. Is not required when Google Analytics is activated.\n    | @see http://webmastertool.naver.com/board/main.naver\n    |\n    */\n    'seo'         => [\n        'google_site_key' => 'ToXKBimREnz49pDNot4b-N9ZJgYcKXPPsHsjhg4Zzuc',\n        'naver_site_key'  => '7cebcc8e5493169f5401870d9ce57f48d18491cd',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Available/allowed fields for query string\n    |--------------------------------------------------------------------------\n    |\n    */\n    'params'      => [\n        'page'   => 'page',\n        'filter' => 'filter',\n        'limit'  => 'limit',\n        'sort'   => 'sort',\n        'order'  => 'order',\n        'search' => 'q',\n        'select' => 'fields',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Available/allowed value for 'filter' query string\n    |--------------------------------------------------------------------------\n    |\n    | 'model_in_lower_case' => ['filter_key' => 'description'],\n    | filter_key will be transformed to camelCase when calling the scope query.\n    |     e.g. no_comment -> noComment\n    |\n    */\n    'filters' => [\n        'article' => [\n            'no_comment' => 'No Comment',\n            'not_solved' => 'Not Solved'\n        ]\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Available/allowed tags for/associated with Article\n    |--------------------------------------------------------------------------\n    |\n    | Used in database/seeds/DatabaseSeeder.php\n    |\n    */\n    'tags' => [\n        'General',\n        'Laravel',\n        'Lumen',\n        'Eloquent',\n        'Servers',\n        'Tips',\n        'Lesson Feedback'\n    ],\n\n];"
  },
  {
    "path": "config/queue.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Queue Driver\n    |--------------------------------------------------------------------------\n    |\n    | The Laravel queue API supports a variety of back-ends via an unified\n    | API, giving you convenient access to each back-end using the same\n    | syntax for each one. Here you may set the default queue driver.\n    |\n    | Supported: \"null\", \"sync\", \"database\", \"beanstalkd\",\n    |            \"sqs\", \"iron\", \"redis\"\n    |\n    */\n\n    'default' => env('QUEUE_DRIVER', 'sync'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Queue Connections\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure the connection information for each server that\n    | is used by your application. A default configuration has been added\n    | for each back-end shipped with Laravel. You are free to add more.\n    |\n    */\n\n    'connections' => [\n\n        'sync' => [\n            'driver' => 'sync',\n        ],\n\n        'database' => [\n            'driver' => 'database',\n            'table'  => 'jobs',\n            'queue'  => 'default',\n            'expire' => 60,\n        ],\n\n        'beanstalkd' => [\n            'driver' => 'beanstalkd',\n            'host'   => 'localhost',\n            'queue'  => 'default',\n            'ttr'    => 60,\n        ],\n\n        'sqs' => [\n            'driver' => 'sqs',\n            'key'    => 'your-public-key',\n            'secret' => 'your-secret-key',\n            'queue'  => 'your-queue-url',\n            'region' => 'us-east-1',\n        ],\n\n        'iron' => [\n            'driver'  => 'iron',\n            'host'    => 'mq-aws-us-east-1.iron.io',\n            'token'   => 'your-token',\n            'project' => 'your-project-id',\n            'queue'   => 'your-queue-name',\n            'encrypt' => true,\n        ],\n\n        'redis' => [\n            'driver'     => 'redis',\n            'connection' => 'default',\n            'queue'      => 'default',\n            'expire'     => 60,\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Failed Queue Jobs\n    |--------------------------------------------------------------------------\n    |\n    | These options configure the behavior of failed queue job logging so you\n    | can control which database and table are used to store the jobs that\n    | have failed. You may change them to any database / table you wish.\n    |\n    */\n\n    'failed' => [\n        'database' => env('DB_CONNECTION', 'mysql'),\n        'table'    => 'failed_jobs',\n    ],\n\n];\n"
  },
  {
    "path": "config/roles.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Package Connection\n    |--------------------------------------------------------------------------\n    |\n    | You can set a different database connection for this package. It will set\n    | new connection for models Role and Permission. When this option is null,\n    | it will connect to the main database, which is set up in database.php\n    |\n    */\n\n    'connection' => null,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Slug Separator\n    |--------------------------------------------------------------------------\n    |\n    | Here you can change the slug separator. This is very important in matter\n    | of magic method __call() and also a `Slugable` trait. The default value\n    | is a dot.\n    |\n    */\n\n    'separator' => '.',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Models\n    |--------------------------------------------------------------------------\n    |\n    | If you want, you can replace default models from this package by models\n    | you created. Have a look at `Bican\\Roles\\Models\\Role` model and\n    | `Bican\\Roles\\Models\\Permission` model.\n    |\n    */\n\n    'models' => [\n        'role' => Bican\\Roles\\Models\\Role::class,\n        'permission' => Bican\\Roles\\Models\\Permission::class,\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Roles, Permissions and Allowed \"Pretend\"\n    |--------------------------------------------------------------------------\n    |\n    | You can pretend or simulate package behavior no matter what is in your\n    | database. It is really useful when you are testing you application.\n    | Set up what will methods is(), can() and allowed() return.\n    |\n    */\n\n    'pretend' => [\n\n        'enabled' => false,\n\n        'options' => [\n            'is' => true,\n            'can' => true,\n            'allowed' => true,\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "config/services.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Third Party Services\n    |--------------------------------------------------------------------------\n    |\n    | This file is for storing the credentials for third party services such\n    | as Stripe, Mailgun, Mandrill, and others. This file provides a sane\n    | default location for this type of information, allowing packages\n    | to have a conventional place to find your various credentials.\n    |\n    */\n\n    'mailgun'  => [\n        'domain' => env('MAILGUN_DOMAIN'),\n        'secret' => env('MAILGUN_SECRET'),\n    ],\n\n    'mandrill' => [\n        'secret' => env('MANDRILL_SECRET'),\n    ],\n\n    'ses'      => [\n        'key'    => env('SES_KEY'),\n        'secret' => env('SES_SECRET'),\n        'region' => 'us-east-1',\n    ],\n\n    'stripe'   => [\n        'model'  => App\\User::class,\n        'key'    => env('STRIPE_KEY'),\n        'secret' => env('STRIPE_SECRET'),\n    ],\n\n    'github'   => [\n        'client_id'     => env('GITHUB_ID'),\n        'client_secret' => env('GITHUB_SECRET'),\n        'redirect'      => env('GITHUB_CALLBACK'),\n    ],\n\n];\n"
  },
  {
    "path": "config/session.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Session Driver\n    |--------------------------------------------------------------------------\n    |\n    | This option controls the default session \"driver\" that will be used on\n    | requests. By default, we will use the lightweight native driver but\n    | you may specify any of the other wonderful drivers provided here.\n    |\n    | Supported: \"file\", \"cookie\", \"database\", \"apc\",\n    |            \"memcached\", \"redis\", \"array\"\n    |\n    */\n\n    'driver' => env('SESSION_DRIVER', 'file'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Lifetime\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the number of minutes that you wish the session\n    | to be allowed to remain idle before it expires. If you want them\n    | to immediately expire on the browser closing, set that option.\n    |\n    */\n\n    'lifetime' => 120,\n\n    'expire_on_close' => false,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Encryption\n    |--------------------------------------------------------------------------\n    |\n    | This option allows you to easily specify that all of your session data\n    | should be encrypted before it is stored. All encryption will be run\n    | automatically by Laravel and you can use the Session like normal.\n    |\n    */\n\n    'encrypt' => false,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session File Location\n    |--------------------------------------------------------------------------\n    |\n    | When using the native session driver, we need a location where session\n    | files may be stored. A default has been set for you but a different\n    | location may be specified. This is only needed for file sessions.\n    |\n    */\n\n    'files' => storage_path('framework/sessions'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Database Connection\n    |--------------------------------------------------------------------------\n    |\n    | When using the \"database\" or \"redis\" session drivers, you may specify a\n    | connection that should be used to manage these sessions. This should\n    | correspond to a connection in your database configuration options.\n    |\n    */\n\n    'connection' => null,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Database Table\n    |--------------------------------------------------------------------------\n    |\n    | When using the \"database\" session driver, you may specify the table we\n    | should use to manage the sessions. Of course, a sensible default is\n    | provided for you; however, you are free to change this as needed.\n    |\n    */\n\n    'table' => 'sessions',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Sweeping Lottery\n    |--------------------------------------------------------------------------\n    |\n    | Some session drivers must manually sweep their storage location to get\n    | rid of old sessions from storage. Here are the chances that it will\n    | happen on a given request. By default, the odds are 2 out of 100.\n    |\n    */\n\n    'lottery' => [2, 100],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Name\n    |--------------------------------------------------------------------------\n    |\n    | Here you may change the name of the cookie used to identify a session\n    | instance by ID. The name specified here will get used every time a\n    | new session cookie is created by the framework for every driver.\n    |\n    */\n\n    'cookie' => 'l5essential',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Path\n    |--------------------------------------------------------------------------\n    |\n    | The session cookie path determines the path for which the cookie will\n    | be regarded as available. Typically, this will be the root path of\n    | your application but you are free to change this when necessary.\n    |\n    */\n\n    'path' => '/',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Session Cookie Domain\n    |--------------------------------------------------------------------------\n    |\n    | Here you may change the domain of the cookie used to identify a session\n    | in your application. This will determine which domains the cookie is\n    | available to in your application. A sensible default has been set.\n    |\n    */\n\n    'domain' => null,\n\n    /*\n    |--------------------------------------------------------------------------\n    | HTTPS Only Cookies\n    |--------------------------------------------------------------------------\n    |\n    | By setting this option to true, session cookies will only be sent back\n    | to the server if the browser has a HTTPS connection. This will keep\n    | the cookie from being sent to you if it can not be done securely.\n    |\n    */\n\n    'secure' => false,\n\n];\n"
  },
  {
    "path": "config/slack.php",
    "content": "<?php\n\nreturn [\n\n  /*\n  |-------------------------------------------------------------\n  | Incoming webhook endpoint\n  |-------------------------------------------------------------\n  |\n  | The endpoint which Slack generates when creating a\n  | new incoming webhook. It will look something like\n  | https://hooks.slack.com/services/XXXXXXXX/XXXXXXXX/XXXXXXXXXXXXXX\n  |\n  */\n\n  'endpoint' => '',\n\n  /*\n  |-------------------------------------------------------------\n  | Default channel\n  |-------------------------------------------------------------\n  |\n  | The default channel we should post to. The channel can either be a\n  | channel like #general, a private #group, or a @username. Set to\n  | null to use the default set on the Slack webhook\n  |\n  */\n\n  'channel' => '#general',\n\n  /*\n  |-------------------------------------------------------------\n  | Default username\n  |-------------------------------------------------------------\n  |\n  | The default username we should post as. Set to null to use\n  | the default set on the Slack webhook\n  |\n  */\n\n  'username' => 'Robot',\n\n  /*\n  |-------------------------------------------------------------\n  | Default icon\n  |-------------------------------------------------------------\n  |\n  | The default icon to use. This can either be a URL to an image or Slack\n  | emoji like :ghost: or :heart_eyes:. Set to null to use the default\n  | set on the Slack webhook\n  |\n  */\n\n  'icon' => null,\n\n  /*\n  |-------------------------------------------------------------\n  | Link names\n  |-------------------------------------------------------------\n  |\n  | Whether names like @regan should be converted into links\n  | by Slack\n  |\n  */\n\n  'link_names' => false,\n\n  /*\n  |-------------------------------------------------------------\n  | Unfurl links\n  |-------------------------------------------------------------\n  |\n  | Whether Slack should unfurl links to text-based content\n  |\n  */\n\n  'unfurl_links' => false,\n\n  /*\n  |-------------------------------------------------------------\n  | Unfurl media\n  |-------------------------------------------------------------\n  |\n  | Whether Slack should unfurl links to media content such\n  | as images and YouTube videos\n  |\n  */\n\n  'unfurl_media' => true,\n\n  /*\n  |-------------------------------------------------------------\n  | Markdown in message text\n  |-------------------------------------------------------------\n  |\n  | Whether message text should be interpreted in Slack's Markdown-like\n  | language. For formatting options, see Slack's help article: http://goo.gl/r4fsdO\n  |\n  */\n\n  'allow_markdown' => true,\n\n  /*\n  |-------------------------------------------------------------\n  | Markdown in attachments\n  |-------------------------------------------------------------\n  |\n  | Which attachment fields should be interpreted in Slack's Markdown-like\n  | language. By default, Slack assumes that no fields in an attachment\n  | should be formatted as Markdown. \n  |\n  */\n\n  'markdown_in_attachments' => [],\n\n  // Allow Markdown in just the text and title fields\n  // 'markdown_in_attachments' => ['text', 'title']\n\n  // Allow Markdown in all fields\n  // 'markdown_in_attachments' => ['pretext', 'text', 'title', 'fields', 'fallback']\n\n];\n"
  },
  {
    "path": "config/view.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | View Storage Paths\n    |--------------------------------------------------------------------------\n    |\n    | Most templating systems load templates from disk. Here you may specify\n    | an array of paths that should be checked for your views. Of course\n    | the usual Laravel view path has already been registered for you.\n    |\n    */\n\n    'paths' => [\n        realpath(base_path('resources/views')),\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Compiled View Path\n    |--------------------------------------------------------------------------\n    |\n    | This option determines where all the compiled Blade templates will be\n    | stored for your application. Typically, this is within the storage\n    | directory. However, as usual, you are free to change this value.\n    |\n    */\n\n    'compiled' => realpath(storage_path('framework/views')),\n\n];\n"
  },
  {
    "path": "database/.gitignore",
    "content": "*.sqlite\n"
  },
  {
    "path": "database/factories/ModelFactory.php",
    "content": "<?php\n\n/*\n|--------------------------------------------------------------------------\n| Model Factories\n|--------------------------------------------------------------------------\n|\n| Here you may define all of your model factories. Model factories give\n| you a convenient way to create models for testing and seeding your\n| database. Just tell the factory how a default model should look.\n|\n*/\n\n$factory->define(App\\User::class, function(Faker\\Generator $faker) {\n    return [\n        'name'           => $faker->name,\n        'email'          => $faker->safeEmail,\n        'password'       => bcrypt('password'),\n        'remember_token' => str_random(60),\n    ];\n});\n\n$factory->define(App\\Article::class, function(Faker\\Generator $faker) {\n    $date = $faker->dateTimeThisMonth;\n    return [\n        'title'      => $faker->sentence(),\n        'content'    => $faker->paragraph(),\n        'created_at' => $date,\n        'updated_at' => $date,\n    ];\n});\n\n$factory->define(App\\Comment::class, function(Faker\\Generator $faker) {\n    return [\n        'content' => $faker->paragraph,\n    ];\n});\n\n$factory->define(App\\Tag::class, function(Faker\\Generator $faker) {\n    $name = ucfirst($faker->optional(0.9, 'Laravel')->word);\n\n    return [\n        'name' => $name,\n        'slug' => str_slug($name),\n    ];\n});\n\n$factory->define(App\\Attachment::class, function(Faker\\Generator $faker) {\n    return [\n        'name' => sprintf(\"%s.%s\", str_random(), $faker->randomElement(['png', 'jpg'])),\n    ];\n});\n\n"
  },
  {
    "path": "database/migrations/.gitkeep",
    "content": ""
  },
  {
    "path": "database/migrations/2014_10_12_000000_create_users_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateUsersTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('users', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name');\n            $table->string('email')->unique();\n            $table->string('password', 60)->nullable();\n            $table->rememberToken();\n            $table->timestamp('last_login')->nullable();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('users');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2014_10_12_100000_create_password_resets_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreatePasswordResetsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('password_resets', function (Blueprint $table) {\n            $table->string('email')->index();\n            $table->string('token')->index();\n            $table->timestamp('created_at');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('password_resets');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_01_15_105324_create_roles_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateRolesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('roles', function (Blueprint $table) {\n            $table->increments('id')->unsigned();\n            $table->string('name');\n            $table->string('slug')->unique();\n            $table->string('description')->nullable();\n            $table->integer('level')->default(1);\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('roles');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_01_15_114412_create_role_user_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateRoleUserTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('role_user', function (Blueprint $table) {\n            $table->increments('id')->unsigned();\n            $table->integer('role_id')->unsigned()->index();\n            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');\n            $table->integer('user_id')->unsigned()->index();\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('role_user');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_01_26_115212_create_permissions_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreatePermissionsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('permissions', function (Blueprint $table) {\n            $table->increments('id')->unsigned();\n            $table->string('name');\n            $table->string('slug')->unique();\n            $table->string('description')->nullable();\n            $table->string('model')->nullable();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('permissions');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_01_26_115523_create_permission_role_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreatePermissionRoleTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('permission_role', function (Blueprint $table) {\n            $table->increments('id')->unsigned();\n            $table->integer('permission_id')->unsigned()->index();\n            $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');\n            $table->integer('role_id')->unsigned()->index();\n            $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('permission_role');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_02_09_132439_create_permission_user_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreatePermissionUserTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('permission_user', function (Blueprint $table) {\n            $table->increments('id')->unsigned();\n            $table->integer('permission_id')->unsigned()->index();\n            $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');\n            $table->integer('user_id')->unsigned()->index();\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('permission_user');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_11_20_062500_create_comments_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateCommentsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('comments', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('author_id')->unsigned()->index();\n            $table->string('commentable_type');\n            $table->integer('commentable_id')->unsigned();\n            $table->integer('parent_id')->unsigned()->nullable();\n            $table->string('title')->nullable();\n            $table->text('content');\n            $table->timestamps();\n            $table->softDeletes();\n\n            $table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');\n            $table->foreign('parent_id')->references('id')->on('comments');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('comments');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_11_20_062513_create_articles_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateArticlesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('articles', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('author_id')->unsigned()->index();\n            $table->string('title');\n            $table->text('content');\n            $table->integer('solution_id')->unsigned()->nullable();\n            $table->boolean('notification')->default(1);\n            $table->tinyInteger('view_count')->default(0);\n            $table->boolean('pin')->default(0);\n            $table->timestamps();\n            $table->softDeletes();\n\n            $table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');\n            $table->foreign('solution_id')->references('id')->on('comments');\n        });\n\n        if (config('database.default') != 'sqlite') {\n            DB::statement('ALTER TABLE articles ADD FULLTEXT search(title, content)');\n        }\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('articles');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_11_20_062601_create_tags_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateTagsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('tags', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name');\n            $table->string('slug')->index();\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('tags');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_11_20_062613_create_attachments_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateAttachmentsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('attachments', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('article_id')->unsigned()->index();\n            $table->string('name');\n            $table->timestamps();\n\n//            $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('attachments');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_11_20_062846_create_article_tag_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateArticleTagTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('article_tag', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('article_id')->unsigned();\n            $table->integer('tag_id')->unsigned();\n            $table->timestamps();\n\n            $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');\n            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('article_tag');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_12_09_165930_create_lessons_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateLessonsTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('lessons', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('author_id')->unsigned();\n            $table->string('name');\n            $table->text('content');\n            $table->timestamps();\n\n            $table->foreign('author_id')->references('id')->on('users');\n        });\n\n        if (config('database.default') != 'sqlite') {\n            DB::statement('ALTER TABLE lessons ADD FULLTEXT docs(name, content)');\n        }\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('lessons');\n    }\n}\n"
  },
  {
    "path": "database/migrations/2015_12_10_151357_create_votes_table.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Database\\Migrations\\Migration;\n\nclass CreateVotesTable extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('votes', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('user_id')->unsigned();\n            $table->integer('comment_id')->unsigned();\n            $table->tinyInteger('up')->nullable();\n            $table->tinyInteger('down')->nullable();\n            $table->timestamp('voted_at');\n\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n            $table->foreign('comment_id')->references('id')->on('comments')->onDelete('cascade');\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::drop('votes');\n    }\n}\n"
  },
  {
    "path": "database/seeds/.gitkeep",
    "content": ""
  },
  {
    "path": "database/seeds/DatabaseSeeder.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Seeder;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Faker\\Factory as Faker;\n\nclass DatabaseSeeder extends Seeder\n{\n    /**\n     * Run the database seeds.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        /*\n         * Prepare seeding\n         */\n        $faker = Faker::create();\n        if (config('database.default') != 'sqlite') {\n            DB::statement('SET FOREIGN_KEY_CHECKS=0');\n        }\n\n//        Not required for Laravel 5.2\n//        @see https://laravel.com/docs/5.2/upgrade#upgrade-5.2.0\n//        Model::unguard();\n\n        /*\n         * Seeding users table\n         */\n        App\\User::truncate();\n        factory(App\\User::class)->create([\n            'name' => 'John Doe',\n            'email' => 'john@example.com',\n            'password' => bcrypt('password')\n        ]);\n        factory(App\\User::class, 9)->create();\n        $this->command->info('users table seeded');\n\n        /**\n         * Seeding roles table\n         */\n        Bican\\Roles\\Models\\Role::truncate();\n        DB::table('role_user')->truncate();\n        $adminRole = Bican\\Roles\\Models\\Role::create([\n            'name' => 'Admin',\n            'slug' => 'admin'\n        ]);\n        $memberRole = Bican\\Roles\\Models\\Role::create([\n            'name' => 'Member',\n            'slug' => 'member'\n        ]);\n\n        App\\User::where('email', '!=', 'john@example.com')->get()->map(function($user) use($memberRole) {\n            $user->attachRole($memberRole);\n        });\n\n        App\\User::whereEmail('john@example.com')->get()->map(function($user) use($adminRole){\n            $user->attachRole($adminRole);\n        });\n        $this->command->info('roles table seeded');\n\n        /*\n         * Seeding articles table\n         */\n        App\\Article::truncate();\n        $users = App\\User::all();\n\n        $users->each(function($user) use($faker) {\n            $user->articles()->save(\n                factory(App\\Article::class)->make()\n            );\n            $user->articles()->save(\n                factory(App\\Article::class)->make()\n            );\n        });\n        $this->command->info('articles table seeded');\n\n        /**\n         * Seeding comments table\n         */\n        App\\Comment::truncate();\n        $articles = App\\Article::all();\n\n        $articles->each(function($article) use($faker, $users) {\n            $article->comments()->save(\n                factory(App\\Comment::class)->make([\n                    'author_id' => $faker->randomElement($users->lists('id')->toArray())\n                ])\n            );\n        });\n        $this->command->info('comments table seeded');\n\n        /*\n         * Seeding tags table\n         */\n        App\\Tag::truncate();\n        DB::table('article_tag')->truncate();\n        $rawTags = config('project.tags');\n\n        foreach($rawTags as $tag) {\n            App\\Tag::create([\n                'name' => $tag,\n                'slug' => str_slug($tag)\n            ]);\n        }\n\n        $tags = App\\Tag::all();\n\n        foreach($articles as $article) {\n            $article->tags()->attach(\n                $faker->randomElements(\n                    $tags->lists('id')->toArray(),\n                    $faker->randomElement([1,2,3])\n                )\n            );\n        }\n\n        $this->command->info('tags table seeded');\n\n        /*\n         * Seeding attachments table\n         */\n        App\\Attachment::truncate();\n        if (! File::isDirectory(attachment_path())) {\n            File::deleteDirectory(attachment_path(), true);\n        }\n\n        $articles->each(function($article) use($faker) {\n            $article->attachments()->save(\n                factory(App\\Attachment::class)->make()\n            );\n        });\n\n        $files = App\\Attachment::lists('name');\n\n        if (! File::isDirectory(attachment_path())) {\n            File::makeDirectory(attachment_path(), 777, true);\n        }\n\n        foreach($files as $file) {\n            File::put(attachment_path($file), '');\n        }\n\n        $this->command->info('attachments table seeded');\n\n        /**\n         * Close seeding\n         */\n//        Not required for Laravel 5.2\n//        @see https://laravel.com/docs/5.2/upgrade#upgrade-5.2.0\n//        Model::reguard();\n        if (config('database.default') != 'sqlite') {\n            DB::statement('SET FOREIGN_KEY_CHECKS=1');\n        }\n    }\n}\n"
  },
  {
    "path": "gulpfile.js",
    "content": "var elixir = require('laravel-elixir');\n\nelixir(function (mix) {\n  mix.sass('app.scss', 'resources/assets/css')\n    .styles([\n      'app.css',\n      '../vendor/dropzone/dist/dropzone.css',\n      '../vendor/earthsong.css',\n    ], 'public/css/app.css');\n\n  mix.scripts([\n    '../vendor/jquery/dist/jquery.js',\n    '../vendor/bootstrap-sass/assets/javascripts/bootstrap.js',\n    '../vendor/fastclick/lib/fastclick.js',\n    '../vendor/select2/dist/js/select2.js',\n    '../vendor/dropzone/dist/dropzone.js',\n    '../vendor/tabby/jquery.textarea.js',\n    '../vendor/autosize/dist/autosize.js',\n    '../vendor/highlightjs/highlight.pack.js',\n    '../vendor/marked/lib/marked.js',\n    'app.js'\n  ], 'public/js/app.js');\n\n  mix.version([\n    'css/app.css',\n    'js/app.js'\n  ]);\n\n    /* font files are static, so doesn't need to be copied every gulp run.\n    //mix.copy(\"resources/assets/vendor/font-awesome/fonts\", \"public/build/fonts\");\n\n    /* To activate Browser Sync, uncomment and run $ gulp watch */\n    //mix.browserSync();\n});\n"
  },
  {
    "path": "lessons/01-welcome.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 0\n---\n\n# 1강 - 처음 만나는 라라벨\n\n라라벨은 php 언어로 짜여진 MVC 아키텍처를 지원하는 웹 프레임웍이다. 루비 언어에 레일즈, 파이썬 언어에 장고와 대칭되는 존재라고 보면 된다. [SitePoint의 2015년 설문조사](http://www.sitepoint.com/best-php-framework-2015-sitepoint-survey-results/)에 따르면, 라라벨은 **(국외에서)** 현재 가장 인기 있는 php 프레임웍으로 알려져 있다. 국산 CMS 중 사용자/사이트 수 측면에서 1위 CMS인 [XE](https://www.xpressengine.com/) 에서도 차기 버전인 XE3 는 라라벨로 전환한다고 발표한 바 있다. \n \n## 인기의 비결은?\n\n- 단순하고(== 쉽고) 우아한 문법\n- 복잡한 것들은 프레임웍 안에서 처리\n- 강력한 확장 기능들\n- PSR(Php Standards Recommendations) 적용\n- 모던 개발 방법론 적용\n- RAD RAD RAD (Rapid Application Development)\n\n**`참고`** 라라벨은 다른 php 프레임웍 대비 \"무겁다\", \"느리다\"고 알려져 있다. 라라벨의 철학은 \"개발 생산성\"이라는 것을 기억하자. 우리가 사는 2015년은, 개발자 인건비에 비하면 큰 메모리에 SSD로 서버 성능을 높이는 비용은 너무나도 싸다. 가령, DigitalOcean의 경우 최고 사양인 8GB메모리, 4Core, 80GB HDD의 IaaS 사용 비용이 월 $80이다. 사용자가 수 억에 달해 스케일아웃으로도 한계에 달해 정말 성능 최적화를 해야할 시점이 된다면 정말 행복한 고민일 것이다. 그때는 훌륭한 개발자들을 뽑아서 하면 된다. 페이스북을 보라~ HHVM 이란 php 엔진도 지들이 직접 만들어 쓰지 않는가? 웬만한 규모에서는 시스템엔지니어 고용 대신 AWS 쓰고, 성능을 최적화하는 마이크로 레벨의 개발보다는 개발 시간을 단축할 수 있는 도구를 사용하는 것이 훨씬 더 현명한 선택일 것이다. \n\n## 내장 기능 (Free)\n\n이 강좌를 통해 소개되는 기본적인 기능외에도 라라벨 5 에는 많은 기능이 포함되어 있다.\n\n- 웹 서비스를 위해 필요한 Cache, Queue, Mail, ...\n- [Service Container](http://laravel.com/docs/container)를 이용한 의존성 자동 주입\n- [Cron 자동화](http://laravel.com/docs/scheduling)\n- [Elixir](http://laravel.com/docs/elixir)를 이용한 CSS/Sass/Less, JS/Coffee 등 Frontend 워크플로우 자동화\n- ... \n\n## 확장 기능 (Free)\n\n- [Homestead](https://github.com/laravel/homestead) 로 개발 환경을 표준화할 수 있다.\n- [Socialite](https://github.com/laravel/socialite)로 소셜 인증을 쉽게 할 수 있다. [Socialite Provider의 목록](http://socialiteproviders.github.io/)을 확인해 보자.\n- [Cashier](https://github.com/laravel/cashier)로 결제 기능을 쉽게 달 수 있다.\n- [Envoy](https://github.com/laravel/envoy) 로 SSH 원격 작업을 자동화할 수 있다.\n- [Laravel Collective](http://laravelcollective.com/) 라라벨 구버전에 있었으나 빠진 기능들의 모음이다.\n\n## 마이크로 프레임웍 - 루멘 (Free)\n\n라라벨을 쓰는 것이 너무 오버라고 생각되는, 아주 간단한 서비스를 개발하려 할 땐,\n\n- [Lumen](http://lumen.laravel.com/)\n\n## 확장 서비스 ($)\n\n- [Forge](https://forge.laravel.com/)를 이용하여 서버 프로비저닝/서버 관리/코드 배포 등을 자동화할 수 있다. ($10/월, 서버 댓수 제한 없음)\n- [Envoyer](https://envoyer.io/)를 이용하여 무중단 코드 배포를 할 수 있다. ($10/월, 10 프로젝트)\n\n## 커뮤니티\n\n- [라라벨 뉴스](https://laravel-news.com/) - 프레임웍 코어 멤버 중의 한명인 Eric Barnes 가 운영하는 뉴스 블로그. 라라벨 개발자라면, 또는 되려면 뉴스레터에 꼭 가입하라.\n- [라라 캐스트](https://laracasts.com/) - 역시 코어 멤버 중의 한명인 Jeffrey Way가 운영하는 동영상 강의 서비스. 매주 2~3개의 강의가 올라오며, 기존에 작성된 거의 400편에 가까운 동영상 강의를 볼 수 있다 ($10/월). 라라벨 사용자가 몰려 있는 서비스로서, 포럼도 같이 운영 중이며 포럼 활동도 아주 활발하다.\n- [LARAVEL.IO](http://laravel.io/forum) - 라라 캐스트 전에 가장 활발한 활동을 하던 포럼이다.\n- [Codecourse](https://www.youtube.com/user/phpacademy) - phpacademy 란 채널이 최근이 이름이 바뀌었다. 무료 동영상 강의를 제공하고 있다.\n- 그 외에도 구글링 해보면 라라벨 관련 *영어* 자료는 넘쳐 난다. \n\n## 한국어 리소스\n\n- [한국어 매뉴얼 (번역 by XE팀)](http://xpressengine.github.io/laravel-korean-docs/)\n- [라라벨 영상 강좌 (by XE팀)](https://www.xpressengine.com/learn/23061328)\n- [한국어 책 (by 정광섭님)](https://www.lesstif.com/pages/viewpage.action?pageId=28606603)\n\n<!--@start-->\n---\n\n이제 라라벨 5 로 여행을 떠나 보자.\n\n- [목록으로 돌아가기](../readme.md)\n- [2강 - 라라벨 5 설치하기](02-hello-laravel.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/02-hello-laravel.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 1\n---\n\n# 2강 - 라라벨 5 설치하기 (on Mac)\n\n## 윈도우즈 사용자라면\n\n[여기를 참고](02-install-on-windows.md)하자. 장기적으로 보고 Mac 이나 Linux 로 전환할 것을 권장한다. 윈도우즈는 코맨드 프롬프트(콘솔)에서 명령어 사용이 불편해서 생산성이 떨어진다.\n\n## 터미널에 익숙해 지자.\n\n기본 내장 터미널 (=='콘솔') 소프트웨어를 사용하지 말고, [iTerm2](https://www.iterm2.com/)(Free) 와 [Oh My Zshell](https://github.com/robbyrussell/oh-my-zsh)(Free) 을 쓸 것을 권장한다. iTerm2 는 Mac 내장 콘솔의 대체 앱이며, Oh My Zshell 은 콘솔의 기능을 더 편리하게 해 주는 플러그인이라 생각하면 된다.\n\n```bash\n$ sh -c \"$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)\"\n```\n\nMac 용 패키지 매니저인 [Homebrew](http://brew.sh/)(Free) 도 반드시 설치해 놓자! `Homebrew` 는 Mac 용 `apt-get` 이라 이해하면 된다.\n \n ```bash\n $ ruby --version # ruby 2.x\n $ ruby -e \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\"\n ```\n\n## 개발 환경 셋업\n\n### [이 코스에서 사용] 로컬 개발 환경\n\nMac 사용자라면 2가지 옵션이 있다. 로컬 Mac 을 개발 머신으로 쓰거나, 다음 절에 설명하는 Homestead 를 쓰는 방법이다. \n\n이 코스에서는 **로컬 Mac을 개발환경으로 쓰는 것을 가정하고 설명**한다. 로컬 Mac에 php, mySql 이 설치되어 있지 않다면 Homebrew 를 이용해 설치하자.\n\n```bash\n$ brew search php56 # Homebrew 설정에 따라 php56 또는 homebrew/php/php56이 출력될 것이다.\n$ brew install homebrew/php/php56\n$ brew search mysql5 # 역시 Homebrew 설정에 결과는 다를 수 있다. 가장 높은 버전을 설치하자.\n$ brew install homebrew/versions/mysql55\n$ /usr/local/bin/mysql.server start\n```\n\n터미널을 반드시 한번 껐다가 켜자. 설치되는 동안 사용자의 콘솔 프로파일에 경로를 업데이트했을텐데, 그 경로를 다시 로드하기 위해서다.\n\n```bash\n$ php --version # 5.6.xx\n$ mysql --version # 5.5.xx\n```\n\n**`참고`** Mac 부트시 자동으로 mySql 서버를 기동시키려면, mySql 설치 코맨드가 끝난 후 출력된 내용을 유심히 살펴보기 바란다. `mv /usr/local/opt/mysql/homebrew.mxcl.mysql.plist ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist`와 같은 명령이 있을텐데, 환경마다 다를 수 있을니 필자가 쓴 코맨드가 아니라, 실제 콘솔에 있는 코맨드를 복사해서 콘솔에 붙여 넣고 실행한다.\n\n### **[OPTIONAL]** 공짜로 쓰는 개발 서버 \"Homestead\"\n\n개발팀 구성원들이 동일한 개발 환경을 가지기 위해서, 또는 Production 과 유사한 환경에서 개발하기 위해서 Homestead 사용을 권장한다. Homestead 는 위에서 언급한 필요 확장 모듈이 기본 설치되어 있다.\n\n설정법은 꽤나 까다로우니 [Homestead 설치 (on Mac)](02-install-homestead-osx.md) 를 참고하자.\n\n## 라라벨이 동작하기 위한 PHP 버전 및 필요 모듈 조건 확인\n\n라라벨을 설치하려는 개발환경 또는 서버가 아래 필요사항을 충족하는 지 확인한다.\n- php 5.5.9 이상\n- php Extensions\n    - OpenSSL\n    - PDO\n    - Mbstring\n    - Tokenizer\n    \n```bash\n$ php --version # PHP 5.6.xx\n$ php -m | grep 'openssl\\|pdo\\|mbstring\\|tokenizer'\n```\n\nHomebrew 를 통해 설치했다면 기본적으로 모든 모듈이 설치되어 있을 것이다. 하나라도 빠진게 있다면 구글링해서 설치하자~\n\n## 이제 라라벨을 설치해 보자.\n\n라라벨 인스톨러를 사용할 것을 권장한다. 왜냐하면 Composer 를 이용해 설치하는 것 보다 훨~씬 빠르니까...\n\n먼저, Composer 가 필요하다. 왜냐하면, 라라벨 인스톨러가 Composer 를 통해 배포되기 때문이다.\n\n```bash\n$ curl -sS https://getcomposer.org/installer | php\n$ mv composer.phar /usr/local/bin/composer\n$ composer --version # Composer version 1.xx\n```\n\n이제 Composer 를 이용해서 라라벨 인스톨러를 설치한다.\n\n```bash\n$ composer global require \"laravel/installer=~1.1\"\n```\n\n끝이 아니다. `laravel`과 `homestead` 코맨드를 어디서든 접근할 수 있게 경로 설정하자.\n\n```bash\n# 터미널에 익숙치 않은 분이 많아 자세히 쓴다.\n\n# 자신이 사용하는 콘솔에 따라 프로파일 이름이 다를 수 있다. ~/.profile, ~/.bash_profile, ~/.zshrc, ...\n# On My Zshell을 설치했다면 ~/.zshrc 이다.\n$ nano ~/.zshrc\n\n# 아래와 같이 써진 줄을 찾아 맨 끝에 :$HOME/.composer/vendor/bin 을 추가하자.\nexport PATH=\"$PATH:$HOME/.composer/vendor/bin\"\n\n# 쇠뿔도 단김에 앞으로 자주 쓰게 될 artisan 코맨드의 별명을 등록해 놓자.\n# 앞으로 자주 쓰게될 php artisan 대신 artisan 만 치면 된다.\n# 열린 파일 맨 끝에 써 넣는다.\nalias artisan=\"php artisan\"\n\n# ctrl + x  -> Y -> enter 순으로 눌러 수정 내용을 저장한다.\n# 수정된 내용이 반영될 수 있도록 콘솔을 다시 시작하거나, 아래 코맨드를 실행한다.\n$ source ~/.zshrc\n\n# laravel 코맨드의 경로가 잘 설정되었는지 확인해 보자.\n$ laravel --version # Laravel Installer version 1.x\n```\n\n휴~, 이제 설치를 위한 준비가 완료되었다. 라라벨 인스톨러로 라라벨 5를 설치하자.\n\n```bash\n$ laravel new myProject\n$ cd myProject\n$ php artisan --version # Laravel Framework version 5.x\n$ chmod -R 777 storage bootstrap/cache\n```\n\n서버를 부트업하고, 라라벨을 시작해 보자!\n\n```bash\n# 로컬 서버를 부트한다.\n$ php artisan serve # 종료하려면 ctrl+c\n# Laravel development server started on http://localhost:8000/\n```\n\n브라우저에서 `http://localhost:8000` 페이지를 방문해서 'Laravel 5' 란 글씨가 써진 화면이 보인다면, 성공적으로 설치한 것이다.\n\n![](./images/02-hello-laravel-img-02.png)\n\n**`참고`** `artisan` 은 라라벨의 코맨드 라인 툴이다. `$ php artisan` 을 실행한 후, 설명을 쭈욱~ 한번 살펴보자. 개발 중에 코드에디터와 콘솔을 오가면서, `artisan` 코맨드를 많이 사용하게 될 것이다.\n\n## 라라벨의 폴더 구조를 살펴 보자.\n\n처음 설치하면 딱 아래와 같은 형태이다. 지금은 눈에 안들어 오니, 그냥 휘~익 훑어 보자. 코스를 진행하다 보면 저절로 익히게 된다.\n\n```\n.\n├── .env                              # 글로벌 설정 중 민감한 값, dev/production 등 앱 실행환경에 따라 변경되어야 하는 값을 써 놓는 곳\n├── app\n│   ├── Console                       \n│   │   ├── Commands                  # 콘솔 코맨드 하우징\n│   │   └── Kernel.php                # 콘솔 코맨드, 크론 스케쥴 등록\n│   ├── Events                        # 이벤트 클래스 하우징\n│   ├── Exceptions                    # Exception 하우징\n│   │   └── Handler.php               # 글로벌 Exception 처리 코드\n│   ├── Listeners                     # 이벤트 핸들러\n│   ├── Jobs\n│   ├── Policies\n│   ├── Http                          # Http 요청 처리 클래스들의 하우징\n│   │   ├── Controllers               # Http Controller\n│   │   ├── Kernel.php                # Http 및 Route 미들웨어 등록\n│   │   ├── Middleware                # Http 미들웨어 하우징\n│   │   ├── Requests                  # Http 폼 요청 미들웨어 하우징\n│   │   └── routes.php                # Http 요청 Url을 Controller에 맵핑시키는 규칙을 써 놓은 테이블\n│   └── Providers                     # 서비스 공급자 하우징 (config/app.php에서 바인딩 됨)\n│       ├── AppServiceProvider.php\n│       ├── AuthServiceProvider.php\n│       ├── EventServiceProvider.php  # 이벤트 리스너, 구독 바인딩\n│       └── RouteServiceProvider.php  # 라우팅 바인딩 (글로벌 라우팅 파라미터 패턴 등이 등록되어 있음)\n├── composer.json                     # 이 프로젝트의 Composer 레지스트리, Autoload 규칙 등이 담겨 있다. (c.f. Node의 package.json)\n├── config                            # database, queue, mail 등 글로벌 설정 하우징\n├── database\n│   ├── migrations                    # 데이터베이스 스키마\n│   └── seeds                         # 생성된 테이블에 Dummy 데이터를 삽입하는 클래스들 (개발 목적)\n├── gulpfile.js                       # Elixir (프론트엔드 빌드 자동화) 스크립트\n├── public                            # 웹 서버에 의해 지정된 Document Root\n├── resources\n│   ├── assets                        # JavaScript, CSS 하우징\n│   ├── lang                          # 다국어 지원을 위한 언어 레지스트리 하우징\n│   └── views                         # 뷰 파일 하우징\n├── storage                           # Laravel5 파일 저장소\n└── vendor                            # composer.json의 저장소\n```\n\n## 라라벨의 프로젝트 구조\n\n아래 그림을 보자. 방금 설치한 상태가 그림 왼쪽에 빨간색으로 표시된 Laravel (`laravel/laravel`) 과 Framework (`laravel/framework`) 가 설치된 상태이다. 별도로 분리해 놓은 이유는 Framework 요소가 Laravel 이 아닌, 가령 [Lumen](http://lumen.laravel.com/) 처럼 다른 프로젝트에서도 사용할 수 있도록 하기 위해서이다.\n \n라라벨이 제공하는 문법과 API 들을 이용해서 User Code (`appkr/l5essential`) 라고 표시된, 우리만의 서비스를 만들게 된다. 이 과정에서 라라벨에서 제공하는 기본 기능외에 외부의 패키지들, User-pulled 3rd Party Packages 라 표시된 부분들도 가져와서 사용하게 된다.  \n\n![](./images/02-hello-laravel-img-03.png)\n\n## 라라벨의 동작 시퀀스\n\n역시 마찬가지다. 지금은 몰라도 된다. 나중에 한번 돌아와서 다시 보게 된다면, 아~ 하고 이해될 것이다.\n\n![](./images/02-hello-laravel-img-01.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [1강 - 처음 만나는 라라벨](01-welcome.md)\n- [3강 - 글로벌 설정 살펴보기](03-configuration.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/02-install-homestead-osx.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 57\n---\n\n# Homestead 설치 (on Mac)\n\n## 사전 요구 사항\n\n[VirtualBox](https://www.virtualbox.org/wiki/Downloads) 와 [Vagrant](http://www.vagrantup.com/downloads.html) 설치가 필요하다. 인스톨러 화면에서 \"Next\" 만 계속 눌러서 쉽게 설치할 수 있다.\n \n## Vagrant Box 설치\n\n라라벨 커뮤니티에서 미리 준비해서 [Vagrant Box Registry](https://atlas.hashicorp.com/boxes/search) 에 배포해 놓은 `laravel/homestead` Vagrant Box (==Virtual Machine Image) 를 다운로드 하는 과정이다. 이 강좌를 쓰는 시점에 `laravel/homestead` Vagrant Box 의 최신 버전은 PHP7 이 기본 포함되어 있는 0.4.0 이다. 여기서는 PHP5 버전을 쓸 것이므로, `--box-version 0.3.3` 옵션을 추가해 주었다.\n\n```bash\n$ vagrant box add laravel/homestead --box-version 0.3.3\n\n# 설치에 실패했다면, 기존 다운로드 찌거기를 지우고 다시 다운로드 받기 위해 --clean 옵션 스위치를 붙여야 한다.\n# 기존에 설치한 laravel/homestead Box 을 덮어쓰고 강제로 다시 설치하려면 --force 옵션 스위치를 붙인다.\n```\n\n설치 과정에 아래 처럼 Virtual Machine Provider 를 선택하는 화면이 나온다. `2) vmware` 는 [Vagrant 용 Plugin](http://www.vagrantup.com/vmware) 을 별도로 사서 설치해야 한다는 점을 알고 있자. 이 강좌를 쓰는 현재 Vmware Vagrant Plugin 의 가격은 $79 이다. 무료로 쓸 수 있는 `1) virtualbox` 를 선택했다. OS 에 따라 수 GB 용량을 다운로드 받아야 하므로 꽤 오랜 시간이 걸린다.\n\n```bash\nThis box can work with multiple providers! The providers that it\ncan work with are listed below. Please review the list and choose\nthe provider you will be working with.\n\n1) virtualbox\n2) vmware_desktop\n\nEnter your choice: 1\n```\n\n## Homestead CLI 설치\n\n[Homestead CLI](https://github.com/laravel/homestead) 는 `vagrant` CLI 의 Wrapper 이다. `vagrant` 대신 `homestead` 코맨드를 이용할 수 있다.  \n\n```bash\n$ composer global require \"laravel/homestead:2.*\"\n```\n\n`homestead` CLI 는 '~/.composer' 디렉토리에 설치된다. 경로 지정없이 `homestead` 명령을 사용하려면, 아래 처럼 경로를 추가해 주어야 한다.\n\n```bash\n# 사용하는 Shell 에 따라 Profile 파일 이름은 다를 수 있다. \n# 필자는 Zshell 을 쓰므로, .zshrc 이다. e.g. .profile, .bashrc\n$ nano ~/.zshrc\n\n# composer global 로 설치한 패키지들의 실행파일을 경로에 넣어 준다.\n# 이 과정이 없다면 $ ~/.composer/vendor/bin/homestead 와 같이 전체 경로를 써주어야 한다.\nexport PATH=\"$PATH:$HOME/.composer/vendor/bin\"\n\n# 수정했다면 ctrl + X, \"Y\" 를 눌러 변경 내용을 저장하고, 엔터를 한번 더 눌러 기존 파일을 덮어 쓴다. \n\n# 그리고, 수정 내용을 현재 콘솔에 적용해 준다. 콘솔을 껐다가 다시 실행해도 된다.\n$ source ~/.zshrc\n```\n\n최신 버전이 `3.*` 이지만, 필자는 굳이 구 버전인 `2.*` 를 설치했다. 새 버전은 `laravel/homestead` Vagrant Box v0.4.0 과 궁합이 맞도록 구현 되어 있을 뿐만아니라, 아래에 나온 편리한 코맨드들도 모두 제거되었기 때문이다.\n\n```bash\n$ homestead\n  Laravel Homestead version 2.1.8\n  \n  Usage:\n    command [options] [arguments]\n  \n  Options:\n    # ...\n  \n  Available commands:\n    destroy     Destroy the Homestead machine\n    edit        Edit a Homestead file\n    halt        Halt the Homestead machine\n    help        Displays help for a command\n    init        Create a stub Homestead.yaml file\n    list        Lists commands\n    make        Install Homestead into the current project\n    provision   Re-provisions the Homestead machine\n    resume      Resume the suspended Homestead machine\n    run         Run commands through the Homestead machine via SSH\n    ssh         Login to the Homestead machine via SSH\n    ssh-config  Outputs OpenSSH valid configuration to connect to Homestead\n    status      Get the status of the Homestead machine\n    suspend     Suspend the Homestead machine\n    up          Start the Homestead machine\n    update      Update the Homestead machine image\n```\n\n`make` 란 명령은 꽤 최근에 추가된 것인데, 각 프로젝트마다 별도의 Homestead 설정을 만들 수 있는 명령이다. Docker 의 Container 개념과 유사하다고 볼 수 있다. 복수의 프로젝트를 개발 중이고, 프로젝트간에 서버 환경이 굉장히 많이 다르다면, 사용하면 좋을 것 같다.\n\n## Homestead 설정\n\n`laravel/homestead` Vagrant VM 을 올바르게 셋팅하기 위한 설정 파일은 '~/.homestead' 디렉토리에 위치해야 한다. 아래 명령으로 이 설정 파일을 초기화하자.\n\n```bash\n$ homestead init\n```\n\nHomestead 설정을 우리 프로젝트에 맞게 수정하자.\n\n```bash\n$ homestead edit\n\n# 로컬에 Sublime Text 가 설치되어 있지 않다면..\n# ~/.homestead/Homestead.yaml 을 편집기로 직접 열면 된다.\n```\n\n```bash\n# ~/.homestead/Homestead.yaml\n\nip: \"192.168.10.10\" # homestead VM 이 사용할 ip 주소\nmemory: 2048\ncpus: 1\nprovider: virtualbox # Virtual Machine Provider\n\n# SSH 로그인에 사용할 public key. 이 키 값은 homestead VM 의 \n# /home/vagrant/.ssh/authorized_keys 에 자동으로 추가된다.\nauthorize: ~/.ssh/id_rsa.pub \n\nkeys:\n    - ~/.ssh/id_rsa # SSH 로그인에 사용할 private key\n\n# 로컬과 VM 간에 공유할 폴더를 설정한다.\n# 이 강좌용 라라벨은 ~/workspace/myProject 에 위치한다고 가정한다.\nfolders:\n    - map: ~/workspace # 로컬 디렉토리 경로\n      to: /home/vagrant/Code # VM 의 디렉토리 경로\n\n# 도메인 이름 (hostname) 과 VM 에 설치된 웹 서버의 Document Root 를 설정한다.\nsites:\n    - map: myproject.dev # 도메인 이름\n      to: /home/vagrant/Code/myProject/public # 웹 서버의 Document Root\n    # 사이트를 추가하려면.. 아래 처럼 추가 사이트를 정의한 다음\n    # VM 콘솔에서 $ homestead provision 명령을 실행한다.\n    - map: example.dev\n      to: /home/vagrant/Code/example/public\n\n# 서버 프로비저닝 과정에서 아래에 정의한 DB 를 만들어 준다.\ndatabases:\n    - myProject\n```\n\n## Host 파일 설정\n\nHomestead 설정에서 myproject.dev 란 도메인을 이용했다. 이런 도메인은 존재하지 않는다. 운영체제의 Host 파일을 수정할 것이다. 운영체제에 포함된 'hosts' 파일은 DNS 로 myproject.dev 에 대한 ip 주소 Resolution 요청이 나가기 전에 요청을 낚아 채서, 'hosts' 파일 안에서 찾는다. 사용자가 요청한 도메인에 해당하는 레코드가 있으면 지정된 ip 주소로 이동할 것이다.\n\n```bash\n$ sudo nano /etc/hosts\n```\n\n```bash\n# /etc/hosts\n\n192.168.10.10    myproject.dev\n```\n\n## Homestead 실행\n\n실행해 보자. 처음 실행할 때는 시간이 좀 걸리는데, 이유는 앞에서 Homestead.yaml 에 설정한, ip 주소, public key 복사, 공유 폴더 설정 등을 하기 때문이다.\n\n```bash\n$ homestead up\n\n# homestead VM 을 중지시킬 때는 $ homestead halt\n# 완전히 끌 때는 $ homestead suspend\n```\n\nVM 에 로그인하고 Homestead.yaml 설정이 잘 먹었나 확인해 보자.\n\n```bash\n$ homestead ssh\n# Welcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.19.0-25-generic x86_64)\n\nvagrant@homestead:~$ ls ~/Code\n# ... myProject ...\n\nvagrant@homestead:~$ ifconfig | grep 192.168.10.10\n# inet addr:192.168.10.10  Bcast:192.168.10.255  Mask:255.255.255.0\n\nvagrant@homestead:~$ cat ~/.ssh/authorized_keys\n# ssh-rsa AAAAB3NzaC1...D3XDfv juwonkim@me.com\n```\n\n**`참고`** ssh 를 이용해 직접 접속하려면 `$ ssh vagrant@myproject.dev -D 2222`. \n\n## 데이터베이스 접속\n\nHost `127.0.0.1`, Port `33060`, Username `homestead`, Password `secret` 로 접속한다. PostgresSQL 의 경우 Port `54320` 으로 접속한다.\n\n![](./images/02-install-homestead-osx-img-01.png)\n\n## 웹 서버 접속\n\nHomestead 에는 Nginx 가 기본으로 탑재되어 있고, Homestead.yaml 의 sites 섹션에서 설정한대로 이미 서비스가 돌고 있는 상태이다.\n\n브라우저에서 'http://myproject.dev' 로 접속해 보자. 테스트용으로 쓸 수 있는 self-signed 인증서가 설치되어 있기 때문에 'https://myproject.dev' 도 사용할 수 있다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/02-install-homestead-windows.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 58\n---\n\n# Homestead 설치 (on Windows)\n\n## 사전 요구 사항\n\n[VirtualBox](https://www.virtualbox.org/wiki/Downloads) 와 [Vagrant](http://www.vagrantup.com/downloads.html) 설치가 필요하다. 인스톨러 화면에서 \"Next\" 만 계속 눌러서 쉽게 설치할 수 있다.\n\n## Vagrant Box 설치\n\n라라벨 커뮤니티에서 미리 준비해서 [Vagrant Box Registry](https://atlas.hashicorp.com/boxes/search) 에 배포해 놓은 `laravel/homestead` Vagrant Box (==Virtual Machine Image) 를 다운로드 하는 과정이다. 이 강좌를 쓰는 시점에 `laravel/homestead` Vagrant Box 의 최신 버전은 PHP7 이 기본 포함되어 있는 0.4.0 이다.\n\n```bash\n$ vagrant box add laravel/homestead\n\n# 설치에 실패했다면, 기존 다운로드 찌거기를 지우고 다시 다운로드 받기 위해 --clean 옵션 스위치를 붙여야 한다.\n# 기존에 설치한 laravel/homestead Box 을 덮어쓰고 강제로 다시 설치하려면 --force 옵션 스위치를 붙인다.\n```\n\n설치 과정에 아래 처럼 Virtual Machine Provider 를 선택하는 화면이 나온다. `2) vmware` 는 [Vagrant 용 Plugin](http://www.vagrantup.com/vmware) 을 별도로 사서 설치해야 한다는 점을 알고 있자. 이 강좌를 쓰는 현재 Vmware Vagrant Plugin 의 가격은 $79 이다. 무료로 쓸 수 있는 `1) virtualbox` 를 선택했다. OS 에 따라 수 GB 용량을 다운로드 받아야 하므로 꽤 오랜 시간이 걸린다.\n\n```bash\nThis box can work with multiple providers! The providers that it\ncan work with are listed below. Please review the list and choose\nthe provider you will be working with.\n\n1) virtualbox\n2) vmware_desktop\n\nEnter your choice: 1\n```\n\n## Homestead 프로젝트 설치\n\n`git` 명령을 쓸 수 없는 경우, [https://github.com/laravel/homestead](https://github.com/laravel/homestead) 를 방문해서 zip 파일을 다운로드 한 후, 적절한 위치에 압축을 해제한다.\n\n```bash\n# Git Bash\n$ cd ~ && git clone https://github.com/laravel/homestead.git Homestead\n```\n\n## Homestead 설정\n\n`laravel/homestead` Vagrant VM 을 올바르게 셋팅하기 위한 설정 파일은 '~/.homestead' 디렉토리에 위치해야 한다. 아래 명령으로 이 설정 파일을 초기화하자.\n\n```bash\n# Git Bash\n$ cd ~/Homestead && bash init.sh\n\n# Windows Command Prompt\n\\> cd %HOMEPATH%\\Homestead\n\\> init\n```\n\nHomestead 설정을 우리 프로젝트에 맞게 수정하자. 코드 에디터 또는 텍스트 편집기로 %HOMEPATH%\\.homestead\\Homestead.yaml 파일을 연다.\n\n```bash\n# /c/Users/{username}/.homestead/Homestead.yaml\n# Or %HOMEPATH%\\.homestead\\Homestead.yaml\n\nip: \"192.168.10.10\" # homestead VM 이 사용할 ip 주소\nmemory: 2048\ncpus: 1\nprovider: virtualbox # Virtual Machine Provider\n\n# SSH 로그인에 사용할 public key. 이 키 값은 homestead VM 의\n# /home/vagrant/.ssh/authorized_keys 에 자동으로 추가된다.\nauthorize: ~/.ssh/id_rsa.pub\n\nkeys:\n    - ~/.ssh/id_rsa # SSH 로그인에 사용할 private key\n\n# 로컬과 VM 간에 공유할 폴더를 설정한다.\n# 이 강좌용 라라벨은 ~/myProject 에 위치한다고 가정한다.\nfolders:\n    - map: ~/myProject # 로컬 디렉토리 경로\n      to: /home/vagrant/myProject # VM 의 디렉토리 경로\n\n# 도메인 이름 (hostname) 과 VM 에 설치된 웹 서버의 Document Root 를 설정한다.\nsites:\n    - map: myproject.dev # 도메인 이름\n      to: /home/vagrant/myProject/public # 웹 서버의 Document Root\n    # 사이트를 추가하려면.. 아래 처럼 추가 사이트를 정의한 다음\n    # VM 콘솔에서 $ vagrant provision 명령을 실행한다.\n    - map: example.dev\n      to: /home/vagrant/example/public\n```\n\n## Host 파일 설정\n\nHomestead 설정에서 myproject.dev 란 도메인을 이용했다. 이런 도메인은 존재하지 않는다. 운영체제의 Host 파일을 수정할 것이다. 운영체제에 포함된 'hosts' 파일은 DNS 로 myproject.dev 에 대한 ip 주소 Resolution 요청이 나가기 전에 요청을 낚아 채서, 'hosts' 파일 안에서 찾는다. 사용자가 요청한 도메인에 해당하는 레코드가 있으면 지정된 ip 주소로 이동할 것이다.\n\n텍스트 편집기나 코드 에디터로 `%WINDIR%\\System32\\drivers\\etc\\hosts` 파일을 열어 아래 레코드를 추가한다.\n\n```bash\n# %WINDIR%\\System32\\drivers\\etc\\hosts\n\n192.168.10.10    myproject.dev\n```\n\n![](./images/02-install-homestead-windows-img-01.png)\n\n## SSH Key 생성\n\nHomestead 설정에서 `authorize: ~/.ssh/id_rsa.pub` 와 `~/.ssh/id_rsa` 를 설정했는데, 해당 파일은 존재하지 않는다. Git Bash 를 쓸 수 없다면, [PuTTYgen](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html) 을 설치하고 private, public key pair 를 만들자.\n\n```bash\n# Git Bash\n\n$ mkdir ~/.ssh\n$ ssh-keygen -t rsa\n# Enter file in which to save the key (/c/Users/suchc/.ssh/id_rsa): <Enter>\n# Enter passphrase (empty for no passphrase): <Enter>\n# Enter same passphrase again: <Enter>\n```\n\n## Homestead 실행\n\n실행해 보자. 처음 실행할 때는 시간이 좀 걸리는데, 이유는 앞에서 Homestead.yaml 에 설정한, ip 주소, public key 복사, 공유 폴더 설정 등을 하기 때문이다. 처음 실행할 때는 방화벽 관련 보안 경고가 뜰 수 있는 데 \"허용\" 해 주자.\n\n```bash\n# Git Bash\n$ cd ~/Homestead && vagrant up\n\n# homestead VM 을 중지시킬 때는 $ vagrant halt\n# 완전히 끌 때는 $ vagrant suspend\n\n# Windows Command Prompt\n\\> cd %HOMEPATH%\\Homestead\n\\> vagrant up\n```\n\nVM 에 로그인하고 Homestead.yaml 설정이 잘 먹었나 확인해 보자. 코맨드 프롬프트에서는 SSH Client 가 없어서 안되는 작업이니, 반드시 Git Bash 를 이용해야 한다.\n\n```bash\n# Git Bash only\n\n$ vagrant ssh\n# Welcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.19.0-25-generic x86_64)\n\nvagrant@homestead:~$ ls ~/myProject\n# app ... bootstrap ...\n\nvagrant@homestead:~$ ifconfig | grep 192.168.10.10\n# inet addr:192.168.10.10  Bcast:192.168.10.255  Mask:255.255.255.0\n\nvagrant@homestead:~$ cat ~/.ssh/authorized_keys\n# ssh-rsa AAAAB3NzaC1...TpJ5HH suchc@homepc\n```\n\n**`참고`** ssh 를 이용해 직접 접속하려면 `$ ssh vagrant@myproject.dev -D 2222`.\n\n## 데이터베이스 접속\n\nHost `127.0.0.1`, Port `33060`, Username `homestead`, Password `secret` 로 접속한다. PostgresSQL 의 경우 Port `54320` 으로 접속한다. 필자는 [SQLyog](https://code.google.com/p/sqlyog/wiki/Downloads) 클라이언트를 이용하였다.\n\n![](./images/02-install-homestead-windows-img-02.png)\n\n## 웹 서버 접속\n\nHomestead 에는 Nginx 가 기본으로 탑재되어 있고, Homestead.yaml 의 sites 섹션에서 설정한대로 이미 서비스가 돌고 있는 상태이다.\n\n브라우저에서 'http://myproject.dev' 로 접속해 보자. 테스트용으로 쓸 수 있는 self-signed 인증서가 설치되어 있기 때문에 'https:://myproject.dev' 도 사용할 수 있다.\n\n![](./images/02-install-homestead-windows-img-03.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/02-install-on-windows.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 2\n---\n\n# 2강 - 라라벨 5 설치하기 (on Windows)\n\nWindows 사용자라면 Mac 으로 전환할 것을 권장한다. 필자는 10년도 훨씬 전에 Windows Server 2000 트랙에서 [MCSE](https://www.microsoft.com/en-us/learning/mcse-certification.aspx) 였었다. 무려 6 주에 걸쳐 매주 한 과목씩 총 6 과목을 시험을 봐야 했었다. 예전엔 Windows 밖엔 쓸 줄 몰랐단 얘기다. \n\n어쨌든 시간이 지나면서 여러 OS 를 경험하고 난 후 필자가 느낀 바는 Windows 는 개인용 PC 운영체제로 나쁘지 않다는 점이다. 서버 운영체제로 쓸 때도 나쁘지 않다. 헌데 **개발자 용으로 쓸 때 Windows 는 Mac 대비 생산성 측면에서 아주아주아주 별로다**. 특히, 콘솔. 아래 그림은 캘리포니아의 어느 개발자 컨퍼런스 모습인데.. 아마 Windows 가 대세인 한국에서 다양한 개발 생산성 도구들을 개발했다면 아래 그림은 완전 역전되었을 지도 모르겠다. \n\n![](http://i2.wp.com/www.dailycal.org/assets/uploads/2013/11/look-at-them-apples.jpg)\n\n## 개발 환경 셋업\n\n시작하기 전에.. 사용자 계정이 한글이거나, 영문이더라도 사용자 계정에 공백이 있다면 반드시 새로운 사용자 계정을 만들고 아래 과정을 수행하시기 바란다.\n\n> 홍길동 (x), user name (x), username (o)\n\n### [이 코스에서 사용] 로컬 개발 환경\n\nWindows 사용자에게도 2가지 옵션이 있다. 로컬 PC를 개발 머신으로 쓰거나, 다음 절에 설명하는 Homestead 를 쓰는 방법이다. \n\n이 코스에서는 **로컬 PC를 개발환경으로 쓰는 것을 가정하고 설명**한다. 로컬 PC에 PHP, Mysql 이 설치되어 있지 않다면 [Bitnami Wamp](https://bitnami.com/stack/wamp) 를 이용해 설치하자. \n\nBitnami 를 이용해 설치한 PHP 실행기가 OS 환경변수에 등록되어 있지 않으므로 등록해 주어야 한다. 제어판 -> 시스템 -> 고급 -> 시스템 변수 또는 환경 변수에서 Path 부분을 찾은 다음, PHP 실행기의 경로를 등록한다. 필자의 경우 `C:\\Bitnami\\wampstack-5.5.30-0\\php` 을 등록하였다. 열려 있던 코맨드 프롬프트 창이 있다면, 재 실행 해 주어야 방금 변경한 환경설정의 적용된다는 것을 꼭 기억하자.\n\n![](./images/02-install-on-windows-img-01.png)\n\n![](./images/02-install-on-windows-img-02.png)\n\n그리고, 코맨드 프롬프트 대체 프로그램인 [Git Bash](https://git-for-windows.github.io/) 를 설치하자. \n\n## **[OPTIONAL]** 공짜로 쓰는 개발 서버 \"Homestead\"\n\n개발팀 구성원들이 동일한 개발 환경을 가지기 위해서, 또는 Production 과 유사한 환경에서 개발하기 위해서 Homestead 사용을 권장한다. Homestead 는 위에서 언급한 필요 확장 모듈이 기본 설치되어 있다.\n\n설정법은 꽤나 까다로우니 [Homestead 설치 (on Windows)](02-install-homestead-windows.md) 를 참고하자.\n\n## 라라벨이 동작하기 위한 PHP 버전 및 필요 모듈 조건 확인\n\n라라벨을 설치하려는 개발환경 또는 서버가 아래 필요사항을 충족하는 지 확인한다.\n- php 5.5.9 이상\n- php Extensions\n    - OpenSSL\n    - PDO\n    - Mbstring\n    - Tokenizer\n\n```bash\n# Git Bash\n$ php --version # PHP 5.5.30\n$ php -m # Git Bash 에서는 파이프 (`|`) 연산자가 먹지 않아 `grep` 명령을 쓸 수 없다.\n\n# Windows Command Prompt\n\\> php --version # PHP 5.5.30\n\\> php -m | findstr openssl\n\\> php -m | findstr pdo\n\\> php -m | findstr mbstring\n\\> php -m | findstr tokenizer\n```\n\nBitnami Wamp 를 설치했다면 모두 설치되어 있을 것이다. 이미 PHP, Mysql 이 설치되어 있었던 경우에, 필요한 모듈 중 하나라도 빠진게 있다면 구글링해서 설치하자~\n\n![](./images/02-install-on-windows-img-04.png)\n\n## 이제 라라벨을 설치해 보자.\n\n라라벨 인스톨러를 사용할 것을 권장한다. 왜냐하면 Composer 를 이용해 설치하는 것 보다 훨~씬 빠르니까...\n\n먼저, Composer 가 필요하다. 왜냐하면, 라라벨 인스톨러가 Composer 를 통해 배포되기 때문이다. [윈도우즈용 Composer 인스톨러](https://getcomposer.org/Composer-Setup.exe)를 다운로드 받아 설치하자. 설치 중에 PHP 경로를 물어본다면, 앞 절에서 설정한 경로로 찾아 들어가서 PHP 실행기를 선택해 준다. \n\n```bash\n\\> composer --version # Composer version 1.xx\n```\n\n![](./images/02-install-on-windows-img-05.png)\n\n이제 Composer 를 이용해서 라라벨 인스톨러를 설치한다.\n\n```bash\n\\> composer global require \"laravel/installer\"\n```\n\n`laravel` 코맨드를 어디서든 접근할 수 있게 Path 환경변수를 설정하자. 필자의 경우 `C:\\Users\\{username}\\AppData\\{Local|Roaming}\\Composer\\vendor\\bin` 을 등록하였다. 환경 변수가 변경되었으면, 열려 있던 콘솔 창을 재 실행해 주어야 한다.\n\n```bash\n\\> laravel --version # Laravel Installer version 1.2.1\n```\n\n휴~, 이제 설치를 위한 준비가 완료되었다. 라라벨 인스톨러로 라라벨 5를 설치하자.\n\n```bash\n\\> laravel new myProject\n\\> cd myProject\n\\> php artisan --version # Laravel Framework version 5.x\n```\n\n![](./images/02-install-on-windows-img-06.png)\n\n서버를 부트업하고, 라라벨을 시작해 보자!\n\n```bash\n# 로컬 서버를 부트한다.\n\\> php artisan serve # 종료하기 ctrl+c\n# Laravel development server started on http://localhost:8000/\n```\n\n브라우저에서 `http://localhost:8000` 페이지를 방문해서 'Laravel 5' 란 글씨가 써진 화면이 보인다면, 성공적으로 설치한 것이다.\n\n![](./images/02-install-on-windows-img-07.png)\n\n**`참고`** `artisan` 은 라라벨의 코맨드 라인 툴이다. `\\> php artisan` 을 실행한 후, 설명을 쭈욱~ 한번 살펴보자. 개발 중에 코드 에디터와 콘솔을 오가면서, `artisan` 코맨드를 많이 사용하게 될 것이다.\n\n프로젝트의 디렉토리 구조와 라라벨의 동작 시퀀스 다이어그램은 Mac 용 설치 문서 \"[2강 - 라라벨 5 설치하기](02-hello-laravel.md)\"를 참조하자.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [1강 - 처음 만나는 라라벨](01-welcome.md)\n- [3강 - 글로벌 설정 살펴보기](03-configuration.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/03-configuration.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 3\n---\n\n# 3강 - 글로벌 설정 살펴보기\n\n## Code Editor 와 DB Client\n\n- [phpStorm](https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program)(1달 Free)을 권장한다. \n- [Sequel Pro](http://www.sequelpro.com/download)(Free)를 권장한다. \n\n설치하자.\n\n## .env\n\n.env에 써진 값들을 config/\\*\\*.php 에서 `env(string $key)`로 읽을 수 있다. 왜 config/\\*\\*.php, 가령 database.php 에 직접 하드코드로 쓰지 않을까? 이유는...\n- local, staging, production 등 어플리케이션 실행 환경에 따라 설정 값이 바뀌어야 할 때 유연하게 대응하기 위해서다.\n- 패스워드 등 민감한 정보를 버전 컨트롤에서 제외하기 위해서다. (.gitignore 파일을 확인해 보자.)\n\n```\nAPP_ENV=local           # 실행환경\nAPP_DEBUG=true          # 디버그 스위치\nAPP_KEY=                # 32bit Application Key\n```\n\n.env 파일이 없다면, 생성하자.\n\n```bash\n$ cp .env.example .env\n```\n\n## Application Key\n\n.env에 설정된 `APP_KEY` 값은 라라벨 프레임웍 전반에 걸쳐 Cipher 알고리즘에서 Seed 값으로 사용된다. 설정되어 있지 않다면 꼭 설정하자.\n\n```bash\n$ php artisan key:generate\n```\n\n## DB 에 연결하자.\n\n먼저 프로젝트에 사용할 데이터베이스를 설정하자. 라라벨에서 .env 파일 수정만으로 DB 설정이 가능하다.\n\n```\nDB_HOST=localhost\nDB_DATABASE=myProject\nDB_USERNAME=homestead\nDB_PASSWORD=secret\n```\n\n실제 DB 접속은 8강 부터 할 것이다. config 디렉토리 아래에 있는 다른 파일들도 살펴 보자.\n\n**`참고`** Homestead 에 설치된 mySQL에 접속하려면, port를 33060으로 설정해야 한다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [2강 - 라라벨 5 설치하기](02-hello-laravel.md)\n- [4강 - Routing 기본기](04-routing-basics.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/04-routing-basics.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 4\n---\n\n# 4강 - Routing 기본기\n\n## 웰컴 뷰를 가지고 놀자\n\nresources/views/welcome.blade.php 를 연다. 이 파일이 바로 2강에서 'Laravel 5'란 큰 글씨로 우리를 반겨 주었던 바로 그 뷰이다. 모든 내용을 지우고, \"Hello World\"를 쓴 후, 로컬서버를 부트업하고 브라우저에서 http://localhost:8000으로 접근해 보자.\n\n```html\n<!-- resources/views/welcome.blade.php -->\nHello World\n```\n\n```bash\n$ php artisan serve\n$ open http://localhost:8000 # 크롬브라우저에 주소를 직접 입력하라는 의미\n```\n\n**`참고`** 앞으로의 실습을 위해 iTerm2의 화면을 그림과 같이 분할하고, #1창에 `$ php artisan serve`, #2창에 `$ php artisan tinker`, #창은 빈 콘솔 로 띄워 놓을 것을 권장한다. 크롬브라우저에는 http://localhost:8000 을 띄워 놓자. 듀얼 모니터라면 한대에 브라우저, 한대에 코드에디터와 콘솔을 띄워 놓으면 좋다.\n\n**`중요`** 실습 중에 .env 파일 또는 config/\\*\\*.php 파일 수정으로 환경 변수가 바뀌면 반드시 로컬 서버를 재실행 해 주어야 한다.\n\n![](./images/04-routing-basic-img-01.png)\n\n## Routing\n\n여기에서 의문점? 분명 홈페이지(/)로 접근했고, welcome.blade.php 와 관련된 어떤 힌트도 제공하지 않았는데 어떻게 이 뷰가 로드되었을까? 요청 Url에 따라 적절한 패스로 연결시켜주는 것이 바로 Routing이 하는 역할이다. \n\napp/Http/routes.php 를 열어보자.\n\n```php\nRoute::get('/', function () {\n    return view('welcome');\n});\n```\n\n'/' 요청이 오면, function 으로 싸진 Closure가 동작한다는 의미이다. Closure 안을 보면, view()라는 function에 'welcome'이란 인자를 넘겨서 반환된 값을 다시 반환한다. 'welcome'이란 인자는 resources/views/welcome.blade.php 란것을 알 수 있다. 즉, Closure에서 반환된 값이 Http 응답으로 전달된다.\n\n`view(string $view)`가 아니라 스트링을 반환하면 어떻게 될까? 브라우저에 스트링이 출력된다.\n\n```php\nRoute::get('/', function () {\n    return 'Hello World';\n});\n```\n\n가령, 라라벨에 기본 내장 되어 있는 resources/views/errors/503.blade.php과 같이 하위 뷰를 응답하려면 어떻게 해야할까? 하위 디렉토리는 '.' 또는 '/'로 구분한다.\n\n```php\nRoute::get('/', function () {\n    return view('errors.503');\n});\n```\n\n**`참고`** `view()`는 Helper Function 이다. `return View::make('welcome')`와 같이 라라벨이 제공하는 Facade('파사드' 또는 '빠사드'라 읽는다.)를 이용할 수도 있다. 필자는 `view()->`까지 입력했을 때 코드힌트가 나와서 Helper Function을 더 선호한다. 말 나온 김에, Facade는 Static Access 형태를 빌려 쓰고 있지만, 실제로 백그라운드에서는 Service Container에 의해서 새로운 instance를 생성하여 메소드에 접근하므로, Anti Pattern이 아니다.\n\n**`참고`** 방금 살펴본 resources/views/errors/503.blade.php 뷰는 라라벨 어플리케이션이 유지보수 모드에 들어갔을 때 사용자에게 보여주는 뷰이다. `$ php artisan down` 명령으로 유지보수 상태로 전환하고, `$ php artisan up` 으로 서비스 상태로 복귀할 수 있다. 유지보수 모드는 웹 서버를 중지 시킨 것은 아니다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [3강 - 글로벌 설정 살펴보기](03-configuration.md)\n- [5강 - 뷰에 데이터 바인딩하기](05-pass-data-to-view.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/05-pass-data-to-view.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 5\n---\n\n# 5강 - 뷰에 데이터 바인딩하기\n\n## 블레이드 템플릿 맛보기\n\nresources/views/index.blade.php 를 만들고 아래와 같이 데이터를 바인딩 시켜 보자. 여기서 `{{ }}`은 라라벨의 템플릿 엔진인 블레이드에서 사용하는 String Interpolation 문법이다. 즉, 뷰 안에서 `<?= ?>`과 같은 역할을 해 주는 것이다.\n\n```html\n<!-- <?= $greeting; ?> <?= $name ? $name : ''; ?> Welcome Back~-->\n<p>\n    {{ $greeting }} {{ $name or '' }}. Welcome Back~\n</p>\n```\n\n**`참고`** HTML 스트링등 특수문자가 포함된 데이터를 뷰에 바인딩 시킬 때는 {{ }}대신 {!! !!}을 사용한다. `{{ $name or '' }}`을 php 문법으로 컴파일 하면, 대략 `echo $name ? $name : '';`와 같다.\n\n## with() 메쏘드로 뷰에 데이터 바인딩하는 방법\n\n```php\nRoute::get('/', function () {\n    $greeting = 'Hello';\n    \n    return view('index')->with('greeting', $greeting);\n});\n```\n\n## with() 메쏘드로 한 개 이상의 데이터를 넘기는 방법\n\n```php\nRoute::get('/', function () {\n    return view('index')->with([\n        'greeting' => 'Good morning ^^/',\n        'name'     => 'Appkr'\n    ]);\n});\n```\n\n## view() 의 2번째 인자로 데이터를 넘기는 방법\n\n```php\nRoute::get('/', function () {\n    return view('index', [\n        'greeting' => 'Ola~',\n        'name'     => 'Laravelians'\n    ]);\n});\n```\n\n**`참고`** 실전에서는 `compact(mixed $varname)` php 내장 함수와 조합하여, `$greeting='World'; return view('index', compact('greeting'));`와 같은 식으로 많이 이용한다.\n\n## view 인스턴스의 Property를 이용하는 방법\n\n```php\nRoute::get('/', function () {\n    $view = view('index');\n    $view->greeting = \"Hey~ What's up\";\n    $view->name = 'everyone';\n    \n    return $view;\n});\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [4강 - Routing 기본기](04-routing-basics.md)\n- [6강 - 블레이드 101](06-blade-101.md)\n<!--@end-->\n\n"
  },
  {
    "path": "lessons/06-blade-101.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 6\n---\n\n# 6강 - 블레이드 101\n\n블레이드는 라라벨의 템플릿 엔진이다. 뷰 안에 포함된 블레이드 문법들은 블레이드 엔진에 의해 php 코드로 컴파일 된다.\n\n## `{{ }}` - String interpolation\n\nphp echo 코맨드와 같은 역할을 해 준다.\n\n```html\n<!-- <?= $greeting; ?> -->\n{{ $greeting }}\n```\n\n## `{{-- --}}` - Comment\n\nHTML 주석으로 컴파일 된다. 그런데 브라우저에서 소스보기로 보면 엄연히 다르다.\n\n```html\n{{-- count(range(1, 10)) --}} <!-- count() 자체가 실행안됨. 즉, 아무것도 출력되지 않음 -->\n<!-- {{  count(range(1, 10)) }} --> <!-- 주석 안에 10이 표시됨 -->\n```\n\n## `@foreach`\n\nresources/views/index.blade.php 에서 `@foreach` 블레이드 문법을 사용해 보자.\n\n```html\n<ul>\n  @foreach($items as $item)\n    <li>{{ $item }}</li>\n  @endforeach\n</ul>\n```\n\n당연히 `$items` 변수를 뷰로 넘겨줘야 한다. 어디서? 5강에서 배운 내용이다. app/Http/routes.php 에서...\n\n```php\nRoute::get('/', function () {\n    $items = [\n        'Apple',\n        'Banana'\n    ];\n\n    return view('index', compact('items'));\n});\n```\n\n**`참고`** `@for`도 사용할 수 있다.\n\n## `@if`\n\nresources/views/index.blade.php 에서 `@if` 블레이드 문법을 사용해 보자.\n\n```html\n@if($itemCount = count($items))\n  <p>There are {{ $itemCount }} items !</p>\n@else\n  <p>There is no item !</p>\n@endif\n```\n\n**`참고`** `@elseif` 당연히 된다. `@unless (== if(!))`도 사용할 수 있다.\n\n## `@forelse`\n\nresources/views/index.blade.php 에서 `@forelse` 블레이드 문법을 사용해 보자. `@forelse`는 `@if`와 `@foreach`의 결합이다. 뷰로 넘어온 변수에 값이 있고 ArrayAccess를 할 수 있으면 , `@forelse`를 타고 그렇지 않으면 `@empty`를 탄다. 자주 이용하게 되니 잘 기억해 두자.\n \n```\n@forelse($items as $item)\n  <p>The item is {{ $item }}</p>\n@empty\n  <p>There is no item !</p>\n@endforelse\n```\n\n`@forelse` 위에서 `<?php $items = []; ?>`로 변수를 오버라이드하고 다시 실험해 보자.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [5강 - 뷰에 데이터 바인딩하기](05-pass-data-to-view.md)\n- [7강 - 블레이드 201](07-blade-201.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/07-blade-201.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 7\n---\n\n# 7강 - 블레이드 201\n\n## @yield, @extends, @section - 마스터 레이아웃 사용하기\n\n페이지마다 반복되는 헤더랑 풋터는 어디에 넣지? 이때 필요한 것이 마스터 레이아웃이다. resources/views/master.blade.php 파일을 만들고, 아래와 같이 HTML 뼈대를 만들어 보자.\n\n```html\n<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Laravel 5 Essential</title>\n</head>\n<body>\n\n  @yield('content')\n\n</body>\n</html>\n```\n\n**`참고`** phpStorm은 [Emmet](http://docs.emmet.io/)을 지원한다. 위 파일에서 `!` 만 입력한 상태에서 <kbd>Tab</kbd>을 누르면 HTML 기본 뼈대가 채워진다. ul>li*3>a<kbd>Tab</kbd> 을 한번 해 보면 Emmet 문법을 왜 익혀야 하는지 금방 알 것이다.\n\nresources/views/index.blade.php는 다음과 같이 수정하고, 브라우저에서 확인해 보자. HTML 소스도 반드시 확인해 보자.\n\n```html\n@extends('master')\n\n@section('content')\n  Your content here !!!\n@stop\n```\n\n여기서 `@extends`라는 키워드는 index.blade.php가 master.blade.php를 상속한다는 뜻이다. 또 `@yield('content')` 와 `@section('content')`를 주목하자. content라고 이름 지어진 섹션이 마스터 레이아웃에서 yield('양도하다', '넘겨주다' 라는 뜻) 된다는 의미다. 섹션은 원하는 숫자만큼 여러개 만들 수 있다. 뷰에서 만든 섹션의 이름으로 마스터 레이아웃에서 yield해 주기만 하면 된다. 가령, 이런 것이 가능해 진다.\n\n```html\n@extends('master')\n\n@section('style')\n  <style>\n    body {background: red;}\n  </style>\n@stop\n\n@section('content')\n  Your content here !!!\n@stop\n\n@section('script')\n  <script>\n    alert(\"Hello Blade~ ^^/\");\n  </script>\n@stop\n```\n\n## @include - 하위 뷰 포함하기\n\nresources/views/footer.blade.php를 만들자.\n\n```html\n<footer>\n  <p>This is footer</p>\n</footer>\n```\n\nresources/views/master.blade.php 또는 resources/views/index.blade.php 어디서든 방금 만든 footer 뷰를 불러와 삽입할 수 있다.\n\n```html\n@include('footer')\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [6강 - 블레이드 101](06-blade-101.md)\n- [8강 - 날 쿼리 :(](08-raw-queries.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/08-raw-queries.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 8\n---\n\n# 8강 - 날 쿼리 :(\n\n## 사용할 테이블을 만들자\n\n[3강 - 글로벌 설정 살펴보기](03-configuration.md)에서 .env 파일에 설정한 내용으로 posts 테이블을 만들어 보자.\n \n> **주의**\n>\n> 홈스테드 환경 사용자는 데이터베이스 관련 모든 명령을, 호스트 컴퓨터의 쉘이 아니라 홈스테드 쉘에서 수행해야 한다. 뒤에 나올 마이그레이션 등도 마찬가지로 홈스테스 쉘에서 수행해야 한다.\n\n```bash\n# 아래 명령들은 이런 내용으로 만든다는 내용을 보여주기 위한 것이며 실제로는 GUI 툴로 해도 무방하다.\n\n$ mysql -uroot\nmysql > CREATE DATABASE myProject;\nmysql > CREATE USER 'homestead' IDENTIFIED BY 'secret';\nmysql > GRANT ALTER, CREATE, INSERT, SELECT, DELETE, REFERENCES, UPDATE, DROP, EXECUTE, LOCK TABLES, INDEX ON myProject.* TO 'homestead';\nmysql > FLUSH PRIVILEGES;\nmysql > exit (enter)\n\n$ mysql -uhomestead -p\nmysql > CREATE TABLE posts(\n    -> id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,\n    -> title VARCHAR(255),\n    -> body TEXT\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\nmysql > INSERT INTO posts(title, body) VALUES('My Title', 'My Body');\nmysql > exit (enter)\n```\n\nmySql에 root로 로그인하여 myProject DB를 만들고, homestead 사용자에 대해 myProject DB에 대한 접근 권한 부여를 반드시 해야 한다. 아래 그림은 Sequel Pro 에서 권한 부여<kbd>Cmd</kbd> + <kbd>U</kbd>하는 과정이다.\n\n![](./images/08-raw-queries-img-01.png)\n\n## 라라벨을 이용해서 DB 쿼리를 해 보자. \n\n**`참고`** 실제로 이렇게 사용하는 경우는 거의 없으니 참고만 하자.\n\n쿼리를 배우기 위해 라라벨에서 제공하는 REPL 을 이용하자. tinker('어설프게 손보고 고치다' 라는 뜻)라고 불리는 artisan 코맨드인데, 라라벨의 모든 환경이 제공되기 때문에 여러가지 실험적인 시도들을 해보기 편리하다.\n\n```bash\n$ php artisan tinker\nPsy Shell v0.5.2 (PHP 5.6.7 — cli) by Justin Hileman\n>>> (cursor)\n```\n\nposts 테이블을 가져와 보자.\n\n```bash\n>>> DB::select('select * from posts');\n=> [\n     {#676\n       +\"id\": 1,\n       +\"title\": \"My Title\",\n       +\"body\": \"My Body\",\n     },\n   ]\n```\n\n레코드를 더 추가하자. 라라벨은 PDO를 이용하기 때문에 ? 처럼 같이 데이터를 바인딩해 줘야 한다.\n\n```bash\n>>> DB::insert('insert into posts(title, body) values(?, ?)', ['Second Title', 'Second Body']);\n=> true\n```\n\nCollection이 아니라 하나의 Instance만 얻으려면 어떻게 해야 할까?\n\n```bash\n>>> $post = DB::selectOne('select * from posts where id = ?', [1]);\n=> {#689\n     +\"id\": 1,\n     +\"title\": \"My Title\",\n     +\"body\": \"My Body\",\n   }\n>>> $post->title;\n=> \"My Title\"\n```\n\n업데이트도 해 보자.\n\n```bash\n>>> DB::update('update posts set title=\"Modified Title\" where id = ?', [2]);\n=> 1\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [7강 - 블레이드 201](07-blade-201.md)\n- [9강 - 쿼리 빌더](09-query-builder.md)\n<!--@end-->\n\n"
  },
  {
    "path": "lessons/09-query-builder.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 9\n---\n\n# 9강 - 쿼리 빌더\n\nSQL 문을 php 코드로 쓴 거라고 보면 된다. 지금은 그냥 SQL로 쓰면 될 것, 더 길고 복잡한 코드로 쓰지?라고 반문할 수 있지만.. 차차 그 편리성을 알게 되니 무작정 따라해 보자.\n\n## 쿼리 빌더를 이용해 보자.\n\n`DB` Facade와 `table()`, `get()` 메소드를 이용하여 Collection(레코드셋)을 가져 와 보자.\n\n```bash\n$ php artisan tinker\n>>> DB::table('posts')->get(); # SELECT * FROM posts\n=> [\n     {#679\n       +\"id\": 1,\n       +\"title\": \"My Title\",\n       +\"body\": \"My Body\",\n     },\n     {#680\n       +\"id\": 2,\n       +\"title\": \"Modified Title\",\n       +\"body\": \"Second Body\",\n     },\n   ]\n```\n\n`first()`, `find()` 메소드로 Instance(레코드)를 가져오자.\n\n```bash\n>>> DB::table('posts')->find(2);\n=> {#688\n     +\"id\": 2,\n     +\"title\": \"Modified Title\",\n     +\"body\": \"Second Body\",\n   }\n>>> DB::table('posts')->first();\n=> {#671\n     +\"id\": 1,\n     +\"title\": \"My Title\",\n     +\"body\": \"My Body\",\n   }\n```\n\n`where()` 예상대로 where 절을 사용하는 거다.\n\n```bash\n# 모두 동일한 쿼리이다. where()에서 = 연산자는 생략 가능하다.\n>>> DB::table('posts')->where('id', '=', 1)->get(); \n>>> DB::table('posts')->where('id', 1)->get();\n>>> DB::table('posts')->whereId(1)->get();\n=> [\n     {#692\n       +\"id\": 1,\n       +\"title\": \"My Title\",\n       +\"body\": \"My Body\",\n     },\n   ]\n```\n\n**`참고`** `whereId()`는 Dynamic Method이다.\n**`참고`** `where()`에 Closure를 쓸 수도 있다 `where(function($query) {$query->where('field', 'operator', 'value);})`\n\n`select()`를 이용하여 필요한 필드만 가져오자.\n\n```bash\n>>> DB::table('posts')->select('title')->get();\n=> [\n     {#686\n       +\"title\": \"My Title\",\n     },\n     {#678\n       +\"title\": \"Modified Title\",\n     },\n   ]\n```\n\n자주 쓰는 메소드들이다. 공식 문서를 보면 알겠지만, `count()`, `distinct()`, `select(DB::raw('count(*) as cnt'))`, `join()`, `union()`, `whereNull()`, `having()`, `groupBy()`, ... 표현하지 못하는 SQL 문장은 없다고 보면 된다.\n- `insert(array $value)`\n- `update(array $values)`\n- `delete(int $id)`\n- `lists(string $column)`\n- `orWhere(string $column, string $operator, mixed $value)`\n- `limit(int $value)` // == `take(int $value)`\n- `orderBy(string $column, string $direction)`\n- `latest()` // == `orderBy('created_at', 'desc')`\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [8강 - 날 쿼리 :(](08-raw-queries.md)\n- [10강 - 엘로퀀트 ORM](10-eloquent.md)\n<!--@end-->\n\n"
  },
  {
    "path": "lessons/10-eloquent.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 10\n---\n\n# 10강 - 엘로퀀트 ORM\n\n엘로퀀트는 라라벨의 ORM (Object Relational Mapper, Active Record Pattern 의 구현체)이다. 데이터베이스는 테이블간 관계를 가지고 있다. 데이터베이스를 추상화한 모델 클래스 간에 관계를 맺어 주는 구현체를 일반적으로 ORM이라 칭한다. 뿐만 아니라 라라벨에서는 config/database.php에 의해 설정된 DB Driver와 ORM 사용으로 인해 데이터베이스와 어플리케이션 간에 디커플링 효과도 얻게 된다. 어플리케이션 코드 수정 한 줄 없이 mySQL을 SQLite로 바꿀 수 있다는 의미이다.\n  \n## 모델\n\n라라벨이 MVC 프레임웍인데 우리가 이제까지 본 것은 V(뷰) 뿐이었다. 드디어 M에 해당하는 모델을 볼 차례이다. authors 라는 테이블을 생성하자.\n\n```bash\n$ mysql -uhomestead -p\nmysql > CREATE TABLE authors(\n    -> id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,\n    -> email VARCHAR(255) NOT NULL,\n    -> password VARCHAR(60) NOT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\nmysql > INSERT INTO authors(email, password) VALUES('john@example.com', 'password');\n```\n\n**`참고`** 이번까지는 수작업으로 테이블을 생성했다. 다음 번 부터는 migration을 통해 테이블을 생성하고, seed를 통해 데이터를 생성할 것이다.\n\n모델을 생성하자. artisan CLI에서 제공하는 Generator 를 이용하자. 코맨드를 수행한 후 app/Post.php, app/Author.php 파일이 생성되었는 지 확인하자.\n\n```\n$ php artisan make:model Post\n$ php artisan make:model Author\n```\n\n**`참고`** 테이블 이름을 users 와 같이 복수로, 모델 이름은 User 처럼 단수로 하는 것이 규칙이다. DB 테이블은 Collection을 담고 있고, 모델은 DB 테이블에 담긴 하나의 레코드를 클래스로 표현한 것이기 때문이다. 규칙을 지킬 수 없는 경우에는, 가령 모델명을 Author, 테이블을 users 라 했을 경우, 라라벨이 둘 간의 관계를 알 수 있도록 Author 모델에 `protected $table = 'users';` 코드를 추가해 주어야 한다.\n\n## 처음 만나는 엘로퀀트 쿼리\n\n전체 Collection을 가져오자. 이번엔 `DB` Facade를 이용하지 않고, `App\\Author` 모델을 이용한 것을 눈여겨 보자.\n\n```bash\n$ php artisan tinker\n>>> App\\Author::get(); # == DB::table('authors')->get();\n=> Illuminate\\Database\\Eloquent\\Collection {#677\n     all: [\n       App\\Author {#678\n         id: 1,\n         email: \"john@example.com\",\n         password: \"password\",\n       },\n     ],\n   }\n```\n\n**`참고`** 쿼리 빌더 에서 사용할 수 있는 대부분의 메소드는 Eloquent Model에서도 사용할 수 있다. 예를 들면, `App\\Author::orderBy('id', 'desc')->limit(1)->lists('email');`와 같이. 사실, 이번 강좌에서 보는 것은 엘로퀀트를 상속한 모델을 이용해서 쿼리 빌더를 쓸 수 있다는 정도이다. 엘로퀀트의 전부가 아니란 얘기다. 엘로퀀트 ORM의 꽃은 모델간의 관계 맺기 이며, 18강에서 다루고 있다.\n\n새로운 Instance를 생성하고 데이터베이스에 저장해 보자.\n\n```bash\n$ php artisan tinker\n>>> $author = new App\\Author;\n>>> $author->email = 'foo@bar.com';\n>>> $author->password = 'password';\n>>> $author->save(); # 메모리에만 존재하던 인스턴스를 데이터베이스에 저장한다.\n# Illuminate\\Database\\QueryException with message '... updated_at in ...'\n```\n\n## QueryException\n\n`save()` 메소드 호출에서 예외가 발생했을 것이다. 엘로퀀트는 모든 모델이 `updated_at`과 `created_at` 필드가 있다고 가정하고, 새로운 Instance가 생성될 때 현재의 timestamp값을 입력하려한다. 그런데, 위 테이블들은 수작업으로 만든 테이블이라 앞서 말한 필드들이 존재하지 않는다. 방법은 필드를 추가하는 방법과, timestamp 입력을 모델에서 끄는 방법이 있는데, 실습을 위해 일단 끄자.\n\n```php\n// Post 모델도 적용해 주자.\nclass Author extends Model\n{\n    public $timestamps = false;\n}\n```\n\n**`중요`** **_모델에 변경이 생기면 실행중이던 tinker 를 다시 실행해 주어야 한다._** tinker 가 로드될 시점에 라라벨 구동을 위한 모든 환경이 로드되므로, 이후 변경을 반영하기 위함이다. <kbd>ctrl</kbd> + <kbd>C</kbd> 또는 `>>> exit` 명령으로 종료할 수 있다. tinker를 재실행 한 후 <kbd>up</kbd> 화살표로 이전 코맨드 이력을 탐색할 수 있다.\n\n```bash\n>>> $author = new App\\Author;\n>>> $author->email = 'foo@bar.com';\n>>> $author->password = 'password';\n>>> $author->save();\n=> true\n```\n\n## 다른 메소드를 이용한 모델 생성\n\n이번에는 `save()` 대신 `create()` 메소드를 이용할 것이다.\n\n```bash\n$ php artisan tinker\n>>> App\\Author::create([\n... 'email' => 'bar@baz.com',\n... 'password' => bcrypt('password')\n... ]);\n# Illuminate\\Database\\Eloquent\\MassAssignmentException with message 'email'\n```\n\n**`참고`** `bcrypt(string $value)` 은 암호화된 60byte스트링를 만들어 준다. Facade로 쓰면 `Hash::make(string $value)` 와 같다.\n\n## MassAssignmentException\n\ntimestamps를 무력화 시킨 후에도, `create()` 메소드를 이용할 때는 에러가 발생했다. `create()` 메소드로 모델 인스턴스를 생성할 때는 해당 모델에 `$fillable` 속성을 지정해 주어야 한다. 폼을 통해 사용자가 넘긴 값을 그대로 DB에 넣을 경우를 대비해, 악의적인 필드가 입력되는 것을 방지하기 위한 조치이다. Post와 Author 모델을 열고 `$fillable` 속성을 지정하자.\n\n```php\nclass Author extends Model\n{\n    protected $fillable = ['email', 'password'];\n}\n```\n\n```php\nclass Post extends Model\n{\n    protected $fillable = ['title', 'body'];\n}\n```\n\ntinker 를 재시작하고 <kbd>up</kbd> 키를 눌러, `create()` 메소드를 다시 실행해 보자.\n\n```bash\n$ php artisan tinker\n>>> App\\Author::create([\n... 'email' => 'bar@baz.com',\n... 'password' => bcrypt('password')\n... ]);\n=> App\\Author {#680 # bcrypt() Helper에 의해 암호화된 60 byte 패스워드를 확인하자.\n     email: \"bar@baz.com\",\n     password: \"$2y$10$tL/9voTNRtH7dfE9yULVaOybUWTcNkLRws9gTawcU85L3PEwRotUS\",\n     id: 3,\n   }\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [9강 - 쿼리 빌더](09-query-builder.md)\n- [11강 - DB 마이그레이션](11-migration.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/11-migration.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 11\n---\n\n# 11강 - DB 마이그레이션\n\n마이그레이션은 데이터베이스를 위한 버전 컨트롤이라 생각하면 된다. 처음 테이블을 생성하고, 가령 이후에 새로운 필드를 추가한다든지, 필드의 이름을 바꾼다든지 등의 이력을 모두 마이그레이션 코드로 남겨 두고, 테이블을 생성했다가 롤백하는 등 자유롭게 이용할 수 있다.\n\n마이그레이션 코드 작성은 정말 지루한 일이다. 토이(toy) 프로젝트를 하는데 마이그레이션을 굳이 작성할 필요는 없다. 하지만, 대형 서비스라면 테이블 스키마를 변경해야 할 수도 있는 새로운 요구사항이 생길 수 있다. 이때 기초공사를 잘못해 두었다면, 개발자에게 엄청난 위기 상황이 닥칠 수도 있는데, 마이그레이션이 위기에서 개발자를 구해주는 데 도움을 줄 것이다. 정말로~ 그리고, 팀으로 여러 명이 테이블 스키마를 변경해 가면서 개발할 때는, `mysqldump` 해서 주고 받는 수고를 피하기 위해 꼭 필요하다.\n\n라라벨에서는 데이터베이스 스키마를 코드로 생성하기 위한 `Blueprint` 클래스를 제공하고 있다. \n\n## Migration 을 만들자.\n\n먼저 기존에 만든 posts, authors 테이블들을 삭제하자.\n\n```bash\n$ mysql -u homestead -p\nmysql> SET FOREIGN_KEY_CHECKS = 0;\nmysql> DROP TABLE posts;\nmysql> DROP TABLE authors;\nmysql> SET FOREIGN_KEY_CHECKS = 1;\n```\n\nartisan CLI 를 이용해 마이그레이션을 만들자.\n\n```bash\n$ php artisan make:migration create_posts_table\n$ php artisan make:migration create_authors_table\n```\n\ndatabase/migrations 디렉토리에 timestamp_create_xxx_table 이란 2개의 마이그레이션이 생성된 것을 확인하자. database/migrations/timestamp_create_posts_table 을 열어보면 `up()`, `down()` 2개의 메소드가 생성된 것을 확인할 수 있다. `up()` 은 마이그레이션을 실행할 때 동작하는 메소드이고 (`$php artisan migrate`), `down()`은 직전 마이그레이션을 롤백 하기 위한 메소드이다 (`$ php artisan migrate:rollback`).\n \n```php\n// CreateAuthorsTable 도 작성하자.\n\nclass CreatePostsTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('posts', function($table) {\n            $table->increments('id'); // id INT AUTO_INCREMENT PRIMARY KEY\n            $table->string('title', 100); // title VARCHAR(100)\n            $table->text('body'); // body TEXT\n            $table->timestamps(); // created_at TIMESTAMP, updated_at TIMESTAMP\n        });\n    }\n\n    public function down()\n    {\n        Schema::dropIfExists('posts'); // DROP TABLE posts\n    }\n}\n```\n\n`up()` 에서는 `Schema` Facade 의 `create()` 메소드를 이용하는데, 첫번째 인자는 테이블 이름, 두번째 인자는 콜백이다. 콜백은 `$table`이란 Blueprint 인스턴스를 주입하며, `string()`, `text()`, `integer()`, `timestamp()` 등 데이터베이스의 데이터 타입에 해당하는 다양한 메소드를 제공한다.\n\n마이그레이션을 실행해 보자.\n\n```bash\n$ php artisan migrate\n# Migration table created successfully.\n# Migrated: 2014_10_12_000000_create_users_table\n# Migrated: 2014_10_12_100000_create_password_resets_table\n# Migrated: 2015_11_10_080603_create_posts_table\n# Migrated: 2015_11_10_080609_create_authors_table\n```\n\n테이블이 정상적으로 생성되었는 지 확인하자.\n \n```bash\n$ mysql -u homestead -p\nmysql> use myProject;\nmysql> describe posts;\nmysql> describe authors;\n```\n \n**`참고`** 마이그레이션을 처음 실행하면, migrations, users, password_resets 등과 같이 라라벨이 기본 내장된 마이그레이션도 같이 실행되어 해당 테이블들이 같이 생성된다.\n \n## 롤백해 보자.\n \n```bash\n$ php artisan migrate:rollback\n\n# 롤백되는 것이 잘 확인되었으면 다음 실습을 위해 다시 마이그레이션하자.\n$ php artisan migrate\n```\n\n## 필드를 추가\n\nauthors 테이블에 name 필드를 추가하는 것을 깜빡했다고 가정하자. 물론, 전체 롤백을 하고, 최초 테이블 생성 마이그레이션에 name 필드를 추가한 뒤 마이그레이션을 다시 실행할 수 도 있다. 그런데, 만약 테이블에 데이터가 있다면... 난감해 진다. 필드를 추가하는 마이그레이션을 작성해 보자.\n\n```bash\n$ php artisan make:migration add_name_to_authors_table\n```\n\n```php\nuse Illuminate\\Database\\Schema\\Blueprint;\n\nclass AddNameToAuthorsTable extends Migration\n{\n    public function up()\n    {\n        Schema::table('authors', function(Blueprint $table) {\n            $table->string('name')->after('email')->nullable(); // nullable()은 NULL 을 허용한다는 얘기\n        });\n    }\n\n    public function down()\n    {\n        Schema::table('authors', function(Blueprint $table) {\n            $table->dropColumn('name');\n        });\n    }\n}\n```\n\n테이블을 새로 생성할 때 쓰던 `create()`가 아니라, 이미 만들어진 테이블에 스키마를 변경하는 것이라 `table()` 메소드를 쓴 것에 주목하자. `after()`는 mySql에서만 쓸 수 있는 메소드로 인자로 넘겨 받은 필드 다음에 새로운 필드를 추가해 준다.\n\n마이그레이션을 실행하고, 필드가 추가되었는 지 확인해 보자.\n\n```bash\n$ php artisan migrate\n```\n\n**`팁`** 이번 마이그레이션에서는 Closure Function 인자에 Blueprint 라고 TypeHint 를 썼다. TypeHint 를 쓰면 phpStorm 에서 `->` 로 코드 힌트를 볼 수 있어서 편리하다.\n**`참고`** `Blueprint` 의 풀 네임스페이스는 `\\Illuminate\\Database\\Schema\\Blueprint` 이다. 코드 내에 두 군데 이상 같은 클래스가 쓰인다면 `use` 키워드로 import 해 주어야 한다. phpStorm 은 Preference 셋팅에 따라 Blueprint 타이핑이 끝나고 나면 자동으로 import 를 해 주어 편리한데, 혹 자동 import 가 안되었다면 `Blueprint` 위에 커서를 놓고 <kbd>option</kdb> + <kbd>Enter</kbd> 을 눌러 컨텍스트 메뉴를 띄운 후 import 할 수도 있다.\n\n## Reset & Refresh\n\n`migrate:rollback` 이 직전 마이그레이션만 롤백하는 반면 `migrate:reset` 는 모든 마이그레이션을 롤백하고 데이터베이스를 초기화 시킨다. `migrate:refresh` 는 리셋을 실행해서 데이터베이스를 청소한 후, 마이그레이션을 처음부터 다시 실행하는 코맨드이다.\n\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [10강 - 엘로퀀트 ORM](10-eloquent.md)\n- [12강 - 컨트롤러](12-controller.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/12-controller.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 12\n---\n\n# 12강 - 컨트롤러\n\nMVC에서 V(뷰)와 M(모델)을 살펴보았다. 이제 마지막 콤포넌트인 C(컨트롤러)를 살펴볼 차례이다.\n\n## Revisit Route\n\n이제까지 모든 HTTP 요청에 대한 처리를 app/Http/routes.php의 Route Closure에서 처리 했다. Router의 역할은 HTTP 요청을 적절한 처리 로직으로 연결시켜주는 것, 즉 컨트롤러에 연결시켜주는 것이다. app/Http/routes.php에 컨트롤러를 이용한 Route를 만들어 보자.\n\n```php\nRoute::get('/', 'IndexController@index');\n```\n\nHTTP GET / 요청이 들어오면, `IndexController`의 `index()` 메소드로 연결시키라는 뜻이다.\n\n## Controller를 만들자.\n\n서버를 부트업하고, '/' 경로로 접근해 보자. `ReflectionException - Class App\\Http\\Controllers\\IndexController does not exist` 란 메시지가 출력되었을 것이다. IndexController가 없기 때문이다. artisan CLI를 이용해서 만들자.\n\n```bash\n$ php artisan make:controller IndexController\n```\n\napp/Http/Controllers/IndexController 가 생성된 것을 확인하자. `index()` 메소드를 만들자.\n\n```php\nclass IndexController extends Controller\n{\n    public function index() {\n        return view('index');\n    }\n}\n```\n\n서버를 부트업하고, / 경로로 접근하여, 정상적으로 뷰가 표시된 것을 확인하자. 4강에서 Route에 Closure에 넣은 내용과 `index()` 메소드의 내용이 동일하다는 것을 인지했을 것이다. Route에 모든 비즈니스 로직을 넣을 수 없을 뿐더러, 코드를 효율적으로 구조화시키기 위해서 컨트롤러를 사용하여 구조화한 것이라 생각하면 된다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [11강 - DB 마이그레이션](11-migration.md)\n- [13강 - RESTful 리소스 컨트롤러](13-restful-resource-controller.md)\n<!--@end-->\n\n"
  },
  {
    "path": "lessons/13-restful-resource-controller.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 13\n---\n\n# 13강 - RESTful 리소스 컨트롤러\n\nREST는 이 코스 범위를 넘어가는 내용이니, 시간 날 때 구글링을 통해서 공부하자. 모든 HTTP 요청 Url 엔드포인트에 대해서 `IndexController@method` 와 같이 연결하면 Route 정의만으로도 수백, 수천 줄이 될 수 있다. REST 원칙에 따라 리소스 이름으로된 Url 엔드포인트를 정의하고, `@method` 없이 컨트롤러에 연결시키는 것이 리소스 컨트롤러라고 이해하고 넘어가자.\n\n## RESTful Resource Route\n\n아래는 Post 모델에 대한 Url 엔드포인트를 'posts'라 했을 때, REST 원칙에 따라 라라벨이 자동으로 생성해 주는 Url 엔드포인트와 PostsController의 메소드간의 연결을 표로 표현한 것이다.\n\nVerb|Endpoint|Method Override|Controller Method|Description\n---|---|---|---|---\nGET|/posts/| |`index()`|Post 모델 Collection 보기\nGET|/posts/{id}| |`show()`|id를 가지는 Post Instance 보기 \nGET|/posts/create| |`create()`|새로운 Post Instance 생성을 위한 폼\nPOST|/posts| |`store()`|새로운 Post Instance 생성\nGET|/posts/{id}/edit| |`edit()`|id를 가진 Post Instance 업데이트 폼\nPOST|/posts/{id}|`_method=PUT` `(x-http-method-override: PUT)`|`update()`|id를 가진 Post Instance 업데이트\nPOST|/posts/{id}|`_method=DELETE` `(x-http-method-override: DELETE)`|`delete()`|id를 가진 Post Instance 삭제\n\napp/Http/routes.php에 posts 경로에 대한 resource 라우트를 정의하자. 그간 배웠던 `get()` 메소드가 아닌, `resource()`란 메소드를 쓰는 것에 유의하자.\n\n```php\nRoute::resource('posts', 'PostsController');\n```\n\nartisan CLI 로 Route 목록을 확인해 보자.\n\n```bash\n$ php artisan route:list\n# ReflectionException - Class App\\Http\\Controllers\\PostsController does not exist\n```\n\n## RESTful Resource Controller 만들기\n\nartisan CLI 로 PostsController를 만들자. 이번엔 --plain 옵션이 빠진다.\n\n```bash\n$ php artisan make:controller PostsController --resource\n\n# Route 목록을 다시 확인해 보자.\n$ php artisan route:list\n```\n\n![](./images/13-restful-resource-controller-img-02.png)\n\n## 테스트\n\napp/Http/Controller/PostsController.php 가 만들어졌는지 확인하자. PostsController의 각 메소드에 Dummy 반환값을 넣고 RESTful 라우트와 컨트롤러가 잘 동작하는지 확인해 보자.\n\n```php\nclass PostsController extends Controller\n{\n    public function index()\n    {\n        return '[' . __METHOD__ . '] ' . 'respond the index page';\n    }\n\n    public function create()\n    {\n        return '[' . __METHOD__ . '] ' . 'respond a create form';\n    }\n\n    public function store(Request $request)\n    {\n        return '[' . __METHOD__ . '] ' . 'validate the form data from the create form and create a new instance';\n    }\n\n    public function show($id)\n    {\n        return '[' . __METHOD__ . '] ' . 'respond an instance having id of ' . $id;\n    }\n\n    public function edit($id)\n    {\n        return '[' . __METHOD__ . '] ' . 'respond an edit form for id of ' . $id;\n    }\n\n    public function update(Request $request, $id)\n    {\n        return '[' . __METHOD__ . '] ' . 'validate the form data from the edit form and update the resource having id of ' . $id;\n    }\n\n    public function destroy($id)\n    {\n        return '[' . __METHOD__ . '] ' . 'delete resource ' . $id;\n    }\n}\n```\n\n테스트를 위해 [PostMan 크롬 확장 프로그램](https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop)을 사용할 것을 권장한다. 이 문서의 표 대로 하나씩 대입해 보자. PostMan에서 GET을 선택하고 http://localhost:8000/posts, http://localhost:8000/posts/1, http://localhost:8000/posts/1/edit.\n\n![](./images/13-restful-resource-controller-img-01.png)\n\n그럼, HTTP 요청 메소드를 POST로 바꾸고, http://localhost:8000/posts를 해보자.\n\n## TokenMismatchException\n\n라라벨은 CSRF(Cross Site Request Forgery) 공격을 방지하기 위해 기존 데이터를 변경하는 행위, 즉, 신규 생성, 업데이트, 삭제 등의 행위에 대해서는 CSRF 토큰을 폼요청에서 제공해야 한다. 가령 `PostsController@create` 메소드에서 응답한 모델 생성 폼에서 숨은 필드로 `_token` 값을 제공해야 한다. 폼 요청을 받은 `PostsController@store` 메소드는 토큰의 유효성을 확인하고, 같은 세션일 경우, 즉, `create()`를 요청한 클라이언트와 `store()`를 요청한 클라이언트가 동일할 경우에만 `store()` 액션을 수행한다. 지금 우리가 PostMan을 통해서 테스트하는 행위 자체가 CSRF 공격이라 볼 수 있다.\n  \n우선 이번 테스트를 위해 CSRF 보호기능을 잠시 끄도록 하자. app/Http/Middleware/VerifyCsrfToken.php를 아래 처럼 수정한다.\n\n```php\nclass VerifyCsrfToken extends BaseVerifier\n{\n    protected $except = [\n        'posts', \n        'posts/*'\n    ];\n}\n```\n\nPOST http://localhost:8000/posts가 정상 동작하는 것을 확인한 후, 이번에는 POST http://localhost:8000/posts/1 으로 요청해 보자. 또 에러가 날 것이다.\n\n## MethodNotAllowedHttpException\n\n브라우저들은 PUT, DELETE 등의 HTTP 동사(==메소드)를 지원하지 않는다. 즉, 브라우저에서는 PUT, DELETE등의 요청을 할 수 없다는 얘기다. 그럼에도 불구하고, REST 원칙을 지키기 위해서 라라벨 뿐 아니라 대부분의 웹 프레임웍들이 메소드 오버라이딩을 사용한다. POST로 폼 전송을 하되 숨은 필드로 `_method=PUT` 등과 같이 \"내 비록 POST로 요청하지만 이건 PUT 요청이오~\" 라고 서버 프레임웍에게 힌트를 주는 방법이다.\n\nhttp://localhost:8000/posts/1 로 PUT, DELETE 요청을 하기 위해서는 폼데이터로 `_method=PUT`, `_method=DELETE` 를 추가해 주어야 한다. PostMan에 Body라 써진 탭을 열고, form-data 에 Key:\"_method\", Value:\"PUT\"을 각각 입력한 후 다시 테스트해 보자.\n\n**`참고`** 숨은 필드를 이용하지 않고 `x-http-method-override: DELETE` 와 같이 HTTP Header를 이용해서 메소드 오버라이딩을 할 수도 있다.\n\n모든 테스트가 끝났으면, `VerifyCsrfToken` 클래스에서 예외 처리 했던 것을 원복 시키자.\n\n```php\nclass VerifyCsrfToken extends BaseVerifier\n{\n    protected $except = [];\n}\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [12강 - 컨트롤러](12-controller.md)\n- [14강 - 이름 있는 Route](14-named-routes.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/14-named-routes.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 14\n---\n\n# 14강 - 이름 있는 Route\n\nNamed Routes는 여러모로 유용하다. 컨트롤러에서 `redirect(string $to)` Helper Function 으로 이동할 Url을 만들거나, 뷰 안에서 다른 Url로 이동하는 링크를 만들 때, 하드코드로 Url을 써 놓는 것 보다 여러 모로 관리상 편리하다. 가령, posts 라는 Url 엔트포인트를 어느날 갑자기 articles 로 모두 바꾸어야 한다고 생각해 보라. 모든 컨트롤러와 뷰를 찾아 다니면서 Url을 변경하는 것이 얼마나 귀찮을까?\n\n## Route 에 이름을 주자\n\napp/Http/routes.php 에서 공부해 보자. Route 메소드의 두번째 인자로 배열을 사용하고, 배열의 키로 'as'를 사용하여 라우트의 이름을 지정한다. 컨트롤러로의 연결은 'uses' 키를 사용한다.\n\n```php\nRoute::get('posts', [\n    'as'   => 'posts.index',\n    'uses' => 'PostsController@index'\n]);\n```\n\n`$ php artisan route:list`로 Name 컬럼을 확인해 보자. 이제 컨트롤러나 뷰에서 'posts.index'란 이름을 사용할 수 있다. 가령 `return redirect(route('posts.index'))` 또는 `<a href=\"{{ route('posts.index') }}\">목록으로 돌아가기</a>`와 같은 식으로 말이다.\n\n```bash\n$ php artisan tinker\n>>> route('posts.index');\n=> \"http://localhost/posts\"\n```\n\n어 틀린데... 포트번호 8000이 빠졌잖아. 클라이언트가 브라우저일 경우 host와 port를 자동으로 인지하지만, 코맨드 라인에서는 HTTP 환경 변수가 없기 때문이다. `config/app.php`을 수정하자.\n\n```php\n'url' => 'http://localhost:8000',\n```\n\nClosure로 쓸 때도 이름을 부여할 수 있다.\n\n```php\nRoute::get('posts', [\n    'as' => 'posts.index',\n    function() {\n        return view('posts.index');\n    }\n]);\n```\n\n## RESTful Resource Route의 이름\n\n```php\nRoute::resource('posts', 'PostsController');\n```\n\n`$ php artisan route:list` 로 확인해 보자. Route 이름이 자동으로 부여 된다. 이제 팅커링 해 보자.\n\n```bash\n$ php artisan tinker\n>>> route('posts.index');\n=> \"http://localhost:8000/posts\"\n>>> route('posts.store');\n=> \"http://localhost:8000/posts\"\n>>> route('posts.create');\n=> \"http://localhost:8000/posts/create\"\n>>> route('posts.destroy', 1);\n=> \"http://localhost:8000/posts/1\"\n>>> route('posts.show', 1);\n=> \"http://localhost:8000/posts/1\"\n>>> route('posts.update', 1);\n=> \"http://localhost:8000/posts/1\"\n>>> route('posts.edit', 1);\n=> \"http://localhost:8000/posts/1/edit\"\n```\n\n**`참고`** 중복된 Route의 경우, 항상 위에 정의된 것이 아래에 정의된 것을 오버라이드 한다. 가령 posts/count 라는 Route가 있다면 RESTful Resource 정의보다 먼저(== 위에) 정의하는게 안전하다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [13강 - RESTful 리소스 컨트롤러](13-restful-resource-controller.md)\n- [15강 - 중첩된 리소스](15-nested-resources.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/15-nested-resources.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 15\n---\n\n# 15강 - 중첩된 리소스\n\n특정 리소스에 딸린 하위 리소스를 보여줘야 하는 경우가 있다. 가령, Post id 1번에 딸린 Comment 목록을 보여주거나, Comment를 생성/수정/삭제하는 경우 등이다.\n\n## 중첩 리소스 Route를 만들자.\n\napp/Http/routes.php에서 아래와 같이 작성해 보자.\n\n```php\nRoute::resource('posts.comments', 'PostCommentController');\n```\n\nartisan CLI 로 PostCommentController 를 만들자.\n\n```bash\n$ php artisan make:controller PostCommentController --resource\n```\n\n`$ php artisan route:list`로 확인해 보자. `posts/{posts}/comments/{comments}` 형태의 라우트를 얻을 수 있다.\n\n![](./images/15-nested-resources-img-01.png)\n\n## Route Parameter 접근\n\nController에서 `$postId`와 `$commentId`에 접근할 수 있다.\n\n```php\nclass PostCommentController extends Controller\n{\n    public function index($postId)\n    {\n        // GET http://localhost:8000/posts/1/comments\n        return '[' . __METHOD__ . \"] \\$postId = {$postId}\"; \n        // [App\\Http\\Controllers\\PostCommentController::index] $postId = 1\n    }\n    \n    ...\n\n    public function show($postId, $commentId)\n    {\n        // GET http://localhost:8000/posts/1/comments/20\n        return $postId . '-' . $commentId;\n        // [App\\Http\\Controllers\\PostCommentController::show] $postId = 1, $commentId = 20\n    }\n}\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [14강 - 이름 있는 Route](14-named-routes.md)\n- [16강 - 사용자 인증 기본기](16-authentication.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/16-authentication.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 16\n---\n\n# 16강 - 사용자 인증 기본기\n\n좀 과장해서, 어떤 프로젝트든 로그인이 거의 업무량의 절반이라고들 한다. 그만큼 User 모델과 연결된 기능들이 많다는 의미로 이해하면 되겠다. 서비스에 들어온 사용자를 식별하는 방법을 인증(Authentication)이라 한다. 바꾸어 말하면, 사용자가 제시한 신분증이 DB에 저장된 User 정보와 동일한지 확인하고, 맞으면 통과시켜 주면서, 세션이라는 명찰을 하나 나눠 주는 행위라 이해할 수 있다. \n\n이번 강좌에서는 라라벨이 제공하는 메소드들을 이용해서 사용자 인증을 직접 구현해 보고, 다음 강좌에서 라라벨에 포함되어 배포(Shipping)되는 네이티브 인증 구현을 살펴보자.\n \n# User 모델\n\n라라벨에는 User 모델과 마이그레이션이 이미 포함되어 있다. app/User.php를 살펴보자.\n \n```php\nclass User extends Model implements ...\n{\n    protected $fillable = ['name', 'email', 'password'];\n\n    protected $hidden = ['password', 'remember_token'];\n}\n```\n\n`$fillable` 속성을 통해 name, email, password 필드는 MassAssign 이 가능하다는 것을 알 수 있다. `$hidden` 속성은 외부에 노출되지 않는 필드들을 정의한 것이다. 그럼, 사용자를 하나 만들어 보자.\n\n```bash\n$ php artisan tinker\n>>> $user = new App\\User;\n>>> $user->name = 'John Doe';\n>>> $user->email = 'john@example.com';\n>>> $user->password = bcrypt('password');\n>>> $user->save();\n```\n\n**`참고`** 마이그레이션을 실행한 적이 없다면, `$ php artisan migrate` 을 먼저 하자.\n\n잘 생성되었나 확인해 보자.\n\n```bash\n# $hidden 속성에 의해 password와 remember_token은 노출되지 않는다.\n$ php artisan tinker\n>>> App\\User::first();\n=> App\\User {#684\n     id: 1,\n     name: \"John Doe\",\n     email: \"john@example.com\",\n     created_at: \"2015-11-10 09:20:09\",\n     updated_at: \"2015-11-10 09:20:09\",\n   }\n```\n\n## 사용자를 인증해 보자.\n\n기본을 이해하기 위해 이번에도 app/Http/routes.php를 이용하자.\n\n```php\nRoute::get('auth', function () {\n    $credentials = [\n        'email'    => 'john@example.com',\n        'password' => 'password'\n    ];\n\n    if (! Auth::attempt($credentials)) {\n        return 'Incorrect username and password combination';\n    }\n\n    return redirect('protected');\n});\n\nRoute::get('auth/logout', function () {\n    Auth::logout();\n\n    return 'See you again~';\n});\n\nRoute::get('protected', function () {\n    if (! Auth::check()) {\n        return 'Illegal access !!! Get out of here~';\n    }\n\n    return 'Welcome back, ' . Auth::user()->name;\n});\n```\n\n서버를 부트업하고 브라우저에서 'auth' Route로 접근해 보자. 인증이 성공되고 바로 'protected' Route로 넘어가는 것을 확인할 수 있다. \n\n이해를 돕기 위해, 'auth' Route의 Closure에다 인증에 필요한 정보를 하드코드를(`$credentials`) 박았다. 실전에서는 `Request::input('email')`과 같은 식으로 받아야 한다. **`Auth::attempt()` 메소드에 `$credentials`를 넘기면, 단순히 true/false만 리턴하는 것이 아니라, 백그라운드에서는 서버에 로그인한 사용자의 세션도 생성한다**는 것을 기억하자.\n\n정상적으로 로그인되고 Redirect되어 'protected' Route로 들어 왔다면 사용자의 세션 정보가 서버에 생성되었을 것이다. 사용자가 로그인되어 있는 지 확인하는 메소드가 `Auth::check()` 이다. 실험을 위해 브라우저에서 'auth/logout' Route로 접근하여 (`Auth::logout()`) 사용자를 로그아웃 시킨 후, 'protected' Route로 다시 접근해 보자.\n \n## 'auth' 미들웨어 \n\n여기서 잠깐! 만약 로그아웃한 후 'protected' Route를 방문했는데 if 블럭이 없었다면 어떻게 될까? `ErrorException-Trying to get property of non-object` 가 발생했을 것이다. 로그인 되지 않았기 때문에 `Auth::user()` 는 null 이고, `null->name`은 성립되지 않기 때문에 예외가 발생한 것이다. if 블럭을 사용하지 않고 Null Pointer를 예방하는 방법이 바로 'auth' 미들웨어 이다.\n\n'auth' 미들웨어를 사용하도록 app/Http/routes.php 를 수정해 보자.\n \n```php\nRoute::get('protected', [\n    'middleware' => 'auth',\n    function () {\n        return 'Welcome back, ' . Auth::user()->name;\n    }\n]);\n```\n \n로그아웃한 후 'protected' Route로 다시 접근해 보자.\n\n## NotFoundHttpException\n\n'auth' 미들웨어는 app/Http/Middleware/Authenticate.php 에 위치하고 있다. 코드를 들여다 보면, 로그인이 안되어 있으면 'auth/login' 으로 Redirect 하도록 되어 있다. 해당 Route가 없어서 그런 것이니, 만들자. app/Http/routes.php 를 다시 수정하고, 'protected' Route를 방문해 보자.\n\n```php\nRoute::get('auth/login', function() {\n    return \"You've reached to the login page~\";\n});\n```\n\n**`참고`** 방금 본 'auth' 미들웨어는 Route by Route로 사용자가 선택해서 적용할 수 있는 'Route 미들웨어'라 한다. 반면, 앞 강좌에서 보았던 'csrf' 미들웨어는 'HTTP 미들웨어'라 칭한다. HTTP 미들웨어는 모든 HTTP 요청이 무조건 거쳐야 하는 글로벌 미들웨어라고 생각하면 된다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [15강 - 중첩된 리소스](15-nested-resources.md)\n- [17강 - 라라벨에 내장된 사용자 인증](17-authentication-201.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/17-authentication-201.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 17\n---\n\n# 17강 - 라라벨에 내장된 사용자 인증\n\n16강에 이어 이번 강좌에서는 라라벨에 딸려서 배포(Shipping)되는 인증 기능을 살펴 보자. 내장된 사용자 인증 기능은 특정 시간내에 로그인 실패가 많으면 로그인을 제한하는 쓰로틀링 기능이 포함되어 있고, 좀 더 나이스하게 코드를 구조화해 놓았다. 핵심은 16강과 동일하다.\n\n## Controllers\n\napp/Http/Controllers/Auth 디렉토리를 보면 2개의 파일이 보인다.\n- AuthController.php - 새 사용자 등록과 로그인/로그아웃 로직을 포함하고 있다.\n- PasswordController.php - 패스워드 리셋 로직을 포함하고 있다. (이 강좌에서는 다루지 않는다.)\n\n## Routes\n\napp/Http/routes.php 를 열어 아래 내용을 추가 하자.\n\n```php\nRoute::get('/', function() {\n    return 'See you soon~';\n});\n\nRoute::get('home', [\n    'middleware' => 'auth',\n    function() {\n        return 'Welcome back, ' . Auth::user()->name;\n    }\n]);\n\n// Authentication routes...\nRoute::get('auth/login', 'Auth\\AuthController@getLogin');\nRoute::post('auth/login', 'Auth\\AuthController@postLogin');\nRoute::get('auth/logout', 'Auth\\AuthController@getLogout');\n\n// Registration routes...\nRoute::get('auth/register', 'Auth\\AuthController@getRegister');\nRoute::post('auth/register', 'Auth\\AuthController@postRegister');\n```\n\n**`참고`** `AuthController`를 눈 씻고 찾아 봐도, `getLogin()` 메소드를 찾을 수 없다. 이들 메소드는 `Illuminate\\Foundation\\Auth\\AuthenticateUsers` 트레이트 에서 찾을 수 있다.\n\n## Views\n\n뷰는 라라벨에 기본 포함되어 있지 않다. [공식 문서](http://laravel.com/docs/authentication#included-views)를 참조해서 뷰를 만들자.\n\n### 로그인 폼 - resources/views/auth/login.blade.php\n\n```html\n@extends('master')\n\n@section('content')\n  <form method=\"POST\" action=\"/auth/login\">\n    {!! csrf_field() !!}\n\n    <div>\n      Email\n      <input type=\"email\" name=\"email\" value=\"{{ old('email') }}\">\n    </div>\n\n    <div>\n      Password\n      <input type=\"password\" name=\"password\" id=\"password\">\n    </div>\n\n    <div>\n      <input type=\"checkbox\" name=\"remember\"> Remember Me\n    </div>\n\n    <div>\n      <button type=\"submit\">Login</button>\n    </div>\n  </form>\n@stop\n```\n\n### 사용자 등록 폼 - resources/views/auth/register.blade.php\n\n```html\n@extends('master')\n\n@section('content')\n  <form method=\"POST\" action=\"/auth/register\">\n    {!! csrf_field() !!}\n\n    <div>\n      Name\n      <input type=\"text\" name=\"name\" value=\"{{ old('name') }}\">\n    </div>\n\n    <div>\n      Email\n      <input type=\"email\" name=\"email\" value=\"{{ old('email') }}\">\n    </div>\n\n    <div>\n      Password\n      <input type=\"password\" name=\"password\">\n    </div>\n\n    <div>\n      Confirm Password\n      <input type=\"password\" name=\"password_confirmation\">\n    </div>\n\n    <div>\n      <button type=\"submit\">Register</button>\n    </div>\n  </form>\n@stop\n```\n\n## 실험해 보자.\n\n서버를 부트업하고, 'auth/register' 와 'auth/login' Route를 방문해 보자. 사용자를 등록하고, 로그인/로그아웃('auth/logout') 해보자.\n\n**`참고`** 라라벨에서 기본 제공하는 인증에서 패스워드는 최소 6자리 이상이어야 한다. `App\\Http\\Controllers\\Auth\\AuthController@validator` 메소드를 보면 `'password' => 'required|confirmed|min:6'` 라고 유효성 검사 규칙이 지정되어 있는 것을 확인할 수 있다. 유효성 검사, 뷰에 쓰인 `old()` 함수에 대해서는 뒤에서 다시 살펴보도록 하자.\n\n**`참고`** 다음으로 넘어가기 전에 로그인 뷰에서 소스보기를 해 보자. `<input type=\"hidden\" name=\"_token\" value=\"jPR...nO2\">` 란 라인을 볼 수 있다. 바로 `csrf_field()` Helper Function이 CSRF 공격을 막기 위해 만든 토큰을 담은 숨은 입력 폼이다. 13강에서 공부한 내용이다. `{!!  !!}`은 '<', '>' 같은 특수문자의 '&lt;', '&gt;' Escaping 되는 것을 막기 위한 블레이드의 Interpolation 문법이다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [16강 - 사용자 인증 기본기](16-authentication.md)\n- [18강 - 모델간 관계 맺기](18-eloquent-relationships.md)\n<!--@end-->\n\n"
  },
  {
    "path": "lessons/18-eloquent-relationships.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 18\n---\n\n# 18강 - 모델간 관계 맺기\n\n쿼리빌더 없이 여러 개의 테이블에서 Join Query하는 것은 정말 번거로운 일이다. 엘로퀀트 ORM을 이용해서 모델간에 관계를 연결하고, 손쉽게 관계된 모델의 속성값들에 접근해 보자.\n\n## 테이블 연결\n\n이전 강좌를 통해 만든 users와 posts 테이블 간의 관계를 생각해 보자. User는 여러 개의 Post를 만들 수 있다. 하나의 Post는 한명의 User에 속한다. 즉, one to many 관계가 형성된다. 테이블을 수정하기 위해 새로운 마이그레이션을 작성하자.\n\n```bash\n$ php artisan make:migration add_user_id_to_posts_table\n```\n\n```php\nclass AddUserIdToPostsTable extends Migration\n{\n    public function up()\n    {\n        Schema::table('posts', function(Blueprint $table) {\n            $table->integer('user_id')->unsigned()->after('id');\n            $table->foreign('user_id')->references('id')->on('users')\n                ->onUpdate('cascade')->onDelete('cascade');\n        });\n    }\n\n    public function down()\n    {\n        Schema::table('posts', function(Blueprint $table) {\n            $table->dropForeign('posts_user_id_foreign'); \n            $table->dropColumn('user_id');\n        });\n    }\n}\n```\n\n`up()` 메소드를 살펴보자. posts 테이블에 user_id 필드를 생성한다. user_id가 음수가 될 수 없으므로 `unsigned()`를 체인했다. 테이블을 생성할 때 외래 키 연결을 하지 않았으므로, 마이그레이션에서 `foreign()` 메소드를 이용하여 `posts_user_id_foreign` 란 이름을 가진 관계를 생성하였다. `references()`, `on()`, `onUpdate()`, `onDelete()` 메소드 들을 사용한 것을 주의 깊게 살펴 보자.\n\n`down()` 메소드는 `dropForeign()`을 `dropColumn()` 보다 먼저 호출했다. 이유는 외래키 연결이 있는 관계에서 컬럼을 삭제할 수 없기 때문이다.\n\n마이그레이션하자.\n\n```bash\n$ php artisan migrate\n```\n\n## 모델간 관계를 연결하자.\n\nUser has many Post. Post belongs to a User. 이 관계를 기억하고, User 모델을 열어 보자.\n\n```php\nclass User extends Model implements ...\n{\n    public function posts() {\n        return $this->hasMany('App\\Post');\n    }\n}\n```\n\n`$this (== App\\User)`는 여러 개의 `App\\Post`를 가질 수 있다라는 식으로 읽으면 되겠다. `posts()`라는 복수 형태로 쓴 것을 유의하자. 실제로 `posts()` 메소드의 최종 결과값이 Collection이기 때문이다. 가령, 메소드 이름을 전혀 생뚱한 `abc()`로 해도 되지만, 사람이 읽어 이해할 수 있는 이름으로 짓는게 좋은 습관이다. 팅커링해 보자.\n\n```bash\n$ php artisan tinker\n>>> App\\User::find(1)->posts()->get();\n=> Illuminate\\Database\\Eloquent\\Collection {#686\n     all: [],\n   }\n```\n\n[] 이 반환되었다. id 1번을 갖는 User 가 생성한 Post가 없기 때문이다. 만들어 보자.\n\n**`팁`** 앞 강의에서 Post 모델에 수정했던 `public $timestamps = false;` 코드는 삭제하자.\n\n```bash\n$ php artisan tinker\n>>> App\\User::find(1)->posts()->create([\n... 'title' => 'My First Article',\n... 'body' => 'My post body...'\n... ]);\n=> App\\Post {#697\n     title: \"My First Article\",\n     body: \"My post body...\",\n     user_id: 1,\n     updated_at: \"2015-11-10 12:33:35\",\n     created_at: \"2015-11-10 12:33:35\",\n     id: 1,\n   }\n```\n\n`find()`로 가져온 User 인스턴스에 `posts()->create()` 메소드를 체인한 것을 주의 깊게 보자. 생성된 Post 모델에 user_id가 자동으로 1이 입력된 것을 확인하자. 좀 더 팅커링해 보자.\n\n```bash\n$ php artisan tinker\n>>> $posts = App\\User::find(1)->posts()->get(); # == App\\User::find(1)->posts\n=> Illuminate\\Database\\Eloquent\\Collection {#687\n     all: [\n       App\\Post {#674\n         id: 1,\n         user_id: 1,\n         title: \"My First Article\",\n         body: \"My post body...\",\n         created_at: \"2015-11-10 12:33:35\",\n         updated_at: \"2015-11-10 12:33:35\",\n       },\n     ],\n   }\n>>> $posts[0]->title;\n=> \"My First Article\"\n>>> $post = App\\Post::find(1);\n=> App\\Post {#689\n     id: 1,\n     user_id: 1,\n     title: \"My First Article\",\n     body: \"My post body...\",\n     created_at: \"2015-11-10 12:33:35\",\n     updated_at: \"2015-11-10 12:33:35\",\n   }\n>>> $post->user()->get();\n# BadMethodCallException with message 'Call to undefined method Illuminate\\Database\\Query\\Builder::user()'\n```\n\n`App\\User::find(1)->posts` 형태로도 1번 id User의 Post Collection을 가져올 수 있다는 것을 기억하자. 실전에서는 `Auth::user()->posts` 와 같이 현재 로그인한 사용자의 모든 Post 를 가져오는 식으로 많이 사용하게 될 것이다. \n \n## 반대 방향 관계 (Reverse Relationship)\n\n$user->posts 가 가능하다면, $post->user 도 가능해야 한다. 그런데 위 팅커링에서는 `BadMethodCallException`이 발생했다. 이유는 User 모델에 Post와 관계를 설정해 주었지만, Post 모델에는 User와의 관계가 설정되어 있지 않기 때문이다. Post 모델을 열자.\n\n```php\nclass Post extends Model\n{\n    public function user() {\n        return $this->belongsTo('App\\User');\n    }\n}\n```\n\n`$this (== App\\Post)`는 `App\\User`에 속한다 라고 읽어 보자. 이제 역방향 관계 설정이 잘 되었는 지 확인해 보자.\n\n```bash\n$ php artisan tinker\n>>> App\\Post::find(1)->user()->first();\n=> App\\User {#691\n     id: 1,\n     name: \"John Doe\",\n     email: \"john@example.com\",\n     created_at: \"2015-11-10 09:20:09\",\n     updated_at: \"2015-11-10 09:36:52\",\n   }\n```\n\n**`참고`** 위 예에서 posts 테이블에 컬럼을 `user_id`로 하지 않았다면 어떻게 해야 하나? 이때는 관계를 설정할 때, `return $this->hasMany('App\\Post', 'custom_field_name');`, `return $this->belongsTo('App\\User', 'custom_foreign_key');` 처럼, 엘로퀀트에게 컬럼 이름을 알려 주어야 한다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [17강 - 라라벨에 내장된 사용자 인증](17-authentication-201.md)\n- [19강 - 데이터 심기](19-seeder.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/19-seeder.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 19\n---\n\n# 19강 - 데이터 심기\n \n앞에서 마이그레이션으로 테이블을 만들어 보았다. 만들어진 테이블에 테스트 데이터 또는 기본 데이터를 심는 과정을 씨딩(Seeding)이라 한다. 라라벨 5부터 Seeding을 효율적으로 하기 위한 Factory 기능이 제공된다. Factory는 데이터베이스 Seeding 뿐만 아니라, 테스트 클래스에서 필요한 데이터를 Stubbing하는데도 유용하게 사용할 수 있다.\n\n## Model Factory\n\ndatabase/factories/ModelFactory.php 를 살펴보자. `App\\User` 모델에 대한 Factory는 기본 제공되는 것을 알 수 있다. `App\\Post` 모델에 대한 Factory를 정의해 보자.\n\n```php\n$factory->define(App\\Post::class, function (Faker\\Generator $faker) {\n    return [\n        'title'   => $faker->sentence,\n        'body'    => $faker->paragraph,\n        'user_id' => App\\User::all()->random()->id\n    ];\n});\n```\n\n`$faker`는 다양한 형태의 Dummy 데이터를 생성해 주는 클래스이다. 'user_id'를 생성할 때, `App\\User::all()->random()->id`를 쓴 것을 주목해 보자. 아무리 테스트를 위한 데이터 심기라 하지만 실제 존재하는 User를 Post와 연결해야 하기 때문이다.\n\n**`참고`** php 5.5 이상에서는 `'App\\Post'` 대신 `App\\Post::class`와 같은 문법으로 사용할 수 있다. 문자열이 아니기 때문에 phpStorm 같은 IDE에서 해당 클래스로 이동할 때 편리하다(<kbd>Cmd</kbd> + Click).\n \n팅커링 해 보자.\n\n```bash\n$ php artisan tinker\n>>> factory('App\\User')->make();\n=> App\\User {#707\n     name: \"Louvenia McDermott Sr.\",\n     email: \"filiberto.moore@gmail.com\",\n   }\n>>> factory('App\\User', 2)->make(); # Instance 2개 생성\n=> Illuminate\\Database\\Eloquent\\Collection {#700\n     all: [\n       App\\User {#703\n         name: \"Jany Ullrich\",\n         email: \"skunde@friesen.org\",\n       },\n       App\\User {#712\n         name: \"Ms. Shanelle Heller III\",\n         email: \"walker84@lebsack.com\",\n       },\n     ],\n   }\n```\n\n**`참고`** `factory()` Helper 에서 호출한 `make()` 메소드는 메모리에 모델 인스턴스만 생성하는 반면, 곧 보게 될 `create()` 메소드는 모델 인스턴스를 생성하고 DB에 저장하는 일까지 한다. \n\n## Seeder 클래스\n\ntinker해 보았던 것을 이제 Seeder 클래스로 만들자.\n\n```bash\n$ php artisan make:seed UsersTableSeeder\n$ php artisan make:seed PostsTableSeeder\n```\n\n`factory()` Helper Function을 이용해서 Seeder 클래스를 채우자. `truncate()` 메소드는 모델과 연결된 테이블 데이터를 깨끗이 지워주는 역할을 해 준다.\n\n```php\n// database/seeds/UsersTableSeeder\nclass UsersTableSeeder extends Seeder \n{\n    public function run() \n    {\n        App\\User::truncate();\n        factory('App\\User', 10)->create();\n    }\n}\n\n// database/seeds/PostsTableSeeder\nclass PostsTableSeeder extends Seeder\n{\n    public function run()\n    {\n        App\\Post::truncate();\n        factory('App\\Post', 20)->create();\n    }\n}\n```\n\nSeeder 클래스가 완성되었으면 마스터 Seeder 클래스인, database/seeds/DatabaseSeeder.php 에 등록하자. `Model::ungard()`는 모든 모델에 대해 MassAssignment를 허용한다는 의미이다.\n\n```php\nclass DatabaseSeeder extends Seeder\n{\n    public function run()\n    {\n        Model::unguard();\n\n        $this->call(UsersTableSeeder::class);\n        $this->command->info('users table seeded');\n        \n        $this->call(PostsTableSeeder::class);\n        $this->command->info('posts table seeded');\n\n        Model::reguard();\n    }\n}\n\n```\n\n## Seeding 하자.\n\n이제 모든 준비가 완료되었으니, Seeding을 하자.\n\n```bash\n$ php artisan db:seed\n```\n\n## QueryException\n\n```bash\n[Illuminate\\Database\\QueryException]\n  SQLSTATE[42000]: Syntax error or access violation: 1701 Cannot truncate a table referenced in a foreign key constraint ...\n```\n\n왜 발생했을까? `truncate()` 메소드 호출에서 `posts.user_id` 와 `users.id` 간의 Foreign Key 제약 때문에 테이블의 레코드 삭제가 불가해서 발생한 것이다. database/seeds/DatabaseSeeder.php에 아래 2 라인을 추가하고 Seeding을 다시 실행해 보자.\n\n```php\nclass DatabaseSeeder extends Seeder\n{\n    public function run()\n    {\n        DB::statement('SET FOREIGN_KEY_CHECKS=0');\n        ...\n        DB::statement('SET FOREIGN_KEY_CHECKS=1');\n    }\n}\n```\n\n이제 될 것이다.\n\n```bash\n$ php artisan db:seed\n```\n\nSeeding이 잘 되었는 지, DB 테이블을 확인해 보자.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [18강 - 모델간 관계 맺기](18-eloquent-relationships.md)\n- [20강 - Eager 로딩](20-eager-loading.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/20-1-pagination.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 21\n---\n\n# 페이징\n\n모델에 데이터가 많아지면 한번에 모든 레코드를 표시할 수가 없게 된다. 이때 필요한 것이 페이징이다.\n\n## 페이징된 콜렉션 만들기\n\napp/Http/routes.php 에 아래와 같이 Route를 써 보자. 모델에 대한 쿼리 끝에 `get()` 이나 `find()` 대신, `paginate()` 메소드를 체인하면 페이징을 위한 준비 완료! 인자는 한번에 반환할 Collection 갯수를 넣는다. 이 예제에서는 10개로 했다.\n\n```php\nRoute::get('posts', function() {\n    $posts = App\\Post::with('user')->paginate(10);\n\n    return view('posts.index', compact('posts'));\n});\n```\n\n## 페이징된 결과 보기\n\n라라벨 페이징은 [twitter bootstrap](http://getbootstrap.com/)과 완벽하게 호환된다. 확인을 위해 resources/views/master.blade.php 에 bootstrap 사용을 선언하자.\n\n```html\n<head>\n  ...\n  <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css\">\n</head>\n```\n\n20강에서 사용하던 resources/views/posts/index.blade.php 를 그대로 사용하자. `@stop` 바로 전에 아래 코드를 추가하자.  `paginate()` 메소드를 체임함으로써, `$posts` 객체는 페이징이 가능한 Paginator 인스턴스로 변경되었고 `render()` 메소드를 쓸 수 있게 된 것이다. 렌더링된 뷰에서 소스보기를 해서 어떤 코드가 추가되었는 지 확인해 보자.\n\n```html\n...\n  @if($posts)\n    <div class=\"text-center\">\n      {!! $posts->render() !!}\n    </div>\n  @endif\n@stop\n```\n\n![](./images/20-1-pagination-img-01.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [20강 - Eager 로딩](20-eager-loading.md)\n- [21강 - 메일 보내기](21-mail.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/20-eager-loading.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 20\n---\n\n# 20강 - Eager 로딩\n\nEager 로딩은 N+1 쿼리 문제를 해결해 주는 방법이다. 겁먹을 필요 없다, 아주 간단하니까.\n\n## N+1 쿼리 문제를 만들어 보자.\n\n\"18강 모델 관계 맺기\" Post와 User 모델을 그대로 사용하자. app/Http/routes.php 를 작성하자.\n\n```php\nRoute::get('posts', function() {\n    $posts = App\\Post::get();\n\n    return view('posts.index', compact('posts'));\n});\n```\n\nresources/views/posts/index.blade.php를 만들자. \"19강 데이터 심기\" 에서 만든 Post 모델의 'title'과, Post 작성자의 'name'을 뷰에 뿌릴 것이다. `@forelse` 루프 안에서 `{{ $post->user->name }}` 와 같은 식으로 User 모델의 'name' 속성에 접근한 것을 확인하자. \n\n```html\n@extends('master')\n\n@section('content')\n  <h1>List of Posts</h1>\n  <hr/>\n  <ul>\n    @forelse($posts as $post)\n      <li>\n        {{ $post->title }}\n        <small>\n          by {{ $post->user->name }}\n        </small>\n      </li>\n    @empty\n      <p>There is no article!</p>\n    @endforelse\n  </ul>\n@stop\n```\n\n서버를 부트업하고 'posts' Route를 방문해 보자. 잘 출력되었는데 이게 무슨 문제란 것인가? 자 여기서 실제 백그라운드에서 발생하는 쿼리를 살펴 보자. app/Http/routes.php 에 아래 코드를 넣고, 브라우저에서 페이지를 새로고침 해 보자.\n\n```php\nDB::listen(function($sql, $bindings, $time){\n    var_dump($sql);\n});\n```\n\n**`알림`** 라라벨 5.2를 사용한다면 위 코드에서 에러가 날 것이다. [여기를 참고](https://github.com/appkr/l5essential/issues/12)해서 알맞게 코드를 수정하자. \n\n다음과 같은 쿼리를 볼 수 있다. 즉, `{{ $post->user->name }}` 에서 매번 쿼리를 하는 것이다.\n\n- `select * from posts` x 1건\n- `select * from users where users.id = ? limit 1` x N건\n\n![](./images/20-eager-loading-img-01.png)\n\n## Eager 로딩으로 N+1개의 쿼리를 2개로 만들어 보자.\n\napp/Http/routes.php 에서 엘로퀀트 쿼리를 아래와 같이 수정하고 브로우저에서 페이지를 새로고침해 보자.\n \n```php\nRoute::get('posts', function() {\n    $posts = App\\Post::with('user')->get();\n\n    return view('posts.index', compact('posts'));\n});\n```\n\n쿼리가 2개로 줄어든 것이 보이는가?\n\n- `select * from posts` x 1건\n- `select * from users where users.id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` x 1건\n\n`with(string|array $relations)` 메소드는 항상 엘로퀀트 모델 바로 뒤, 다른 메소드를 체인하기 전에 써야 한다. 메소드의 인자는 테이블 이름이 아니라, 모델 클래스에서 정의한 관계를 나타내는 메소드 이름임을 잘 기억하자.\n\n## Lazy Eager 로딩\n\n가끔 엘로퀀트를 이용한 쿼리를 먼저 만들어 놓고, 나중에 관계를 로드해야 하는 경우가 발생할 수 있다. 예를 들면, 쿼리 하나를 여러 번 재사용할 경우, 앞에서는 Eager 로딩이 필요없었지만, 나중에 필요하게 되는 경우 등이 해당된다. 이때는 `load(string|array $relations)` 메소드를 이용할 수 있다.\n\n```php\nRoute::get('posts', function() {\n    $posts = App\\Post::get();\n    $posts->load('user');\n\n    return view('posts.index', compact('posts'));\n});\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [19강 - 데이터 심기](19-seeder.md)\n- [추가 - 페이징](20-1-pagination.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/21-mail.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 22\n---\n\n# 21강 - 메일 보내기\n\n## mailgun 서비스 가입하자\n\n실습을 위해 라라벨에 기본 값으로 설정되어 있는 [Mailgun 서비스](http://www.mailgun.com/)에 가입하자. 월 1만통까지는 공짜라고 한다. 가입 후 반드시, 가입할 때 사용한 메일 계정으로 들어가서 활성화 링크를 눌러줘야 정상적으로 메일 발송이 가능하다. \n\n## 메일 설정\n\nconfig/mail.php 를 열어 보내는 사람 정보를 채우자.\n\n```php\n'from' => ['address' => 'john@example.com', 'name' => 'John Doe'],\n```\n\n.env 를 열어 메일을 설정해 보자. MIAL_ 로 시작하는 나머지 설정은 모두 지우자.\n\n```bash\nMAIL_DRIVER=smtp\nMAIL_USERNAME=your_mailgun_login_email\nMAIL_PASSWORD=your_mailgun_login_password\n```\n\n## 메일을 보내 보자.\n\napp/Http/routes.php 에 메일을 보내는 Route를 작성하자. 노파심에 다시 얘기하면, 학습을 위해 편의상 routes.php 에 작성하지만, 실전에서는 컨트롤러 (또는 서비스 로직)에 들어가야 하는 내용이다.\n\n```php\nRoute::get('mail', function() {\n    $to = 'YOUR@EMAIL.ADDRESS';\n    $subject = 'Studying sending email in Laravel';\n    $data = [\n        'title' => 'Hi there',\n        'body'  => 'This is the body of an email message',\n        'user'  => App\\User::find(1)\n    ];\n\n    return Mail::send('emails.welcome', $data, function($message) use($to, $subject) {\n        $message->to($to)->subject($subject);\n    });\n});\n```\n\n`send()` 메소는 3개의 인자를 받는다. 첫번째는 사용할 뷰, 두번 째는 뷰에서 바인딩 시킬 데이터, 세번째는 콜백이다.\n\n**`참고`** `send()` 대신 `queue()` 메소드를 사용하는 것이 편리하다. Queue 설정이 되어 있지 않으면, `send()`로 자동 폴백된다.\n\nresources/views/emails/welcome.blade.php 를 만들자.\n\n```html\n<h1>{{ $title }} {{ $user->name }}</h1>\n<hr/>\n<p>{{ $body }}</p>\n<hr/>\n<footer>Mail from {{ config('app.url') }}</footer>\n```\n\n블레이드 문법을 통해서 `send()` 메소드를 통해 넘겨 받은 데이터들을 바인딩하는 것을 볼 수 있다. `config(string $key) (== Config::get(string $key))` 함수를 통해 config/**.php 에 위치한 설정 값을 읽을 수 있다.\n\n브라우저를 열고 'mail' Route를 방문한 후, `$to`로 지정한 메일 계정으로 가서 이메일이 잘 왔나 확인해 보자.\n\n![](./images/21-mail-img-01.png)\n \n## 테스트 방법\n\n메일이 잘 가는 지를 테스트하기 위해 매번 실제로 메일을 보내는 것은 여러가지로 좋지 않다. 라라벨에서는 메일 테스트를 위해 'log' 드라이버를 제공하며, 메일 발송 결과를 storage/logs/laravel.log 에서 확인할 수 있다. .env에서 수정할 수 있다.\n\n```bash\nMAIL_DRIVER=log\n```\n\n로그파일은 tail 명령을 이용하면 관찰하기 편리하다.\n\n```bash\n$ tail -f ./storage/logs/laravel.log\n```\n\n**`참고`** 실전에서는 `Mail::queue()` 메소드를 한번 Wrapping 한 도메인 레이어용 메일러를 별도로 만들고, 컨트롤러의 생성자에 의존성 주입을 해서 사용한다. 또는 컨트롤러에서 이런 데이터로 메일을 보내줘라고 이벤트를 생성하고, 이벤트를 구독하는 클래스에서 별도의 프로세스로 메일을 보내는 작업을 하게 된다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [추가 - 페이징](20-1-pagination.md)\n- [22강 - 이벤트](22-events.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/22-events.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 23\n---\n\n# 22강 - 이벤트\n\n라라벨 이벤트 시스템은 Observer 또는 PubSub 패턴을 구현할 수 있게 해 준다. 필자가 알고 있는 이벤트 방식 구조체의 잇점 몇가지는 아래와 같다.\n\n- 사용자에게 빠른 응답을 제공할 수 있다. (Non blocking I/O)\n- 리스너를 여러개 구현하면, 이벤트 하나로 여러가지 작업을 동시에 수행할 수 있다.\n\n## 시나리오\n\n어떤 목적인지 모르겠지만, 사용자가 로그인 하면 users 테이블에 last_login 필드에 로그인 시간을 업데이트한다고 가정하자.\n\n**`참고`** 이벤트는 주로 IO 가 수반되는 경우에 많이 사용된다. smtp 로 이메일을 보낸다든가, HTTP 클라이언트로 외부 서비스로 부터 데이터를 가져온다든가, 파일 시스템으로부터 큰 파일을 읽을 때 등이 대표적인 예이다.\n \n## 마이그레이션\n\nusers 테이블에 last_login 필드를 추가하자.\n\n```bash\n$ php artisan make:migration add_last_login_to_users_table\n```\n\n마이그레이션 코드를 작성하자.\n\n```php\nclass AddLastLoginToUsersTable extends Migration\n{\n    public function up()\n    {\n        Schema::table('users', function(Blueprint $table) {\n            $table->timestamp('last_login')->nullable();\n        });\n    }\n\n    public function down()\n    {\n        Schema::table('users', function(Blueprint $table) {\n            $table->dropColumn('last_login');\n        });\n    }\n}\n```\n\n마이그레이션을 실행하자.\n\n```bash\n$ php artisan migrate\n```\n\nUser 모델을 수정하자. `$dates` 속성에 'last_login' 필드를 추가함으로써, 'updated_at', 'created_at' 처럼 `Carbon\\Carbon` 이 제공하는 다양한 메소드에 접근할 수 있다.\n\n```php\nclass User extends Model implements ...\n{\n    protected $dates = ['last_login'];\n}\n```\n\n## 구조체를 만들어 보자.\n\n이번에도 app/Http/routes.php 를 사용할 것이다. 제 \"16강 사용자 인증 기본기\"에서 사용했던 내용을 좀 훔쳐오자. \n \n```php\nRoute::get('auth', function () {\n    $credentials = [\n        'email'    => 'john@example.com',\n        'password' => 'password'\n    ];\n\n    if (! Auth::attempt($credentials)) {\n        return 'Incorrect username and password combination';\n    }\n\n    Event::fire('user.login', [Auth::user()]);\n\n    var_dump('Event fired and continue to next line...');\n\n    return;\n});\n\nEvent::listen('user.login', function($user) {\n    var_dump('\"user.log\" event catched and passed data is:');\n    var_dump($user->toArray());\n});\n```\n\ntinker 로 로그인에 사용할 사용자를 만들자.\n\n```bash\n$ php artisan tinker\n>>> App\\User::create([\n... 'email' => 'john@example.com',\n... 'name' => 'John Doe',\n... 'password' => bcrypt('password')\n... ]);\n=> App\\User {#684\n     email: \"john@example.com\",\n     name: \"John Doe\",\n     updated_at: \"2015-11-10 14:17:48\",\n     created_at: \"2015-11-10 14:17:48\",\n     id: 11,\n   }\n```\n\n서버를 부트업하고 브라우저에서 'auth' Route 로 접근해 보자. `Event::fire(string|object $event, mixed $payload)` 에서 이벤트를 던지고, `Event::listen(string|array $events, mixed $listener)`이 이벤트를 받아서 처리하는 식의 구조체이다. `Event::fire()` 대신 `event()` Helper Function을 이용할 수도 있다.\n\n![](./images/22-events-img-01.png)\n\n## 이벤트를 처리하자.\n\n구조체가 만들어 졌으니, 시나리오 대로 로그인 시각을 저장하자.\n\n```php\nEvent::listen('user.login', function($user) {\n    $user->last_login = (new DateTime)->format('Y-m-d H:i:s');\n\n    return $user->save();\n});\n```\n\nartisan CLI 로도 확인해 보자. 'last_login' 필드가 `Carbon\\Carbon` 인스턴스로 잘 동작하는 것을 확인할 수 있다.\n\n```bash\n$ php artisan tinker\n>>> $user = App\\User::find(11);\n=> App\\User {#672\n     id: 11,\n     name: \"John Doe\",\n     email: \"john@example.com\",\n     created_at: \"2015-11-10 14:17:48\",\n     updated_at: \"2015-11-10 14:24:36\",\n     last_login: \"2015-11-10 14:24:36\",\n   }\n>>> $user->last_login;\n=> Carbon\\Carbon {#679\n     +\"date\": \"2015-11-10 14:24:36.000000\",\n     +\"timezone_type\": 3,\n     +\"timezone\": \"UTC\",\n   }\n```\n\n## 라라벨 공식 문서에서의 이벤트\n\n처음 접하는 분들이 보기에 라라벨 공식 문서의 이벤트 설명은 정말 어렵다. 하지만, 기본적으로 위 예제와 같은 동작을 좀 더 관리하기 편리하도록 쪼개 놓은 것이라고 볼 수 있다.\n\n공식 문서의 `event(new PodcastWasPurchased($podcast))` 에서 이벤트 이름과 이벤트 데이터를 객체로 넘긴 것이며, app/Proviers/EventServiceProvider.php 에서 이벤트 이름과 이벤트 핸들러를 연결시켜 준 것이다. 연결된 이벤트 핸들러는 결국은 우리 예제의 `Event::listen()` 에 두번 째 인자로 전달한 Closure를 별도 클래스로 떼 놓은 것이다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [21강 - 메일 보내기](21-mail.md)\n- [23강 - 입력 값 유효성 검사](23-validation.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/23-validation.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 24\n---\n\n# 23강 - 입력 값 유효성 검사\n\n항상 듣는 말이다. **\"사용자가 입력한 값은 절대 신뢰하지 마라.\"** 유효성 검사는 사용자의 악의적인 해킹 시도 또는 잘못된 데이터 입력으로 부터 서비스를 보호하는 기본 중에 기본이므로 굉장히 중요하다. 프론트엔드에서 자바스크립트로 한번 걸렀다고 해도, HTTP 클라이언트를 통해서 직접 요청할 수 있으므로 백엔드에서도 반드시 유효성 검사를 수행해야 한다.\n \n## 라라벨이 지원하는 유효성 검사 규칙\n\n이 예제에서 사용하는 `required`, `min` 뿐 아니라, `string`, `confirmed`, `exists`, `required_if`, 등등등 굉장히 많다. [공식 문서](http://laravel.com/docs/validation#available-validation-rules)를 참고하자.\n\n## 유효성 검사 레이어를 만들어 보자.\n\napp/Http/routes.php 를 이용하자. 여러 번 말하지만 학습 목적이며, 실제로는 컨트롤러에 작성되어야 한다.\n\n```php\nRoute::post('posts', function(\\Illuminate\\Http\\Request $request) {\n    $rule = [\n        'title' => ['required'], // == 'title' => 'required'\n        'body' => ['required', 'min:10'] // == 'body' => 'required|min:10'\n    ];\n\n    $validator = Validator::make($request->all(), $rule);\n\n    if ($validator->fails()) {\n        return redirect('posts/create')->withErrors($validator)->withInput();\n    }\n\n    return 'Valid & proceed to next job ~';\n});\n\nRoute::get('posts/create', function() {\n    return view('posts.create');\n});\n```\n\n`Validator::make(array $formData, array $rule)` 메소드로 `Validator` 인스턴스를 만든다. 첫번 째 인자는 폼 데이터인데, 예제에서는 `$request` 인스턴스를 주입하고 `$request->all()` 로 접근했다. 두번 째 인자는 유효성 규칙이다. `Validator` 인스턴스에 대해 `fails()` 메소드로 if 테스트를 수행하고, 유효성 검사를 통과하지 못했을 경우, 'posts/create' Route로 Redirect 시켰다. 이때, `withErrors($validator)` 로 Sesson 에 에러 데이터를 굽는다. 또, `withInput()`으로 Session에 방금 넘겨 받은 폼 데이터를 'posts/create' Route로 돌아갔을 때도 쓸 수 있도록 한다.\n\n**`참고`** `$request` 인스턴스 주입 대신, `Request::input(string $key)/Input::get(string $key)`, `Request::all()/Input::all()` 과 같이 라라벨 Facade를 이용할 수도 있다. \n\n## 폼을 만들자.\n\nresources/views/posts/create.blade.php 를 만들어 보자.\n\n```html\n@extends('master')\n\n@section('content')\n  <h1>New Post</h1>\n  <hr/>\n  <form action=\"/posts\" method=\"POST\">\n    <input type=\"hidden\" name=\"_token\" value=\"{{ csrf_token() }}\"/>\n\n    <div>\n      <label for=\"title\">Title : </label>\n      <input type=\"text\" name=\"title\" id=\"title\" value=\"{{ old('title') }}\"/>\n      {!! $errors->first('title', '<span>:message</span>') !!}\n    </div>\n\n    <div>\n      <label for=\"body\">Body : </label>\n      <textarea name=\"body\" id=\"body\" cols=\"30\" rows=\"10\">{{ old('body') }}</textarea>\n      {!! $errors->first('body', '<span>:message</span>') !!}\n    </div>\n\n    <div>\n      <button type=\"submit\">Create New Post</button>\n    </div>\n  </form>\n@stop\n```\n\n이 폼에서는 `{!! $errors->first('title', '<span>:message</span>') !!}` 와 같이 블레이드 문법으로 POST 'posts' Route에서 넘겨 받은 `$errors` 인스턴스에 접근하고 있다. `$errors->all()`로 전체 에러 메시지백을 받은 후, 루프를 돌면서 에러를 뿌리는 방법도 있다. `$errors` 변수는 모든 뷰에서 항상 존재하기 때문에 `if (isset($errors))` 등과 같은 방어 조치를 할 필요가 없다는 것을 기억해 두자. `$errors`는 `withErrors()`에 의해 세션에 구워진 값이다.\n\n`{{ old(string $key) }}` Helper Function 을 사용한 것도 주의 깊게 보자. `old()`는 이전 입력 값이 Session에 없으면 '' 를 반환하고, 값이 있으면 반환한다. `withInput()`에 의해 세션에 구워진 값이다.\n\n## 테스트 해 보자.\n\n브라우저에서 'posts/create' Route를 열자. New Post 입력 폼이 열렸을 것이다. Title 입력박스에만 'First Article'이라고만 입력하고, '폼 제출' 버튼을 눌러 보자. 'post/create' `$validator->fails()` 블럭에서 'posts/create' Route로 Redirect되면서, Body 텍스트 영역 옆에 에러 메시지가 출력되었을 것이다. Title에 방금 입력했던 값이 폼에 입력되어 있는 것도 확인하자.\n\n**`참고`** `create.blade.php` 에서 `{{ var_dump(Session::all()) }}`을 넣고, 폼 전송을 다시 해 보자.\n\n## 다양한 폼 유효성 검사 방법\n\n[공식문서](http://laravel.com/docs/validation)를 보면 크게 3가지 유효성 검사 방법을 설명하고 있다.\n \n1. `Validator` 인스턴스를 직접 만드는 방법\n2. 컨트롤러에서 기본으로 사용할 수 잇는 `validate()` 메소드를 이용하는 방법\n3. `FormRequest`를 이용하는 방법\n\n1 번은 우리 예제에서 이미 다루었다.\n\n2 번은 모든 컨트롤러가 `App\\Http\\Controllers\\Controller` 라는 베이스 컨트롤러를 상속하고 있고, 베이스 컨트롤러가 포함하고 있는 `ValidatesRequests` 트레이트에 정의된 `validate()` 메소드를 이용하는 방법이다. 사용법은 1번과 거의 유사하다. 메소드의 첫 번째 인자로, 1번 방법에서는 `Request::all()` 배열을 넘긴 반면, 이 방법에서는 `Illuminate\\Http\\Request` 인스턴스 자체를 넘기면 된다. 많이 하는 질문 중에 하나가 유효성 검사 규칙을 어디에 두어야 하냐는 것인데, 정답은 없다. 컨트롤러에 두어도 되는데, 보통 모델 클래스에 Static 속성으로 정의하는 것을 많이 보았다. 아래 Post 모델과 컨트롤러의 예제를 보자.\n \n```\n// app/Http/routes.php\nRoute::resource('posts', 'PostsController');\n\n// app/Post.php\nclass Post extends Model\n{\n    public static $rules = [\n        'title' => ['required'],\n        'body' => ['required', 'min:10']\n    ];\n}\n\n// app/Http/Controllers/PostsController.php\nclass PostsController extends Controller\n{\n    public function create()\n    {\n        return view('posts.create');\n    }\n\n    public function store(Request $request)\n    {\n        $this->validate($request, \\App\\Post::$rules);\n\n        return '[' . __METHOD__ . '] ' . 'validate the form data from the create form and create a new instance';\n    }\n}\n```\n\n3 번 Form Request를 이용하는 방법이 가장 깔끔하긴 하다. [공식 문서](http://laravel.com/docs/validation#form-request-validation)를 참고하자.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [22강 - 이벤트](22-events.md)\n- [24강 - 예외 처리](24-exception-handling.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/24-exception-handling.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 25\n---\n\n# 24강 - 예외 처리\n\n## 예외 던지기\n\n라라벨에서 예외(Exception)는 컨트롤러 또는 서비스 로직을 수행하는 도중 어디서든 던질 수 있다. app/Http/routes.php를 이용하여, 예외를 던지는 방법은 실습해 보자.\n\n```php\nRoute::get('/', function() {\n    throw new Exception('Some bad thing happened');\n});\n```\n\n'/' Route로 접근해서 Whoops 페이지를 확인해 보자. `throw new My\\Name\\Space\\CustomException('message');` 처럼 자신만의 Exception 클래스를 만들어서 던질 수도 있다. \n\n**`참고`** Production 환경에서는 보안을 위해 Stack Trace가 모두 찍히는 DEBUG 옵션을 꺼야 한다. .env 파일에서 `APP_ENV=production`, `APP_DEBUG=false`로 바꾼 후 '/' Route를 다시 방문해 보자. 웹 서버를 재시작해야 변경 내용을 확인할 수 있다.\n\n또 다른 방법은 `abort(404)` 처럼, `abort(int $code, string $message)` Helper Function을 이용하는 방법이다. `abort()`는 `HttpException` 을 던진다. \n\n## 예외를 캐치하자.\n\n라라벨에서는 `try{} catch($e){}` 로 싸지 않아도, 글로벌 하게 예외를 잡아준다. 바로 app/Exceptions/Handler.php 가 주인공이다. 클래스를 살펴보자.\n\n```php\nclass Handler extends ExceptionHandler\n{\n    protected $dontReport = [];\n\n    public function report(Exception $e) {}\n\n    public function render($request, Exception $e) {}\n}\n```\n\n`$dontReport` 속성에는 `report()` 메소드를 타지 않을 예외 클래스들의 리스트를 정의한다.\n\n`report()` 메소드는 기본적으로 로그 (storage/logs/laravel.log)에 예외의 내용을 쓴다. 여기서 관리자 이메일, 슬랙, BugSnag와 같은 외부 서비스에 예외 내용 등을 리포트하는 로직을 더 구현해 넣을 수 있다.\n\n`render()` 메소드에서는 예외를 Http 응답으로 렌더링하는 로직들을 포함한다.\n\n## 예외를 처리하자.\n\napp/Exceptions/Handler.php의 `render()` 메소드에 아래 내용을 추가해 보자. `ModelNotFoundException` 이 발생하면 지정된 뷰를 내용으로 하는 HTTP 404 응답을 반환하라는 의미이다.\n \n```php\nclass Handler extends ExceptionHandler\n{\n    public function render($request, Exception $e)\n    {\n        if ($e instanceof \\Illuminate\\Database\\Eloquent\\ModelNotFoundException) {\n            return response(view('errors.notice', [\n                'title'       => 'Page Not Found',\n                'description' => 'Sorry, the page or resource you are trying to view does not exist.'\n            ]), 404);\n        }\n\n        return parent::render($request, $e);\n    }\n}\n```\n\n`Handler@render()` 메소드에서 뷰로 리턴할 resources/views/errors/notice.blade.php 뷰를 만들자.\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <title>{{ $title }}</title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\">\n  <style>\n    * { line-height: 1.5; margin: 0; }\n    html { color: #888; font-family: sans-serif; text-align: center; }\n    body { left: 50%; margin: -43px 0 0 -150px; position: absolute; top: 50%; width: 300px; }\n    h1 { color: #555; font-size: 2em; font-weight: 400; }\n    p { line-height: 1.2; }\n    @media only screen and (max-width: 270px) {\n      body { margin: 10px auto; position: static; width: 95%; }\n      h1 { font-size: 1.5em; }\n    }\n  </style>\n</head>\n<body>\n<h1>{{ $title }}</h1>\n\n<p>{{ $description }}</p>\n</body>\n</html>\n```\n\nroutes.php 에서 `ModelNotFoundException`을 발생시키자. 해당 예외는 엘로퀀트 모델에 존재하지 않는 인스턴스를 쿼리했을 때 발생한다. 브라우저에서 '/' Route를 방문하여 렌더링 된 결과를 확인하자.\n\n```php\nRoute::get('/', function() {\n    return App\\Post::findOrFail(100);\n});\n```\n\n![](./images/24-exception-handling-img-01.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [23강 - 입력 값 유효성 검사](23-validation.md)\n- [25강 - 컴포저](25-composer.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/25-composer.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 26\n---\n\n# 25강 - 컴포저\n\n2강에서 라라벨 5 처음 설치할 때 Composer를 설치했을 것이다. 그땐 무엇인지 모르고 마냥 썼을 수도 있지만, 이제 그 정체를 조금만 핥아 보자. Composer는 php의 패키지 매니저이다. 패키지 레지스트리는 [패키지스트](https://packagist.org/)라 불린다. Java에 Maven, Python에 PyPi, Ruby에 Gem, Node에 Npm이 있다면, php엔 Composer가 있다. 라라벨도 버전 4로 넘어가면서 Composer를 본격적을 도입하고, 코어 프레임웍과 외부 패키지로 분리했다.\n\n작은 서비스를 개발할 때는 패키지를 관리하는 일이 필요없지만, 서비스가 커질 수록 패키지 관리의 필요성은 급증한다. 급기야 **패키지를 관리하지 않아서, 개발자들이 패키지에 의해서 관리 당해지는 웃지 못할 사태**가 벌어질 수 있다. 패키지 매니저를 쓸 때 개인적으로 좋은 점을 정리해 봤다.\n\n- 기억력을 보조한다 (레지스트리 역할).\n- 이미 만들어진 바퀴를 쉽게 가져다 쓰고, 모양을 약간 바꾸어 쓸 수도 있다 (Code Reuse). \n- 외부 패키지들은 버전 관리에서 빠지기 때문에 코드 풋프린트가 줄어들고 Git에 푸시 할 때 빠르다.\n- 외부 패키지들의 업데이트를 자동화할 수 있다. 즉, 일일이 확인하고, 다운로드하고, 설치해 줄 필요 없다.\n\n## 시나리오\n\n어느 날 고객사에서 기존에 개발한 블로그 서비스에 Markdown 기능을 추가해 달라는 요청을 했다고 가정해 보자. 구글링을 통해 여러 패키지들을 검토해 본 후 여러 CMS들이 쓰고 있다는 말에 낚여서 `erusev/parsedown-extra` 을 쓰기로 했다고 가정하자.\n\n**`참고`** Markdown 은 과거의 위키 문법 처럼 빠른 글쓰기는 지원하는 초경량 마크업 도구이다. 지금 보는 이 문서들이 모두 Markdown 으로 작성되었고, Github가 컴파일해 주는 것이다.\n\n## 패키지를 설치해 보자.\n\n```bash\n$ composer require \"erusev/parsedown-extra: 0.7.*\" \n# 버전 없이 쓸 때는 따옴표를 안쳐도 된다.\n# 버전 앞에 ':' 대신 '='를 쓸 수도 있다.\n```\n\n꽤 오랜 시간이 걸릴 것이다 :(. 프로젝트 디렉토리에 위치한 composer.json을 열어서 `require` 섹션에 엔트리가 정상적으로 업데이트된 것을 확인하자.\n\n```json\n{\n    \"...\": \"...\",\n    \"require\": {\n        \"php\": \">=5.5.9\",\n        \"laravel/framework\": \"5.1.*\",\n        \"erusev/parsedown-extra\": \" 0.7.*\"\n    },\n    \"...\": \"...\",\n}\n```\n\n**`참고`** 프로젝트 디렉토리에 위치한 composer.json 파일을 열고, `require` 섹션에 필요한 패키지를 직접 추가해 준 후, `$ composer update` 코맨드를 실행하는 방법으로도 설치할 수 있다.\n\n**`참고`** 라라벨 전용으로 만들어진 패키지의 경우에는 설치 후, Service Provider, Facade, 설정 파일 발행 등 해당 패키지 사용을 더 편리하게 사용하기 위한 추가적인 작업이 필요할 수 있다. 해당 패키지의 Github 또는 Packagist 페이지의 설명을 참조하자.\n\n**`참고`** 0.7.*은 0.7로 시작하는 버전 중 가장 최신 버전이란 의미이다. 모든 필드와 규칙을 설명할 수 없으므로, [공식 문서](https://getcomposer.org/doc/) 또는 XE팀에서 번역한 [한글본](https://xpressengine.github.io/Composer-korean-docs/)을 참조하자.\n\n## 패키지를 이용해 보자.\n\napp/Http/routes.php 를 이용하자.\n\n```php\nRoute::get('/', function() {\n    $text =<<<EOT\n**Note** To make lists look nice, you can wrap items with hanging indents:\n\n    -   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n        Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n        viverra nec, fringilla in, laoreet vitae, risus.\n    -   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n        Suspendisse id sem consectetuer libero luctus adipiscing.\nEOT;\n\n    return app(ParsedownExtra::class)->text($text);\n});\n```\n\n서버를 부트업하고 '/' Route를 방문해 보자. Html로 잘 포맷팅 된 문서를 보고 있으면 성공한 것이다.\n\n![](./images/25-composer-img-01.png)\n\n입력 문자열로 긴 스트림을 쓰기 위해서 [Heredoc](http://php.net/manual/kr/language.types.string.php#language.types.string.syntax.heredoc) 문법을 사용하였다. 실전에서는 POST 로 넘겨 받은 폼 데이터의, 가령 'body' 필드 값일 것이며, `Input::get('body')/Request::input('body')`로 값을 얻어 올 수 있을 것이다.\n\n설치한 `erusev/parsedown`의 [Github 페이지](https://github.com/erusev/parsedown)를 참고하여 사용법을 익혔다. 이 패키지는 `namespace`를 쓰지 않아 Root 네임스페이스에 존재한다. 인스턴스를 생성하고, `text()` 메소드에 컴파일할 문자열들을 넘겨 주었다. 실전에서는 컴파일 된 결과를 뷰의 데이터로 바인딩하거나, `markdown()`과 같은 커스텀 Helper Function을 만들어 뷰에서 직접사용하면 된다.\n\n여기서 주목할 만한 것은, `app()` 이란 Helper Function의 등장이다. 이는 `new ParsedownExtra()`와 같은 역할을 한다고 보면 된다. `app()` 을 쓰는 것이 `new` 키워드를 쓰는 것 보다 더 좋은 점은 `ParsedownExtra` 클래스의 생성자에 주입되는 다른 인스턴스가 있다면(의존성 주입), `app()`의 경우 자동으로 주입을 해 준다. 다시 설명하면, `new` 키워드를 썼을 때에 꼭 해야 하는, 아래 예와 같이 복잡한 의존성 주입이 필요없다는 얘기다. 이는 라라벨의 Service Container 의 기능인데, 이 코스의 범위를 벗어난다 생각되므로, [공식 문서](http://laravel.com/docs/container)를 참조하기 바란다.\n\n```php\n$sb = new SkateBoard(new Roller(new Wheel, new Joint), new Plate);\n$sb->run();\n```\n\n## 어디에 어떤 패키지가 있는 지 어떻게 알아요?\n\n유용성, 인기도, 완성도 측면에서 검증되어 큐레이션된 패키지 들이 있는 곳을 소개한다. 필요한 기능이 있다면 직접 만들려 하지 말고, 이 목록을 탐색하고 구글링해 보자.\n\n- [ziadoz/awesome-php](https://github.com/ziadoz/awesome-php)\n- [chiraggude/awesome-laravel](https://github.com/chiraggude/awesome-laravel)\n- [TimothyDJones/awesome-laravel](https://github.com/TimothyDJones/awesome-laravel)\n\n> **`참고`** 컴포저를 사용하다 보면, 아래와 같은 메시지를 만나는 경우가 있다. Github 에 정해진 시간당 요청할 수 있는 한도를 초과했다는 의미인데, 메시지를 자세히 보면 답이 있다. 제시한 URL 로 이동하여 토큰을 만들고, 복사하여 'Token(hidden):' 에 붙여 넣으면 끗! \n> Could not fetch https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4, please create a GitHub OAuth token to go over the API rate limit.  \n> Head to https://github.com/settings/tokens/new?scopes=repo&description=xxx to retrieve a token. It will be stored in \"/home/vagrant/.composer/auth.json\" for future use by Composer.  \n> Token (hidden):\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [24강 - 예외 처리](24-exception-handling.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/26-document-model.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 27\n---\n\n# 실전 프로젝트 1 - Markdown Viewer \n\n라라벨 공식 문서와 유사하게 왼쪽 사이드바에 문서 목록, 오른쪽 본문 영역에 HTML 로 컴파일된 문서가 표시되는 헝태로 최종 목표이미지를 잡아 보자. 이 실전 프로젝트를 통해 25강까지 배운 기본기 외에 Filesystem, Custom Helper, Cache, Elixir 등을 더 사용해 보게될 것이다.\n\n## 26강 - Document 모델\n\n이 강좌의 마크다운 문서들은 docs 폴더에 위치하고 있다. 생각해 보면, DB 테이블에서 데이터를 가져오는 것이 아니라, 파일시스템에서 가져와야 한다. 파일시스템에 접근하는 방법을 알아 보자.\n  \n### File vs Storage\n\n라라벨에서 `File`과 `Storage` 2개의 Facade가 있다. 공식문서에서 `File`이 빠진 것으로 보아 `Storage`의 사용을 권장하는 것처럼 보인다. 두 Facade의 API(== public 메소드)는 거의 동일하지만, `Storage`는 파일 저장위치를 config/filesystems.php 에 지정해 놓으면 그 디렉토리 밖을 벗어날 수 없다. 우리의 docs 폴더는 프로젝트 루트에 위치하므로, `File` Facade를 이용해야 한다.\n\n**`참고`** `put(string $path, string $contents)` 파일 쓰기, `files(string $directory)` 파일 목록 가져오기, `glob(string $pattern)` 패턴에 맞는 파일 목록 가져오기, `isDirectory(string $directory)` 디렉토리 체크, `makeDirectory(string $path, int $mode)` 디렉토리 만들기 등은 실전에서 자주 사용하게 되니 사용법을 익혀 두자.\n\n\n### Document 모델을 만들자.\n\n```bash\n$ php artisan make:model Document\n```\n\nDocument 모델은 엘로퀀트를 상속하지 않는다. 잘 생각해 보면, 컨트롤러의 기본 동작인 CRUD(Create, Read, Update, Delete) 중 Read만, 즉, 컨트롤러에서 요청한 이름에 해당하는 파일을 잘 읽어서 반환해 주는 메소드 하나만 필요하다.\n\n```php\n<?php\n\nnamespace App;\n\nuse Illuminate\\Support\\Facades\\File;\n\nclass Document\n{\n    private $directory = 'docs';\n\n    public function get($file = null)\n    {\n        $file = is_null($file) ? 'index.md' : $file;\n        if (! File::exists($this->getPath($file))) {\n            abort(404, 'File not exist');\n        }\n\n        return File::get($this->getPath($file));\n    }\n\n    private function getPath($file)\n    {\n        return base_path($this->directory . DIRECTORY_SEPARATOR . $file);\n    }\n}\n```\n\n`getPath()`란 메소드를 먼저 보자. `base_path()`는 프로젝트 루트 디렉토리의 절대 경로를 반환하는 Helper이다. 추가 경로를 인자를 넣으면 덧붙여서 반환해 준다. \n \n```bash\n$ php artisan tinker\n>>> base_path();\n=> \"/Users/Juwon/workspace/myProject\"\n>>> base_path('docs/file.ext');\n=> \"/Users/Juwon/workspace/myProject/docs/file.ext\"\n```\n\n**`참고`** DIRECTORY_SEPARATOR 상수는 윈도우즈 시스템에서는 `\\` *nix 에서는 `/`를 반환한다.\n\n`File::exists(string $path)` 로 인자로 넘어온 파일이 존재하지 않으면, `abort()` Helper로 404 NotFoundHttpException 을 던지도록 했다. if 테스트를 통과하면, 인자로 받은 마크다운 파일의 내용을 읽어서 반환한다. 인자로 넘겨 받은 `$file` 값이 없을 경우를 대비해, index.md 를 기본값으로 지정했다.   \n\n### 동작 테스트\n\napp/Http/routes.php 에서 동작 테스트를 해 보자. [25강 - 컴포저](25-composer.md)에서 사용한 내용을 조금만 수정해서 사용할 것이다.\n\n```php\nRoute::get('docs/{file?}', function($file = null) {\n    $text = (new App\\Document)->get($file);\n\n    return app(ParsedownExtra::class)->text($text);\n});\n```\n\n이전에 보지 못했던 `'docs/{file?}'` 엔드포인트가 먼저 눈에 띈다. 여기서 `file`을 'Route 파라미터'라고 한다. 파라미터는 중괄호로 싼다. 올드스쿨식으로 표현하자면 docs?file= 과 같다고 보면 된다. 파라미터로 받은 `$file`을 바로 뒤 콜백에 인자로 넘긴 것이 보일 것이다. 물음표는 `file` 파라미터가 있을 수도 있고 없을 수도 있다는 의미이다. 즉, docs, docs/any-text 를 모두 이 Route에서 처리한다는 의미이다. \n\n25강에 `$text` 변수의 값을 Heredoc 으로 하드코드로 넣어 주었다면, 여기서는 Document 모델의 `get()` 메소드 요청으로 부터 받아왔다. 인스턴스 생성과 메소드 호출을 인라인으로 한 줄에 표현하기 위해 () 문법을 이용하였다.\n\n서버를 부트업하고 테스트해 보자.\n\n![](./images/26-document-model-img-01.png)\n\n### 예외 처리\n\n`Document` 모델에서 `abort(404)`를 던진 것에 대한 예외처리를 하자. [24강 - 예외 처리](24-exception-handling.md)에서 배운 app/Exceptions/Handler.php 에다, `or $e instanceof NotFoundHttpException` 을 추가해 주자.\n\n```php\n    public function render($request, Exception $e)\n    {\n        if ($e instanceof ModelNotFoundException or $e instanceof NotFoundHttpException) {\n            return response(view('errors.notice', [\n                'title'       => 'Page Not Found',\n                'description' => 'Sorry, the page or resource you are trying to view does not exist.'\n            ]), 404);\n        }\n\n        return parent::render($request, $e);\n    }\n```\n\n![](./images/26-document-model-img-02.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [27강 - Document 컨트롤러](27-document-controller.md)\n<!--@end-->\n\n\n"
  },
  {
    "path": "lessons/27-document-controller.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 28\n---\n\n# 실전 프로젝트 1 - Markdown Viewer \n\n## 27강 - Document 컨트롤러\n\n이번 강좌에서는 routes.php 에서 콜백으로 정의했던 내용을 컨트롤러로 옮기고, ParsedownExtra도 좀 더 편하게 사용할 수 있도록 커스텀 Helper Function을 만들어 보자.\n\n### Custom Helper\n\n라라벨 내장 Helper Function 처럼, 여기저기서 편하게 마크다운 컴파일러를 불러 쓸 수 있도록 하기 위해, app/helpers.php 를 만들자. \n\n```php\nfunction markdown($text) {\n    return app(ParsedownExtra::class)->text($text);\n}\n```\n\n라라벨이 부트업될 때 helpers.php 파일도 포함시키기 위해, composer.json에 files 엔트리를 추가하자.\n\n```json\n\"autoload\": {\n  \"classmap\": [\"...\"],\n  \"files\": [\"app/helpers.php\"],  \n  \"psr-4\": {\"...\": \"...\"},\n},\n```\n\nautoload 파일을 리프레시하기 위해 아래 코맨드를 수행하자.\n\n```bash\n$ composer dump-autoload\n\n# autoload가 잘 되었는지 tinker 로 테스트해 보자\n$ php artisan tinker\n>>> markdown('**bold**');\n=> \"<p><strong>bold</strong></p>\"\n```\n \n### Document 컨트롤러를 만들자.\n\n```bash\n$ php artisan make:controller DocumentsController\n```\n\n잘 생각해 보면, DocumentsController도 마크다운으로 컴파일된 내용을 데이터로 하고 뷰를 리턴하는 `show()` 메소드 하나면 충분하다.\n\n```php\n<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Document;\nuse App\\Http\\Requests;\n\nclass DocumentsController extends Controller\n{\n    protected $document;\n\n    public function __construct(Document $document)\n    {\n        $this->document = $document;\n    }\n\n    public function show($file = null)\n    {\n        return view('documents.index', [\n            'index'   => markdown($this->document->get()),\n            'content' => markdown($this->document->get($file ?: '01-welcome.md'))\n        ]);\n    }\n}\n```\n\n생성자(Constructor)에서 `App\\Document` 인스턴스를 주입(Dependency Injection)했다. 뷰에 2개의 데이터를 바인딩하는데 `$index`는 왼쪽 사이드 바에 보여줄 목록이며, `$content`는 본문이다. \n\n### Route를 정의하자.\n\nRoute 정의가 훨씬 간단해 졌다. [14강 - 이름 있는 Route](14-named-routes.md)에서 배운 것 처럼, Route 이름은 필수이다.\n\n```php\nRoute::get('docs/{file?}', [\n    'as'   => 'documents.show',\n    'uses' => 'DocumentsController@show'\n]);\n```\n\n### 뷰를 만들자.\n\nresources/views/documents/index.blade.php 를 만들자.\n\n```html\n@extends('master')\n\n@section('content')\n  <header class=\"page-header\">\n    Documents Viewer\n  </header>\n\n  <div class=\"row\">\n    <div class=\"col-md-3 sidebar__documents\">\n      <aside>\n        {!! $index !!}\n      </aside>\n    </div>\n  </div>\n\n  <div class=\"col-md-9 article__documents\">\n    <article>\n      {!! $content !!}\n    </article>\n  </div>\n@stop\n```\n\n서버를 띄우고 뷰에 잘 뿌려지는지 확인해 보자.\n\n![](./images/27-document-controller-img-01.png)\n\n기본 기능은 이걸로 완료되었다. 다음 강의에서는 백엔드의 부하 감소를 위해 Cache 기능을 활용하는 것을 배우도록 하자. 좀 더 나이스하게 보이기 위해서 CSS 작업을 할 것인데, 빌드를 위해 Elixir도 사용해 볼 것이다.  \n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [26강 - Document 모델](26-document-model.md)\n- [28강 - Cache](28-cache.md)\n<!--@end-->\n\n"
  },
  {
    "path": "lessons/28-cache.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 29\n---\n\n# 실전 프로젝트 1 - Markdown Viewer \n\n## 28강 - Cache\n\n우리가 사용한 마크다운 파일은 자주 변경되지 않는다. 즉, 매번 사용자가 요청할 때 마다 모델에서 요청한 파일을 읽어 들이고, ParsedownExtra 클래스 인스턴스를 만들어서 `text()` 메소드를 호출한다는 것은 서버의 CPU 및 메모리 자원뿐만아니라 사용자의 시간을 낭비하는 일이다. 이럴 때 필요한 것이 서버측 캐시이다. 캐시는 HTTP 요청에 대한 응답을 파일 또는 메모리에 저장해 두었다가 두번째 요청부터는 저장소에서 바로 꺼내어 주는 기능이다. 데이터베이스 드라이버와 마찬가지로 라라벨 캐시도 다양한 드라이버를 지원한다.\n\n### 캐시 설정\n\n.env 와 config/cache.php를 열어서 기본 캐시 드라이버 설정을 확인하자. `file` 드라이버를 사용하고 있고, 캐시 저장소는 storage/framework/cache 인 것을 알 수 있다. 우선 실습을 위해 `file` 드라이버를 그냥 사용하도록 하자.\n\n```bash\nCACHE_DRIVER=file\n```\n\n```php\n'...' => '...',\n'file' => [\n    'driver' => 'file',\n    'path'   => storage_path('framework/cache'),\n],\n```\n\n### 컨트롤러에 캐시 기능 추가\n\n`DocumentsController::show()` 메소드를 수정할 것이다. 캐시는 `key => value` 저장소라는 것을 기억하자.\n\n```php\n    public function show($file = '01-welcome.md')\n    {\n        $index = \\Cache::remember('documents.index', 120, function () {\n            return markdown($this->document->get());\n        });\n\n        $content = \\Cache::remember(\"documents.{$file}\", 120, function() use ($file) {\n            return markdown($this->document->get($file));\n        });\n\n        return view('documents.index', compact('index', 'content'));\n    }\n```\n\n`Cache` Facade 를 이용한다. \n\n`remember()` 메소드의 첫번 째 인자는 키 이름이다. 이 키 이름으로 데이터를 저장할 것이다. 두번째 인자는 캐시를 유지할 시간이다. 키 이름에 해당하는 값이 캐시 저장소에 없으면, 세번째 인자로 받은 콜백을 실행한다. 이 콜백에서 반환되는 값을 캐시 키 값으로 해서, 두번째 인자로 지정된 시간만큼 캐시 저장소에 가지고 있는다. 지정된 시간 내에 들어온 요청에 대해서는 세번째 인자인 콜백을 실행하지 않고, 캐시 저장소에서 키 값에 대응되는 값(value)를 찾은 후 반환하는 식이다. \n\n이 예제에서는 키 이름을 `document.index` 와 `documents.문서이름`으로 지정했고, 첫 캐시가 적재된 이후 2시간 동안은 캐시에서 바로 응답하도록 했다. 가령, 8시 정각에 첫 요청이 들어와 새로운 캐시가 생성되었다면, 10시까지는 캐시에서 응답을 하다가, 10시 1초 이후에 요청이 들어오면 다시 콜백을 수행하고 캐시 저장소에 키와 값을 적재하게 된다. (무슨 얘긴지 이해 되었기를 바라는 마음에서 반복해서 설명했다.)\n\n**`참고`** 앞 강의에서 계속 Closure라는 용어를 썼다. 이번 강의에서는 콜백이란 용어를 썼다. 엄격하게 다르지만, 지금은 같은 용어라고 생각하자.\n\n**`참고`** \"어떨 때는 클래스 앞에 `\\` 를 쓰고 어떨 때는 안 쓰고 왜 그래요?\" \"이번에는 일부러 쓴 것이다.\" `\\`는 루트 네임스페이스를 의미한다. 우리 컨트롤러는 `App\\Http\\Controllers` 네임스페이스 아래에 위치한다. 컴퓨터에서 절대경로와 상대 경로를 얘기할 때랑 마찬가지로, `Cache`라고 그냥 쓰면, `App\\Http\\Controllers\\Cache`를 의미하게 되고(상대 경로), 그런 클래스는 존재하지 않는다. 해서 루트 (`\\`) 네이스페이스에 존재하는 `Cache` 라고 명시적으로 쓴 것이다. 클래스를 시작하기 전에 `use` 키워드로 전체 경로를 표시해 주면 `\\`를 생략할 수 있다. (이는 네임스페이스가 있는 모든 언어 마찬가지다. Java의 경우 `use` 대신 `import`를 사용한다. `import org.apache.http.client.HttpClient` 처럼.)\n \n### 실험해 볼까?\n\n서버를 띄우고, '/docs' Route를 처음으로 방문해 보자. 그리고, storage/framework/cache 아래에 캐시 파일이 생성된 것을 확인해 보자. 또, 'docs' Route를 다시 방문해 봐도, 우리 예제가 무겁지 않아서 별로 빨라진 것은 못 느낄 것이다. `Document::show()` 메소드에 `dd('reached')` 와 같은 디버그 코드를 넣고 다시 요청해 보자. 클라이언트 측의 요청이 캐시에 의해 바로 응답되고, `Document` 모델에 도달하지 않을 것을 알 수 있을 것이다. `docs/01-welcome.md` 를 수정하고 재요청해봐도 수정된 내용은 표시되지 않을 것이다, 2시간 동안은...\n \n### 그럼, 2시간 내에 내용이 변경되면 어떻게 하지?\n\n일단은 artisan CLI를 이용해 수동으로 지워 보자. 변경이 생기면 이벤트를 던져서 캐시를 초기화하는 것은 뒤에 다시 배운다.\n\n```bash\n$ php artisan cache:clear\n```\n \n ### (OPTIONAL) Memcached\n \n파일 캐시도 훌륭하다. 하지만 실전에서는 memcache나 redis와 같은 인 메모리(in-memory) 캐시를 주로 사용한다. 여기서는 memcached를 사용할 것이다.\n  \n.env 를 수정하자.\n\n```bash\nCACHE_DRIVER=memcached\n```\n\n먼저 이전에 사용했던 file 캐시를 삭제하고 memcached 를 설치하고 실행하자.\n\n```bash\n$ rm -rf storage/framework/cache/*\n$ brew search memcache\n$ brew install homebrew/php/php56-memcached # 자신의 php 버전에 맞는 모듈을 설치하자.\n\n# 설치 종료 후 콘솔에 표시된 memcached 시작 코맨드를 잘 살펴보자.\n# 필자의 장치에는 이미 설치되어 있어, 알고 있던 코맨드를 남긴다.\n$ memcached -u memcached -d -m 30 -l 127.0.0.1 -p 11211\n# 본 강좌랑 무관하므로 사용법은 구글링으로 찾아 보시길..\n```\n\nfile 캐시에서 했던 방법과 동일한 방법으로 캐시 기능이 잘 동작하는 지 확인해 보자. 설정 값이 변경되었으므로 테스트 전에 `$ php artisan serve` 를 재기동하는 것을 잊지 말고.\n\n**`참고`** 서버 측 뿐만 아니라, 클라이언트(브라우저) 측에서도 캐싱을 한다. 라라벨과 무관하므로 설명하지 않는다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [27강 - Document 컨트롤러](27-document-controller.md)\n- [29강 - Elixir, 만병통치약?](29-elixir.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/29-elixir.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 30\n---\n\n# 실전 프로젝트 1 - Markdown Viewer \n\n## 29강 - Elixir, 만병통치약?\n\n**`필독`** 프론트엔드에 관심이 없다면 이 강좌를 읽을 필요 없다.\n\nElixir('엘릭서'라 읽음)은 만병통치약을 뜻하는 단어이다. 라라벨의 Elixir란 이름은 어디에서 유래되었는 지 모르겠다. Elixir는 여러 기능을 가지고 있지만, 함축하자면 프론트엔드 리소스, 그러니까 CSS 와 Javascript 같은 리소스의 빌드를 자동화하는 도구라고 생각할 수 있다. 여기서 말하는 빌드란 Minification, CSS Vendor Prefixing, 여러 파일 병합, Sass/Less/Coffee/Babel 스크립트의 컴파일, ... 등을 의미한다. 프론트엔드 빌드 자동화를 수행하는 구현체는 Ruby on Rails 에서 Asset Pipeline 이란 이름으로 세상에 먼저 소개되었고, 이후 Django Pipeline 등 여러 프레임웍에서 따라한 것으로 필자는 알고 있다. 라라벨도 그중 하나!! \n\n라라벨 5 버전이 출시되고 Elixir 가 공개되기 이전에 개발자들은 [Gulp](http://gulpjs.com/)나 [Grunt](http://gruntjs.com/)를 이용하여 빌드 자동화 스크립트를 작성해 왔다. 하지만 라라벨 5의 Elixir는 기존 빌드 스크립트들의 복잡함과 어려움을 극도로 단순화하여, 초보자도 쉽게 사용할 수 있는 API를 제시하고 있다. (그럼에도 불구하고, 여전히 어렵고 복잡하다.)\n\n### 필요한 프론트엔드 리소스 정의\n\n우리 프로젝트에 필요한 프론트엔드 리소스는 무엇인가? 앞선 강좌를 통해 우린 이미 Twitter Bootstrap을 가져다 쓴 바 있다. 이번 강좌에서는 CDN 버전을 그대로 사용하지 않고, 우리 서비스의 로컬 리소스로 추가할 것이다. 그 외 아이콘을 쓰기 위한 FontAwesome, 앞으로 계속 진행될 학습을 위해 이 프로젝트 전용 스타일시트와 자바스크립트 파일을 만들 것이다. 강좌를 진행하면서 이 목록에 더 많은 프론트엔드 리소스들이 추가될 것이다. \n\n- Twitter Bootstrap\n- FontAwesome\n- resources/assets/sass/app.scss\n- resources/assets/js/app.js\n\n이번 강좌를 통해, 위에 나열된 2개의 외부 의존성과 내가 만든 2개의 리소스에 대한 빌드 자동화 방법을 배워볼 것이다.\n\n### 필요한 글로벌 툴들 설치\n\n먼저 [nodejs](https://nodejs.org)가 필요하다. 공식 사이트를 방문한 후, 인스톨러를 다운로드 받아 클릭-클릭으로 설치할 수 있다. 이 글을 쓰는 시점에 4.2.2 LTS 버전과 5.0 두 개의 버전이 존재하는데, 4.2.2 LTS를 받자. 인스톨러를 통해 node 런타임과 npm (node package manager)가 동시에 설치된다.\n\n```bash\n$ node --version # v4.2.2\n$ npm --version # 2.14.7\n```\n\nElixir는 Gulp 툴의 Wrapper이다. Gulp에 의존한다는 얘기~ 고로, 설치하자. 개발 머신 전체에서 `gulp`란 명령을 쓸 수 있도록 글로벌로(`-g`)로 설치한다.\n\n```bash\n$ sudo npm install -g gulp\n$ gulp --version # 3.9.0\n```\n\n3rd Party(남이 만든 것이란 의미. 내껀 1st Party라 한다) 스타일시트와 자바스크립트 리소스를 관리하기 위해 Bower 툴을 설치하자. \n\n```bash\n$ sudo npm install -g bower\n$ bower --version # 1.6.5\n```\n\n여기까지 작업은 다른 프로젝트에서도 계속 사용하게 될 글로벌 패키지들의 설치로, 최초 딱 한번만 수행하면 된다. 이 다음부터 설명하는 것은 매 프로젝트마다 해 주어야 하는 설치 작업이다.\n\n### Elixir 의존 패키지 설치 및 최초 실행\n\nElixir가 의존하는 node 패키지들을 설치하자. 설치할 패키지들은 package.json 파일에 정의되어 있으며, 라라벨 프로젝트가 생성될 때 같이 생성되었다. 아래 작업은 라라벨에서 `composer install` 했던 것과 동일한 작업이라 생각하면 된다.\n\n```bash\n$ npm install\n```\n\nnode_modules 폴더 아래에 뭔가 잔뜩 설치되었을 것이다. Elixir가 잘 동작하는지 확인해 보자. 아래 코맨드를 수행하기 전에 public/css 디렉토리가 있는지 확인해 보자. 없을 것이다. 코맨드 실행 후 다시 확인해 보자.\n  \n```bash\n$ gulp\n```\n\n### Bower 패키지 설치\n\nphp/composer.json, nodejs/package.json 처럼 Bower 용 패키지들을 담을 레지스트리 파일인, bower.json 을 만들자. 또, .bowerrc 파일로 Bower 패키지들의 설치 위치도 변경하자 (디폴트는 프로젝트 루트의 bower_components). 또, .gitignore 파일에 Bower 패키지 저장소가 버전 컨트롤에서 제외되도록 정의해 놓자.\n\n```bash\n$ touch bower.json && echo '{\"name\":\"myProject\"}' > bower.json # bower.json 파일을 만들고, JSON 오브젝트를 써 놓는다.\n$ touch .bowerrc && echo '{\"directory\":\"resources/assets/vendor\",\"analytics\":false}' > .bowerrc\n$ echo '/resources/assets/vendor' >> .gitignore # >> 은 기존 파일에 내용 append의 의미다.\n```\n\nBower 패키지를 설치하자. `--save-dev` 는 bower.json 파일에 devDependencies 로 써 놓는다는 의미이다. 버전 컨트롤에서 제외시켰는데, bower.json에 의존성을 써 놓았기 때문에, 다른 개발자가 프로젝트의 버전 컨트롤 저장소를 clone/pull 했을 때 `$ bower install` 코맨드로 의존성을 설치할 수 있다. 이 강좌에서는 scss 문법을 이용할 것이라, `bootstrap-sass` 패키지를 설치했다. resources/assets/vendor 디렉토리에 설치한 패키지들이 있는지 확인해 보자. \n\n```bash\n$ bower install bootstrap-sass --save-dev\n$ bower install font-awesome --save-dev\n```\n\n### 휴~ 이제 빌드 스크립트를 쓰자.\n\n`$ gulp` 명령에 반응하는 스크립트는 프로젝트 루트에 위치한 gulpfile.js 이다. 아래는 sass 컴파일하고, 자바스크립트들을 머지한 후, 파일 이름에 버전을 매기고, fonts 파일을 정해진 위치에 배포하는 gulpfile.js 스크립트이다.\n\n```javascript\nvar elixir = require('laravel-elixir');\n\nelixir(function (mix) {\n  mix\n    .sass('app.scss')\n    .scripts([\n      '../vendor/jquery/dist/jquery.js',\n      '../vendor/bootstrap-sass/assets/javascripts/bootstrap.js',\n      'app.js'\n    ], 'public/js/app.js')\n    .version([\n      'css/app.css',\n      'js/app.js'\n    ])\n    .copy(\"resources/assets/vendor/font-awesome/fonts\", \"public/build/fonts\");\n});\n```\n\nElixir의 Javascript API 들은 대부분 관례로 정해진 상대 경로를 기준으로 하므로, [문서](http://laravel.com/docs/elixir)를 잘 살펴보고 이용해야 한다. 필자가 아는 관례들은 아래에 정리해 두었다.\n\nAPI|Base Directory|Description\n---|---|---\n`less(src, output, options)`|resources/assets/less|less 문법으로 써진 스타일시트를 css로 컴파일\n`sass(src, output, options)`|resources/assets/sass|sass, scss 문법으로 써진 스타일시트를 css로 컴파일\n`styles(styles, output, baseDir)`|resources/assets/css|css 문법으로 써진 파일을 읽어서 머지하고 public/css로 배포\n`coffee(src, output, options)`|resources/assets/coffee|coffee 문법으로 써진 자바스크립트를 js로 컴파일\n`babel(scripts, output, baseDir, options)`|resources/assets/babel|ES6 또는 7 문법으로 써진 자바스크립트를 js로 컴파일\n`scripts(scripts, output, baseDir)`|resources/assets/js|js 파일을 읽어서 머지하고 public/js로 배포\n`copy(src, output)`|프로젝트 루트|`src` 파일/디렉토리를 `output`으로 복사\n`version(src, buildPath)`|public|`src`로 넘겨 받은 css, js 파일을 버전을 부여하여 public/build/css, public/build/js 디렉토리로 배포\n\nBootstrap과 FontAwesome의 스타일시트들은 `styles()` API를 이용하지 않고, app.scss에서 import 하였다. 이 과정과 무관하므로 app.scss에 작성된 내용들은 설명하지 않으므로, 소스코드를 살펴 보기 바란다.\n\n```css\n@import \"../vendor/bootstrap-sass/assets/stylesheets/bootstrap\";\n@import \"../vendor/font-awesome/scss/font-awesome\";\n...\n```\n\n### Version & Cache Busting\n\n브라우저 입장에서 보면 app.css 파일은 정적(static) 파일이다. 즉, 캐싱 기능이 있는 브라우저에서, 웹 서버에 요청을 해서 304 Not Modified 응답을 받으면, 브라우저는 로컬 캐시 저장소에 가지고 있던 파일을 사용한다. 웹 서버는 바보라 정적 파일의 변경을 눈치채지 못할 수 있다. 그래서 개발측에서 수정한 파일의 이름이 같으면, 캐시 정책이 만료되기 전에는, 웹 서버는 app.css 파일에 대한 브라우저의 요청에 계속 304로만 답하게 된다. 변경된 프론트엔드용 정적 리소스가 서비스에 바로 반영될 수 있도록 하는 테크닉이 Cache Busting의 핵심이다. 과거에는 app.css?t=1447665283 와 같이 랜덤 스트링을 붙여 브라우저가 매번 새로운 파일을 받아가도록 하기도 했었다. \n\n라라벨 Elixir에서는 `version()` API를 이용해서 Cache Busting을 자동화 해 준다. 빌드된 파일들은 public/build 디렉토리에 저장되고, 뷰에서 `elixir()` Helper를 이용해서 사용할 수 있다. `$ gulp` 명령을 실행할 때 마다, public/build 아래의 .js, .css 파일명이 변경되는 것을 확인할 수 있을 것이다. 빌드를 위해 생성된 중간 파일들은 필요 없으므로, 버전 컨트롤에서 제외하자.\n\n```bash\n$ echo /public/css >> .gitignore\n$ echo /public/js >> .gitignore\n```\n\nCache Busting을 사용할 수 있도록 resources/views/master.blade.php 를 수정해 보자. `{{ elixir('css/app.css') }}`, `{{ elixir('js/app.js') }}`를 주목해 보자. `elixir()` Helper는 public/build/rev.manifest.json 의 내용을 읽어서 가장 최신으로 빌드된 리소스의 파일명을 쓸 수 있도록 하는 기능을 한다.\n\n```html\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, user-scalable=no\">\n    <title>Laravel 5 Essential</title>\n\n    <link rel=\"stylesheet\" href=\"{{ elixir('css/app.css') }}\">\n    @yield('style')\n</head>\n<body>\n    <div class=\"container\">\n        @yield('content')\n\n        @include('footer')\n    </div>\n\n    <script src=\" {{ elixir('js/app.js') }}\"></script>\n    @yield('script')\n\n</body>\n</html>\n```\n\n### 췍!\n\n이제 카드를 까보자. resources/assets/sass/app.scss, resources/views/docs/index.md를 더 수정했다. 거듭말하지만, 프론트엔트 코스가 아니므로 자세한 설명은 하지 않으니, 코드를 참조하기 바란다. \n\n![](./images/29-elixir-img-01.png)\n\n**`참고`** 28강에서 우리가 캐시 기능을 추가했던 것을 기억하는가? 스타일시트나 뷰를 변경한 후, `$ php artisan cache:clear`를 해서 기존 캐시를 지워주어야 변경된 내용을 확인할 수 있다. 개발기간 중에는 불편할 수 있으니, 컨트롤러에서 캐시 기능을 주석처리해 놓는 것도 좋다. 다만, 버전 컨트롤에 업로드하기 전에 반드시 주석을 풀어줘야 한다.\n\n**`참고`** Elixir 에는 liveReload 유사 기능을 내장하고 있다. 파일이 변경되면 브라우저에 바로 반영해 주는 기능이다. `browserSync()` 기능을 사용하려면, [공식문서](http://laravel.com/docs/elixir#browser-sync)를 확인해 보자.\n\n### production 빌드\n\ncss vendor prefix, css minify, js uglify 까지 하면, production 환경에 적합한 프론트엔드 리소스를 빌드할 수 있다. `--production` 옵션을 이용하자.\n\n```bash\n$ gulp --production\n```\n\n![](./images/29-elixir-img-02.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [28강 - Cache](28-cache.md)\n- [30강 - Debug & Final Touch](30-final-touch.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/30-final-touch.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 31\n---\n\n# 실전 프로젝트 1 - Markdown Viewer \n\n## 30강 - Debug & Final Touch\n\n**`필독`** 프론트엔드에 관심이 없더라도, 1번과 2번은 백엔드 내용이므로 보도록 하자.\n\n29강까지 작성한 우리 프로젝트에는 3가지 문제가 있다.\n\n1.  이미지가 정상적으로 표시되지 않는다.\n2.  브라우저의 이미지 캐시가 동작하지 않는다.  \n3.  코드 블럭에 Syntax Highlight가 없다.\n\n### 이미지 표시하기\n\n우리 이미지는 public 디렉토리 밖에, 그러니까 public 과 같은 레벨인 docs 디렉토리에 위치하고 있다. 즉 웹 서버가 접근할 수 없는 위치에 있다는 것이다. 이럴 경우에는 Route 에서 이미지 파일에 대한 요청을 받아서, 컨트롤러에서 DocumentRoot(==public) 바깥 쪽에 위치한 이미지를 찾아 정확한 Content-Type 으로 응답해 주어야 한다.\n\napp/Http/routes.php 에 이미지 요청을 컨트롤러와 연결시키는 Route를 작성하자. 기존 문서 요청과 Route가 거의 동일하여, 이를 분리시키기 위하여 라라벨 Route의 글로벌 패턴이란 기능을 사용하였다. `Route::pattern()`의 첫번째 인자는 Route Parameter 이름, 두번째 인자는 정규표현식이다. 이 예제의 정규표현식은 01-welcome-image-01.png 에서는 매칭이 발생하고, 01-welcome.md 에서는 매칭이 발생하기 않는다. 해서, `Route::get('docs/{image}')`에서는 이미지 파일만 응답하고, `Route::get('docs/{file?}')` 에서는 나머지 docs로 시작하는 모든 경우에 대해 응답하게 된다.\n\n```php\nRoute::pattern('image', '(?P<parent>[0-9]{2}-[\\pL-\\pN\\._-]+)-(?P<suffix>img-[0-9]{2}.png)');\n\nRoute::get('docs/{image}', [\n    'as'   => 'documents.image',\n    'uses' => 'DocumentsController@image'\n]);\n\nRoute::get('docs/{file?}', [\n    'as'   => 'documents.show',\n    'uses' => 'DocumentsController@show'\n]);\n```\n\n**`참고`** Route Parameter에 대한 패턴이, 가령 `{image}`에 대한 패턴이 여러군데 쓰이면 `Route::pattern()`과 같이 글로벌 패턴을 사용한다. 여러 곳에 쓰지 않고 특정 Route 에서만 사용된다면, `Route::get('docs/{image}', '...')->where('image', 'pattern')` 처럼 사용할 수도 있다. \n\n**`참고`** 정규표현식의 작성 및 테스트를 위해서는 [Regex101](https://regex101.com/) 사이트를 이용할 것을 추천한다. 필자가 본 정규표현식 툴 중 최고이다.\n\n이미지 응답을 만들기 위해서 intervention/image 패키지를 이용할 것이다. composer 로 설치하고, [매뉴얼](http://image.intervention.io/getting_started/installation#laravel)에 따라 config/app.php 파일에 서비스프로바이더, Facade도 추가하자.\n\n```bash\n$ composer require \"intervention/image:2.3.*\"\n```\n\n```php\n//config/app.php\nreturn [\n    ...,\n    'providers' => [\n        ...,\n        Intervention\\Image\\ImageServiceProvider::class,\n    ],\n    \n    'aliases' => [\n        ...,\n        'Image' => Intervention\\Image\\Facades\\Image::class,\n    ]\n];\n```\n\n이제 Image Facade를 이용할 수 있으니, Document 모델과 DocumentsController 를 수정하자. Document 모델에서 중복 제거를 위해 여러군데 refactoring 된 것을 확인할 수 있다.\n\n```php\n// app/Document.php\n<?php\n\nnamespace App;\n\nuse File;\nuse Image;\n\nclass Document\n{\n    private $directory;\n\n    public function __construct($directory = 'docs')\n    {\n        $this->directory = $directory;\n    }\n\n    public function get($file = 'index.md')\n    {\n        return File::get($this->getPath($file));\n    }\n\n    public function image($file)\n    {\n        return Image::make($this->getPath($file));\n    }\n\n    private function getPath($file)\n    {\n        $path = base_path($this->directory . DIRECTORY_SEPARATOR . $file);\n\n        if (! File::exists($path)) {\n            abort(404, 'File not exist');\n        }\n\n        return $path;\n    }\n}\n```\n\n`image()` 메소드에서 인자로 넘겨 받은 파일을 찾아 `\\Intervention\\Image\\Image` 인스턴스를 리턴한다. \n\n```php\n// app/Http/Controllers/DocumentsController.php\n<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Document;\nuse Cache;\nuse Image;\nuse Request;\n\nclass DocumentsController extends Controller\n{\n    protected $document;\n\n    public function __construct(Document $document)\n    {\n        $this->document = $document;\n    }\n\n    public function show($file = '01-welcome.md')\n    {\n        ...\n    }\n\n    public function image($file)\n    {\n        $image = $this->document->image($file);\n\n        return response($image->encode('png'), 200, [\n            'Content-Type'  => 'image/png'\n        ]);\n    }\n}\n```\n\n`image()` 메소드에서 `Content-Type`을 png 타입으로 지정하고, 모델로 부터 넘겨 받은 이미지 인스턴스를 컨텐츠로 해서 HTTP 응답을 하고 있다.\n\n![](./images/30-final-touch-img-01.png)\n\n### 브라우저 캐시 살리기\n\nintervention/image 를 이용해서 만든 이미지 응답은 웹 서버가 접근할 수 있는 DocumentRoot(== public)에 있는 리소스로 만들어진 것이 아니다. 정해진 Route 규칙에 따라 요청하면 서버에서 이미지를 DocumentRoot 밖에서 찾아 반응하는 이미지 응답이기 때문에, 웹 서버가 브라우저 캐싱에 관여할 수 없다. 해서 수동으로 브라우저 캐싱 기능을 살려 주어야 한다.\n \n구현을 위해 웹서버와 브라우저간의 캐싱 메카니즘을 이해해야 한다. 브라우저가 리소스(이 예제에서는 이미지) 요청을 할 때, 캐시에 요청할 URL 과 연결된 캐시가 있는 지 확인하고, 키 값을 얻어온다. 이 키 값은 이전 동일 URL 요청에서 서버가 Etag 헤더 값으로 응답한 것이다. 얻어온 키 값은 If-Non-Match 헤더의 값으로 지정하고 서버에 리소스를 요청한다. 요청을 받은 서버는 If-Non-Match 헤더의 값과 URL 에 해당하는 서버의 Etag 로직에 의해 생성된 값을 비교하여, 같으면 304 Not Modified를, 다르면 200 OK와 함께 요청한 리소스를 HTTP 바디로 해서 응답한다. 아래 그림을 보자.\n\n![](http://4.bp.blogspot.com/-Oj6tyOt8ag0/VY4EkXx2OZI/AAAAAAAAAEI/7UJnCP4Y8OE/s640/etags.png)\n*`Image Source` [\"Etags and browser cache, June 26 2015\"](http://thespringthing.blogspot.kr/2015/06/etags-and-browser-cache.html)*\n\n먼저 Etag를 만드는 로직을 Document 모델에 구현하자. `md5()` php 내장 해시 함수를 사용하였다. Etag 값은 고유하기만 하면 어떤 문자열을 사용해도 상관없다.\n\n```php\nclass Document\n{\n    ...\n    public function etag($file)\n    {\n        return md5($file . '/' . File::lastModified($this->getPath($file)));\n    }\n    ...\n}\n```\n\nDocumentsController 에서 요청으로 받은 Etag값과 Document 모델에서 생성한 Etag 값과 비교하여 같으면 304, 같지 않으면 200을 응답하는 로직을 만들어보자.\n \n```php\nclass DocumentsController extends Controller\n{\n    ...\n    public function image($file)\n    {\n        $image = $this->document->image($file);\n        $reqEtag = Request::getEtags();\n        $genEtag = $this->document->etag($file);\n\n        if (isset($reqEtag[0])) {\n            if ($reqEtag[0] === $genEtag) {\n                return response('', 304);\n            }\n        }\n\n        return response($image->encode('png'), 200, [\n            'Content-Type'  => 'image/png',\n            'Cache-Control' => 'public, max-age=0',\n            'Etag'          => $genEtag,\n        ]);\n    }\n}\n```\n\n![](./images/30-final-touch-img-03.png)\n\n### Syntax Highlight 적용하기\n\nSyntax Highlight를 위한 Bower 콤포넌트를 설치하자!\n\n```bash\n$ bower install google-code-prettify --save-dev\n```\n\ngulpfile.js에 방금 다운로드 받은 패키지를 추가하자.\n\n```javascript\nelixir(function (mix) {\n  mix\n    .sass('...')\n    .scripts([\n      '...',\n      '../vendor/google-code-prettify/src/run_prettify.js',\n      'app.js'\n    ], 'public/js/app.js')\n    ....\n  });\n}\n```\n\n해당 패키지에 대한 [사용법은 여기](https://code.google.com/p/google-code-prettify/wiki/GettingStarted)서 익혔다. 마크다운 컴파일러는 코드블럭을 `<pre>` 태그로 컴파일 한다. 따라서, `<pre>` 태그에 방금 설치한 google-code-prettify의 스타일시트가 반응하도록 클래스를 추가해 줄 것이다. 마크다운 문서에 직접 추가할 수 없으니, resources/assets/js/app.js에 jQuery를 이용해 동적으로 추가해 보자.\n\n```javascript\n$(\"pre\").addClass(\"prettyprint\");\n```\n\ngulp 커맨드로 다시 빌드하고, 캐시도 지운 후 Syntax Highlight가 작 적용되었는지 확인해 보자.\n\n```bash\n$ gulp --production\n$ php artisan cache:clear\n```\n\n![](./images/30-final-touch-img-02.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [29강 - Elixir](29-elixir.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/31-forum-features.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 32\n---\n\n# 실전 프로젝트 2 - Forum\n\n댓글이 가능한 간단한 포럼을 구현해 본다. 이를 통해 라라벨의 Request &amp; Response 라이프싸이클에 대한 이해를 높인다. 뿐만 아니라, CRUD, Event, File/Image Upload, 인증과 권한부여 등에 대해 배워볼 예정이다.\n\n## 31강 - 포럼 요구사항 기획\n\n[StackOverflow](http://stackoverflow.com/) 또는 [라라캐스트 포럼](https://laracasts.com/discuss)을 머릿 속에 떠올리며 어떤 기능들이 필요할지?, 최종 결과물은 어떤 모습을 하고 있을 지?, 개발해야 할 항목들을 하나씩 정리해 보자. 일단 쭈욱~ 나열하고, 강좌 진행 상황에 따라 개발 항목을 삭제하거나, 추가하도록 하자.\n \n-    **사용자 인증 및 역할 기반 접근 제어**\n    -    네이티브 인증\n    -    소셜 인증\n    -    admin, member 역할에 따른 접근 제어\n-    **고품질의 레이아웃/UI**\n    -    메뉴, 사용자 등록 폼, 로그인 폼\n    -    Gravatar로 사용자 사진을 보여준다.\n    -    모바일에 대응한다.\n    -    영어, 한글 2가지 언어를 지원한다.\n-    **포럼**\n    -    포럼 생성, 포럼 목록, 포럼 상세 보기, 포럼 수정, 포럼 삭제\n    -    권한이 있는 사용자만 포럼을 생성할 수 있다.\n    -    관리자 또는 포럼 소유자만이 포럼을 수정 또는 삭제 할 수 있다.\n    -    파일 또는 이미지를 첨부할 수 있다.\n    -    마크다운 문법을 지원한다. 작성 중 프리뷰 기능을 쓸 수 있다.\n    -    태그 기능을 지원한다.\n    -    필터 기능을 지원한다.\n    -    포럼 생성시 지정된 사용자에게 이메일을 발송한다.\n    -    포럼 생성시 댓글에 대한 알림 기능을 토글할 수 있다.\n    -    \"답변됨\" 기능을 지원한다.\n    -    Full Text Search 기능을 지원한다.\n-    **댓글**\n    -    댓글의 댓글 기능을 지원한다.\n    -    포럼과 댓글은 one to many 관계를 가진다. (포럼 삭제시 댓글 삭제)\n    -    권한이 있는 사용자만 댓글을 생성할 수 있다.\n    -    관리자 또는 댓글 소유자만이 댓글을 수정 또는 삭제할 수 있다.\n    -    마크다운 문법을 지원한다.\n    -    포럼 생성자가 알림을 켜 놓은 경우, 댓글 생성시 연결된 포럼 생성자에게 이메일을 발송한다.\n-    **포럼/댓글 공통**\n    -    성능 향상을 위해 서버 사이드 캐싱을 이용한다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [32강 - 사용자 로그인](32-login.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/32-login.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 33\n---\n\n# 실전 프로젝트 2 - Forum\n\n실습을 진행하기 전에 기존에 만들었던 파일 중, 쓰지 않을 파일이나, 쓰지 않을 코드 블럭들을 삭제할 것을 권장한다. 정리하지 않아도 무방하긴 하지만...\n\n## 32강 - 사용자 로그인\n\n기본기 16강, 17강에서 배운 내용을 기반으로 사용자 로그인 기능을 만들어 보자. 여러개로 쪼개기도 뭣 하고... 그리고, 진도를 좀 많이 빼기 위해, 이번 강좌에서 욕심을 좀 냈으니 지치지 말고 따라해 주기 바란다.\n\n### Route 정의\n\napp/Http/routes.php에 사용자 등록, 로그인/아웃, 비밀번호 초기화, 홈페이지, 로그인 후 이동할 페이지 등에 사용할 엔드포인트를 먼저 만들자. 서비스에 사용할 수 있을 만큼의 퀄리티를 내기 위해 이번 강좌부터는 코드량이 좀 많다.\n\n```php\nRoute::get('/', [\n    'as' => 'root',\n    'uses' => 'WelcomeController@index'\n]);\n\nRoute::get('home', [\n    'as' => 'home',\n    'uses' => 'WelcomeController@home'\n]);\n\n/* User Registration */\nRoute::group(['prefix' => 'auth', 'as' => 'user.'], function () {\n    Route::get('register', [\n        'as'   => 'create',\n        'uses' => 'Auth\\AuthController@getRegister'\n    ]);\n    Route::post('register', [\n        'as'   => 'store',\n        'uses' => 'Auth\\AuthController@postRegister'\n    ]);\n});\n\n/* Session */\nRoute::group(['prefix' => 'auth', 'as' => 'session.'], function () {\n    Route::get('login', [\n        'as'   => 'create',\n        'uses' => 'Auth\\AuthController@getLogin'\n    ]);\n    Route::post('login', [\n        'as'   => 'store',\n        'uses' => 'Auth\\AuthController@postLogin'\n    ]);\n    Route::get('logout', [\n        'as'   => 'destroy',\n        'uses' => 'Auth\\AuthController@getLogout'\n    ]);\n});\n\n/* Password Reminder */\nRoute::group(['prefix' => 'password'], function () {\n    Route::get('remind', [\n        'as'   => 'reminder.create',\n        'uses' => 'Auth\\PasswordController@getEmail'\n    ]);\n    Route::post('remind', [\n        'as'   => 'reminder.store',\n        'uses' => 'Auth\\PasswordController@postEmail'\n    ]);\n    Route::get('reset/{token}', [\n        'as'   => 'reset.create',\n        'uses' => 'Auth\\PasswordController@getReset'\n    ]);\n    Route::post('reset', [\n        'as'   => 'reset.store',\n        'uses' => 'Auth\\PasswordController@postReset'\n    ]);\n});\n```\n\n`Route::group()`은 여러개의 Route에 공통된 Prefix Url, Route Name을 붙이거나, 미들웨어를 동시에 적용할 때 사용할 수 있다. 여기에 사용한 모든 컨트롤러와 메소드는 라라벨 기본으로 내장되어 배포되는 `App\\Http\\Controllers\\Auth\\AuthController`, `App\\Http\\Controllers\\Auth\\PasswordController`의 것을 그대로 사용한 것이다.\n\napp/Http/Controllers/WelcomeController.php 는 별도로 만들어 주고, Route 와 연결된 메소드를 써 주어야 한다.\n\n```bash\n$ php artisan make:controller WelcomeController\n```\n\n```php\n<?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Http\\Requests;\n\nclass WelcomeController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth', ['only' => ['home']]);\n    }\n\n    public function index()\n    {\n        return view('index');\n    }\n\n    public function home()\n    {\n        return view('home');\n    }\n}\n```\n\n16~17강에서 'auth' 미들웨어를 배운것을 떠올려 보자. `Route::get('url', ['middleware' => 'auth', ...]);` 식으로 썼을 것이다. Route 대신 컨트롤러에서 메소드별로 미들웨어를 적용할 수 있는데, 위 예와 같이 생성자 메소드에서 `$this->middleware('middleware-to-use')` 식으로 쓴다. 그리고, 두번째 인자로 `only` 키워드를 사용했는데, 지정된 메소드에서만 이 미들웨어를 적용하겠단 의미이다. 즉, 여기서는 `home()` 메소드에 접근하기전에 'auth' 미들웨어를 거쳐야 하고, 'auth' 미들웨어에 의해 로그인되어 있지 않을 경우, 'auth/login' Route 로 이동하게 된다. \n\nRoute가 잘 정의되었는지 확인해 보자. 에러가 안났다는 것은 엔드포인트와 컨트롤러의 메소드가 잘 연결되었다는 의미이다. \n\n```bash\n$ php artisan route:list\n```\n\n![](./images/32-login-img-01.png)\n\n### 마스터 템플릿을 손보자!\n\n먼저, 뷰 디렉토리를 좀 더 구조화 하기 위해, 기존의 master.blade.php 파일은 resources/views/layouts/master.blade.php 로 이동하였다.\n\n좀 더 있어 보이는 레이아웃을 위해 [Bootstrap 사이트](http://getbootstrap.com/getting-started/)에서 괜찮은 템플릿을 좀 훔쳐와서, resources/views/layouts/master.blade.php 에 적용해 보았다. 구조화를 위해 navigation.blade.php, footer.blade.php 로 내용을 좀 나누었으니 코드를 살펴 보자.\n\n내친 김에 플래시 메시지도 사용할 것이다. 플래시 메시지란 컨트롤러에서 세션에 구워 뷰에 전달할 메시지를 의미한다. 뷰에서는 `Session::get('key')` 로 값을 얻을 수 있다. 이 프로젝트에서는 laracasts/flash 패키지를 이용할 것이다.\n\n```bash\n$ composer require \"laracasts/flash:1.3.*\"\n```\n\n```php\n// config/app.php\n'providers' => [\n    ...\n    Laracasts\\Flash\\FlashServiceProvider::class,\n],\n'aliases' => [\n    ...\n    'Flash' => Laracasts\\Flash\\Flash::class,\n],\n```\n\n```html\n<!-- resources/views/layouts/master.blade.php -->\n<!DOCTYPE html>\n<html>\n\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, user-scalable=no\">\n  <meta name=\"csrf-token\" content=\"{{ csrf_token() }}\" />\n\n  <title>Laravel 5 Essential</title>\n\n  <link href=\"{{ elixir(\"css/app.css\") }}\" rel=\"stylesheet\">\n  @yield('style')\n\n  <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n  <!--[if lt IE 9]>\n  <script src=\"//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js\"></script>\n  <script src=\"//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js\"></script>\n  <![endif]-->\n</head>\n\n<body>\n  @include('layouts.partial.navigation')\n\n  @include('layouts.partial.flash_message')\n\n  <div class=\"container\">\n    @yield('content')\n  </div>\n\n  @include('layouts.partial.footer')\n\n  <script src=\"{{ elixir(\"js/app.js\") }}\"></script>\n  @yield('script')\n</body>\n\n</html>\n```\n\n`@include` 로 하위 뷰들을 포함하고 있다. `<meta name=\"csrf-token\" content=\"{{ csrf_token() }}\" />`는 자바스크립트에서 XHR 요청을 할 때 사용하기 위해 포함시켜 놓은 것이다 ([공식 문서 참고](http://laravel.com/docs/routing#csrf-protection)). \n\n```html\n<!-- resources/views/layouts/partial/navigation.blade.php -->\n<nav class=\"navbar navbar-default navbar-fixed-top\" role=\"navigation\">\n\n  <div class=\"container-fluid\">\n    <div class=\"navbar-header\">\n      <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-responsive-collapse\">\n        <span class=\"sr-only\">Toggle Navigation</span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n      </button>\n\n      <a href=\"{{ route('home') }}\" class=\"navbar-brand\">\n        <img src=\"/images/laravel_logo.png\" style=\"display: inline-block; height: 1.2rem;\"/>\n      </a>\n    </div>\n\n    <div class=\"collapse navbar-collapse navbar-responsive-collapse\">\n      <ul class=\"nav navbar-nav navbar-right\">\n        @if(! auth()->check())\n          <li>\n            <a href=\"{{ route('session.create') }}\"><i class=\"fa fa-sign-in icon\"></i> Login</a>\n          </li>\n          <li>\n            <a href=\"{{ route('user.create') }}\"><i class=\"fa fa-certificate icon\"></i> Sign up</a>\n          </li>\n        @else\n          <li>\n            <a href=\"{{ route('documents.show') }}\"><i class=\"fa fa-book icon\"></i> Document Viewer</a>\n          </li>\n          <li>\n            <a href=\"#\"><i class=\"fa fa-weixin icon\"></i> Forum</a>\n          </li>\n          <li>\n            <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">\n              <i class=\"fa fa-user icon\"></i> {{ auth()->user()->name }} <b class=\"caret\"></b>\n            </a>\n            <ul class=\"dropdown-menu\">\n              <li><a href=\"{{ route('session.destroy') }}\"><i class=\"fa fa-sign-out icon\"></i> Log out</a></li>\n            </ul>\n          </li>\n        @endif\n      </ul>\n    </div>\n  </div>\n</nav>\n```\n\n`@if(! auth()->check())` 로 로그인이 안되어 있으면 로그인과 사용자 등록 링크를, 로그인되어 있으면 메뉴들과 로그아웃 링크를 보여 주도록 뷰를 분기시키고 있다.\n\n```html\n<!-- resources/views/layouts/partial/flash_message.blade.php -->\n@if (session()->has('flash_notification.message'))\n  <div class=\"alert alert-{{ session('flash_notification.level') }} alert-dismissible flash-message\" role=\"alert\">\n    <button type=\"button\" class=\"close\" data-dismiss=\"alert\">\n      <span aria-hidden=\"true\">&times;</span>\n      <span class=\"sr-only\">Close</span>\n    </button>\n    {{ session('flash_notification.message') }}\n  </div>\n@endif\n\n@if ($errors->has())\n  <div class=\"alert alert-danger alert-dismissible flash-message\" role=\"alert\">\n    <button type=\"button\" class=\"close\" data-dismiss=\"alert\">\n      <span aria-hidden=\"true\">&times;</span>\n      <span class=\"sr-only\">Close</span>\n    </button>\n    Some errors found in the form. Please review and correct them and retry !\n  </div>\n@endif\n```\n\n첫번 째 블럭은 세션에 flash_notification으로 시작하는 값이 있으면 [Bootstrap CSS로 나이스하게 디자인된 Alert](http://getbootstrap.com/components/#alerts)를 보여 준다. 두번째 블럭은 23강 유효성 검사에서 배운 세션에 구워 놓은 `$errors` 값이 있으면 폼을 다시 한번 체크하라고 Alert를 띄워 준다. \n\n```html\n<!-- resources/views/layouts/partial/footer.blade.php -->\n<footer class=\"footer\">\n  <ul class=\"list-inline pull-right locale\">\n    <li><i class=\"fa fa-language\"></i></li>\n    <li class=\"active\"><a href=\"#\">English</a></li>\n    <li><a href=\"#\">한국어</a></li>\n  </ul>\n\n  <div>\n    &copy; {{ date('Y') }} &nbsp; <a href=\"https://github.com/appkr/l5essential\">Laravel 5 Essential</a>\n  </div>\n</footer>\n```\n\n다국어 지원할 것을 대비해 footer 영역에 미리 링크를 준비해 놓았다.\n\nresources/views/index.blade.php, resources/views/home.blade.php 뷰 파일들은 각자의 취향에 맞게 적절한 내용을 담아 만들도록 하자.\n\n![](./images/32-login-img-02.png)\n\n### 뷰를 만들자.\n\n이제 사용자 등록, 로그인, 비밀번호 초기화 폼을 만들 것인데, `App\\Http\\Controllers\\Auth\\AuthController`, `App\\Http\\Controllers\\Auth\\PasswordController` 의 메소드들에 미리 정의된 뷰의 이름들을 잘 확인하고 뷰 파일을 만들자. 필자는 기본 내장된 컨트롤러 메소드 이름이 굉장히 헷갈려서 맘에 들지 않아, 아래 테이블로 정리해 보았다.\n\nRoute|Route 이름|컨트롤러 메소드|연결된 뷰|뷰의 역할\n---|---|---|---|---\n/|index|WelcomeController@index|index|인덱스 페이지\nhome|home|WelcomeController@home|home|로그인한 후 이동할 페이지\nauth/register|user.create|AuthController@getRegister|auth.register|사용자 등록 폼\nauth/login|session.create|AuthController@getLogin|auth.login|사용자 로그인 폼\nauth/remind|reminder.create|PasswordController@getEmail|auth.password|비밀번호 초기화 링크 요청 이메일 발송 폼\n | | |emails.password|비밀번호 초기화 링크를 담은 이메일 뷰\nauth/reset/{token}|reset.create|PasswordController@getReset|auth.reset|비밀번호 초기화 폼\n\n**`참고`** `getRegister()` 메소드는 `Illuminate\\Foundation\\Auth\\RegistersUsers` trait에서, `getLogin()` 메소드는 `Illuminate\\Foundation\\Auth\\AuthenticatesUsers` trait에서, `getEmail()` 와 `getReset()` 메소드는 `Illuminate\\Foundation\\Auth\\ResetsPasswords` trait에서 각각 찾아야 한다. 이들 trait들을 `App\\Http\\Controllers\\Auth\\AuthController`, `App\\Http\\Controllers\\Auth\\PasswordController`가 use 키워드로 사용하고 있다. \n\n```html\n<!-- resources/views/auth/register.blade.php -->\n@extends('layouts.master')\n\n@section('content')\n  <form action=\"{{ route('user.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n  \n    {!! csrf_field() !!}\n\n    <div class=\"page-header\">\n      <h4>Sign up</h4>\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"text\" name=\"name\" class=\"form-control\" placeholder=\"Full name\" value=\"{{ old('name') }}\" autofocus/>\n      {!! $errors->first('name', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"Email address\" value=\"{{ old('email') }}\"/>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password, minimum 6 chars\"/>\n      {!! $errors->first('password', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"password\" name=\"password_confirmation\" class=\"form-control\" placeholder=\"Confirm password\" />\n      {!! $errors->first('password_confirmation', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <button class=\"btn btn-primary btn-block\" type=\"submit\">Sign me up~</button>\n    </div>\n\n  </form>\n@stop\n```\n\n스샷에서 입력값 유지, 유효성 검사, 앞 절에서 설치한 플래시메시지 등 모든 기능이 동작하는 것을 확인할 수 있다. \n\n![](./images/32-login-img-03.png)\n\n```html\n<!-- resources/views/auth/login.blade.php -->\n@extends('layouts.master')\n\n@section('content')\n  <form action=\"{{ route('session.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n\n    <div class=\"page-header\">\n      <h4>Login</h4>\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"Email address\" value=\"{{ old('email') }}\" autofocus/>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\">\n      {!! $errors->first('password', '<span class=\"form-error\">:message</span>')!!}\n    </div>\n\n    <div class=\"form-group\">\n      <div class=\"checkbox\">\n        <label>\n          <input type=\"checkbox\" name=\"remember\" value=\"{{ old('remember', 1) }}\" checked> Remember me\n        </label>\n      </div>\n    </div>\n\n    <div class=\"form-group\">\n      <button class=\"btn btn-primary btn-block\" type=\"submit\">Get me in~</button>\n    </div>\n\n    <div class=\"description\">\n      <p>&nbsp;</p>\n      <p class=\"text-center\">Not a member? <a href=\"{{ route('user.create') }}\">Sign up</a></p>\n      <p class=\"text-center\"><a href=\"{{ route('reminder.create')}}\">Remind my password</a></p>\n    </div>\n\n  </form>\n@stop\n```\n\n`<input type=\"checkbox\" name=\"remember\">` 의 값은 `Auth::attempt(array $credentials, bool $remember)` 메소드의 2번째 인자로 전달된다. 2번째 인자 없이 로그인하면 2시간동안 로그인 세션이 유지된다. 체크박스에 체크가 되어 `true` 값이 전달되면, 5년동안 로그인이 유지된다. \n\n![](./images/32-login-img-04.png)\n\n```html\n<!-- resources/views/auth/password.blade.php -->\n@extends('layouts.master')\n\n@section('content')\n  <form action=\"{{ route('reminder.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n\n    <h4>Password Remind</h4>\n    \n    <p class=\"text-muted\">\n      Provide the same email address that you've registered and check your email inbox to reset the password.\n    </p>\n  \n    <div class=\"form-group\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"Email address\" value=\"{{ old('email') }}\" autofocus>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n  \n    <button class=\"btn btn-primary btn-block\" type=\"submit\">Send Reminder</button>\n\n  </form>\n@stop\n```\n\n![](./images/32-login-img-05.png)\n\n```html\n<!-- resources/views/emails/password.blade.php -->\nClick here to reset your password: {{ route('reset.create', $token) }}\n```\n\n.env 파일에서 `MAIL_DRIVER=log`로 바꾸어 놓고, 비밀번호 초기화를 위한 이메일이 잘 나가는지 확인해 보았다.\n\n![](./images/32-login-img-06.png)\n\n```html\n<!-- resources/views/auth/reset.blade.php -->\n@extends('layouts.master')\n\n@section('content')\n  <form action=\"{{ route('reset.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n\n    <input type=\"hidden\" name=\"token\" value=\"{{ $token }}\">\n\n    <h4>Reset Password</h4>\n    \n    <p class=\"text-muted\">\n      Provide your email address and NEW PASSWORD.\n    </p>\n\n    <div class=\"form-group\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"Email address\" value=\"{{ old('email') }}\" autofocus>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"password\" name=\"password\" class=\"form-control\" placeholder=\"New password\">\n      {!! $errors->first('password', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"password\" name=\"password_confirmation\" class=\"form-control\" placeholder=\"Confirm password\">\n      {!! $errors->first('password_confirmation', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <button class=\"btn btn-primary btn-block\" type=\"submit\">Reset My Password</button>\n\n  </form>\n@stop\n```\n\n비밀번호 초기화 이메일에서 받은 링크를 브라우저에 붙여 넣어 비밀번호를 초기화할 수 있다.\n\n![](./images/32-login-img-07.png)\n\n디자인을 위해 resources/assets/sass/app.scss 도 일부 내용이 변경되었다. 상세 설명은 생략하니, 코드를 참고하기 바란다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [31강 - 포럼 요구사항 기획](31-forum-features.md)\n- [33강 - 소셜 로그인](33-social-login.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/32n33-auth-refactoring.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 41\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 32/33 보충 - 인증 리팩토링\n\n잠깐 쉬어가자~ 32강 33강에서 구현했던 라라벨 내장 인증 Route와 컨트롤러의 메소드가 맘에 들지 않아, 인증 레이어를 다시 구성하고, Integration Test 부분도 추가했다.  \n\n또, 앞 강의에서 발생한 버그들도 수정했다.\n\n### 인증 재구현\n\n라라벨 내장 인증 기능을 사용함에 있어서 Route 정의에 연결된 'AuthController'의 메소드들이 trait 와 프레임웍 속에 숨어 있어서, 읽기도 쉽지 않을 뿐더러, 필요에 의해서 내부를 수정하면, 다음 프레임웍 업데이트 때, 나의 수정 내용이 엎어쳐지는 불상사가 발생할 수 있다. 라라벨에 내장된 인증 구현에 대한 의존성을 버리기 위해서, \n\n- `App\\Http\\Controllers\\UsersController` (가입)\n- `App\\Http\\Controllers\\SessionsController` (로그인/아웃)\n- `App\\Http\\Controllers\\SocialController` (소셜 로그인)\n- `App\\Http\\Controllers\\PasswordsController` (비밀번호 재설정)\n\n으로 각각 분리하여 작성하였다.\n\n#### 문제점 인식\n\n서비스마다 로그인에 대한 정책이 있기 마련인데, 필자는 우리 서비스(이하 'myProject')의 사용자들이 소셜 로그인도 할 수 있고, 네이티브 로그인도 할 수 있게 하고 싶다. 여기서는 사용자의 Github 이메일 계정과, myProject 에 회원 가입한 이메일 계정이 동일할 경우만을 가정한다. \n\n**`참고`** Github 이메일과 myProject의 사용자 이메일 주소가 서로 다르다면, 두 개의 서로 다른 계정으로 인식될 것이다. 즉, myProject 에 들어와서 사용자가 생성하는 Article, Comment 등의 모델은 그때 그때 로그인한 소셜 또는 네이티브 사용자에게 속할 것이다. 프로그램적으로 해결할 수 있는 문제가 아니므로, 정책적으로 해결하거나, 사용자가 수동으로 계정을 연결할 수 있는 방법과 장치를 제공해야 할 것이다.  \n\n기존 소셜 로그인 코드를 잠시 살펴 보자. 아래 코드에서 `User::firstOrCreate()` 메소드에서 Github 로 부터 받은 정보를 이용하여 **'password'가 없는 사용자를 생성**하고 있다는 것을 기억하고 있자.\n\n```php\n// 기존 코드\n// app/Http/Controllers/Auth/AuthController.php\n\npublic function handleProviderCallback()\n{\n    $user = \\Socialite::driver('github')->user();\n    $user = User::firstOrCreate([\n        'name'  => $user->getName(),\n        'email' => $user->getEmail(),\n    ]);\n    ...\n}\n```\n\n아래와 같은 경우의 수가 발생할 수 있다.\n\n1. myProject 에 회원 가입을 먼저하고, 소셜 로그인을 시도하는 경우\n    1. 사용자 이름까지 같을 경우 -> 로그인 됨\n    2. **사용자 이름이 다르면, 사용자 생성을 시도하게 됨 -> 동일 이메일을 가진 User 가 하나 더 생김**\n2. 소셜 로그인을 하여, 빈 'password'를 가진 User 모델이 생성된 상태에서, 네이티브 인증을 시도하는 경우\n    1. 'password' 가 없으므로 네이티브 로그인 불가능\n    2. myProject 에 회원 가입을 시도하는 경우, **같은 이메일을 가진 User 가 이미 있으므로 가입 불가능**\n\n다음과 같은 방법으로 해결해 보자.\n\n1. myProject 에 회원 가입을 먼저하고, 소셜 로그인을 시도하는 경우\n    1. `firstOrCreate()` 부분을 'email'로 먼저 쿼리하고, 없으면 User를 생성하는 로직으로 다시 작성하자.\n2. 소셜 로그인을 하여, 빈 'password'를 가진 User 모델이 생성된 상태에서... \n    1. myProject 에 회원 가입을 시도하는 경우, 기존 소셜 로그인으로 'password' 없이 생성된 계정에 'password'를 업데이트한다.\n    2. 비밀번호 재설정을 시도하는 경우, 소셜 로그인 사용자라고 안내한다.\n\n우선, 기존 마이그레이션의 'password' 필드에 `nullable()` 속성을 추가하였다. 수정했으면 `$ php artisan migrate:refresh --seed`\n\n```php\n// database/migrations/create_users_table.php\n\npublic function up()\n{\n    // ...\n    $table->string('password', 60)->nullable();\n}\n```\n\n#### Route 정의\n\n![](./images/32n33-auth-refactoring-img-01.png)\n\n잘 보면, `Route::get('social/{provider}', 'SocialController@execute')` 부분에서 'social/github', 'social/facebook' 등으로 소셜 로그인 공급자를 더 붙일 수 있도록 Route 구조를 좀 변경할 것을 확인할 수 있다.\n\n```php\n// app/Http/routes.php\n\n/* User Registration */\nRoute::get('auth/register', [\n    'as'   => 'users.create',\n    'uses' => 'UsersController@create'\n]);\nRoute::post('auth/register', [\n    'as'   => 'users.store',\n    'uses' => 'UsersController@store'\n]);\n\n/* Social Login */\nRoute::get('social/{provider}', [\n    'as'   => 'social.login',\n    'uses' => 'SocialController@execute',\n]);\n\n/* Session */\nRoute::get('auth/login', [\n    'as'   => 'sessions.create',\n    'uses' => 'SessionsController@create'\n]);\nRoute::post('auth/login', [\n    'as'   => 'sessions.store',\n    'uses' => 'SessionsController@store'\n]);\nRoute::get('auth/logout', [\n    'as'   => 'sessions.destroy',\n    'uses' => 'SessionsController@destroy'\n]);\n\n/* Password Reminder */\nRoute::get('auth/remind', [\n    'as'   => 'remind.create',\n    'uses' => 'PasswordsController@getRemind',\n]);\nRoute::post('auth/remind', [\n    'as'   => 'remind.store',\n    'uses' => 'PasswordsController@postRemind',\n]);\nRoute::get('auth/reset/{token}', [\n    'as'   => 'reset.create',\n    'uses' => 'PasswordsController@getReset',\n]);\nRoute::post('auth/reset', [\n    'as'   => 'reset.store',\n    'uses' => 'PasswordsController@postReset',\n]);\n```\n\n**`중요`** Route 정의가 변경되었으므로, 회원 가입, (소셜) 로그인, 비밀번호 재설정 관련해서 기존에 뷰 코드에 박아 놓았던, `route()` Helper 를 이용한 링크들을 모두 수정해 주어야 한다.\n\n**`참고`** 기존에 'resources/views/auth' 아래에 위치하던 뷰들도 'users', 'sessions', 'passwords' 아래로 옮기고, 이름도 적절히 변경하였다. 각 컨트롤러에서 `view()`를 반환할 때 바뀐 위치로 적용해 주어야 한다.\n\n#### 'SocialController(소셜 로그인)' 구현\n\n앞 절의 Route 정의에서 `Route::get('social/{provider}', 'SocialController@execute')`로 썼다. 소셜 인증 과정에는 Github 'Authorize application' 페이지로 이동하는 Route 하나, 앞 과정에서 사용자가 승인하면 Github 에서 myProject 로 콜백해 주는 Route 총 두 개가 필요했던 것을 `execute()` 하나로 줄였다. `execute()` 메소드에서 myProject의 Router로 들어오는 HTTP 요청 쿼리스트링의 'code' 필드의 유무에 따라 분기시킨 것이다. 전체적인 과정은 아래 그림을 참조하자.\n\n![](./images/32n33-auth-refactoring-img-02.png)\n\n`$user = (\\App\\User::whereEmail($user->getEmail())->first()) ?: \\App\\User::create([...]);` 부분에서 기존의 `firstOrCreate()` 메소드를 다시 썼다. 'email' 로만 쿼리해서 있으면 myProject 에 로그인해 주고, 해당 'email'을 가진 레코드가 없으면, 'email', 'name' 필드를 가진 사용자를 생성시키도록 수정하였다.\n\n```php\n// app/Http/Controllers/SocialController.php\n\nclass SocialController extends Controller\n{\n    public function execute(Request $request, $provider)\n    {\n        if (! $request->has('code')) {\n            return $this->redirectToProvider($provider);\n        }\n\n        return $this->handleProviderCallback($provider);\n    }\n\n    protected function redirectToProvider($provider) { // ...}\n\n    protected function handleProviderCallback($provider)\n    {\n        $user = $this->socialite->driver($provider)->user();\n\n        $user = (\\App\\User::whereEmail($user->getEmail())->first())\n            ?: \\App\\User::create([\n                'name'  => $user->getName(),\n                'email' => $user->getEmail(),\n            ]);\n\n        // ...\n    }\n}\n```\n\nRoute 가 바뀌었으므로, [Github Developer Applications Console](https://github.com/settings/developers)를 방문하여 Authorization callback URL 을 'http://localhost:8000/social/github' 로 변경하여야 한다.\n\n**`참고`** `handleProviderCallback()` 에서 보통은 Github 에서 받은 사용자 정보로 폼을 포함한 뷰를 한번 더 사용자에게 보여주며, 다른 이메일, 비밀번호, 사용자 이름 등을 더 받아 `App\\User` 모델로 저장하는 것이 정석이다. 이렇게 구현하면, 위에서 언급한 복잡한 Sync 과정이 불필요하다.\n\n#### UsersController(가입) 구현\n\n기존 대비 특별히 달라진 부분들만 살펴보도록 하자.\n\n`store()` 메소드에서는, 먼저 `App\\User` 모델에 새로 정의한 `noPassword() (== whereNull('password'))` 란 [쿼리스코프](http://laravel.com/docs/eloquent#query-scopes)를 이용하여 회원 가입 요청에서 사용자가 제출한 'email' 값과 일치하고, 'password' 가 `null` 인 사용자를 찾는다. 이는 소셜로 로그인하면서 생성된 계정을 의미한다. 소셜로 생성된 계정이면 `syncAccountInfo()` 메소드로 처리 로직을 위임하고, 소셜 로그인 이력이 없는 회원 가입 요청이면 `createAccount()` 메소드로 위임했다.\n\n`syncAccountInfo()` 메소드에서는, 사용자가 회원 가입 폼에 입력한 값들에 대한 유효성 검사를 수행하고, 통과하면 폼에서 넘겨 받은 'password' 값으로 기존에 `null` 이던 값을 대체하였다. Github 사용자 이름과, myProject 에서 사용하는 이름이 다를 수 있으므로, 'name' 필드도 넘겨 받은 값으로 업데이트하였다. 여기서 주목할 점은 `createAccount()` 메소드와 폼 데이터에 대한 유효성 검사 규칙이 약간 다르다는 것이다. 소셜 로그인으로 이미 사용자는 생성된 상태이므로, 'email' 필드 검사 규칙에서 'unique:users' 규칙이 빠졌다.\n\n`createAccount()` 는 기존과 크게 달라진 점이 없다.\n\n```php\n// app/Http/Controllers/UsersController.php\n\nclass UsersController extends Controller\n{\n    public function store(Request $request)\n    {\n        if ($user = User::whereEmail($request->input('email'))->noPassword()->first()) {\n            // Filter through the User model to find whether there is a social account\n            // that has the same email address with the current request\n            return $this->syncAccountInfo($request, $user);\n        }\n\n        return $this->createAccount($request);\n    }\n\n    protected function syncAccountInfo(Request $request, User $user)\n    {\n        $validator = \\Validator::make($request->except('_token'), [\n            'name'     => 'required|max:255',\n            'email'    => 'required|email|max:255',\n            'password' => 'required|confirmed|min:6',\n        ]);\n\n        if ($validator->fails()) {\n            return back()->withInput()->withErrors($validator);\n        }\n\n        $user->update([\n            'name' => $request->input('name'),\n            'password' => bcrypt($request->input('password'))\n        ]);\n\n        \\Auth::login($user);\n        flash(trans('auth.welcome', ['name' => $user->name]));\n\n        return redirect(route('home'));\n    }\n\n    protected function createAccount(Request $request) {// ...}\n}\n```\n\n#### SessionsController(로그인/아웃) 구현\n\n여기서는 기존 대비 크게 달라진 점이 없이, trait나 프레임웍 속에 숨어 있던 것을 도메인레이어로 옮겨 놓았을 뿐이므로, 설명을 생략한다.\n\n#### PasswordsController(비밀번호 재설정) 구현\n\nmyProject 에 가입하지 않고, 소셜 로그인으로만 사용하던 사용자가 갑자기 비밀번호 재설정 시도를 할 경우를 대비한 방어조치만 추가했다. 나머지 부분들은 기존 대비 크게 다르지 않다.\n\n```php\n// app/Http/Controllers/PasswordsController.php\n\npublic function postRemind(Request $request)\n{\n    // ...\n    if (User::whereEmail($request->input('email'))->noPassword()->first()) {\n        flash()->errors(sprintf(\"%s %s\", trans('auth.social_olny'), trans('auth.no_password')));\n        return back();\n    }\n    //...\n}\n```\n\n#### 인증 관련 통합 테스트 추가\n\n설명은 생략하지만, 'tests/Http/Controllers' 디렉토리 하위에 포함된 코드들을 살펴보고, 테스트를 수행해 볼 것을 권장한다. 필자가 아직은 실력이 미천해서 외부로 HTTP 요청이 발생하는 'SocialController' 와 이메일을 보내야 하는 'PasswordsController' 부분은 테스트 코드를 쓰지 못했다 (PR 또는 가르침 환영합니다 ^^/)\n \n```bash\n$ phpunit\n```\n\n### 디버그 및 자잘한 개선\n\n\n'config/services.php' 에 하드코드로 박아 놓았던 Github 소셜 로그인 관련 설정 값들을 '.env'로 옮겼다.\n\n로그인 하지 않은 상태에서 `@if (auth()->user()->isAdmin() ...)` 이 들어간 뷰를 방문하면 null 포인터 에러가 나는 버그가 있었다. `@if ($currentUser and ($currentUser->isAdmin() ...))` 으로 변경하였다. 로그인을 하면 `auth()->user()` 는 로그인한 사용자에 해당하는 `App\\User` 인스턴스를 반환하는데, 로그인 되어 있지 않으면 `null`을 반환한다. `null->isAdmin()` 은 당연히 성립할 수 없는 코드이다. \n\n아울러, 뷰 코드에 `Auth::check()` 로 된 부분들도 `App\\Http\\Controlelrs\\Controller::__construct()` 에서 뷰에 공유한 `$currentUser` 변수로 대체하였다. 만들었으면 써야 하기에...\n\n코드에디터(또는 IDE)에서 <kbd>Cmd</kbd> + Mouse Click 으로 , Facade 에 연결된 메소드로 이동을 쉽게 하기 위해서 ['barryvdh/laravel-ide-helper'](https://github.com/barryvdh/laravel-ide-helper) 패키지를 Dev Dependency 로 추가하였다. `$ composer require barryvdh/laravel-ide-helper --dev`. 설정법은 스스로 찾아서 적용하기 바라고, 설명하고 싶었던 것은 다른 것이다. 개발 과정 중에만 필요한 패키지를 설치하고, 해당 패키지가 제공하는 ServiceProvider를 'config/app.php' 에 등록할텐데, production 서버에 올릴 때 매번 불필요한 패키지 라인을 주석처리 하는 것은 귀찮은 일이다. 이때 `App\\Providers\\AppServiceProvider` 를 이용하면 편리하게 local 또는 dev 환경일 때만 로드되도록 할 수 있다. 참고로 아래 코드에서 `$this->app->environment()` 는 `\\App::environment()` 또는 `app()->environment()` 로도 쓸 수 있다.\n\n```php\n// app/Providers/AppServiceProvider.php\n\npublic function register()\n{\n    if ($this->app->environment('local')) {\n        $this->app->register(\\Barryvdh\\LaravelIdeHelper\\IdeHelperServiceProvider::class);\n    }\n}\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [39강 - Attachment 기능 구현](39-attachments.md)\n- [40강 - Comment 기능 구현](40-comments.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/33-social-login.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 34\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 33강 - 소셜 로그인\n\n소셜 로그인을 지원하지 않는 서비스는 구닥다리로 느껴진다. 소셜 로그인은 내 서비스에 들어 온 사용자의 신분확인을 제 3자에게 위탁(아웃소싱)하는 행위라 보면 되며, 기술적인 백그라운드는 Oauth 이다 (동작 시퀀스가 궁금하다면 [조대협님의 블로그](http://bcho.tistory.com/913)를 참조하자). \n\n간단히만 설명하자면... 내 서비스에서 사용자가 소셜로그인 버튼을 누르면, 우리 서비스('myProject'라 하자.)에 대한 여러가지 정보를 쿼리스트링으로 담고 소셜로그인 서비스 제공자의 페이지로 이동하게 된다. 표시된 UI 에서 사용자가 승인을 누르게 되는데, 이는 \"내가 myProject 서비스에 이 소셜서비스의 권한을 위임해 줄게. 다는 안되고 UI 아래에 표시된 scope로 지정된 만큼만...\" 의 의미이다. 즉 myProject는 소셜로그인 서비스를 통해 사용자의 신원을 확인하게 되는 과정인 것이다. \n\n![](./images/33-social-login-img-03.png)\n\n이 코스에서는 github의 소셜로그인을 이용해 본다.\n\n### Socialite 확장 기능\n\n소셜로그인을 위한 구현체는 라라벨 기본 패키지에 포함되어 있지 않고 별도로 설치해야 한다.\n\n```bash\n$ composer require \"laravel/socialite:2.0.*\"\n```\n\n```php\n// config/app.php\n'providers' => [\n    // Other service providers...\n    Laravel\\Socialite\\SocialiteServiceProvider::class,\n],\n\n'aliases' => [\n    // Other aliases...\n    'Socialite' => Laravel\\Socialite\\Facades\\Socialite::class,\n]\n```\n\n### Oauth Credential 설정\n\n[Github Developer Applications Console](https://github.com/settings/developers) 을 방문하여 'Register new application' 버튼을 눌러 아래 그림과 같이 정보를 입력하자. Authorization callback URL 은 'http://localhost:8000/auth/github/callback'으로 하자.\n\n![](./images/33-social-login-img-01.png)\n\n![](./images/33-social-login-img-02.png)\n\nApplication 등록이 완료되어 위 그림과 같은 등록정보 페이지를 확인할 수 있는데, 여기서 'Client ID'와 'Client Secret'를 복사하여, config/services.php 에 github 소셜로그인 정보를 셋팅한다. 물론 .env 파일에 넣고, `env()` Helper 로 읽어 오는 것이 정석이다.\n\n```php\n// config/services.php\n\nreturn [\n    // Other services setting\n    \n    'github' => [\n        'client_id' => '복사한 Client ID',\n        'client_secret' => '복사한 Client Secret',\n        'redirect' => route('session.github.callback'),\n    ],\n];\n```\n\n### Route 정의\n\n공식문서대로 구현하자. 대신 Route 이름을 주자.\n\n```php\nRoute::group(['prefix' => 'auth', 'as' => 'session.'], function () {\n    // Other route definitions...\n    \n    /* Social Login */\n    Route::get('github', [\n        'as'   => 'github.login',\n        'uses' => 'Auth\\AuthController@redirectToProvider'\n    ]);\n    Route::get('github/callback', [\n        'as'   => 'github.callback',\n        'uses' => 'Auth\\AuthController@handleProviderCallback'\n    ]);\n});\n```\n\n### 컨트롤러 메소드 정의\n\napp/Http/Controllers/Auth/AuthController.php 에 아래 메소드를 추가한다.\n\n```php\nclass AuthController extends Controller\n{\n    ...\n    \n    public function redirectToProvider()\n    {\n        return \\Socialite::driver('github')->redirect();\n    }\n\n    public function handleProviderCallback()\n    {\n        $user = \\Socialite::driver('github')->user();\n\n        dd($user);\n    }\n}\n```\n\n`redirectToProvider()` 메소드는 사용자가 소셜로그인 버튼을 눌렀을 때, Github 승인 페이지로 이동시켜주는 Redirect 응답을 만들어 준다. Github 쪽에서 모든 작업이 완료되면, 앞 절에서 우리가 설정한 Authorization callback URL로 Redirect 시키면서 Payload로 여러가지 정보들을 넘겨준다. 요청을 받은 `handleProviderCallbck()` 메소드는 Github 로 부터 넘겨 받은 Payload를 기반으로 `Laravel\\Socialite\\Two\\User` 인스턴스를 만든다.\n \n'http://localhost:8000/auth/github' 주소를 직접 쳐서 여기까지 테스트를 해 보자.\n \n![](./images/33-social-login-img-04.png)\n\n### 소셜 사용자 등록 및 로그인 처리\n\nGithub를 이용해서 로그인한 사용자를 우리 서비스의 사용자로도 등록시키자. 또, 세션을 만들어야 하므로, 로그인 처리도 하기 위해 `handleProviderCallback()` 메소드를 업데이트하자. 엘로퀀드 모델에서 `firstOrCreate()` 메소드는 인자로 주어진 정보와 일치하는 레코드가 있으면 반환하고, 없으면 새로 생성하는 역할을 한다.\n\n```php\nclass AuthController extends Controller\n{\n    ...\n    \n    public function handleProviderCallback()\n    {\n        $user = \\Socialite::driver('github')->user();\n\n        $user = User::firstOrCreate([\n            'name'  => $user->getName(),\n            'email' => $user->getEmail(),\n        ]);\n\n        auth()->login($user, true);\n\n        return redirect(route('home'));\n    }\n```\n\n'http://localhost:8000/auth/github' 주소를 직접 쳐서 여기까지 테스트를 해 보자.\n \n![](./images/33-social-login-img-05.png)\n\n**`참고`** Github 사용자의 경우, 현재는 비밀번호가 없기 때문에 네이티브 로그인 기능으로 로그인할 수 없다. users 테이블에 소셜로그인으로 생성된 사용자에 대한 유효성을 표시하는 플래그를 만들고, 로그인 이메일은 맞는데 비밀번호가 없고 소셜 로그인 유효성 플래그가 있는 경우, 비밀번호를 추가로 받아 네이티브로도 로그인할 수 있게 하는 등의 기능 확장은 /각/자/ 해 보자. 또, Github 뿐만 아니라, 여러 소셜 로그인 공급자를 등록할 수 있도록 Social 모델을 만들어서 User 모델과 연결시키는 수준의 기능확장도 /각/자/ 도전해 보자.\n\n### 소셜 로그인 버튼 추가\n\n사용자가 Github 를 이용해 우리 서비스에 로그인할 수 있도록 로그인 페이지에 버튼을 달아 주자.\n\n```html\n@section('style')\n  <style>\n    /* 딱 이 페이지에서만 필요한 스타일링이 있어 여기에 정의했다. */\n    /* 뭘 했는지는 코드를 살펴보자. */\n  </style>\n@stop\n\n@section('content')\n  <form action=\"{{ route('session.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n\n    <div class=\"page-header\">\n      <h4>Login</h4>\n    </div>\n\n    <div class=\"form-group\">\n      <a class=\"btn btn-default btn-block\" href=\"{{ route('session.github.login') }}\">\n        <strong><i class=\"fa fa-github icon\"></i> Login with Github</strong>\n      </a>\n    </div>\n    \n    ...\n@stop\n```\n\n![](./images/33-social-login-img-06.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [32강 - 사용자 로그인](32-login.md)\n- [34강 - 사용자 역할](34-role.md)\n<!--@end-->\n\n \n \n"
  },
  {
    "path": "lessons/34-role.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 35\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 34강 - 사용자 역할\n\n역할 기능을 이용해 RBAC (== Role Based Access Control)을 구현할 것이다. 앞에서 배운 'auth' 미들웨어가 할 수 있는 것은 특정 엔드포인트에 들어가려면 로그인(== Authentication, 인증)이 필요하다 정도라면, 접근 제어 또는 권한 부여(== Authorization 또는 Access Control)는 특정 엔드포인트는 admin 역할을 가진 사용자만 들어갈 수 있도록 할 수 있다. 우리 프로젝트를 예로 들면, 포럼 글은 로그인한 사용자 누구나 볼 수 있지만, 수정이나 삭제는 admin 또는 소유자만 할 수 있도록 하는 것이 권한 부여의 기능이다. \n\n### 패키지 설치\n\n사용자에게 역할을 부여하기 위해 bican/roles 패키지를 이용할 것이다. 라라벨에도 [Authorization](http://laravel.com/docs/authorization) 기능을 지원하고 있으나, 필자에겐 사용법이 너무 어려웠다.\n \n```bash\n$ composer require \"bican/roles: 2.1.*\"\n```\n\n```php\n// config/app.php\n\nreturn [\n    'providers' => [\n        // Other service providers ...\n        Bican\\Roles\\RolesServiceProvider::class,\n    ],\n];\n```\n\n```bash\n$ php artisan vendor:publish --provider=\"Bican\\Roles\\RolesServiceProvider\" --tag=config\n$ php artisan vendor:publish --provider=\"Bican\\Roles\\RolesServiceProvider\" --tag=migrations\n$ php artisan migrate\n```\n\nUser 모델을 수정하자. 라라벨 네이티브 Authorization을 사용하지 않을 것이므로 `AuthorizableContract` 와 `Authorizable` trait를 삭제하자.\n\n```php\nuse ...\nuse Bican\\Roles\\Traits\\HasRoleAndPermission;\nuse Bican\\Roles\\Contracts\\HasRoleAndPermission as HasRoleAndPermissionContract;\n\nclass User extends Model implements AuthenticatableContract,\n                                    /*AuthorizableContract,*/\n                                    CanResetPasswordContract,\n                                    HasRoleAndPermissionContract\n{\n    use Authenticatable;\n    use CanResetPassword;\n    use HasRoleAndPermission;\n    ...\n}\n```\n\nRoute 별로 역할에 따른 권한부여를 쉽게 하기 위해서, bican/roles 패키지에 내장되어 배포되는 미들웨어를 app/Http/Kerlen.php 에 등록해 놓자. 나중에 Route에서 `'middleware' => 'role:admin'` 또는 컨트롤러에서 `$this->middleware('role:admin')` 처럼 사용할 수 있다.\n \n```php\nclass Kernel extends HttpKernel\n{\n    ...\n    protected $routeMiddleware = [\n        // Other middleware registrations ...\n        'role' => \\Bican\\Roles\\Middleware\\VerifyRole::class,\n    ];\n}\n```\n\n### 역할을 만들자.\n\n관리자모드에서 사용자와 역할을 관리하는 UI를 만드는 것이 좋다. 여기서는 artisan CLI의 tinker 코맨드를 이용한다.\n\n```bash\n$ php artisan tinker\n>>> $admin = Bican\\Roles\\Models\\Role::create([\n... 'name' => 'Admin',\n... 'slug' => 'admin'\n... ]);\n=> Bican\\Roles\\Models\\Role {#718\n     name: \"Admin\",\n     slug: \"admin\",\n     updated_at: \"2015-11-18 06:10:59\",\n     created_at: \"2015-11-18 06:10:59\",\n     id: 1,\n   }\n>>> $member = Bican\\Roles\\Models\\Role::create([\n... 'name' => 'Member',\n... 'slug' => 'member'\n... ]);\n=> Bican\\Roles\\Models\\Role {#730\n     name: \"Member\",\n     slug: \"member\",\n     updated_at: \"2015-11-18 06:11:57\",\n     created_at: \"2015-11-18 06:11:57\",\n     id: 2,\n   }\n```\n\nUser 13번에 admin 역할을 부여하고, 나머지는 member 역할을 부여할 것이다. \n\n```bash\n$ php artisan tinker\n>>> $users = App\\User::where('id', '!=', 13)->get();\n>>> $users->map(function($user) {\n... $user->roles()->sync([2]);\n... });\n>>> $user = App\\User::find(13);\n>>> $user->roles()->sync([1]);\n```\n\nUser 와 Role 은 Many to Many 관계를 갖는다. 1명의 User가 여러 개의 Role을 가질 수 있고, admin Role을 가진 User는 여러 명이 있을 수 있다. Forum, Tag, Comment 모델을 다룰 때 뒤에서 다시 살펴볼 것이다. \n\n**`참고`** `Bican\\Roles\\Models\\Role` 모델과 `App\\User` 모델에 추가한 trait를 잘 따라가보면, 우리가 흔히 보았던 `return $this->belongsToMany('App\\User')` 와 같은 관계 설정을 확인할 수 있다.\n\n`map()` 메소드는 `array_map()`과 같은 동작을 한다. Many To Many 관계는 role_user 란 피봇테이블을 이용하여 관계를 기록하는데, `$user->roles()->attach(int|array $id)` 로 관계를 기록하고, `$user->roles()->detach(int|array $id)`로 관계를 끊을 수 있다. `$user->roles()->sync(array $ids)` 메소드는 인자로 넘겨 받은 $ids 목록과 피봇테이블에 써진 관계를 비교해, 인자에 없고 테이블에 있으면 테이블에서 해당 $id들 삭제하고, 인자에 있고 테이블에 없으면 테이블에 해당 $id들을 추가해 준다.\n  \n### 테스트\n\n지금 당장 쓰지 않으니, 모든 기능이 동작하는 지 확인만하고 넘어가도록 하자.\n\n```bash\n$ php artisan tinker\n>>> App\\User::find(12)->is('admin'); \n=> false\n>>> App\\User::find(13)->is('admin');\n=> true\n>>> App\\User::find(13)->is('admin|member', true); \n# == is(['admin', 'member'], true); or isAll(['admin', 'member']);\n=> false\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [33강 - 소셜 로그인](33-social-login.md)\n- [35강 - 다국어 지원](35-locale.md)\n<!--@end-->\n\n"
  },
  {
    "path": "lessons/35-locale.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 36\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 35강 - 다국어 지원\n\n필자도 좀 오버했다는 생각이 들긴 한다. 그래도 기획에 들어 있는 내용이니 해 보자.\n\n### 설계 의사 결정\n\n생각을 해 보자. 뷰(UI)에 제시된 영어/한국어 선택지 중 사용자가 선호하는 언어를 선택한다. \n> Q : 사용자의 선호를 서비스에 어떻게 전달할 것인가? \n> A : 링크에 쿼리스트링으로 달아서 사용자 선택값을 전달하도록 하자. \n\n사용자의 선호를 기억해 두었다가 다음번에 방문했을 때는 링크 선택지를 다시 누르지 않고 기존에 선택한 언어로 서비스가 제공되어야 한다. 기억해둔다 == 저장한다. \n> Q : 어디에 저장할 것인가? \n> A : 필자는 쿠키로 선택했다. User 모델에 써 두는 것은 사용자가 로그인 하기 전에 알 수 없기 때문이다.\n\n그런데, 잘 생각해 보면, \n> Q : 브라우저 요청에 따라 서버에서 뷰를 만들고 응답하기 전에 언어값이 반영되어야 한다. \n> A : 즉, 브라우저의 요청에 붙은 쿠키값을 읽어 라라벨이 부트업되는 시점부터 전체 프레임웍의 언어가 바뀌어 있어야 한다는 의미다. \n\n어렵다~\n\n**`잡담`** 쿠키는 프론트엔드, 즉 브라우저에 저장된다. 가령, 폰트 사이즈에 대한 사용자 설정이라면 서버를 거칠 필요가 없이 자바스크립트에서 미리 저장된 쿠키 또는 localStorage 를 읽어서 동적으로 CSS 속성을 변경하면 된다. 그런데, 폰트 사이즈가 아니다. AngularJS와 같은 프론트엔드 프레임웍을 사용한다면, 서버에서 언어 딕셔너리 전체를 JSON으로 내려받고, 사용자가 브라우저에 저장한 값을 읽어 컨트롤러나 뷰모델에서 런타임에 동적으로 스트링들을 바꿀 수도 있다. 서버 로드를 줄이는 측면에서 좋지만, 프론트엔드쪽의 코드량이나 메모리 사용량이 늘어난다. 결국은 BE개발자와 FE개발자간의 폭탄 떠넘기기 문제이다.\n\n### 공유된 뷰 데이터\n\n전혀 관련없어 보이지만, 좀 있어 보면 왜 이걸 했는지 안다~. 컨트롤러에서 뷰를 반환할 때 뷰에서 쓸 데이터를 바인딩하는 것으로 입문코스에서 배웠다. 데이터 중에서는 뷰마다 달라지지 않을 뿐 더러, 모든 뷰에서 가지고 있으면 편리한 데이터들이 있다. 이 때 `View::share(string $key, mixed $value)` 메소드를 이용한다. 모든 컨트롤러가 상속하는 app/Http/Controllers/Controller.php 의 생성자에서 뷰에 쓰일 공통 데이터를 공유해 보자.\n\n```php\nabstract class Controller extends BaseController\n{\n    public function __construct() {\n        $this->setSharedVariables();\n    }\n\n    protected function setSharedVariables() {\n        view()->share('currentLocale', app()->getLocale());\n        view()->share('currentUser', auth()->user());\n        view()->share('currentRouteName', \\Route::currentRouteName());\n        view()->share('currentUrl', \\Request::fullUrl());\n    }\n}\n```\n\n**`주의-주의-주의`** abstract Controller에서 생성자를 사용했으므로, 이를 상속 받는 컨트롤러들이 생성자를 사용하고 있다면, 반드시 `parent::__construct()` 를 호출해 주어야 하다는 점이다. DocumentsController, WelcomeController, AuthController, PasswordController 에 적용하자. 적용하지 않으면 `$current*` 변수가 없어서 에러가 난다.\n\n```php\nclass DocumentsController extends Controller\n{\n    public function __construct(Document $document)\n    {\n        $this->document = $document;\n        parent::__construct();\n    }\n    ...\n}\n```\n\n### 뷰를 수정하자.\n\n사용자가 언어를 토글할 수 있는 방법은 뷰이다. 앞선 강좌에서 resources/views/layouts/footer.blade.php 를 언어 선택을 위한 정적 메뉴를 만들었던 것을 기억할 것이다. 동적 메뉴로 고치자.\n\n```html\n<footer class=\"footer\">\n  <ul class=\"list-inline pull-right locale\">\n    <li><i class=\"fa fa-language\"></i></li>\n    @foreach (['en' => 'English', 'ko' => '한국어'] as $locale => $language)\n      <li class=\"{{ ($locale == $currentLocale) ? 'active' : '' }}\">\n        <a href=\"{{ route('locale', ['locale' => $locale, 'return' => urlencode($currentUrl)]) }}\">\n          {{ $language }}\n        </a>\n      </li>\n    @endforeach\n  </ul>\n\n  ...\n</footer>\n```\n\n`@foreach`로 루프를 돌면서 링크를 뿌리고 있다. `$currentLocale`, `$currentUrl` 변수는 앞 절에서 공유된 뷰 데이터이다. 이 partial 뷰는 마스터 뷰에 포함되어 있고, 마스터 뷰를 이용하는 어떤 뷰라도 컴파일될 때, 이 변수들은 사용할 수 있다. English와 한국어 중 사용자가 선택한 언어에 'active' 클래스를 표시하기 위해 3항 연산자를 사용했고, 언어 변경 요청후 현재 Url로 다시 돌아 오기 위해 return 이란 쿼리스트링을 달았다. \n\n### Route & 컨트롤러 정의\n\n사용자가 뷰에서 누른 언어 변경 요청 링크에 응답하는 Route를 만들고, 컨트롤러에 연결하자.\n\n```php\nRoute::get('locale', [\n    'as' => 'locale',\n    'uses' => 'WelcomeController@locale'\n]);\n```\n\nWelcomeController를 수정한다. `Cookie::forever(string $key, mixed $value)` 메소드를 이용해서 브라우저의 요청에서 넘겨 받은 쿼리스트링의 locale 값으로(== 'en' or 'ko') 쿠키 인스턴스를 만들었다. 만들어진 쿠키 인스턴스를 다음 응답에 실어서 보내기 위해서 `Cookie::queue()` 로 예약을 걸어 두었다. 그 다음 Redirect 응답을 만드는데, 쿼리스트링에 return 값이 있을 때와 없을 때를 3항 연산자로 분기시켰다.\n\n```php\nclass WelcomeController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth', ['only' => ['home']]);\n        parent::__construct();\n    }\n    \n    ...\n    \n    public function locale()\n    {\n        $cookie = cookie()->forever('locale__myProject', request('locale'));\n\n        cookie()->queue($cookie);\n\n        return ($return = request('return'))\n            ? redirect(urldecode($return))->withCookie($cookie)\n            : redirect(route('home'))->withCookie($cookie);\n    }\n}\n```\n\n여기서 서버를 띄우고 홈페이지로 접근해서 footer 영역에서 '한국어' 링크를 눌러보자.\n\n**`참고`** 라라벨이 내 보내는 쿠키는 해킹 툴들로 값을 조작하는 것을 방지하지 위해 암호화 되어 있다. `Crypt::decrypt(string $payload)` 메소드로 풀어서 써야 한다. \n\n![](./images/35-locale-img-01.png)\n\n브라우저에 저장된 쿠키 값을 읽어서 tinker 로 해독해 보았다.\n\n```bash\n$ php artisan tinker\n>>> Crypt::decrypt('eyJ...SJ9');\n=> \"ko\"\n```\n\n그런데, 아무리 눌러도 '한국어' 링크가 active 상태로 바뀌지 않는다.\n\n### AppServiceProvider\n\n우리가 이제까지 작업한 것은 쿠키 값을 셋팅하는 행위였을 뿐이다. 런타임에 기본 언어를 바꾸라고 라라벨에게 어떤 명령도 하지 않았다. app/Providers/AppServiceProvider.php 를 수정하자. `Request::cookie(string $key)` 메소드로 앞서 브라우저와 주고 받은 쿠키 값을 읽어 와서 `App::setLocale(string $locale)` 메소드로 기본 언어를 바꾸라고 라라벨에게 명령했다.\n\n```php\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        if ($locale = request()->cookie('locale__myProject')) {\n            app()->setLocale(\\Crypt::decrypt($locale));\n        }\n    }\n    ...\n}\n```\n\n다시 확인해 보자. 이제 잘 될 것이다.\n\n**`참고`** ServiceProvider의 `boot()`와 `register()` 메소드들은 라라벨이 부트업될 때 실행된다. 둘 간의 차이점은 [공식문서](http://laravel.com/docs/master/providers#writing-service-providers)에 잘 설명되어 있다. 쉽게 `register()`에서는 외부에서 가져온 인스턴스 생성등 라라벨 프레임웍과 크게 무관한 작업을, `boot()`에서는 프레임웍의 기능이 어느 정도 살아 나서, 사용자 코드들을 수행하기 직전에 수행된다고 생각하면 된다. 즉, `register()` 에서는 Helper나 Event 등이 동작하지 않는 상태인 것이다. \n\n### 기본 언어 설정\n\n기본 언어는 config/app.php 에 'locale' 키로 설정되어 있다. 앞에서 우리가 한 것은 런타임에 언어를 바꾸라고 변경한 것이다 'fallback_locale'은 곧 배울 `trans(string $key)` Helper 에서 $key 에 해당하는 언어별 스트링 정의가 없을 경우, 폴백되는 언어 설정의 의미한다. \n\n```php\nreturn [\n    'locale' => 'en',\n    'fallback_locale' => 'en',\n];\n```\n\n### 언어 파일 만들기\n\n뷰에서 `trans(string $key)` 로 언어 파일을 사용할 수 있다. 언어 딕셔너리들은 resources/lang 아래에 정의되어 있다. 현재는 'en' 디렉토리만 존재하는데, 기본언어 또는 런타임에 설정한 언어가 'en' 이라면, 'en' 디렉토리 밑에서 `$key` 값을 찾게 된다. 즉, ko 란 디렉토리를 만들고, 딕셔너리를 정의해 놓으면 한국어 서비스를 할 수 있다는 의미이다.\n\n그리고, 뷰에 하드코드로 박아놓은 스트링들은 `{{ trans('auth.failed') }}` 식으로 모두 바꾸도록 하자.\n\n```bash\n$ php artisan tinker\n>>> trans('auth.failed');\n=> \"These credentials do not match our records.\"\n>>> app()->setLocale('ko');\n>>> trans('auth.failed');\n=> \"로그인 정보가 정확하지 않습니다.\"\n```\n\n필자는 resources/lang/en/auth.php에 딕셔너리 키들을 더 추가하고, documents.php와 forum.php 를 추가로 생성했다. 이 부분은 코드를 참고해서 각자 알아서 하셔야 한다. \n\n딕셔너리에서 변수를 사용하는 예 살펴보자. 딕셔너리에서 `'key' => '... :변수명 ...'` 으로 쓰고, 뷰에서 `trans('key', ['변수명' => '바인딩 할 값'])`식으로 사용한다는 것을 기억하자.\n\n```php\n// resources/lang/en/auth.php\nreturn [\n    'title_signup_help' => '... Please <a href=\":url\">login via Github</a> ...',\n];\n```\n\n```html\n<!-- resoucres/views/auth/register.blade.php -->\n<p class=\"text-muted\">\n  {!!  trans('auth.title_signup_help', ['url' => route('session.create')]) !!}\n</p>\n```\n\n## `icon()` Helper\n\n다국어와 뷰를 작업하는 김에... \n`icon()` Helper는 뷰에서 호출했을 때, FontAwesome 아이콘을 뿌리기 위한 HTML 스트링을 반환해 주는 역할을 할 것이다. `route()` Helper랑 마찬가지로 Route 이름을 넣어줄거냐? 하드코드로 뷰나 컨트롤러에 Url을 박아 넣을 거냐?의 의사결정인 것이다. 프로젝트의 성격(규모)나 개인의 선호도에 달린 것이므로 어떻게 구현할지는 각자가 알아서 선택하도록 하자.\n\n```php\n// app/helpers.php\n...\nif (! function_exists('icon')) {\n    function icon($class, $addition = 'icon', $inline = null) {\n        $icon   = config('icons.' . $class);\n        $inline = $inline ? 'style=\"' . $inline . '\"' : null;\n\n        return sprintf('<i class=\"%s %s\" %s></i>', $icon, $addition, $inline);\n    }\n}\n```\n\n```php\n// config/icons.php\nreturn [\n    'login'       => 'fa fa-sign-in',\n    ...,\n];\n```\n\n```html\n<!-- resources/views/auth/login.blade.php -->\n...\n<li>\n  <a href=\"{{ route('session.create') }}\">{!! icon('login') !!} {{ trans('auth.title_login') }}</a>\n</li>\n...\n```\n\n![](./images/35-locale-img-02.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [34강 - 사용자 역할](34-role.md)\n- [36강 - 마이그레이션과 모델](36-models.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/36-models.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 37\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 36강 - 마이그레이션과 모델\n\n이번 강좌에서는 포럼에서 사용할 테이블들을 생성하기 위한 마이그레이션을 만들고, 각 테이블에 대응되는 엘로퀀트 모델을 만들것이다. 이번 강좌를 통해 One to Many, Many to Many, Polymorphic Many to Many 등 모델간 관계를 배울 것이다.\n\n### 테이블 설계\n\n[31강 - 포럼 개발 기획](31-forum-features.md)을 참고해서 articles, comments, tags, attachments 총 4개의 메인 테이블과 article_tag 란 피봇 테이블로 설계해 보았다. \n \n![](./images/36-models-img-01.png)\n\n- Article 모델\n    - Article 인스턴스는 1명의 User가 작성한 것이다. (외래키 'author_id')\n    - 하나의 Article에 대해 여러 개의 Comment가 달릴 수 있다.\n    - 하나의 Comment를 Best Answer로 선택할 수 있다. (외래키 'solution_id')\n    - 하나의 Article에 여러 개의 Tag를 붙일 수 있다.\n    - 하나의 Article에 여러 개의 첨부파일을 붙일 수 있다.\n    - Article 인스턴스에 'notification' 필드값이 셋팅되어 있는 상태에서, Comment가 등록되면 'author_id'를 가진 User에게 이메일을 보낼 것이다.\n- Comment 모델\n    - Comment 인스턴스는 특정 User가 작성한 것이다. (외래키 'commentable_id')\n    - Comment의 Comment, 즉 대댓글 기능을 위해, 하나의 Comment는 부모 Comment를 가질 수 있다. 즉, Comment 내부에서 재귀적인 관계가 형성된다.\n    - Comment는 Article 모델과 관계를 가질 수도 있지만, 다른 모델과 다형적인 관계를 가질 수도 있다. (Polymorphic Many to Many라 한다. 'commentable_type', 'commentable_id'로 필드명을 정했다.)\n- Tag 모델\n    - 하나의 Tag 가 여러 개의 Article과 연결되어 있다.\n- Attachment 모델\n    - Attachment 인스턴스는 하나의 Article에 소속된다.\n    \n가령, 우리 프로젝트에 Post, Application과 같은 모델이 더 있고, 모든 모델들은 모두 댓글 기능이 있다고 가정해 보자. 이 때, ArticleComment, PostComment, ApplicationComment로 총 3개의 모델을 만들고 각각 관계를 연결하는 것이 아니라, [**Polymorphic Many to Many**](http://laravel.com/docs/eloquent-relationships#many-to-many-polymorphic-relations) 관계를 이용할 수 있다. Comment 모델 하나로, Article의 Comment로도, Post의 Comment로도 쓸 수 있는 것이다. \n\nArticle과 Tag는 Many to Many 관계를 가지고, 이를 위해 article_tag란 피봇테이블을 도입했다. Role과 User간의 Many to Many 관계 연결을 위한 role_user 피봇테이블은 [34강 - 사용자 역할](34-role.md)을 진행하는 과정에서 'bican/role' 패키지를 설치하는 과정에 생성된 것이다.\n\n### 마이그레이션 작성\n\nartisan CLI를 이용한다. `--migration` 옵션을 주면, 모델을 만들 때 마이그레이션도 같이 생성해 준다. article_tag 테이블을 만들 때는 `--create=테이블이름` 옵션을 이용했는데, 이 옵션을 주면 마이그레이션 작성시 타이핑을 좀 줄일 수 있다 (차이는 직접 경험해 보자). \n\n```bash\n$ php artisan make:model Comment --migration\n$ php artisan make:model Article --migration\n$ php artisan make:model Tag --migration\n$ php artisan make:model Attachment --migration\n$ php artisan make:migration create_article_tag_table --create=\"article_tag\"\n```\n\n마이그레이션을 만들 때 주의할 점이 있다. 마이그레이션 파일들은 파일명에 타임스탬프를 담고 있고, 생성 순서에 따라 순차적으로 실행된다. 우리 프로젝트에서는 create_articles_table 마이그레이션에서 comments 테이블과 'solution_id'를 이용해서 외래키 관계를 설정하고 있다. comments 테이블이 먼저 생성되어 있어야 articles 테이블에서 comment_id 외래키로 테이블간 연결할 수 있다. 즉, 마이그레이션은 순서가 중요하다.\n\n혹, 순서가 잘못되어 마이그레이션 실행시 오류가 발생했다면... 이번 마이그레이션 실행으로 인해, 생성된 테이블이나, migrations 테이블에 추가된 엔트리가 있다면 삭제한다. 수동으로 파일명의 타임스탬프를 조작해 주어 실행 순서를 변경시킨 후, 마이그레이션을 다시 실행할 수 있다.  \n\n`down()` 메소드에 해당하는 리버스 마이그레이션은 아래에서 생략하였다.\n\n```php\n// database/migrations/create_comments_table\nclass CreateCommentsTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('comments', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('author_id')->unsigned()->index();\n            $table->string('commentable_type');\n            $table->integer('commentable_id')->unsigned();\n            $table->integer('parent_id')->unsigned();\n            $table->string('title');\n            $table->text('content');\n            $table->timestamps();\n\n            $table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');\n            $table->foreign('parent_id')->references('id')->on('comments')->onDelete('cascade');\n        });\n    }\n}\n```\n\n```php\n// database/migrations/create_articles_table\nclass CreateArticlesTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('articles', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('author_id')->unsigned()->index();\n            $table->string('title');\n            $table->text('content');\n            $table->integer('solution_id')->unsigned()->nullable();\n            $table->boolean('notification')->default(1);\n            $table->timestamps();\n\n            $table->foreign('author_id')->references('id')->on('users')->onDelete('cascade');\n            $table->foreign('solution_id')->references('id')->on('comments');\n        });\n    }\n}\n```\n\n```php\n// database/migrations/create_tags_table\nclass CreateTagsTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('tags', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name');\n            $table->string('slug')->index();\n            $table->timestamps();\n        });\n    }\n}\n```\n\n```php\n// database/migrations/create_attachments_table\nclass CreateAttachmentsTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('attachments', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name');\n            $table->integer('article_id')->unsigned()->index();\n            $table->timestamps();\n        });\n    }\n}\n```\n\n```php\n// database/migrations/create_article_tag_table\nclass CreateArticleTagTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('article_tag', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('article_id')->unsigned();\n            $table->integer('tag_id')->unsigned();\n            $table->timestamps();\n\n            $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');\n            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');\n        });\n    }\n}\n```\n\n마이그레이션을 실행하자.\n\n```bash\n$ php artisan migrate\n```\n\n### 모델 작성 \n\n테이블 설계에서 정리한 내용을 기반으로 모델간의 관계를 설정하고, `$fillable`, `$hidden` 필드를 설정하자.\n\n```php\n// app/User.php\n\nclass User extends Model implements ...\n{\n    ...\n    \n    /* Relationships */\n\n    public function articles()\n    {\n        return $this->hasMany(Article::class, 'author_id');\n    }\n\n    public function comments()\n    {\n        return $this->hasMany(Comment::class, 'author_id');\n    }\n}\n```\n\n```php\n// app/Comment.php\n\nclass Comment extends Model\n{\n    protected $fillable = [\n        'commentable_type',\n        'commentable_id',\n        'author_id',\n        'parent_id',\n        'title',\n        'content'\n    ];\n\n    protected $hidden = [\n        'author_id',\n        'commentable_type',\n        'commentable_id',\n        'parent_id'\n    ];\n\n    /* Relationships */\n\n    public function author()\n    {\n        return $this->belongsTo(User::class, 'author_id');\n    }\n\n    public function commentable()\n    {\n        return $this->morphTo();\n    }\n\n    public function replies()\n    {\n        return $this->hasMany(Comment::class, 'parent_id');\n    }\n\n    public function parent()\n    {\n        return $this->belongsTo(Comment::class, 'id', 'parent_id');\n    }\n}\n```\n\n```php\n// app/Article.php\n\nclass Article extends Model\n{\n    protected $fillable = [\n        'author_id',\n        'title',\n        'content',\n        'notification'\n    ];\n\n    protected $hidden = [\n        'author_id',\n        'solution_id',\n        'notification'\n    ];\n\n    /* Relationships */\n\n    public function author()\n    {\n        return $this->belongsTo(User::class, 'author_id');\n    }\n\n    public function tags()\n    {\n        return $this->belongsToMany(Tag::class);\n    }\n\n    public function comments()\n    {\n        return $this->morphMany(Comment::class, 'commentable');\n    }\n\n    public function solution()\n    {\n        return $this->hasOne(Comment::class, 'id', 'solution_id');\n    }\n\n    public function attachments()\n    {\n        return $this->hasMany(Attachment::class);\n    }\n}\n```\n\n```php\n// app/Tag.php\n\nclass Tag extends Model\n{\n    protected $fillable = [\n        'name',\n        'slug'\n    ];\n\n    /* Relationships */\n\n    public function articles()\n    {\n        return $this->belongsToMany(Article::class);\n    }\n}\n```\n\n```php\n// app/Attachment.php\n\nclass Attachment extends Model\n{\n    protected $fillable = [\n        'name'\n    ];\n\n    protected $hidden = [\n        'article_id'\n    ];\n\n    /* Relationships */\n\n    public function article()\n    {\n        return $this->belongsTo(Article::class);\n    }\n}\n```\n\n### 모델 팩토리 작성\n\nTag 팩토리의 `$faker->optional(0.9, 'Laravel')->word` 문법은 [fzaninotto/faker API](https://github.com/fzaninotto/Faker#unique-and-optional-modifiers), Attachment 팩토리의 `$faker->randomElement(['png', 'jpg'])` 문법은 [fzaninotto/faker API](https://github.com/fzaninotto/Faker#formatters)를 참고하자.\n\n```php\n$factory->define(App\\User::class, function (Faker\\Generator $faker) {\n    return [\n        'name'           => $faker->name,\n        'email'          => $faker->email,\n        'password'       => bcrypt(str_random(10)),\n        'remember_token' => str_random(10),\n    ];\n});\n\n$factory->define(App\\Article::class, function (Faker\\Generator $faker) {\n    return [\n        'title'   => $faker->sentence(),\n        'content' => $faker->paragraph(),\n    ];\n});\n\n$factory->define(App\\Comment::class, function (Faker\\Generator $faker) {\n    return [\n        'title'   => $faker->sentence,\n        'content' => $faker->paragraph,\n    ];\n});\n\n$factory->define(App\\Tag::class, function (Faker\\Generator $faker) {\n    $name = ucfirst($faker->optional(0.9, 'Laravel')->word);\n\n    return [\n        'name' => $name,\n        'slug' => str_slug($name),\n    ];\n});\n\n$factory->define(App\\Attachment::class, function (Faker\\Generator $faker) {\n    return [\n        'name' => sprintf(\"%s.%s\", str_random(), $faker->randomElement(['png', 'jpg'])),\n    ];\n});\n```\n\n`App\\Attachment` 모델은 사용자가 업로드한 파일의 이름(또는 경로)을 담고 있는 모델이란 것을 이해하고 넘어가자. 가령, 사용자가 'foo.png'를 업로드 했다면, 이 모델의 'name' Attribute는 'foo.png'가 되는 것이다.\n  \n**`참고`** 필자가 필드(field), Attribute, Property 란 용어를 혼용해서 사용하는데 모두 같은 의미로 이해하자. HTML 폼이나 DB 테이블에서는 필드라는 이름이 좀 더 적절하고, 오브젝트 컨텍스트에서는 Attribute나 Property란 용어가 더 적절할 것이다. \n\n### Seeder 작성\n\n편의상 app/database/seeds/DatabaseSeeder.php 에 전부 몰아 넣었지만, 쪼개서 설명한다.\n\n```php\nuse Faker\\Factory as Faker;\n\nclass DatabaseSeeder extends Seeder\n{\n    public function run()\n    {\n        /*\n         * Prepare seeding\n         */\n        $faker = Faker::create();\n        DB::statement('SET FOREIGN_KEY_CHECKS=0');\n        Model::unguard();\n\n        /*\n         * Seeding users table\n         */\n        App\\User::truncate();\n        factory(App\\User::class)->create([\n            'name' => 'John Doe',\n            'email' => 'john@example.com',\n            'password' => bcrypt('password')\n        ]);\n        factory(App\\User::class, 9)->create();\n        $this->command->info('users table seeded');\n```\n\n`truncate()` 메소드로 users 테이블을 비운다. 테스트를 위해 사용할 john@example.com 계정을 만들고, 나머지 Dummy 계정 9개를 만들었다. \n\n```php\n        /**\n         * Seeding roles table\n         */\n        Bican\\Roles\\Models\\Role::truncate();\n        DB::table('role_user')->truncate();\n        $adminRole = Bican\\Roles\\Models\\Role::create([\n            'name' => 'Admin',\n            'slug' => 'admin'\n        ]);\n        $memberRole = Bican\\Roles\\Models\\Role::create([\n            'name' => 'Member',\n            'slug' => 'member'\n        ]);\n\n        App\\User::where('email', '!=', 'john@example.com')->get()->map(function($user) use($memberRole) {\n            $user->attachRole($memberRole);\n        });\n\n        App\\User::whereEmail('john@example.com')->get()->map(function($user) use($adminRole){\n            $user->attachRole($adminRole);\n        });\n        $this->command->info('roles table seeded');\n```\n\n'Admin' 과 'Member' 역할을 만들고, john@example.com 계정에는 'Admin' 역할을, 나머지 계정에는 'Member' 권한을 할당하였다. `$user->attachRole(Bican\\Roles\\Models\\Role|int $role)` 메소드는 'bican/role' 에서 제공하는 Helper 메소드로, `$user->roles()->attach(array $roleId)` 또는 `$user->roles()->sync(array $roleId)`와 같은 역할을 한다.\n\n```php\n        /*\n         * Seeding articles table\n         */\n        App\\Article::truncate();\n        $users = App\\User::all();\n\n        $users->each(function($user) use($faker) {\n            $user->articles()->save(\n                factory(App\\Article::class)->make()\n            );\n        });\n        $this->command->info('articles table seeded');\n```\n\n앞서 생성된 모든 `App\\User` 컬렉션을 `$users` 변수에 담았다. `each()` 메소드로 루프를 돌면서, `article()` 관계를 이용해 `App\\Article` 인스턴스를 만들었다 \n\n```php\n        /**\n         * Seeding comments table\n         */\n        App\\Comment::truncate();\n        $articles = App\\Article::all();\n\n        $articles->each(function($article) use($faker, $users) {\n            $article->comments()->save(\n                factory(App\\Comment::class)->make([\n                    'author_id' => $faker->randomElement($users->lists('id')->toArray())\n                ])\n            );\n        });\n        $this->command->info('comments table seeded');\n```\n\nArticle 모델과 동일하게, 이번에는 앞서 생성된 `App\\Article` 전체 컬렉션을 `$articles` 변수에 담고, 루프를 돌면서 미리 모델에서 정의한 관계를 이용해 `App\\Comment` 인스턴스를 만든다. 여기서 `factory()->make()` 메소드에 인자로 넘긴 값은, 모델 팩토리에서 정의한 값을 오버라이드하거나 추가하는 값이다. 'author_id' 필드를 `$faker->randomElement()` 메소드를 이용하여 넣어 주었다.\n\n![](./images/36-models-img-02.png)\n\n```php\n        /*\n         * Seeding tags table\n         */\n        App\\Tag::truncate();\n        DB::table('article_tag')->truncate();\n        $articles->each(function($article) use($faker) {\n            $article->tags()->save(\n                factory(App\\Tag::class)->make()\n            );\n        });\n        $this->command->info('tags table seeded');\n```\n\n'article_tag' 피봇테이블은 모델을 정의하지 않았기 때문에, DB Facade를 이용하여 `truncate()` 하였다.\n\n```php\n        /*\n         * Seeding attachments table\n         */\n        App\\Attachment::truncate();\n        if (! File::isDirectory(attachment_path())) {\n            File::deleteDirectory(attachment_path(), true);\n        }\n\n        $articles->each(function($article) use($faker) {\n            $article->attachments()->save(\n                factory(App\\Attachment::class)->make()\n            );\n        });\n\n        $files = App\\Attachment::lists('name');\n\n        if (! File::isDirectory(attachment_path())) {\n            File::makeDirectory(attachment_path(), 777, true);\n        }\n\n        foreach($files as $file) {\n            File::put(attachment_path($file), '');\n        }\n\n        $this->command->info('attachments table seeded');\n\n        /**\n         * Close seeding\n         */\n        Model::reguard();\n        DB::statement('SET FOREIGN_KEY_CHECKS=1');\n    }\n}\n```\n\n`App\\Attachment` Seeder에서는 DB 테이블에 저장되는 모델 뿐 아니라, 사용자가 업로드하여 서버의 파일 시스템에 저장되는 파일들도 같이 생성해 주어야 한다. 해서, `truncate()` 하는 과정에서 파일이 저장된 디렉토리를 청소해 주었고, Seeding 하면서 Dummy 파일도 같이 생성해 주었다.\n\n### Helper Function\n\nSeeding 과정에서 사용한 `attachment_path()` Helper 을 app/helpers.php 에 만들어 주자.\n\n```php\nif (! function_exists('attachment_path')) {\n    /**\n     * @param string $path\n     *\n     * @return string\n     */\n    function attachment_path($path = '')\n    {\n        return public_path($path ? 'attachments'.DIRECTORY_SEPARATOR.$path : 'attachments');\n    }\n}\n```\n\n### 테스트\n\nSeeding 을 실행하자. 마이그레이션부터 완전 다시 할 것이다.\n\n```bash\n$ php artisan migrate:refresh --seed\n\n# Above command is equivalent to the following 3 commands... \n# php artisan migrate:reset\n# php artisan migrate\n# php artisan db:seed\n```\n\n오류 없이 실행되었다면, 마이그레이션, 모델과 관계설정, 모델 팩토리, Seeder 모두가 정상적으로 작성된 것이다. 더블 체크를 위해 artisan CLI 로 더 확인해 보아도 좋다.\n \n```bash\n$ php artisan tinker\n\n>>> $user = App\\User::find(1);\n>>> $user->articles()->first();\n>>> $user->comments()->first();\n\n>>> $article = App\\Article::find(1);\n>>> $article->author()->first();\n>>> $article->tags()->first();\n>>> $article->comments()->first();\n>>> $article->attachments()->first();\n\n>>> $comment = App\\Comment::find(1);\n>>> $comment->author()->first();\n>>> $comment->commentable()->first();\n>>> $comment->replies()->first();\n>>> $comment->parent()->first();\n\n>>> $tag = App\\Tag::find(1);\n>>> $tag->articles()->first();\n\n>>> $attachment = App\\Attachment::find(1);\n>>> $attachment->article()->first();\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [35강 - 다국어 지원](35-locale.md)\n- [37강 - Article 기능 구현](37-articles.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/37-articles.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 38\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 37강 - Article 기능 구현\n\n이번 강좌를 통해 포럼의 핵심인 Article 기능을 구현할 것이다. 캐싱이나 이벤트 등은 나중에 다듬기로 하고, 컨트롤러와 뷰 위주로 작업을 해 보자. \n\n### Route 정의 및 컨트롤러 생성\n\nRESTful 리소스 컨트롤러를 이용한다.\n\n```php\n// app/Http/routes.php\n\nRoute::resource('articles', 'ArticlesController');\n```\n\n```bash\n$ php artisan make:controller ArticlesController --resource\n$ php artisan route:list\n```\n\n`index()`와 `show()` 메소드, 즉 포럼 목록 보기와 개별 포럼 상세 보기만 guest 에게 허용할 것이다. 그리고, 사이드바에 모든 태그 목록을 뿌리기 위해, [35강 - 다국어 지원](35-locale.md)에서 했던 것 처럼, `$allTags` 란 변수를 포럼을 위한 모든 뷰에 공유할 것이다.\n\n```php\nclass ArticlesController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth', ['except' => ['index', 'show']]);\n        view()->share('allTags', \\App\\Tag::with('articles')->get());\n        parent::__construct();\n    }\n}\n```\n\n### 목록 보기 구현\n\n완성된 모양을 먼저 보자.\n\n![](./images/37-articles-img-01.png)\n\nresources/views/articles/index.blade.php 는 포럼 목록을 보여주는 뷰이다. 크게 보면 Tag 를 보여주는 왼쪽 영역과, 목록을 보여주는 오른쪽 영역으로 구분된다. 왼쪽 영역에서는 검색 폼 (layouts/partial/search.blade.php) 과 전체 태그 목록(tags/partial/index.blade.php)을 블레이드 문법으로 `@include` 하고 있다. 오른쪽은 포럼 엔트리들을 표시하는데, 각 엔트리(articles/partial/article.blade.php)는 사용자의 [Gravatar](http://ko.gravatar.com/) (users/partial/avatar.blade.php)를 보여주는 영역과 각 Article과 연결된 태그의 목록(tags/partial/list.blade.php)을 보여주는 영역으로 구성되어 있다.\n\n`ArticleController::index()` 메소드를 작성하자. Eager Loding 으로 'comments', 'author', 'tags' 관계를 포함하고, `paginate()` 메소드로 한번에 10개의 Article 인스턴스를 불러오도록 하였다.\n\n```php\nuse App\\Article;\n\nclass ArticlesController extends Controller\n{\n    public function index()\n    {\n        $articles = Article::with('comments', 'author', 'tags')->latest()->paginate(10);\n\n        return view('articles.index', compact('articles'));\n    }\n}\n```\n \n위에 나열한 뷰들을 작성하자. 레이아웃 관련된 내용들은 각자 입맛에 맞게 작성하도록 하자.\n \n```html\n<!-- resources/views/articles/index.blade.php -->\n\n@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    ...\n  </div>\n\n  <div class=\"row container__forum\">\n    <div class=\"col-md-3 sidebar__forum\">\n      <aside>\n        @include('layouts.partial.search')\n        @include('tags.partial.index')\n      </aside>\n    </div>\n\n    <div class=\"col-md-9\">\n      <article>\n        @forelse($articles as $article)\n          @include('articles.partial.article', ['article' => $article])\n        @empty\n          <p class=\"text-center text-danger\">{{ trans('errors.not_found_description') }}</p>\n        @endforelse\n\n        <div class=\"text-center\">\n          {!! $articles->appends(Request::except('page'))->render() !!}\n        </div>\n      </article>\n    </div>\n\n  </div>\n@stop\n```\n\n하위 뷰에 데이터를 넘겨 줄 때는, `@include('articles.partial.article', ['article' => $article])` 식으로 넘긴다는 것을 익혀 두자. \n\n`{{ $articles->appends(Request::except('page'))->render() }}` 는 나중에 Url 뒤에 여러 개의 쿼리스트링이 붙을 것을 대비해, 미리 `appends()` 메소드를 이용해서 page 쿼리를 빼고 나머지들은 모두 붙이도록 했다. 가령, GET /articles?solved=0 요청의 페이징 링크는 /articles?solved=0&page=1, /articles?solved=0&page=2 와 같은 식으로 생성된다.\n\n```html\n<!-- resources/views/layouts/partial/search.blade.php -->\n\n<form action=\"#\" method=\"get\" role=\"search\">\n  <input type=\"text\" name=\"q\" value=\"{{ Input::get('q') }}\" class=\"form-control\" placeholder=\"Search\"/>\n</form>\n```\n\n풀텍스트 검색 기능은 나중에 구현할 것이므로, 폼만 만들어 놓고 넘어가자.\n\n```html\n<!-- resources/views/tags/partial/index.blade.php -->\n \n<p class=\"lead\">\n  {!! icon('tags') !!} Tags\n</p>\n\n<ul class=\"list-unstyled\">\n  @foreach($allTags as $tag)\n    <li class=\"{{ (Route::current()->parameter('id') == $tag->id) ? 'active' : '' }}\">\n      <a href=\"#\">\n        {{ $tag->name }}\n        @if ($tagCount = $tag->articles->count())\n          <span class=\"badge badge-default\">{{ $tagCount }}</span>\n        @endif\n      </a>\n    </li>\n  @endforeach\n</ul>\n```\n\n`ArticlesController::__construct()` 에서 모든 뷰에 공유한 `$allTags` 변수를 여기서 이용한다.\n \n'active' 클래스를 표시하기 위해 삼항 연산자를 이용하였고, `Route::current()->parameter('id')` 로 현재 요청의 Route 파라미터를 얻어 왔다. 아직 Route 가 정의되지 않았으므로 이 기능은 동작하지 않는데, 곧 고칠 것이다.\n\n`$tagCount = $tag->articles->count()` 로 각 Tag 에 해당하는 Article 의 갯수를 구하고, 태그 이름 옆에 숫자로 표시하였다. `ArticlesController::__construct()` 에서 `$allTags` 변수에서 Eager Loading 을 한 이유가, 여기서 N + 1 쿼리 문제를 피하기 위해서였다.\n \n **`참고`** 태그 리스트를 포함한 왼쪽 영역은 여러 뷰에서 사용하므로, [뷰 컴포저](http://laravel.com/docs/views#view-composers)로 구성하면 더 깔끔하다. 이 코스 수준을 넘어서는 내용으로 각자 공부해서 적용해 보자. \n\n```html\n<!-- resources/views/articles/partial/article.blade.php -->\n \n<div class=\"media\">\n  @include('users.partial.avatar', ['user' => $article->author])\n\n  <div class=\"media-body\">\n    <h4 class=\"media-heading\">\n      <a href=\"{{ route('articles.show', $article->id) }}\">\n        {{ $article->title }}\n\n        @if ($commentCount = $article->comments->count())\n          <span class=\"badge pull-right\">\n            {!! icon('comments') !!} {{ $commentCount }}\n          </span>\n        @endif\n\n        @if ($article->solution_id)\n          <span class=\"badge pull-right\">\n            {!! icon('check') !!} {{ trans('forum.solved') }}\n          </span>\n        @endif\n      </a>\n    </h4>\n\n    <p class=\"text-muted\">\n      <a href=\"{{ gravatar_profile_url($article->author->email) }}\" style=\"margin-right: 1rem;\">\n        {!! icon('user') !!} {{ $article->author->name }}\n      </a>\n      {!! icon('clock') !!} {{ $article->created_at->diffForHumans() }}\n    </p>\n\n    @include('tags.partial.list', ['tags' => $article->tags])\n  </div>\n</div>\n```\n\n`@include('users.partial.avatar', ['user' => $article->author])` 로, `$user` 변수를 사용자 사진을 표시할 하위 뷰에 데이터를 넘겨 준다. \n\n`$commentCount = $article->comments->count()` 로,  각 Article에 연결된 Tag 의 갯수를 구하고, Article 제목 옆에 갯수를 표시하였다. \n\n기본기 강좌에서 'created_at', 'updated_at'은 `Carbon\\Carbon` 인스턴스라고 얘기한바 있다. `$article->created_at->diffForHumans()` 메소드를 쓰면 '6 hours ago' 처럼 Article 생성 시각을 표시할 수 있다.\n\n`@include('tags.partial.list', ['tags' => $article->tags])` 로, 각 Article 인스턴스에 연결된 Tag 의 목록을 넘겨 준 것을 기억해 놓자.\n\n```html\n<!-- resources/views/users/partial/avatar.blade.php -->\n\n@if ($user)\n  <a class=\"pull-left hidden-xs hidden-sm\" href=\"{{ gravatar_profile_url($user->email) }}\">\n    <img class=\"media-object img-thumbnail\" src=\"{{ gravatar_url($user->email, 64) }}\" alt=\"{{ $user->name }}\">\n  </a>\n@else\n  <a class=\"pull-left hidden-xs hidden-sm\" href=\"{{ gravatar_profile_url('john@example.com') }}\">\n    <img class=\"media-object img-thumbnail\" src=\"{{ gravatar_url('john@example.com', 64) }}\" alt=\"Unknown User\">\n  </a>\n@endif\n```\n\n`gravatar_profile_url()`, `gravatar_url()` Helper를 이용하여, 사용자의 프로파일 주소와 아바타를 가져왔다. 이 Helper들은 다음 섹션에서 구현할 것이다. 로그인한 사용자만 포럼을 남길 수 있게 조치했으므로, `$user` 변수가 없을 가능성은 없다. `$user = null` 인 경우를 대비해, 미리 조심해서 나쁠 것은 없다. \n\n```html\n<!-- resources/views/tags/partial/list.blade.php -->\n\n@if ($tags->count())\n  <span class=\"text-muted\">{!! icon('tags') !!}</span>\n  <ul class=\"tags__forum\">\n    @foreach ($tags as $tag)\n      <li class=\"label label-default\">\n        <a href=\"#\">{{ $tag->name }}</a> </li>\n    @endforeach\n  </ul>\n@endif\n```\n\n'articles/partial/article.blade.php' 에서 넘겨 받은 `$tags` 변수를 이용하여, 각 Article 에 연결된 Tag 들의 이름을 뿌려준다. 링크 href 속성에 '#'로 표시된 부분은 나중에 다시 업데이트할 것이다.\n\n#### Gravatar Helper\n\n```php\n// app/helpers.php\n\nfunction gravatar_profile_url($email)\n{\n    return sprintf(\"//www.gravatar.com/%s\", md5($email));\n}\n\nfunction gravatar_url($email, $size = 72)\n{\n    return sprintf(\"//www.gravatar.com/avatar/%s?s=%s\", md5($email), $size);\n}\n```\n\n```bash\n$ php artisan tinker\n>>> gravatar_url('juwonkim@me.com');\n=> \"//www.gravatar.com/avatar/6a7346bbad52884566008892003fc6ac?s=72\"\n```\n\n's' 쿼리는 가져올 아바타 이미지의 사이즈를 의미한다.\n\n### 상세 보기 구현\n\n목록에서 Article 엔트리의 제목을 누르면 'GET /articles/{id}' 로 넘어가도록 목록 보기 뷰에서 링크를 걸었다. 이 Route 에 해당하는 `ArticlesController::show()` 메소드를 작성하자.\n\n```php\nclass ArticlesController extends Controller\n{\n    public function show($id)\n    {\n        $article = Article::with('comments', 'author', 'tags')->findOrFail($id);\n\n        return view('articles.show', compact('article'));\n    }\n}\n```\n\n앞에서 작업을 많이 했기에 'articles/show.blade.php' 는 의외로 간단하다. Article 인스턴스의 'content' 속성값을 뿌리기 위해, 이전에 만든 `markdown()` Helper를 이용하였다.\n \n```html\n<!-- resources/views/articles/show.blade.php -->\n\n@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    ...\n  </div>\n\n  <div class=\"row container__forum\">\n    <div class=\"col-md-3 sidebar__forum\">\n      <aside>\n        @include('layouts.partial.search')\n        @include('tags.partial.index')\n      </aside>\n    </div>\n\n    <div class=\"col-md-9\">\n      <article>\n        @include('articles.partial.article', ['article' => $article])\n\n        <p>\n          {!! markdown($article->content) !!}\n        </p>\n      </article>\n      ...\n      <article>\n        Comment here\n      </article>\n    </div>\n  </div>\n@stop\n```\n\n'Comment here' 라고 된 부분이 보일 것이다. 여기에 댓글 작성 폼과, 그간 작성된 댓글 목록이 표시될 것이다.\n\n![](./images/37-articles-img-02.png)\n \n### 포럼 쓰기 구현\n\n#### 쓰기 UI 구현\n\n새 포럼 글을 쓰는 UI는 목록 보기 뷰나 상단의 네비게이션 메뉴에 위치하면 적절할 것 같다.\n\n```html\n<!-- resources/views/articles/index.blade.php -->\n\n<div class=\"page-header\">\n  <a class=\"btn btn-primary pull-right\" href=\"{{ route('articles.create') }}\">\n    {!! icon('forum') !!} {{ trans('forum.create') }}\n  </a>\n  ...\n</div>\n...\n```\n\n#### 쓰기 폼 구현\n\n포럼을 쓰기 위한 폼을 만들자.\n\n```php\n// app/Http/Controllers/ArticlesController\n\npublic function create()\n{\n    $article = new Article;\n\n    return view('articles.create', compact('article'));\n}\n```\n\n`$article = new Article;` 부분은 create 와 edit 뷰에서 폼을 공용으로 사용하기 위한 편법이다. 뒤에 나오는 공용 폼에서 `<input type=\"text\" ... value=\"{{ old('title', $article->title) }}\"/>` 에서 edit 뷰에서는 Article 인스턴스가 바인딩되지만, create 뷰에는 바인딩되지 않기 때문에 'Undefined variable: article' 에러가 난다. `old()` Helper 에서 세션에 `$title` 값이 있으면 쓰고, 없으면 `$article->title`로 폴백하라는 의미이다. \n\n```html\n<!-- resources/articles/create.blade.php -->\n\n@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    ...\n  </div>\n\n  <div class=\"container__forum\">\n    <form action=\"{{ route('articles.store') }}\" method=\"POST\" role=\"form\" class=\"form__forum\">\n      {!! csrf_field() !!}\n\n      @include('articles.partial.form')\n\n      <div class=\"form-group\">\n        <p class=\"text-center\">\n          <a href=\"{{ route('articles.create') }}\" class=\"btn btn-default\">\n            {!! icon('reset') !!} Reset\n          </a>\n          <button type=\"submit\" class=\"btn btn-primary my-submit\">\n            {!! icon('plane') !!} Post\n          </button>\n        </p>\n      </div>\n    </form>\n  </div>\n@stop\n```\n\n`@include('articles.partial.form')` 은 포럼 수정하기에서도 동일하게 사용되는 폼이므로 하위 뷰로 뺐다.\n\n```html\n<!-- resources/articles/partial/form.blade.php -->\n\n<div class=\"form-group\">\n  <label for=\"title\">{{ trans('forum.title') }}</label>\n  <input type=\"text\" name=\"title\" id=\"title\" class=\"form-control\" value=\"{{ old('title', $article->title) }}\"/>\n  {!! $errors->first('title', '<span class=\"form-error\">:message</span>') !!}\n</div>\n\n<div class=\"form-group\">\n  <label for=\"content\">{{ trans('forum.content') }}</label>\n  <textarea name=\"content\" class=\"form-control\" rows=\"10\">{{ old('content', $article->content) }}</textarea>\n  {!! $errors->first('content', '<span class=\"form-error\">:message</span>') !!}\n</div>\n\n<div class=\"form-group\">\n  @include('articles.partial.tagselector')\n</div>\n\n<div class=\"form-group\">\n  <div class=\"checkbox\">\n    <label>\n      <input type=\"checkbox\" name=\"notification\" checked=\"{{ $article->notification ?: 'checked' }}\">\n      {{ trans('forum.notification') }}\n    </label>\n  </div>\n</div>\n```\n\n`@include('articles.partial.tagselector')`, 나중에 포럼을 작성/수정할 때 태그를 선택하는 UI를 추가할 것이다. 여유가 된다면, 'content' 필드에 쓴 내용을 마크다운으로 미리보기하는 기능도 추가해 볼 것이다.\n\n![](./images/37-articles-img-03.png)\n\n#### 저장 로직 구현\n\n기본기 강좌의 [23강 - 입력 값 유효성 검사](23-validation.md)에서는 다루지 않았는데, 여기서는 [Form Request](http://laravel.com/docs/validation#form-request-validation) 를 사용하여 사용자의 입력값 유효성 검사를 할 것이다.\n\n```bash\n$ php artisan make:request ArticlesRequest\n```\n\n```php\n// app/Http/Requests/ArticlesRequest.php\n\nclass ArticlesRequest extends Request\n{\n    public function authorize()\n    {\n        return true;\n    }\n\n    public function rules()\n    {\n        return [\n            'title'   => 'required',\n            'content' => 'required',\n        ];\n    }\n}\n```\n\n`authorize()` 메소드에서 `false` 를 반환하면, 403 Forbidden 응답이 떨어진다. 우선은 `true`를 반환하자.\n\n`rules()` 메소드에서 각 필드별로 검사할 규칙을 정의한다. 여기서는 'required' 만 이용했다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nuse App\\Http\\Requests\\ArticlesRequest;\n\nclass ArticlesController extends Controller\n{\n    public function store(ArticlesRequest $request)\n    {\n        $article = Article::create($request->all());\n        flash()->success(trans('forum.created'));\n        \n        return redirect(route('articles.index'));\n    }\n}\n```\n\n`store()` 메소드에 원래 있던 `Illuminate\\Http\\Request` 대신, 방금 만든 `App\\Http\\Requests\\ArticlesRequest` 을 주입했다. 우리가 만든 Form Request는 원래있던 Request 객체를 상속하고 있고, 거기다 유효성 검사 기능을 추가한 것이다. Form Request 는 미들웨어와 유사한 기능을 하고 있는데, 우리가 만든 Form Request를 통과하지 못하면, `store()` 메소드는 전혀 실행되지 않는다. \n\n`flash()` 메소드는 [32강 - 사용자 로그인](32-login.md) 에서 설치한 'laracasts/flash' 패키지에 포함된 Helper로, `success()`, `error()` 등에 메소드를 체인해서 사용할 수 있다. \n\nTag UI 가 준비되면, 유효성 검사 로직과 저장 로직을 다시 손 볼 것이다.\n\n### 포럼 수정 구현\n\n#### 수정 UI 구현\n\n수정 및 삭제 UI는 주로 목록 보기 또는 상세 보기에서 접근할 수 있다. 여기서는 상세 보기 뷰에서 구현한다. \n\n```html\n<!-- resources/articles/show.blade.php -->\n\n<article>\n...\n  <p class=\"text-center\">\n    <a href=\"{{route('articles.edit', $article->id)}}\" class=\"btn btn-info\">\n      {!! icon('pencil') !!} Edit \n    </a>\n  </p>\n</article>\n```\n\n#### 수정 폼 구현\n\n쓰기 폼에서 공용 폼을 만들었기에 한결 간편해 졌다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function edit($id)\n{\n    $article = Article::findOrFail($id);\n\n    return view('articles.edit', compact('article'));\n}\n```\n\n```html\n<!-- resources/articles/edit.blade.php -->\n\n@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    ...\n  </div>\n\n  <div class=\"container__forum\">\n    <form action=\"{{ route('articles.update', $article->id) }}\" method=\"POST\" role=\"form\" class=\"form__forum\">\n      {!! csrf_field() !!}\n      {!! method_field('PUT') !!}\n\n      @include('articles.partial.form')\n\n      <div class=\"form-group\">\n        <p class=\"text-center\">\n          <a href=\"{{ route('articles.edit', $article->id) }}\" class=\"btn btn-default\">\n            {!! icon('reset') !!} Reset\n          </a>\n          <button type=\"submit\" class=\"btn btn-primary\">\n            {!! icon('plane') !!} Edit\n          </button>\n        </p>\n      </div>\n    </form>\n  </div>\n@stop\n```\n\n`{!! method_field('PUT') !!}` 는 [13강 - RESTful 리소스 컨트롤러](13-restful-resource-controller.md) 에서 설명한 메소드 오버라이드를 위한 숨김 필드를 생성해 주는 Helper 로, `<input type=\"hidden\" name=\"_method\" value=\"PUT\">` 태그를 생성한다.\n\n#### 수정 로직 구현\n\n포럼 쓰기에서 만든 FormRequest를 그대로 사용하자.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function update(ArticlesRequest $request, $id)\n{\n    $article = Article::findOrFail($id);\n    $article->update($request->except('_token', '_method'));\n    flash()->success(trans('forum.updated'));\n\n    return redirect(route('articles.index'));\n}\n```\n\n![](./images/37-articles-img-04.png)\n\n### 포럼 삭제 구현\n\n#### 삭제 UI 구현\n\n일반적으로 삭제는 Ajax 요청을 이용하는데, 여기서는 전통적인 폼 요청을 통해서 하도록 하자.\n\n```html\n<!-- resources/articles/show.blade.php -->\n\n...\n  <div class=\"text-center\">\n    <form action=\"{{ route('articles.destroy', $article->id) }}\" method=\"post\">\n      {!! csrf_field() !!}\n      {!! method_field('DELETE') !!}\n      <button type=\"submit\" class=\"btn btn-danger\">\n        {!! icon('delete') !!} Delete\n      </button>\n      <a href=\"{{route('articles.edit', $article->id)}}\" class=\"btn btn-info\">\n        {!! icon('pencil') !!} Edit\n      </a>\n    </form>\n  </div>\n</article>\n```\n\n#### 삭제 로직 구현\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function destroy($id)\n{\n    Article::findOrFail($id)->delete();\n    flash()->success(trans('forum.deleted'));\n\n    return redirect(route('articles.index'));\n}\n```\n\n### 접근 제어 (Authorization)\n\n상세 보기에서 관리자이거나 사용자 자신이 작성한 포럼만 수정하거나 삭제할 수 있도록 할 것이다. [34강 - 사용자 역할](34-role.md) 에서 설치한 'bican/roles' 패키지가 밥값을 할 차례이다... 라고 생각하고, 이용하려고 했으나 뭔가 여의치 않다. \n\n해서 User 와 Article 모델에 Helper 메소드를 만들었다. 어쨌든, 뷰에서 접근을 제한하여 버튼 UI 자체가 표시되지 않게 하는 게 우선이고...\n \n```php\n// app/User.php\n\npublic function isAdmin()\n{\n    return $this->roles()->whereSlug('admin')->exists();\n}\n```\n\n```php\n// app/Article.php\n\npublic function isAuthor()\n{\n    return $this->author->id == auth()->user()->id;\n}\n```\n\n```html\n<!-- resources/articles/show.blade.php -->\n\n  @if (auth()->user()->isAdmin() or $article->isAuthor())\n  <div class=\"text-center\">\n    <form ...>\n      <button ...>Delete</button>\n    </form>\n    <a ...>Edit</a>\n  @endif\n</article>\n```\n\n다음은 CURL 코맨드 등을 이용하여 직접 Route 에 접근하는 것을 막아야 한다. 이를 위해 Route 미들웨어를 만들고, app/Http/Kernel.php 에 Route 미들웨어라고 등록할 것이다.\n\n```bash\n$ php artisan make:middleware CanAccessArticle\n```\n\n```php\n// app/Http/Middleware/CanAccessArticle.php\n\nclass CanAccessArticle\n{\n    public function handle($request, Closure $next)\n    {\n        $user = $request->user();\n        $articleId = $request->route('articles');\n\n        if (! \\App\\Article::whereId($articleId)->whereAuthorId($user->id)->exists() and ! $user->isAdmin()) {\n            flash()->error(trans('errors.forbidden') . ' : ' . trans('errors.forbidden_description'));\n\n            return back();\n        }\n\n        return $next($request);\n    }\n}\n```\n\n`Illuminate\\Http\\Request` 인스턴스에서는 `user()` 메소드를 사용할 수 있으며, `auth()->user()` 와 동일한 결과를 얻을 수있다. 로그인한 사용자 id와 Route 파라미터로 넘겨 받은 Article id로 Article 모델을 검색하여 레코드가 있으면, 작성자이므로 통과시켜 주는 식이다.\n\n**`참고`** 미들웨어에서 Route를 통해 사용자로부터 넘겨 받은 파라미터를 이용할 수 있다. [미들웨어 파라미터](http://laravel.com/docs/middleware#middleware-parameters)를 잘 이용하면, Article 모델 뿐 아니라 여러 모델에 적용할 수 있는 미들웨어를 만들수 있을 것이다.\n\n```php\n// app/Http/Kernel.php\n\nprotected $routeMiddleware = [\n    // Other Route Middlewares ...\n    'accessible' => \\App\\Http\\Middleware\\CanAccessArticle::class,\n];\n```\n\n컨트롤러에서 미들웨어를 등록하자. 미들웨어는 순차적으로 실행되므로 반드시 'auth' 미들웨어 다음에 정의되어야 한다. 이유는 사용자 로그인을 먼저 걸러주고 난 이후에, 이 사용자가 해당 Route와 컨트롤러 메소드에 접근할 수 있는 지 체크하는 식이다. \n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function __construct()\n{\n    ...\n    $this->middleware('accessible', ['except' => ['index', 'show', 'create']]);\n}\n```\n\n#### 테스트\n\nartisan CLI의 tinker 코맨드로 사용자의 비밀번호를 수정하자.\n\n```bash\n$ php artisan tinker\n>>> $user = App\\User::find(2);\n>>> $user->password = bcrypt('password');\n>>> $user->save();\n```\n\n1번과 2번 사용자로 번갈아 로그인한 후 구현한 내용이 잘 동작하는 지 확인해 보자.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [36강 - 마이그레이션과 모델](36-models.md)\n- [38강 - Tag 기능 구현](38-tags.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/38-tags.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 39\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 38강 - Tag 기능 구현\n\n이번 강좌에서는 37강에서 구현하던 포럼의 Article 기능에 Tag 기능을 더할 것이다. \n\n### 태그 선택 UI 구현\n\n`ArticlesController::__construct()` 에서 뷰에 공유한 `$allTags` 변수를 이용하여, `<select>` 태그를 만든다.\n\n```html\n<!-- resources/views/articles/partial/tagselector.blade.php -->\n\n<div class=\"form-group\">\n  <label for=\"tags\">{{ trans('forum.tags') }}</label>\n  <select class=\"form-control\" multiple=\"multiple\" id=\"tags\" name=\"tags[]\">\n    @foreach($allTags as $tag)\n      <option value=\"{{ $tag->id }}\" {{ in_array($tag->id, $article->tags->lists('id')->toArray()) ? 'selected=\"selected\"' : '' }}>{{ $tag->name }}</option>\n    @endforeach\n  </select>\n  {!! $errors->first('tags', '<span class=\"form-error\">:message</span>') !!}\n</div>\n```\n\n앞서 보았다시피, 이 뷰는 'create' 와 'edit'에서 공통으로 사용하는 'resources/views/articles/partial/form.blade.php' 의 하위 뷰이다. 코드가 좀 지저분 한데, 삼항 연산자로 각 `<option>` 태그에 'selected' 속성을 표시하는 연산을 하고 있다.\n\n'form.blade.php' 에서 `@include('articles.partial.tagselector')` 로 'tagselector' 뷰를 하위로 포함하면서 `$article` 변수를 넘겨주지 않았다. 부모 뷰에서 `$article` 변수가 유효하기에 자식 뷰에서도 쓸 수 있는 것이다. `@include` 되는 뷰에서 쓸 변수와 같은 변수이면, `['varAtSubView' => $currentVar]` 식으로 변수 이름을 바꿀 필요가 없다는 것을 기억하고 있자.\n\n![](./images/38-tags-img-01.png)\n\n**`참고`** [Laravel Collective의 Form Helper](http://laravelcollective.com/docs/5.1/html#drop-down-lists)를 이용하면, 복잡한 `<select>` 박스를 좀 더 쉽게 쓸 수 있다. 바로 아래 코드 블럭을 보면, 여전히 복잡하긴 하지만, 그래도 코드량을 상당히 줄일 수 있다는 것을 알 수 있다. \n\n```html\n<div class=\"form-group\">\n  {!! Form::label('tags', trans('forum.tags')) !!}\n  {!! Form::select('tags', $allTags, old('tags', $article->tags->lists('id')->toArray()), ['multiple' => 'multiple', 'class' => 'form-control'])}}\n  {!! $errors->first('tags', '<span class=\"form-error\">:message</span>') !!}\n</div>\n```\n\n### 컨트롤러 구현\n\n#### 유효성 검사 보강\n\n37강에서 'tags' 필드에 대해서는 유효성 검사를 수행하지 않았다. 여기서 추가한다.\n\n```php\n// app/Http/Requests/ArticlesRequest.php\n\npublic function rules()\n{\n    return [\n        // Other Validation Rules...\n        'tags'    => 'required|array'\n    ];\n}\n```\n\n#### 기존 컨트롤러 로직의 문제점 확인\n\n앞선 37강에서 `$request->all()`로 모든 폼 데이터를 Article 엘로퀀트 모델의 `create()` 메소드에 인자로 넣었다. 이 때 'notification' 필드가 문제가 된다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function store(ArticlesRequest $request)\n{\n    dd($request->all());\n}\n```\n\n`dd()` Helper 로 확인해 보면 아래와 같이 찍힌다. 코드를 찾아보면, 'articles' 테이블 마이그레이션에서 `$table->boolean('notification')->default(1);` 처럼 정의했었다. \"on\" 과 같은 string 값을 받을 수 없고, 0|1 만 받을 수 있다.\n\n```php\narray:4 [▼\n  \"_token\" => \"QCfBxat0DDhVi06rb3aMmaTRfz6uxnvm1Dbp6i0v\"\n  \"title\" => \"...\"\n  \"content\" => \"...\"\n  \"notification\" => \"on\"\n]\n```\n\n#### 컨트롤러 보강\n\n위 문제점의 수정을 포함해서, `ArticlesController::store()`, `ArticlesController::update()` 메소드에서 UI 에서 전달한 'tags[]' 필드를 받고, Article 모델과 Tag 모델간의 관계를 지정하는 코드를 작성하도록 하자.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function store(ArticlesRequest $request)\n{\n    $payload = array_merge($request->except('_token'), [\n        'notification' => $request->has('notification')\n    ]);\n\n    $article = $request->user()->articles()->create($payload);\n    $article->tags()->sync($request->input('tags'));\n    flash()->success(trans('forum.created'));\n\n    return redirect(route('articles.index'));\n}\n\n...\n\npublic function update(ArticlesRequest $request, $id)\n{\n    $payload = array_merge($request->except('_token'), [\n        'notification' => $request->has('notification')\n    ]);\n\n    $article = Article::findOrFail($id);\n    $article->update($payload);\n    $article->tags()->sync($request->input('tags'));\n    flash()->success(trans('forum.updated'));\n\n    return redirect(route('articles.index'));\n}\n```\n\n`$request->has(string $key)` 는 폼 데이터에 '$key' 값이 있는 기 검사한 후, true/false 를 반환한다. 2 개의 메소드에 중복된 부분들이 많이 보이지만, 설명의 복잡성을 피하기 위해 손대지 않았다.\n\n**`참고`** 엘로퀀트 모델에서 [Mutator](http://laravel.com/docs/eloquent-mutators#accessors-and-mutators) 를 쓸 수 있다. 이를 이용하면 컨트롤러에서 `'notification' => $request->has('notification')` 와 같이 데이터 변환을 하지 않아도, 모델이 생성되는 시점에서 `Article::$notification` 속성 값을 boolean 으로 바꾸어 놓을 수 있다.\n\n### 미려한 UI\n\n좀 Off Topic 이긴하지만, 나이스한 태그 선택 UI를 위해, [select2 jQuery 플러그인](https://select2.github.io/)을 설치하고 사용할 것이다.\n\n```bash\n$ bower install select2 --save-dev\n```\n\n메인 Sass 파일에 select2 의 스타일시트를 @import 한다.\n\n```css\n/* resources/assets/sass/app.scss */\n\n@import \"../vendor/font-awesome/scss/font-awesome\";\n@import \"../vendor/select2/src/scss/core\";\n// ...\n```\n\nGulp 빌드 태스크에 select2 의 JS 파일을 포함한다.\n\n```javascript\n// gulpfile.js\n\nelixir(function (mix) {\n  mix\n    .scripts([\n      // Other Files...\n      '../vendor/select2/dist/js/select2.js',\n      'app.js'\n    ], 'public/js/app.js')\n    // Other Scripts...\n});\n```\n\n빌드하자.\n\n```bash\n$ gulp # 또는 gulp --production\n```\n\n이제 `layouts.master` 를 상속하는 모든 뷰에서 select2 JS 인스턴스에 접근할 수 있다. 우리는 포럼 쓰기, 수정 폼에서만 사용할 것이고, 폼은 공용으로 빼 놓았고, 그 폼은 다시 tagselector.blade.php 를 `@import` 하므로.. 한 곳에서만, 즉 'tagselector.blade.php' 에서만 select2 를 활성화 시키는 스크립트를 쓰면 된다. \n\n```html\n<!-- resources/views/articles/partial/tagselector.blade.php -->\n\n...\n\n@section('script')\n  <script>\n    $(\"select#tags\").select2({\n      placeholder: \"{{ trans('forum.tags_help') }}\",\n      maximumSelectionLength: 3\n    });\n  </script>\n@stop\n```\n\n'placeholer', 'maximumSelectionLength' 등, select2 JS 인스턴스의 옵션은 [공식문서](https://select2.github.io/examples.html)를 참조하자.\n\n![](./images/38-tags-img-02.png)\n\n### 태그 링크 살리기\n\n#### Route 정의\n\n포럼 목록 보기에서 왼쪽의 태그 리스트에서 태그 이름을 누르면, 해당 태그에 속하는 포럼 글 목록만 보여 주게 할 것이다. 'GET /tags/1/articles' 와 같은 Url 요청이 들어오면 Tag 1번에 연결된 Article 목록을 보여줄 것이다.\n\n```php\n// app/Http/routes.php\n\nRoute::get('tags/{id}/articles', [\n    'as'   => 'tags.articles.index',\n    'uses' => 'ArticlesController@index'\n]);\nRoute::resource('articles', 'ArticlesController');\n```\n\n#### 컨트롤러 작성\n\n기존에 만든 `ArticlesController@index` 를 사용할 것이므로, 약간의 분기가 필요하다. 'GET /tags/{id}/articles' 에서는 id 파라미터가 있고, 'GET /articles' 에서는 없다는 것에 착안하자. (또는 Route 이름으로 분기할 수도 있을 것이다.)\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function index($id = null)\n{\n    $query = $id\n        ? Tag::find($id)->articles()\n        : new Article;\n\n    $articles = $query->with('comments', 'author', 'tags')->latest()->paginate(10);\n\n    return view('articles.index', compact('articles'));\n}\n```\n\n#### 뷰 수정\n\nTag 와 관련된 뷰는 'resources/views/tags' 아래에 위치하고 있다. Named Route 를 썼으므로 `route()` Helper를 이용하여 링크를 살려줄 수 있다.\n\n```html\n<!-- resources/views/tags/partial/index.blade.php -->\n\n...\n<ul ...>\n  @foreach($allTags as $tag)\n    <li class=\"{{ (Route::current()->parameter('id') == $tag->id) ? 'active' : '' }}\">\n      <a href=\"{{ route('tags.articles.index', $tag->id) }}\">\n        ...\n      </a>\n    </li>\n  @endforeach\n</ul>\n```\n\n```html\n<!-- resources/views/tags/partial/list.blade.php -->\n\n...\n<ul ...>\n  @foreach ($tags as $tag)\n    <li ...>\n      <a href=\"{{ route('tags.articles.index', $tag->id) }}\">{{ $tag->name }}</a>\n    </li>\n  @endforeach\n</ul>\n```\n\n![](./images/38-tags-img-03.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [37강 - Article 기능 구현](37-articles.md)\n- [39강 - Attachment 기능 구현](39-attachments.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/39-attachments.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 40\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 39강 - Attachment 기능 구현\n\nQ. 구현을 시작하기 전에 \"첨부 파일을 언제 올릴 것이냐?\"에 대한 질문에 대한 답을 먼저 결정해야 한다. 포럼 글 (== Article)을 쓰는 시점에 허용할 것이냐, 아니면 포럼 글이 이미 작성되고 난 이후에 상세보기에서 허용할 것이냐? \n: A. **우리는 포럼 글을 작성하는 시점에 파일 첨부를 허용할 것이다.** \n\nQ. 또 하나의 질문은 'title', 'content', 'tags' 와 같은 포럼 Article 메타데이터와 파일을 한번에 전송할 것이냐? 아니면 파일 따로, 메타데이터 따로 전송할 것이냐? 이다. \n: A. **우리는 Async 방식으로 전송하는 것으로 한다**.\n\n좀 더 괜찮은 UI를 위해 첨부파일이 이미지 파일일 경우, 작성 중인 본문에 마크다운 문법으로 이미지를 입력할 수 있도록 하기 위해서다 (주제를 벗어난 내용이므로, 설명은 하지 않지만, 코드에는 포함되어 있을 예정이다).\n \n여기까지 디자인 결정에서, 문제점이 보이는가? 첨부 파일을 업로드하는 시점에는 해당 Article 이 존재하지 않기 때문에, 방금 서버에 생성한 파일을 어느 Article 과 연결시켜야 할 지 알 수 없는 상태가 된다. 다음과 같은 시퀀스로 해결을 시도해 보자.\n\n1. 'articles.create' 폼에서 Ajax 로 첨부파일을 업로드 한다.\n2. `AttachmentsController::store()` 메소드에서 처리하고, 처리된 파일의 id, 컨텐트 타입, 전체 Url을 JSON으로 내려준다.\n3. 폼 페이지는 서버에서 받은 JSON의 id, 즉 서버에 이미 저장된 Attachment 모델의 id 값들을 attachments[] 라는 필드 이름으로 폼에 추가한다.\n4. 폼이 전송되면, `ArticlesController::store()` 에서, 현재 생성하는 Article 과 attachments[] 필드로 넘겨 받은 id 들을 연결시켜 준다.\n\n잠깐!!! 다시 생각해 보면, 포럼을 수정할 때도, 기존에 첨부한 파일에 추가해서 파일을 더 첨부할 수 있는데, 이때는 Article id를 이미 알고 있는 상태이다. 그래서, 수정할 때는 아래 두 단계로 끝날 수 있지 않을까 생각된다.\n\n1. 1 'articles.edit' 폼에서 첨부파일 업로드 Ajax 데이터에 Article id를 달아서 보낸다.\n2. 2 `AttachmentsController::store()` 메소드에서, 지금 생성할 Attachment 모델에, 첨부파일 업로드 Ajax 요청으로 넘겨 받은 Article 의 id을 연결시킨다.\n\n### Dropzone.js\n\n[Dropzone.js](http://www.dropzonejs.com/) 는 Drag & Drop 방식으로 파일을 끌어다 놓으면, 페이지 리로드 없이 서버에 Ajax 로 파일을 업로드를 요청을 하고, 서버의 응답을 동적으로 보여주는 JS 라이브러리이다. \n\n```bash\n$ bower install dropzone --save-dev\n```\n\nbower 로 끌고온 Dropzone은 Sass 파일이 없어서, Gulp 태스크를 기존과 다르게 좀 수정했다. 수정 후 `$ gulp` 코맨드로 빌드한다. 기존 대비 `sass()` 빌드에서 두번째 인자로 빌드 결과물을 저장할 위치를 지정하고, `styles()` 빌드에서 방금 빌드한 sass 파일과 dropzone의 스타일시트를 머지하는 부분이 달라졌다. \n\n**`참고`** `sass()` 나 `styles()` 빌드는 기본적으로 'public/css' 에 결과물을 저장한다. `styles()` 든 `scripts()` 든 파일명을 `all.css`, `all.js` 로 저장하는데, 이를 오버라이드하기 위해서 각 빌드 메소드의 두번째 인자로 파일명을 명시적으로 지정해 주었다. 만약 파일명을 지정하지 않았다면, `version()` 메소드의 인자를 `['css/all.css', 'js/all.js']` 로 해 주면 되고, 'resources/views/layouts/master.blade.php' 에서 `{{ exilir(\"all.ext\") }}` 로 연결시켜 주면 된다.\n\n```javascript\nelixir(function (mix) {\n  mix\n    .sass('app.scss', 'resources/assets/css')\n    .styles([\n      'app.css',\n      '../vendor/dropzone/dist/dropzone.css'\n    ], 'public/css/app.css')\n    .scripts([\n      // Other JS Libraries\n      '../vendor/dropzone/dist/dropzone.js',\n      'app.js'\n    ], 'public/js/app.js')\n    // ...\n});\n```\n\n포럼 쓰기, 수정 폼에 Dropzone 파일 업로드 UI를 붙여 보자. 앞 강에서 생성했던 'tagselector.blade.php'는 포럼 외에 다른 곳에 쓸 일이 없을 것 같아, 'form.blade.php'에 머지하였다.\n\n```html\n<!-- resources/views/articles/partial/form.blade.php -->\n\n...\n<div class=\"form-group\">\n  <label for=\"my-dropzone\">Files</label>\n  <div id=\"my-dropzone\" class=\"dropzone\"></div>\n</div>\n...\n\n@section('script')\n  <script>\n    Dropzone.autoDiscover = false;\n\n    var myDropzone = new Dropzone(\"div#my-dropzone\", {\n      url: \"/files\",\n    }\n  </script>\n@stop\n```\n\n![](./images/39-attachments-img-01.png)\n\n여기까지 *'1. 'articles.create' 폼에서 Ajax 로 첨부파일을 업로드 한다.'* 였다. 브라우저의 개발자 도구의 네트워크 탭을 켜 놓고, Dropzone UI 에 파일을 놓아 보면, 실제로 'POST /files' Route 로 요청이 나가는 것이 보일 것이다. 물론, 아직 서버에서 받아 주지 않기 때문에 에러가 발생할 것이다.\n \n### 첨부파일 저장 로직 구현\n\n*'2. `AttachmentsController::store()` 메소드에서 처리하고, 처리된 파일의 id, 컨텐트 타입, 전체 Url을 JSON으로 내려준다.'* 부분을 구현할 것이다.\n\n#### Route 작성\n\n'public/attachments' 라는 디렉토리를 첨부파일 저장 위치로 만들었기 때문에, Route 엔드포인트를 'attachments' 로 할 수 없다. 해서 앞 절에서 'files'로 했다.\n\n```php\n// app/Http/routes.php\n\nRoute::resource('files', 'AttachmentsController', ['only' => ['store', 'destroy']]);\n```\n\n#### 컨트롤러 작성\n\nRESTful 리소스 컨트롤러를 사용했는데, 세번째 인자로 'only' 키워드를 이용하여 `store()` 와 `destroy()` 메소드만 사용하는 것으로 정의했다. 특정 메소드만 제외하고 싶으면 `['except' => ['show']]` 처럼 'except' 키워드를 이용할 수 있다.\n\n```bash\n$ php artisan make:controller AttachmentsController\n```\n\n```php\n// app/Http/Controllers/AttachmentsController.php\n\npublic function store(Request $request)\n{\n    if (! $request->hasFile('file')) {\n        return response()->json('File not passed !', 422);\n    }\n\n    $file = $request->file('file');\n    $name = time() . '_' . str_replace(' ', '_', $file->getClientOriginalName());\n    $file->move(attachment_path(), $name);\n\n    $attachment = \\App\\Attachment::create(['name' => $name]);\n\n    return response()->json([\n        'id'   => $attachment->id,\n        'name' => $name,\n        'type' => $file->getClientMimeType(),\n        'url'  => sprintf(\"/attachments/%s\", $name),\n    ]);\n}\n```\n\n`! $request->hasFile('file')` 부분에서 'file' 필드가 있는 지 확인한다. 없으면, `response()->json()` 메소드로 파일이 없다는 메시지를 JSON 으로 응답한다.\n\n`$request->file('file')` 로 `Symfony\\Component\\HttpFoundation\\File\\UploadedFile` 인스턴스를 얻어 온다. 이 인스턴스에서 `move()`, `getClientOriginalName()`, `getClientMimeType()`, `getClientOriginalExtension()` 등의 메소드를 사용할 수 있다. 파일 이름 중복을 피하기 위해 `time()` php 내장 함수를 파일명 앞에서 붙여 주었다. `move()` 메소드로 'public/attachments' 디렉토리에 파일을 저장하였다.\n\nAttachment 모델을 만들고, JSON 응답에 'id', 'name', 'type', 'url' 등의 필드 값을 포함하였다.\n \n그런데, 여기까지 작업하고 폼에서 파일을 업로드해 보면 에러가 날 것이다. 이유는 attachments 테이블의 article_id는 articles 테이블에 외래키 관계가 걸려있기 때문이다. 다시 말하면, attachments 테이블에 레코드를 생성할 때, articles 테이블에 존재하는 id 값이 이 테이블의 article_id 로 연결되어야 하는데, 현재는 article_id 를 알 수 없기 때문에 발생하는 것이다. 마이그레이션을 수정하고 다시 실행해 보자.\n\n```php\n// database/migrations/create_attachments_table.php\n\n// 아래 라인을 주석 처리하자.\n// $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');\n```\n\n```bash\n$ php artisan migrate:refresh --seed\n```\n\n다시 테스트 해 보자. public/attachments 에 파일이 잘 업로드 되었고, attachments 테이블에 article_id 가 없는 새로운 레코드가 추가되었는지 확인해야 한다.\n\n![](./images/39-attachments-img-02.png)\n\n**`참고`** 여기서 의문!!! \"파일만 업로드해 놓고 포럼 작성 또는 수정을 포기하면 어떻게 하나요?\" 이런 의문이 들었어야 한다. JS 쪽에서 많은 부분을 구현할 수록, 즉 브라우저에 자유도를 많이 줄 수록 (반면 사용자 UX는 좋아질수록), 이런 문제는 많아진다. 서버에서 crontab을 이용해서 article_id가 없는 Attachment 모델을 주기적으로 청소할 것이다. 라라벨에는 cron 을 쉽게 작성할 수 있는 기능이 포함되어 있고, 이 코스에서 곧 만나게 될 것이다. \n\n### 다시 폼으로\n\n*'3. 폼 페이지는 서버에서 받은 JSON의 id, 즉 서버에 이미 저장된 Attachment 모델의 id 값들을 attachments[] 라는 필드 이름으로 폼에 추가한다.'* 부분을 구현할 차례다. [Dropzone.js 의 이벤트 부분](http://www.dropzonejs.com/#events)을 참고하여 JS 코드를 작성해 보자.\n \n```javascript\n// resources/views/articles/partial/form.blade.php\n\nvar myDropzone = new Dropzone(\"div#my-dropzone\", {...});\n\nmyDropzone.on(\"success\", function(file, data) {\n  $(\"<input>\", {\n    type: \"hidden\",\n    name: \"attachments[]\",\n    class: \"attachments\",\n    value: data.id\n  }).appendTo(form);\n});\n```\n\nDropzone.js의 'success' 이벤트는 앞서 지정한 'POST /files' Route 로의 요청에서 200 OK 응답을 받았음을 의미한다. `on()` 메소드의 두번째 인자인 콜백에서, `<input type=\"hidden\" name=\"attachments[]\" value=\"\">` 와 같은 숨김 입력 필드를 동적으로 만들고 (== DOM 조작), `<form>` 태그의 자식 태그로 추가한다. 가령, 첨부파일을 3개 업로드해서 모두 성공했고, 응답된 Attachment id 가 21, 22, 23 이라면, JS에 의해 이 페이지에 동적을 추가되는 필드는 아래와 같다.\n   \n```html\n<form ...>\n  <input type=\"hidden\" name=\"attachments[]\" value=\"21\">\n  <input type=\"hidden\" name=\"attachments[]\" value=\"22\">\n  <input type=\"hidden\" name=\"attachments[]\" value=\"23\">\n</form>\n```\n\n이 상태에서 폼 전송을 하면, 당연히 'attachments[]' 필드들도 같이 서버로 전송될 것이다.\n\n![](./images/39-attachments-img-03.png)\n\n**`참고`** 여기서 또 의문!!! 가령, 사용자가 크롬 개발자 도구에서 'attachments[]' 의 필드값을 23에서 10으로 변경하거나, 숨김 필드를 고의적으로 수십 개만들어서 요청하면, 보안상 문제 있는 것 아닌가요? 맞다. 앞의 예처럼 사용자가 조작한 Attachment의 id가 이미 존재하는 id라면, 첨부파일이 엉뚱한 Article 에 연결될 수 있다. 원래 서버의 모델 id 를 연속된 값으로 사용하는 것은 Anti-Pattern이고, 사용자가 예측할 수 없는 난수를 사용하는 것이 정석인데, 이 강좌에서 이 내용까지 포함하는 것은 오버라 생각된다. 다음 절에서 엘로퀀트의 `whereIn()` 를 이용하므로, 없는 id 로 조작하는 것에 대해서는 안전하다는 것까지만 알고 넘어가자.\n\n### 컨트롤러 마무리\n\n*'4. 폼이 전송되면, `ArticlesController::store()` 에서, 현재 생성하는 Article 과 attachments[] 필드로 넘겨 받은 id 들을 연결시켜 준다.'* 부분을 구현하기 위해 `ArticlesController::store()` 메소드를 재방문한다. 첨부파일은 Dropzone.js의 Ajax 요청에 의해 `AttachmentsController@store` 에서 'article_id'가 없는 상태로 이미 생성되었다는 것을 기억하자. \n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function store(ArticlesRequest $request)\n{\n    // ...\n    \n    if ($request->has('attachments')) {\n        $attachments = \\App\\Attachment::whereIn('id', $request->input('attachments'))->get();\n        $attachments->each(function($attachment) use($article) {\n            $attachment->article()->associate($article);\n            $attachment->save();\n        });\n    }\n\n    // ...\n}\n```\n\n`$request->input('attachments')` 는 앞 절에서 JS의 의해 동적으로 생성한 폼 데이터들의 값이고, 배열 형태를 가진다. 이 예제에서 `whereIn(string $column, array $values)` 메소드는 `whereIn('id', [21, 22, 23])` 과 같이 해석되어, Attachment 모델에서 id 가 21, 22, 23 번으로 이루어진 Collection을 `$attachments` 변수에 담는다. `$attachments` Collection 에 대해 루프를 돌면서, Attachment 모델 생성과정에서 입력하지 못한, 'article_id' 필드를 업데이트한다. `$attachment->article()->associate($article)` 는 `$attachment->article_id = $article->id` 와 같은 의미로 이해하면 된다.\n\n![](./images/39-attachments-img-04.png)\n\n### 포럼 수정에서 첨부파일 업로드 구현\n\n#### 수정 폼 구현\n\n이제 수정 폼 (e.g. 'GET /articles/1/edit') 을 브라우저에서 열어보자. 아주 정상적으로 잘 표시될 것이다. 그런데, 포럼 작성 폼과 달리 수정 폼에서는 Article id 를 이미 가지고 있다. `AttachmentsController::store()` 로 전송되는 폼 데이터에 Article id 가 포함되어야 한다. *1. 1 'articles.edit' 폼에서 Ajax 데이터에 Article id를 달아서 첨부파일을 업로드한다.* 부분이다.\n \n```javascript\n// resources/views/articles/partial/form.blade.php\n\nvar myDropzone = new Dropzone(\"div#my-dropzone\", {\n  url: \"/files\",\n  params: {\n    _token: \"{{ csrf_token() }}\",\n    articleId: \"{{ $article->id }}\"\n  }\n});\n```\n\n#### 컨트롤러 수정\n\n*2. 2 `AttachmentsController::store()` 메소드에서 생성된 Attachment 모델을 넘겨 받은 Article id 에 연결시킨다.* 부분을 구현할 것이다.\n\n```php\n// app/Http/Controllers/AttachmentsController.php \n\npublic function store(Request $request)\n{\n    // ...\n    $file->move(attachment_path(), $name);\n\n    $articleId = $request->input('articleId');\n\n    $attachment = $articleId\n        ? \\App\\Article::findOrFail($articleId)->attachments()->create(['name' => $name])\n        : \\App\\Attachment::create(['name' => $name]);\n\n    // return response() ...\n}\n```\n\n동일한 폼으로 동일한 컨트롤러가 반응하기 위해서 `$request->input('articleId')` 가 true 이면 `Article::attachments()` 관계를 이용하여 Attachment 모델을 생성하고, false 이면 Attachment 모델을 바로 생성하고 `ArticlesController::store()` 에서 `Attachment::$article_id` 를 업데이트할 여지를 남겨 두었다.\n\n테스트해 보자. 포럼 생성에서 첨부파일 업로드, 포럼 수정에서 첨부파일 업로드, 모두 잘 동작하는 것을 확인할 수 있을 것이다.\n\n### Final Touch\n\n#### 첨부 파일 목록 표시 및 삭제 구현\n\n포럼 상세 보기에서 첨부된 파일을 볼 수 있었으면 좋겠다. 'attachments.partial.list' 에 첨부파일 리스트를 출력하는 뷰를 생성하고, 'articles.show' 뷰에 `@include` 하였다.\n\n```html\n<!-- resources/views/articles/show.blade.php -->\n\n<div class=\"col-md-9\">\n  <article>\n    @include('articles.partial.article', ['article' => $article])\n\n    @include('attachments.partial.list', ['attachments' => $article->attachments])\n    \n    <!-- ... -->\n  </article>\n</div>\n```\n\n작업하는 김에 관리자나 포럼 글의 소유자이면 첨부파일을 삭제할 수 있는 기능도 추가하였다.\n\n```html\n<!-- resources/views/attachments/partial.list.blade.php -->\n\n@if ($attachments->count())\n  <ul class=\"tags__forum\">\n    @foreach ($attachments as $attachment)\n      <li class=\"label label-default\">\n        {!! icon('download') !!}\n        <a href=\"/attachments/{{ $attachment->name }}\">{{ $attachment->name }}</a>\n        @if (auth()->user()->isAdmin() or $article->isAuthor())\n          <form action=\"{{ route('files.destroy', $attachment->id) }}\" method=\"post\" style=\"display: inline;\">\n            {!! csrf_field() !!}\n            {!! method_field('DELETE') !!}\n            <button type=\"submit\">x</button>\n          </form>\n        @endif\n      </li>\n    @endforeach\n  </ul>\n@endif\n```\n\nAjax 로 첨부파일을 삭제할 경우를 대비해, `if (\\Request::ajax())` 부분이 들어갔다.\n\n```php\n// app/Http/Controllers/AttachmentsController.php\n\npublic function destroy($id)\n{\n    $attachment = \\App\\Attachment::findOrFail($id);\n\n    $path = attachment_path($attachment->name);\n    if (\\File::exists($path)) {\n        \\File::delete($path);\n    }\n\n    $attachment->delete();\n\n    if (\\Request::ajax()) {\n        return response()->json(['status' => 'ok']);\n    }\n\n    flash()->success(trans('forum.deleted'));\n\n    return back();\n}\n```\n\n![](./images/39-attachments-img-05.png)\n\n#### Article 삭제\n\n놓치기 쉬운데, Article 모델이 삭제되면 연결된 Attachment 모델 및 첨부파일들도 삭제되어야 한다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function destroy($id)\n{\n    $article = Article::with('attachments')->findOrFail($id);\n\n    foreach($article->attachments as $attachment) {\n        \\File::delete(attachment_path($attachment->name));\n        $attachment->delete();\n    }\n\n    $article->delete();\n\n    flash()->success(trans('forum.deleted'));\n\n    return redirect(route('articles.index'));\n}\n```\n\n#### 부가 기능 참고\n\n첨부파일이 이미지일 경우, 첨부된 이미지를 `<textarea name='content'></textarea>` 영역의 최종 커서 위치에 이미지 마크다운으로 추가하는 기능과, 첨부파일을 업로드했지만 작성 또는 수정 폼을 전송하기 전에 이미 서버에 생성된 첨부파일을 Ajax 요청으로 삭제할 수 있는 기능을 추가적으로 구현했다. JS 내용이라 설명은 생략한다.\n\n```html\n<!-- resources/views/articles/partial/form.blade.php -->\n\n@section('script')\n  <script>\n    // ...\n\n    var insertImage = function(objId, imgUrl) {\n      var caretPos = document.getElementById(objId).selectionStart;\n      var textAreaTxt = $(\"#\" + objId).val();\n      var txtToAdd = \"![](\" + imgUrl + \")\";\n      $(\"#\" + objId).val(\n        textAreaTxt.substring(0, caretPos) +\n        txtToAdd +\n        textAreaTxt.substring(caretPos)\n      );\n    };\n\n    myDropzone.on(\"success\", function(file, data) {\n      file._id = data.id;\n      file._name = data.name;\n\n      $(\"<input>\", {\n        type: \"hidden\",\n        name: \"attachments[]\",\n        class: \"attachments\",\n        value: data.id\n      }).appendTo(form);\n\n      if (/^image/.test(data.type)) {\n        insertImage('content', data.url);\n      }\n    });\n\n    myDropzone.on(\"removedfile\", function(file) {\n      $.ajax({\n        type: \"POST\",\n        url: \"/files/\" + file._id,\n        data: {\n          _method: \"DELETE\",\n          _token: $('meta[name=\"csrf-token\"]').attr('content')\n        }\n      }).success(function(data) {\n        console.log(data);\n      })\n    });\n  </script>\n@stop\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [38강 - Tag 기능 구현](38-tags.md)\n- [32/33 보충 - 인증 리팩토링](32n33-auth-refactoring.md)\n- [40강 - Comment 기능 구현](40-comments.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/40-comments.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 42\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 40강 - Comment 기능 구현\n\n이번 강에서 Comment 의 기본 기능들을 구현한다. 뷰 구조가 워낙 복잡해서 잘 설명할 수 있을 지 모르겠지만, 최선을 다하리라 다짐해 본다. 뷰에 관심 없는 분들은, 모델과 컨트롤러 코드 위주로 이해하고 넘어가시길 바란다. 다음 강에서도 Markdown Helper Overlay, Markdown 미리보기, Markdown 작성 도우미 등의 사용자 경험을 향상시키기 위한 기능들을 추가해 보려 한다.\n\n### 버그 수정\n\n먼저, 기존에 잘못 작성된 마이그레이션에 `nullable()` 속성을 추가했다. 수정했으니 마이그레이션 실행 `$ php artisan migrate:refresh --seed` 이젠 알아서 척척~\n\n```php\n// database/migrations/create_comments_table.php\n\npublic function up()\n{\n    Schema::create('comments', function (Blueprint $table) {\n        $table->integer('parent_id')->unsigned()->nullable();\n        $table->string('title')->nullable();\n        // ...\n    }\n}\n```\n \n### 동작 구조 설계\n \n37강 - Article 기능 구현에서 보았듯이, Comment (== 댓글)는 포럼 상세 보기에서 표시할 것이다. 여기에 댓글 목록, 수정 폼, 삭제 폼, 쓰기 폼 등을 덧 붙일 것이다. 즉, `ArticlesController::show()` 메소드에서 앞서 나열한 뷰들에 필요한 데이터를 주어야 한다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function show($id)\n{\n    $article = Article::with('comments', 'author', 'tags')->findOrFail($id);\n    $commentsCollection = $article->comments()->with('replies', 'author')->whereNull('parent_id')->latest()->get();\n\n    return view('articles.show', [\n        'article'         => $article,\n        'comments'        => $commentsCollection,\n        'commentableType' => Article::class,\n        'commentableId'   => $article->id\n    ]);\n}\n```\n\n`App\\Article` 모델에서 Morph Many to Many 로 정의한 `comments()` 를 체인해서 `App\\Comment` 인스턴스를 얻었다. 얻어진 `App\\Comment` 모델에 Eager Loading 으로 `replies()` 등의 관계를 호출한 후 'parent_id'가 `null` 인 레코드들만 가져와서, `$commentsCollection` 에 담았다. 즉, 부모 댓글이 없는 최상위 댓글만 가져오겠단 의미이다.\n\n`view()`를 반환하면서, `$commentableType`, `$commentableId` 변수도 뷰에 바인딩하였다.\n \n```html\n<!-- resources/views/articles/show.blade.php -->\n \n@section('content')\n  \n  <!-- Other HTML codes ... -->\n\n     <article>\n       @include('comments.index')\n     </article>\n   </div>\n  </div>\n@stop\n```\n \n'articles.show' 뷰에서 'comments.index' 뷰를 `@include` 하였다. 'comments.index' 뷰를 만들고 컨트롤러에서 바인딩시킨 변수들이 잘 넘어 왔는 지 확인해 보자.\n\n```html\n<!-- resources/views/comments/index.blade.php -->\n\n<div class=\"container__forum\">\n  <?php var_dump($comments->toArray()) ?>\n  <?php var_dump($commentableType) ?>\n  <?php var_dump($commentableId) ?>\n</div>\n```\n\n![](./images/40-comments-img-01.png)\n\n### 뷰 구조\n\n앞 절에서 'comments.index' 뷰로 뷰 데이터들이 잘 넘어오는 것을 확인했으니, 뷰 구조를 좀 더 확장해서 볼 것이다. 먼저 아래 그림을 확인하자. 빨강은 뷰 이름, 검정은 HTML class 이름이다. \n\n![](./images/40-comments-img-02.png)\n\n```html\n<!-- resources/views/comments/index.blade.php -->\n\n<div class=\"container__forum\">\n  @if($currentUser)\n    @include('comments.partial.create')\n  @endif\n\n  @forelse($comments as $comment)\n    @include('comments.partial.comment', ['parentId' => $comment->id])\n  @empty\n  @endforelse\n</div>\n```\n\n최상위 댓글을 작성할 수 있는 뷰인 'comments.partial.create' 뷰를 로그인이 되었을 경우에만 `@include` 하였다. \n\n`@forelse` 로 반복하면서, 'comments.partial.comment' 뷰를 이용해 현재 포럼 상세 보기에 해당하 `App\\Article` 모델과 연결된 댓글들의 목록을 보여줄 것이다. 여기서 하위 뷰에 `$parentId` 란 변수를 넘겨 주었는데, 이는 하위 뷰에서 대댓글을 작성할 때 유용하게 사용된다.\n \n```html\n<!-- resources/views/comments/partial/comment.blade.php -->\n\n<div class=\"media media__item\" data-id=\"{{ $comment->id }}\">\n\n  @include('users.partial.avatar', ['user' =>  $comment->author])\n\n  <div class=\"media-body\">\n    @if($currentUser and ($comment->isAuthor() or $currentUser->isAdmin()))\n      @include('comments.partial.control')\n    @endif\n  \n    <h4 class=\"media-heading\">\n      <!-- Gravatar and comment generated time are presented here ... -->\n    </h4>\n    <p>{!! markdown($comment->content) !!}</p>\n    \n    @if ($currentUser)\n    <p class=\"text-right\">\n      <!-- \"Reply\" button is presented here ... -->\n    </p>\n    @endif\n\n    @if($currentUser and ($comment->isAuthor() or $currentUser->isAdmin()))\n      @include('comments.partial.edit')\n    @endif\n\n    @if($currentUser)\n      @include('comments.partial.create', ['parentId' => $comment->id])\n    @endif\n\n    @forelse ($comment->replies as $reply)\n      @include('comments.partial.comment', ['comment'  => $reply])\n    @empty\n    @endforelse\n  </div>\n</div>\n```\n\n이 뷰에서는 현재 화면에 뿌리는 댓글을 수정 또는 삭제를 트리거하기 위한 컨트롤 요소를 'comments.partial.control' 뷰에 포함하고 있다. \n\n또, 대댓글을 작성하는 'comments.partial.create' 폼, 현재 댓글을 수정할 수 있는 'comments.partial.edit' 폼을 포함하고 있다. Article 모델과 같이 Comment 모델에도 `isAuthor()` 메소드를 추가했는데, 이렇게 중복이 발생하는 경우에는 trait 로 빼는 것이 좋을 것 같다. \n\n이 뷰에서 가장 눈여겨 볼 것은, 재귀적으로 뷰를 `@include` 하고있다는 것이다. 다시 말하면, `$comment->replies` 값이 있으면 (== 대댓글), 자기 뷰 안에 자기 자신 즉, 'comments.partial.comment' 자식뷰를 계속 Nesting 한다는 것이다. \n\n```html\n<!-- resources/views/comments/partial/create.blade.php -->\n\n<div class=\"media media__create\">\n  @include('users.partial.avatar', ['user' => $currentUser])\n  <div class=\"media-body\">\n    <form action=\"{{ route('comments.store') }}\" method=\"POST\" role=\"form\" class=\"form-horizontal form-create-comment\">\n      {!! csrf_field() !!}\n      <input type=\"hidden\" name=\"commentable_type\" value=\"{{ $commentableType }}\">\n      <input type=\"hidden\" name=\"commentable_id\" value=\"{{ $commentableId }}\">\n      @if(isset($parentId))\n        <input type=\"hidden\" name=\"parent_id\" value=\"{{ $parentId }}\">\n      @endif\n      \n      <!-- Other HTML form tags ... -->\n\n    </form>\n  </div>\n</div>\n```\n\n앞서 보았듯이, 위 뷰는 일반 댓글을 작성하기 위한 폼으로도, 'comments.partial.comment' 의 재귀적 호출 즉, 댓글의 댓글을 작성하기 위한 폼으로도 사용된다. 재귀적 호출일 때, 일종의 플래그 역할을 하기 위해서 하위 뷰에 `$parentId` 변수를 넘겨 주었고, 위 댓글 작성 폼이 최상위 댓글이 아니라 댓글의 댓글 작성 폼으로 사용되었을 때 부모 댓글이 있음을 `CommentsController::store()` 에 알리기 위해서 `@if(isset($parentId))` 로 숨김 필드를 선택적으로 생성하였다.\n\n현재 로그인한 사용자, 즉 신규 댓글을 작성할 사용자의 사진을 보여주기 위해 `@include('users.partial.avatar', ['user' => $currentUser])` 를 호출했고, 뷰에 공유된 데이터인 `$currentUser` 를 넘겨 주었다.\n\n댓글 작성 후 폼 전송을 하게 될 텐데, 이 때 서버 측이 어떤 모델의 어떤 id에 연결시킬 지 힌트를 주기 위해 `$commentableType`, `$commentableId` 변수를 숨김 필드에 담았다.\n\n```html\n<!-- resources/views/comments/partial/control.blade.php -->\n\n<div class=\"dropdown pull-right hidden-xs hidden-sm\">\n  <span class=\"dropdown-toggle btn btn-default btn-xs\" type=\"button\" data-toggle=\"dropdown\">\n    {!! icon('dropdown') !!}\n  </span>\n  <ul class=\"dropdown-menu\" role=\"menu\">\n    <li role=\"presentation\">\n      <a role=\"menuitem\" tabindex=\"-1\" alt=\"edit\" class=\"btn__edit\">\n        {!! icon('update') !!} Edit\n      </a>\n    </li>\n    <li role=\"presentation\">\n      <a role=\"menuitem\" tabindex=\"-1\" alt=\"delete\" class=\"btn__delete\">\n        {!! icon('delete') !!} Delete\n      </a>\n    </li>\n  </ul>\n</div>\n```\n\n댓글 수정 및 삭제 컨트롤 UI를 위해 [Bootstrap Dropdowns](http://getbootstrap.com/components/#dropdowns) 에서 디자인을 훔쳐와서 적용했을 뿐, 구현상 특별한 점은 없다.\n\n```html\n<!-- resources/views/comments/partial/edit.blade.php -->\n\n<div class=\"media media__edit\">\n  <div class=\"media-body\">\n    <form action=\"{{ route('comments.update', $comment->id) }}\" method=\"POST\" role=\"form\" class=\"form-horizontal\">\n      {!! csrf_field() !!}\n      {!! method_field('PUT') !!}\n\n      <div class=\"form-group\" style=\"width:100%; margin: auto;\">\n        <textarea name=\"content\" class=\"form-control\" style=\"width:100%; padding:1rem;\">{{ old('content', $comment->content) }}</textarea>\n        {!! $errors->first('content', '<span class=\"form-error\">:message</span>') !!}\n      </div>\n\n      <p class=\"text-right\" style=\"margin:0;\">\n        <button type=\"submit\" class=\"btn btn-primary btn-sm\" style=\"margin-top: 1rem;\">\n          {!! icon('plane') !!} Edit\n        </button>\n      </p>\n    </form>\n  </div>\n</div>\n```\n\n수정 폼도 우리가 앞에서 흔히 봐 왔던 폼이다. 다만 이미 'commentable_type', 'commentable_id' 가 이미 저장되어 있는 `App\\Comment` 모델을 수정하는 것이므로, 기존의 댓글 작성 폼과 달리 숨김 필드가 필요 없다.\n\n여기까지 작업하고 테스트해 보면, 에러가 날 것이다. Route 정의와 컨트롤러가 없어서 이다.\n\n### 컨트롤러 구현\n\n```bash\n$ php artisan make:controller CommentsController --resource\n```\n\n'index', 'create', '...' 뷰 요청하는 메소드는 필요없으므로 Route 정의에서 제외했다.\n\n```php\n// app/Http/routes.php\n\nRoute::resource('comments', 'CommentsController', ['only' => ['store', 'update', 'destroy']]);\n```\n\n#### 댓글 생성 로직 구현\n\n댓글 기능을 한번만 구현하고, `App\\Article`, `App\\Something`, ... 여러 모델에서 사용하기 위해서 우리가 선택한 디자인은 Morph Many to Many 였다 (사실은 학습 목적이 더 강하다). 이 절의 컨트롤러 구현에서 여러 모델에서 Comment 기능을 공유해서 쓰기 위해, 어떻게 했는 지 눈여겨 살펴보기 바란다.\n\n```php\n// app/Http/Controllers/CommentsController.php\n\nclass CommentsController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('auth');\n        $this->middleware('author:comment', ['except' => ['store']]);\n    }\n\n    public function store(Request $request)\n    {\n        $this->validate($request, [\n            'commentable_type' => 'required|in:App\\Article',\n            'commentable_id'   => 'required|numeric',\n            'parent_id'        => 'numeric|exists:comments,id',\n            'content'          => 'required',\n        ]);\n\n        $parentModel = \"\\\\\" . $request->input('commentable_type');\n        $parentModel::find($request->input('commentable_id'))\n            ->comments()->create([\n                'author_id' => \\Auth::user()->id,\n                'parent_id' => $request->input('parent_id', null),\n                'content'   => $request->input('content')\n            ]);\n\n        flash()->success(trans('forum.comment_add'));\n\n        return back();\n    }\n}\n```\n\n유효성 검사 규칙 중에 'in:App\\Article' 부분이 보일 것이다. 연결된 모델이 늘어나면, 'in:App\\Article,App\\Something' 처럼 콤마(,)를 찍고 계속 넣을 수 있다. \n\n'parent_id' 유효성 검사에서는 'exists:comments,id' 을 쓰고 있는데, 'comments' 테이블에 `whereId($request->input('parent_id'))`로 쿼리했을 때 레코드가 있어야 한다는 의미이다. 그럴 경우는 거의 없겠지만, 대댓글을 작성하는 중에 원본 댓글의 작성자가 삭제하는 경우를 생각해 볼 수 있을 것이다.\n\n`$parentModel = \"\\\\\" . $request->input('commentable_type')` 은 문자열 '\\App\\Article' 을 생성하고 `$parentModel` 변수에 담는다. 코드에서 `$parentModel::find()` 는 결국 `\\App\\Article::find()` 로 치환된다. 유효성 검사를 한번 거쳤으므로 없는 모델에 쿼리하는 Exception 은 발생하지 않을 것이다.\n\n#### 미들웨어 수정\n\n위 절의 `CommentsController::__construct()` 에서 `ArticlesController::__construct()` 에서 썼던 `CanAccessArticle (별칭 'accessible')` 미들웨어를 썼다. 권한에 맞게 생성, 수정, 삭제 UI를 뷰에서 숨겼다고는 하나, ArticlesController 에서와 마찬가지로 HTTP Client 를 이용하여 직접 요청하는 경우에 대해서도 방어해야 하기에... [미들웨어 파라미터](http://laravel.com/docs/middleware#middleware-parameters) 기능을 이용해서 여러 컨트롤러에서 사용할 수 있도록 기존 미들웨어를 수정해 보자.\n\n네이밍은 항상 힘들다. 'CanAccessArticle' 에서 좀 더 일반적인 'AuthorOnly' 로, 그리고 별칭은 'author' 로 수정했다.\n\n```php\n// app/Http/Kernel.php\n\nprotected $routeMiddleware = [\n    // ...\n    'author' => \\App\\Http\\Middleware\\AuthorOnly::class,\n];\n```\n\n미들웨어 파라미터 사용법이다. `handle()` 메소드의 세번째 인자로 `$param`을 받았다. 이는 소문자로 된 모델 이름이라고 우리 나름의 규칙을 정하자.  `$model` 을 받아 오는 부분은 `CommentsController::store()` 에서 한거랑 비슷한 구현이다. `str_plural(string $value)` 은 라라벨 내장 Helper 로, 인자로 넘겨 받은 영문으로 된 `$value` 를 복수 단어로 변환해 준다.\n\n미들웨어 파라미터는 컨트롤러에서 `$this->middleware('미들웨어별칭:파라미터')` 식으로 쓸 수 있다.\n\n```php\n// app/Http/Middlewares/AuthorOnly.php\n\npublic function handle(Request $request, Closure $next, $param)\n{\n    $user = $request->user();\n    $model = '\\\\App\\\\' . ucfirst($param);\n    $modelId = $request->route(str_plural($param));\n\n    if (! $model::whereId($modelId)->whereAuthorId($user->id)->exists() and ! $user->isAdmin()) {\n        flash()->error(trans('errors.forbidden') . ' : ' . trans('errors.forbidden_description'));\n        return back();\n    }\n\n    return $next($request);\n}\n```\n\n미들웨어를 수정했으니 기존의 `ArticlesController` 도 `$this->middleware('author:article', [...]);` 로 수정해 주자.\n\n#### 댓글 수정 및 삭제 로직 구현\n\n수정 로직은 특별한게 없다. 일단, 아래 코드를 보자.\n\n```php\n// app/Http/Controllers/CommentsController.php\n\nclass CommentsController extends Controller\n{\n    // Other methods ...\n    \n    public function update(Request $request, $id)\n    {\n        $this->validate($request, ['content' => 'required']);\n    \n        Comment::findOrFail($id)->update($request->only('content'));\n        flash()->success(trans('forum.comment_edit'));\n    \n        return back();\n    }\n    \n    public function destroy(Request $request, $id)\n    {\n        $comment = Comment::find($id);\n        $this->recursiveDestroy($comment);\n\n        if ($request->ajax()) {\n            return response()->json('', 204);\n        }\n\n        flash()->success(trans('forum.deleted'));\n\n        return back();\n    }\n\n    public function recursiveDestroy(Comment $comment)\n    {\n        if ($comment->replies->count()) {\n            $comment->replies->each(function($reply) {\n                if ($reply->replies->count()) {\n                    $this->recursiveDestroy($reply);\n                } else {\n                    $reply->delete();\n                }\n            });\n        }\n\n        return $comment->delete();\n    }\n}\n```\n\n개인의 취향일 수도 있다. 마이그레이션에서 정의한 `$table->foreign('parent_id')->references('id')->on('comments')->onDelete('cascade');` 에 의해 대댓글은 자동 삭제된다. 그런데 필자의 경우에는, 좀 더 안전하게 하기 위해서, 코드 레벨에서 먼저 한번 삭제한다. 이를 위해서, `recursiveDestroy()` 라는 재귀적 호출을 하는 메소드를 만들었고, `destroy()` 메소드에서 호출하였다.\n\n그런데... 댓글을 직접 삭제하는 경우도 있지만, Comment 의 부모 모델인 Article 을 삭제하는 경우도 있다. 우리 모델은 'Morph Many to Many' 라는 것을 기억하자. 즉, 데이터베이스의 외래키 관계가 형성될 수 없다는 의미이다. 그렇다면 Article 모델이 삭제되면 연결된 Comment 도 삭제하도록 코드 레벨에서 구현해야 한다. 그런데 여기서, 디자인 의사 결정이 필요하다. 'Article 이 삭제되었으니, 연결된 그 자식 모델들도 전부 삭제할거냐? 남겨 놓고, '삭제된 글'이라는 자리표시자(== Placeholder) 를 남기고 댓글은 삭제하지 말고 남겨 놓을 것인가?' 의 결정. 여기서는 전부 삭제하는 것으로 하자.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function destroy($id)\n{\n    $article = Article::with('attachments', 'comments')->findOrFail($id);\n\n    foreach($article->attachments as $attachment) {\n        \\File::delete(attachment_path($attachment->name));\n    }\n\n    $article->attachments()->delete();\n    $article->comments->each(function($comment) { // foreach 로 써도 된다.\n        app(\\App\\Http\\Controllers\\CommentsController::class)->recursiveDestroy($comment);\n    });\n    $article->delete();\n\n    flash()->success(trans('forum.deleted'));\n\n    return redirect(route('articles.index'));\n}\n```\n\n이 강좌와 관련된 부분은 `$article->comments->each(function($comment) {...}` 부분인데, `app()` Helper 로 다른 컨트롤러에 있는 메소드를 접근하고 있다. 사실상은 Anti-pattern 이며, `recursiveDestroy()` 메소드를 trait 등으로 빼는 것이 좋을 것 같다. \n\n### 화장하기\n\n여기까지 작성하고, 브라우저에서 보면 스크린샷 처럼 나오지 않고, 아주 못~쉥긴 댓글 뷰가 표시될 것이다. 아래와 같은 뷰 로직을 생각해 보자.\n\n![](./images/40-comments-img-03.png)\n  \n1. 최상위 'comments.partial.create' 는 항상 표시된다.\n2. 페이지 로드시 'comments.partial.comment' 에 포함된 현재 댓글 수정 폼, 대댓글 작성 폼은 표시되지 않는다.\n3. 'Reply' 버튼을 클릭하면 해당 댓글 아래에 대댓글 작성 폼이 토글(표시/숨김) 된다. 해당 댓글에 수정 폼이 표시되어 있다면 숨긴다.\n4. 'comments.partial.control' 조각 뷰에서 수정을 선택하면 해당 댓글 수정 폼이 표시된다. 해당 댓글에 대댓글 작성폼이 표시되어 있다면 숨긴다.\n5. 'comments.partial.control' 조각 뷰에서 삭제를 선택하면 해당 댓글 삭제 Ajax 이 나가고, 삭제 성공시 플래시 메시지를 표시한다.\n\n위 내용을 구현한 CSS, JS 코드인데, 코드에 대한 설명은 생략한다. 일단 jQuery로 썼는데, 이 코스를 통해서 기회가 된다면 [Vue.js](http://vuejs.org/) 로 다시 쓸 생각이다. 라라벨과 같은 완벽한 Backend 를 갖추고, 프론트엔드에서 또 다시 AngularJS 와 같은 모든 것을 갖춘 프레임웍을 쓴다는 것은 오버라는 생각이든다 (개발해야 할 코드량이 많다는 의미다). 그런 면에서 뷰 모델만 건드리는 Vue.js 와 같은 라이브러리가 합리적인 선택이라 생각된다.\n  \n```html\n<!-- resources/views/comments/index.blade.php -->\n\n@section('style')\n  <style>\n    /* 2. 페이지 로드시 'comments.partial.comment' 에 포함된 현재 댓글 수정 폼, 대댓글 작성 폼은 표시되지 않는다. */\n    div.media__create:not(:first-child),\n    div.media__edit {\n      display: none;\n    }\n  </style>\n@stop\n\n@section('script')\n  <script>\n    $(\"button.btn__reply\").on(\"click\", function(e) {\n      // 3. 'Reply' 버튼을 클릭하면 해당 댓글 아래에 대댓글 작성 폼이 토글(표시/숨김) 된다. \n      // 해당 댓글에 수정 폼이 표시되어 있다면 숨긴다.\n      var el__create = $(this).closest(\".media__item\").find(\".media__create\").first(),\n          el__edit = $(this).closest(\".media__item\").find(\".media__edit\").first();\n\n      el__edit.hide(\"fast\");\n      el__create.toggle(\"fast\").end().find('textarea').focus();\n    });\n\n    $(\"a.btn__edit\").on(\"click\", function(e) {\n      // 4. 'comments.partial.control' 조각 뷰에서 수정을 선택하면 해당 댓글 수정 폼이 표시된다. \n      // 해당 댓글에 대댓글 작성폼이 표시되어 있다면 숨긴다.\n      var el__create = $(this).closest(\".media__item\").find(\".media__create\").first(),\n          el__edit = $(this).closest(\".media__item\").find(\".media__edit\").first();\n\n      el__create.hide(\"fast\");\n      el__edit.toggle(\"fast\").end().find('textarea').first().focus();\n    });\n\n    $(\"a.btn__delete\").on(\"click\", function(e) {\n      // 5. 'comments.partial.control' 조각 뷰에서 삭제를 선택하면 해당 댓글 삭제 Ajax 이 나가고, \n      // 삭제 성공시 플래시 메시지를 표시한다.\n      var commentId = $(this).closest(\".media__item\").data(\"id\");\n\n      if (confirm(\"Are you sure to delete this comment?\")) {\n        $.ajax({\n          type: \"POST\",\n          url: \"/comments/\" + commentId,\n          data: {\n            _method: \"DELETE\"\n          }\n        }).success(function(data) {\n          flash('success', 'Deleted ! The page will reload in 3 secs.', 2500);\n          reload(3000);\n        })\n      }\n    });\n  </script>\n@stop\n```\n\n이번 강좌를 진행하는 동안 'resources/assets/js/app.js' 에 자잘한 Cosmetic Change 들이 있었다. 변경 내용들은 Commit 로그를 참고하도록 하자.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [39강 - Attachment 기능 구현](39-attachments.md)\n- [32/33 보충 - 인증 리팩토링](32n33-auth-refactoring.md)\n- [41강 - UI 개선](41-ui-makeup.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/41-ui-makeup.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 43\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 41강 - UI 개선\n\n이번 강에서 전반적인 UI 개선 작업을 하고, 다음 강에서는 이벤트, 알림, 캐싱 등 서버 사이드 쪽 개선 작업을 하도록 하자. 먼저 무엇을 개선할지 정의하자.\n\n1. 포럼 본문 또는 댓글을 쓸 때\n  1. 사용자가 입력하는 내용을 실시간으로 마크다운 컴파일하여 보여준다.\n  2. textarea 요소에서 코드를 쓸 경우를 대비해, <kbd>Tab</kbd> 키 입력을 지원하자. (원래는 <kbd>Tab</kbd> 키를 치면 다음 요소로 이동해 버린다.)\n  3. 사용자가 입력한 내용이 길어지는 것을 대비해, textarea 요소의 크기를 입력 내용의 양에 따라 자동으로 조절하자.\n2. 마크다운 문법을 잘 모르는 사용자를 배려하여, 사용법을 페이지에서 보여주자.\n3. 파일 첨부 UI를 토글할 수 있도록 하자.\n\n### UI 콤포넌트 설치\n\n위의 기획에 따라, 필자의 경험과 인터넷 검색을 통해 적절한 프론트엔드 라이브러리를 아래와 같이 선택하였다.\n\n- [Fastclick](https://github.com/ftlabs/fastclick) : 모바일 디바이스에서 터치 반응을 개선한다.\n- [Tabby](https://github.com/alanhogan/Tabby) : textarea 에서 <kbd>Tab</kbd> 키 입력을 지원한다. \n- [Autosize](https://github.com/jackmoore/autosize) : 텍스트 길이에 따라 textarea 요소의 높이를 자동으로 조정한다.\n- [Marked](https://github.com/chjj/marked) : 클라이언트 사이드에서의 마크다운 컴파일 기능을 지원한다. \n- [Highlightjs](https://github.com/components/highlightjs) : 코드에서 Syntax Highlight 기능을 지원한다. 기존 Google Code Prettify 를 대체한다.\n- [Earthsong](http://daylerees.github.io/) : Syntax Highlight 에서 Earthsong 테마를 입힌다. Highlightjs 내장 테마를 대체한다.\n\n**`참고`** Earthsong 테마는 [Dayle Rees](http://daylerees.com/) 가 개발했다. 그는 라라벨 코어 멤버로 활동할 뿐 아니라, [PHP PANDA](https://leanpub.com/php-pandas) 등 여러 권의 PHP 서적을 낸 바 있다. 그가 만든 [Color Scheme](https://github.com/daylerees/colour-schemes) 은 모르는 개발자가 없을 정도로 유명하다. Color Scheme에서 제공하는 다양한 에디터 테마를 보려면 [Color Scheme Gallery](http://daylerees.github.io/)를 확인해 보자.\n\n```bash\n# highlightjs를 쓸 것이므로 google-code-prettify 는 제거한다.\n$ bower uninstall google-code-prettify --save-dev\n$ bower install fastclick tabby autosize marked highlightjs --save-dev\n# Bower 콤포넌트가 아니므로, github 에서 raw URL를 따서 CURL 로 다운로드하였다.\n$ curl https://raw.githubusercontent.com/daylerees/colour-schemes/master/highlightjs/contrast/earthsong-contrast.css -o ./resources/assets/vendor/earthsong.css\n```\n\n빌드스크립트를 수정하자. 수정 후 빌드 코맨드는 이젠 척척 알아서.. `$ gulp` (or `$ gulp --production`)\n\n```javascript\n// gulpfile.js\n\nelixir(function (mix) {\n  mix\n    .styles([\n      // ...\n      '../vendor/earthsong.css',\n      'app.css'\n    ], 'public/css/app.css')\n    .scripts([\n      // ...\n      '../vendor/fastclick/lib/fastclick.js',\n      '../vendor/tabby/jquery.textarea.js',\n      '../vendor/autosize/dist/autosize.js',\n      '../vendor/highlightjs/highlight.pack.js',\n      '../vendor/marked/lib/marked.js',\n      'app.js'\n    ], 'public/js/app.js')\n    // ...\n});\n```\n\n### 포럼 본문 및 댓글 쓰기 개선\n\n#### Fastclick\n\n쉬운 것 먼저 하자. Fastclick 기능 추가는 `attach()` 메소드 호출 하나로 끝난다.\n\n```javascript\n// resources/assets/js/app.js\n\nvar csrfToken = $('meta[name=\"csrf-token\"]').attr('content'),\n    routeName = $('meta[name=\"route\"]').attr('content'),\n    textAreas = $('textarea');\n\n/* Global Settings */\n\n/* Activate Fastclick */\nwindow.addEventListener('load', function() {\n  FastClick.attach(document.body);\n}, false);\n\n/* Set Ajax request header.\n Document can be found at http://laravel.com/docs/routing#csrf-x-csrf-token */\n$.ajaxSetup({\n  headers: {\n    'X-CSRF-TOKEN': csrfToken\n  }\n});\n```\n\n작업하는 김에 코드들도 약간 정리했다. `csrfToken` 부분은 앞 절에서 설명했을 것이다.\n\n`textareas` 란 글로벌 변수를 주목하자. 이 스크립트는 모든 페이지 로딩시 같이 로딩된다. 즉, 페이지 로딩시 마다, textarea 요소가 있는 페이지에서는 `textareas` 변수가 셋팅이 된다.\n\nFastclick 적용 결과는 눈에 딱히 보이지는 않는다. 모바일 브라우저에서 접근해서 확인해야 하는데, 필자도 별로 체감은 되지 않는 것 같다.\n\n#### Highlightjs\n\n역시 쉽다. 'articles.show' 뷰 등에서는 기존에 작성한 포럼 본문이 표시되고, 코드 블럭을 포함하고 있을 수 있다. 'articles.show' 페이지가 로드되자 마자, 코드 블럭이 있으면 Highlightjs 가 작동한다. 주의할 점은 페이지 로드 이후에 자바스크립트에 의해서 동적으로 DOM에 추가된 코드블럭에는 Highlightjs 가 적용되지 않는다는 점이다.  \n\n```javascript\n// resources/assets/js/app.js\n\n/* Activate syntax highlight. \n   This will affect code blocks right after the page renders */\nhljs.initHighlightingOnLoad();\n```\n\n![](./images/41-ui-makeup-img-01.png)\n\n#### Tabby & Autosize\n\n역시 쉽다. 위에서 `textareas` 란 변수를 지정한 것을 기억할 것이다. Tabby 와 Autosize 기능은 `textareas.length` 값이 있을 때만 동작시키는 것으로 했다. \n\n```javascript\n// resources/assets/js/app.js\n\nif (textAreas.length) {\n  /* Activate Tabby on every textarea element */\n  textAreas.tabby({tabString: '    '});\n  \n  /* Auto expand textarea size */\n  autosize(textAreas);\n}\n```\n\n![](./images/41-ui-makeup-img-02.png)\n\n#### Marked & Hightlightjs\n\n이 부분은 쉽지 않다. 사용자가 textarea 에 입력하는 내용을 Marked 로 컴파일하여 미리보기 요소에 보여줄 것이다.\n\n먼저, textarea 요소가 포함되어 있는 'articles.partial.form' 뷰와 'comments.partial.create', 'comments.partial.edit' 뷰에 미리보기를 표시할 HTML 요소를 추가하자. \n\n```html\n<!-- resources/views/articles/partial/form.blade.php -->\n\n<div class=\"form-group\">\n  <label for=\"content\">{{ trans('forum.content') }}</label>\n  <textarea name=\"content\" class=\"form-control forum__content\" rows=\"10\">{{ old('content', $article->content) }}</textarea>\n  {!! $errors->first('content', '<span class=\"form-error\">:message</span>') !!}\n  <div class=\"preview__forum\">{{ markdown(old('content', 'Preview will be shown here...')) }}</div>\n</div>\n```\n\n```css\n/* resources/assets/sass/_forum.scss */\n\ndiv.preview__forum {\n  display: none;\n  @extend .form-control;\n  margin-top: $baseline;\n  height: auto;\n}\n```\n\n'div.preview__forum' 이란 요소를 추가하고, 처음 로드될 때 상태를 `display:none;` 로 지정하였다. \n\n유효성 검사 에러가 발생할 경우를 대비해, `{{ markdown(old('content', '...')) }}` 라고 쓴 것도 놓치지 말자. 포럼/댓글 작성/수정 폼 전송시에는 컴파일되지 않은 Raw 상태로 `*Controller::store()` 메소드에 전달되고, 유효성 검사에서 튕길 경우, `withInput()` 에 의해서 사용자가 작성한 폼 값들을 세션에 구워서 폼을 전송했던 뷰로 되돌려 보낸다. 이 때 서버는 뷰를 응답하기 전에, `markdown()` Helper 를 이용해서 미리 HTML 로 컴파일 된 내용을 'div.preview__forum' 요소에 넣어 놓는 부분이다. 당연히 textarea 요소에는 컴파일되지 않은 Raw 상태를 그대로 뿌리게 된다.\n\n이제 자바스크립트 부분을 보도록 하자.\n\n```javascript\n// resources/assets/js/app.js\n\nif (textAreas.length) {\n  // Other library activation codes ...\n  \n  textAreas.on(\"focus\", function (e) {\n    // Show preview pane when a textarea is in focus\n    $(this).siblings(\"div.preview__forum\").first().show();\n  });\n\n  textAreas.on(\"keyup\", function(e) {\n    // Register 'keyup' event handler\n    var self = $(this),\n        content = self.val(),\n        previewEl = self.siblings(\"div.preview__forum\").first();\n\n    // Compile textarea content\n    var compiled = marked(content, {\n      renderer: new marked.Renderer(),\n      gfm: true,\n      tables: true,\n      breaks: true,\n      pedantic: false,\n      sanitize: true,\n      smartLists: true,\n      smartypants: false\n    });\n\n    // Fill preview container with compiled content\n    previewEl.html(compiled);\n    // Add syntax highlight on the preview content\n    previewEl.find('pre code').each(function(i, block) {\n      hljs.highlightBlock(block)\n    });\n  }).trigger(\"keyup\");\n}\n```\n\n먼저 textarea 에 커서가 들어가면 (== 'focus' 이벤트), jQuery의 `show()` 메소드를 이용하여 'div.preview__forum' 요소를 `display: block;` 상태로 변경시켰다.\n\n그 다음은 textarea 에 'keyup' 이벤트가 발생했을 때 이다. textarea 에 입력한 내용을 읽어오고, 미리보기를 표시할 요소를 잡아 `content`, `previewEl` 변수가 각각 담았다.\n\n`marked()` 메소드를 이용해서 `content` 를 컴파일하여 `compiled` 변수에 담은 후, `previewEl` 의 내용을 `compiled` 로 채워 넣었다.\n\n앞서 설명했듯이, Highlightjs 가 페이지 로드 이후에 동적으로 DOM 에 추가된 코드블럭에 대해서는 동작을 못하기 때문에, 이 부분을 처리하는 코드도 추가하였다.\n\n![](./images/41-ui-makeup-img-03.png)\n\n### 마크다운 사용법 Modal\n\nBootstrap 에는 Modal 요소를 포함하고 있다. 이를 활용하자.\n\n먼저, Modal에 본문으로 표시될, 마크다운 사용법을 담고 있는 뷰를 만들고, 적절한 위치에 `@include` 시키자.\n\n```html\n<!-- resources/views/articles/partial/form.blade.php -->\n\n<div class=\"form-group\">\n  <a href=\"#\" class=\"help-block pull-right hidden-xs\" id=\"md-caller\">\n    <small>{!! icon('preview') !!} Markdown Cheatsheet</small>\n  </a>\n  <label for=\"content\">{{ trans('forum.content') }}</label>\n  <!-- ... -->\n</div>\n\n<!-- ... -->\n\n@include('layouts.partial.markdown')\n\n@section('script')\n  <script>\n    // Other codes ...\n    \n    /* Modal window for Markdown Cheatsheet */\n    $(\"#md-caller\").on(\"click\", function(e) {\n      e.preventDefault();\n      $(\"#md-modal\").modal();\n      return false;\n    });\n  </script>\n@stop\n```\n\n```html\n<!-- resources/views/layouts/partial/markdown.blade.php -->\n\n<div class=\"modal fade\" id=\"md-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n  <div class=\"modal-dialog modal-lg\">\n    <div class=\"modal-content\">\n      <div class=\"modal-header\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"modal\">\n        <span aria-hidden=\"true\">&times;</span>\n        <span class=\"sr-only\">Close</span></button>\n        <h4 class=\"modal-title\">Markdown Cheatsheet</h4>\n      </div>\n\n      <div class=\"modal-body table-responsive\">\n        <table class=\"table\">\n        <!-- Content of markdown cheatsheet ... -->\n        </table>\n      </div>\n\n      <div class=\"modal-footer\">\n        <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n      </div>\n    </div>\n  </div>\n</div>\n```\n\n'a#md-caller' 가 클릭되었을 때, `modal()` 메소드를 호출하는 것으로 처리하였다.\n\n![](./images/41-ui-makeup-img-04.png)\n\n### 파일 첨부 UI 토글\n\n미리보기까지 들어가면서, 폼이 너무 길어지게 되어 줄일 필요성이 대두되었다. 나머지 폼들은 모두 채워야 하지만, 파일 첨부는 선택적으로 해도 되는 요소이므로, 사용자가 필요할 때만 열어서 파일을 올려 놓을 수 있도록 하자.\n\n```html\n<!-- resources/views/articles/partial/form.blade.php -->\n\n<div class=\"form-group\">\n  <label for=\"my-dropzone\">\n    Files\n    <small class=\"text-muted\">\n      Click to attach files <i class=\"fa fa-chevron-down\"></i>\n    </small>\n    <small class=\"text-muted\" style=\"display: none;\">\n      Click to close pane <i class=\"fa fa-chevron-up\"></i>\n    </small>\n  </label>\n  <div id=\"my-dropzone\" class=\"dropzone\"></div>\n</div>\n\n<!-- ... -->\n\n@section('script')\n  <script>\n    var dropzone  = $(\"div.dropzone\"),\n      dzControl = $(\"label[for=my-dropzone]>small\");\n\n    dzControl.on(\"click\", function(e) {\n      dropzone.fadeToggle(0);\n      dzControl.fadeToggle(0);\n    });\n    \n    // Other codes ...\n  </script>\n@stop\n```\n\n![](./images/41-ui-makeup-img-05.png)\n\n### 그 외 추가된 장식들\n\n- Back to top 버튼이 추가되었다. 페이지 스크롤이 발생했을 때 버튼이 표시되며, 누르면 페이지의 맨 위로 이동하는 그거다. (resources/views/layouts/partial/footer.blade.php, resources/assets/js/app.js)\n- 모바일에서 Forum, Documents 를 열었을 때 좌측에 표시되던 태그, 문서목록을 숨기도록 하였다. 그리고 뷰 하단에 작은 버튼을 두어 누르면, 목록이 열리도록 하였다. (resources/assets/sass/\\_mediaqueries.scss, resources/assets/js/app.js)\n- 페이지에서 블럭을 잡았을 때, 선택 영역의 색상을 수정했다. (resources/assets/sass/\\_commons.scss)\n\n![](./images/41-ui-makeup-img-06.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [40강 - Comment 기능 구현](40-comments.md)\n- [42강 - 서버 사이드 개선](42-be-makeup.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/42-be-makeup.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 44\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 42강 - 서버 사이드 개선\n\n아직 추가해야 할 기능들이 많지만, 이번 강으로 실전 프로젝트 2편은 마무리하기로 한다. 먼저 무엇을 개선할 지 리스트업하자.\n\n1. 포럼에서 필터, 풀텍스트 검색, 정렬 기능을 제공한다.\n2. 응답 성능 향상을 위해, 서버 사이드 캐싱을 활성화한다. `event:generate` 코맨드 이용한다.\n3. 포럼에 댓글, 또는 댓글에 대댓글이 달릴 경우, 원본 글 작성자에게 이메일 알림을 발송한다. 이벤트를 수동으로 만들 것이다.\n4. 서비스 디렉토리를 만들고, 기존 Markdown 컴파일러를 상속하여, 커스텀 컴파일 규칙을 만든다.\n5. 앞 강에서 누락된 베스트 답글을 선택하고 표시하는 기능을 추가할 것이다.\n\n### 필터, 풀 텍스트 검색, 정렬 기능\n\n3가지 기능 모두가 `ArticlesController::index()` 와 관련이 있어 한번에 설명하기로 한다. 주목할 점은 필터를 적용하면 필터가 적용된 포럼 글만 표시된다. 풀 텍스트 검색을 적용하면 검색어에 해당하는 포럼 글만 표시된다. 반면, 정렬은 페이지에 표시할 포럼 콜렉션 자체를 변경하지는 않으며, 필터나 검색에 의해 선택된 포럼 콜렉션의 오름차순, 내림차순 정렬, 즉 Decoration만 하는 역할을 한다는 점을 기억하자. \n\n2가지 필터. 필터 추가는 독자들이 얼마든지 할 수 있을 것이다. URL 쿼리의 필드명은 'f' 로 하자. (e.g. f=nocomment)\n\n- `nocomment`: 댓글이 없는 포럼 글\n- `notsolved`: 베스트 답글이 없는 포럼 글\n\n2가지 정렬 기준. URL 쿼리에서 's' 는 정렬할 기준 필드, 'd' 는 정렬방향으로 사용자에게 받는 걸로 하자. (e.g. s=created_at&d=asc)\n\n- `created_at` 필드에 의한 정렬. Age 라 칭하자.\n- `view_count` 필드에 의한 정렬. View 라 칭하자.\n\n**`참고`** 간단해서 설명은 생략했지만, 포럼 상세보기 (`ArticlesController::show()`) 가 페이지 노출되었을 때 'view_count' 를 올리는 로직을 본 강좌에서 추가하였다.\n \n#### UI 구현\n\n기존의 'layouts.partial.search' 에 작성했던 검색 폼을 'articles.partial.search' 로 이동하였다. 기존 대비 폼에 action 속성이 추가되었고, 폼 전송을 하면 GET /articles?s=키워드 요청이 발생하며, 이는 `ArticlesController::index()` 에서 처리된다. 검색 키워드를 담고 폼을 통해 전송되는 필드 이름이 'q' 라는 것을 기억하자.  \n\n```html\n<!-- resources/views/articles/partial/search.blade.php -->\n\n<form action=\"{{ route('articles.index') }}\" method=\"get\" role=\"search\" id=\"search__forum\">\n  <input type=\"text\" name=\"q\" value=\"{{ Request::input('q') }}\" class=\"form-control\" placeholder=\"Search\"/>\n</form>\n```\n\n필터 목록을 표시할 UI를 추가하였다.\n\n```html\n<!-- resources/views/tags/partial/index.blade.php -->\n\n<!-- Tags list here ... -->\n\n<p class=\"lead\">\n  {!! icon('filter') !!} Filters\n</p>\n<ul class=\"list-unstyled\">\n  @foreach(['nocomment' => 'No Comment', 'notsolved' => 'Not Solved'] as $filter => $name)\n    <li class=\"{{ (Request::input('f') == $filter) ? 'active' : '' }}\">\n      <a href=\"{{ route('articles.index', ['f' => $filter]) }}\">\n        {{ $name }}\n      </a>\n    </li>\n  @endforeach\n</ul>\n```\n\n포럼 목록 보기에서 정렬 UI 를 추가하였다.\n\n```html\n<!-- resources/views/articles/index.blade.php -->\n\n<div class=\"btn-group pull-right sort__forum\">\n  <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n    {!! icon('sort') !!} Sort by <span class=\"caret\"></span>\n  </button>\n  <ul class=\"dropdown-menu\" role=\"menu\">\n    @foreach(['created_at' => 'Age', 'view_count' => 'View'] as $column => $name)\n      <li class=\"{{ Request::input('s') == $column ? 'active' : '' }}\">{!! link_for_sort($column, $name) !!}</li>\n    @endforeach\n  </ul>\n</div>\n```\n\n위 뷰에서 정렬 링크를 생성하기 위해 `link_for_sort()` 라는 함수를 추가했는데 본문보다 코드에 설명하는 것이 더 효율적이라 생각되어, 코드 중간중간에 주석을 달았다. \n\n```php\n// app/helpers.php\n\nfunction link_for_sort($column, $text, $params = [])\n{\n    // 현재 요청의 'd' 쿼리 파라미터가 asc 이면, $reverse 에 desc\n    $direction = Request::input('d');\n    $reverse = ($direction == 'asc') ? 'desc' : 'asc';\n\n    // 정렬을 위한 쿼리 파라미터(s) 의 값이 있으면,\n    // 오름차순 또는 내림차순 아이콘을 함수의 인자로 넘겨 받은 $text 에 붙인다. \n    if (Request::input('s') == $column) {\n        $text = sprintf(\n            \"%s %s\",\n            $direction == 'asc' ? icon('asc') : icon('desc'),\n            $text\n        );\n    }\n\n    // 현재 요청의 쿼리 스트링에서 'page', 's', 'd' 등을 제외한 나머지 쿼리 스트링과\n    // 이 함수의 인자로 넘겨 받은 값들로 생성한 's', 'd' 등의 쿼리 스트링을 합쳐서\n    // Anchor 태그의 href 속성 값에서 사용할 $queryString 생성한다.\n    $queryString = http_build_query(array_merge(\n        Input::except(['page', 's', 'd']),\n        ['s' => $column, 'd' => $reverse],\n        $params\n    ));\n\n    // 현재 요청 URL 을 Request::url() 로 얻어 오고,\n    // 앞에서 만든 $queryString 문자열을 합쳐서 완전한 HTML <a> 태그를 생성한다. \n    return sprintf(\n        '<a href=\"%s?%s\">%s</a>',\n        urldecode(Request::url()),\n        $queryString,\n        $text\n    );\n} \n```\n\n위 함수에서 선택된 정렬 링크를 한번 더 선택하면, 오름차순, 내림차순 간에 토글된다. 물론, 아이콘도 같이 변경된다.\n\n#### 마이그레이션\n\n[MySql 공식 문서](https://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html)를 이용하여 MySql 네이티브 풀텍스트 검색을 구현하기로 한다. 이를 위해 기존 마이그레이션을 약간 수정해야 한다.\n\n```php\n// database/migrations/create_articles_table.php\n\nclass CreateArticlesTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('articles', function (Blueprint $table) { // ... });\n\n        DB::statement('ALTER TABLE articles ADD FULLTEXT search(title, content)');\n    }\n    \n    // ...\n}\n```\n\n마이그레이션을 실행한다.\n\n```bash\n$ php artisan migrate:refresh --seed\n```\n\n#### 컨트롤러 구현\n\n`index()` 메소드 안에 필터, 검색, 정렬 로직을 넣으면 길어져서 `filter()` 란 메소드로 빼내었다. 이번에도 코드에서 주석으로 설명한다.\n\n**`참고`** 라라벨 커뮤니티에서는 비즈니스 로직과 데이터 소스를 디커플링시키고, 코드의 재활용성을 높이기 위해서 [Repository Pattern](https://github.com/domnikl/DesignPatternsPHP/tree/master/More/Repository) 을 많이 사용한다. `filter()` 메소드와 같은 내용들은 Repository 로 옮겨져서 다른 클래서에서도 사용할 수 있도록 하면 좋을 것이다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    public function index(FilterArticlesRequest $request, $id = null)\n    {\n        $query = $id\n            ? Tag::findOrFail($id)->articles()\n            : new Article;\n\n        $query = $query->with('comments', 'author', 'tags', 'solution', 'attachments');\n        $articles = $this->filter($request, $query)->paginate(10);\n\n        return view('articles.index', compact('articles'));\n    }\n\n    protected function filter($request, $query)\n    {\n        if ($filter = $request->input('f')) {\n            // 'f' 쿼리 스트링 필드가 있으면, 그 값에 따라 쿼리를 분기한다.\n            switch ($filter) {\n                case 'nocomment':\n                    $query->noComment();\n                    break;\n                case 'notsolved':\n                    $query->notSolved();\n                    break;\n            }\n        }\n\n        if ($keyword = $request->input('q')) {\n            // 이번에도 'q' 필드가 있으면 풀텍스트 검색 쿼리를 추가한다.\n            $raw = 'MATCH(title,content) AGAINST(? IN BOOLEAN MODE)';\n            $query->whereRaw($raw, [$keyword]);\n        }\n\n        // 's' 필드가 있으면 사용하고, 없으면 created_at 을 기본값으로 사용한다.\n        $sort = $request->input('s', 'created_at');\n        // 'd' 필드가 있으면 사용하고, 없으면 desc 를 기본값으로 사용한다.\n        $direction = $request->input('d', 'desc');\n\n        return $query->orderBy($sort, $direction);\n    }\n    \n    // Other codes ...\n}\n```\n\n컨트롤러 구현 중에 좀 더 가독성 높은 쿼리를 위해, Article 모델에 아래 2개의 쿼리스코프를 추가하였다.\n\n```php\n// app/Article.php\n\nclass Article extends Model\n{\n    public function scopeNoComment($query)\n    {\n        return $query->has('comments', '<', 1);\n    }\n\n    public function scopeNotSolved($query)\n    {\n        return $query->whereNull('solution_id');\n    }\n}\n```\n\n`ArticlesController::index()` 에서 `FilterArticlesRequest` 란 Form Request 를 받는다. 이는 브라우저의 주소표시줄을 통해 사용자의 눈에도 보이는 HTTP GET 쿼리 스트링을 통해서, 'f', 's', 'd' 등의 필드 값이 전달되기 때문에, 서비스에서 허용하지 않는 문자열이 들어오는 것을 막기 위한 조치이다.\n\n```php\n// app/Http/Requests/FilterArticlesRequest.php\n\nclass FilterArticlesRequest extends Request\n{\n    public function rules()\n    {\n        return [\n            'f' => 'in:nocomment,notsolved',   // filter\n            's' => 'in:created_at,view_count', // Sort: Age(created_at), View(view_count)\n            'd' => 'in:asc,desc',              // Direction: Ascending or Descending\n            'q' => 'alpha_dash',               // Search query\n        ];\n    }\n}\n```\n\n컨트롤러 코드에서 풀텍스트 검색을 위해 `whereRaw()` 란 날 SQL을 쓸 수 있는 메소드를 이용하였고, 특수한 MySql 쿼리를 이용하였다. 쿼리는 앞서 언급한 [MySql 공식 문서](https://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html)를 참고하였다.\n\n**`참고`** 여기서는 MySql 네이티브 풀텍스트 검색을 이용했지만, 데이터베이스 엔진의 의존성을 버리고 빠른 성능을 달성하기 위해서는 [Elastic Search](https://www.elastic.co/downloads/elasticsearch) 등을 검토해 보기 바란다.\n\n![](./images/42-be-makeup-img-01.png)\n\n### 캐시\n\n#### 동작 원리\n\n아래와 같은 원리로 동작할 것이다. () 안에 포함된 내용은 'file', 'database' 캐시에는 적용되지 않는다.\n\n- `ArticlesController::index()` 에서 Article 모델의 콜렉션을 캐시에 ('xxx' 라는 태그로) 저장한다.\n- 신규 Article 모델의 생성, 기존 모델의 수정 또는 삭제시 이벤트를 던져 ('xxx' 태그를 가진) 캐시를 삭제한다.\n\n#### 도우미 패키지 설치\n\n라라벨의 캐시 기능을 좀 더 편리하게 사용하기 위해서 [watson/rememberable](https://github.com/dwightwatson/rememberable) 패키지를 가져와서 사용할 것이다. 라라벨 4 버전에 있다가 5 버전에서 빠진 기능이다.\n\n```bash\n$ composer require watson/rememberable\n```\n\n이 패키지는 `Watson\\Rememberable\\Rememberable` 이란 Trait를 제공하는데, Model 에서 use 키워드로 활성화시켜 주면, `remember(\\DateTime|int $minutes)` 란 메소드에 접근할 수 있다. 모든 모델에서 앞서 언급한 Trait 를 써주는 것은 피곤하기도 하거니와, 코드 구조화 측면에서 추상 모델 클래스 (abstract Model) 를 하나 만들고, 우리 프로젝트의 모델들은 이 추상 모델을 상속 받도록 하자. 이 추상 모델은 Eloquent 를 상속 받을 것이다.\n \n```php\n// app/Mode.php\n\n<?php\n\nnamespace App;\n\nuse Illuminate\\Database\\Eloquent\\Model as Eloquent;\nuse Watson\\Rememberable\\Rememberable;\n\nabstract class Model extends Eloquent\n{\n    use Rememberable;\n}\n```\n\n원래 'Article.php' 에 있던 `use Illuminate\\Database\\Eloquent\\Model` 선언이 'Model.php' 로 이동한 것을 확인하자. \n\n```php\n// app/Article.php\n\n<?php\n\nnamespace App;\n\nclass Article extends Model { // ... }\n```\n\n#### 컨트롤러에서 캐시 기능 활성화\n\n`remember()` 메소드는 분 단위로 지정된 캐시의 수명을 인자로 받게 되어 있다. 5분이라고 지정했다. \n\n`with()` 메소드 바로 뒤에 `remember()` 메소드를 체인했는데, 이는 Eager Loading 된 관계를 포함하여 모든 Article 콜렉션을 캐시에 저장한다는 의미이다. \n\n[캐시 태그](http://laravel.com/docs/cache#cache-tags) 는 캐시 키에 대한 별칭이라고 볼 수 있다. 가령, 'dogs' 란 캐시 키를 지정하고, 'animals' 란 캐시 태그를 지정한 후, 'animals' 태그에 속하는 모든 캐시를 한방에 지울 수 있다. 주의할 점은 `remember()` 메소드와 결합되었을 때는 `tags()` 메소드 대신 `cacheTags(string|array $cacheTags)` 를 사용하여야 한다는 점이다.\n\n[캐시 태그](http://laravel.com/docs/cache#cache-tags) 를 쓸 때 또 하나 주의할 점은, 'file', 'database' 캐시 드라이버에서는 태그를 쓸 수 없다는 점이다. 아래 코드에서 `taggable()` Helper 가 태그 사용 가능성을 체크해 준다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    public function index(FilterArticlesRequest $request, $id = null)\n    {\n        $query = $id\n            ? Tag::findOrFail($id)->articles()\n            : new Article;\n\n        $query = taggable()\n            ? $query->with('comments', 'author', 'tags', 'attachments')->remember(5)->cacheTags('articles')\n            : $query->with('comments', 'author', 'tags', 'solution', 'attachments')->remember(5);\n\n        // ...\n    }\n}\n```\n\n앞서 언급한 `taggable()` Helper 는 'config/cache.php' 를 읽어 와서, default 드라이버가 'file' 또는 'database' 인지를 체크한다.\n\n```php\n// app/helpers.php\n\nfunction taggable()\n{\n    return !in_array(config('cache.default'), ['file', 'database']);\n}\n```\n\n#### 캐시 삭제 이벤트\n\n모델에 변경 사항이 있을 때 이벤트를 던져, 지정된 태그의 캐시만 비울 것이다. 앞서 설명했듯이, 캐시 태그 기능은 'file', 'database' 캐시 드라이버에서 지원되지 않으므로, 캐시 전체를 비우는 식으로 구현할 것이다.\n\n모델에 변경이 발생하는 `store()`, `update()`, `destroy()` 메소드에서 각각 이벤트를 던져야 한다. `ModelChanged` 라고 이름 지었고, 이벤트 데이터로 지워야 할 태그의 리스트를 전달하였다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    public function store(ArticlesRequest $request)\n    {\n        // ...\n        event(new ModelChanged(['articles', 'tags']));\n    }\n    \n    // ...\n}\n```\n\n[22강 - 이벤트](22-events.md) 에서 배운 내용과는 다른 방법을 이용할 것이다. \n\n이벤트 이름과, 리스너 이름을 먼저 정한다. 이벤트 이름은 앞서 컨트롤러에서 `ModelChanged` 로 정했고, 리스너는 `CacheHandler` 로 정했다.\n\n```php\n// app/Prividers/EventServiceProvider.php\n\nclass EventServiceProvider extends ServiceProvider\n{\n    protected $listen = [\n        \\App\\Events\\ModelChanged::class => [\n            \\App\\Listeners\\CacheHandler::class\n        ],\n    ];\n    \n    // ...\n}\n```\n\nartisal CLI 로 이벤트 클래스와 리스너 클래스를 만든다. 'app/Events/ModelChanged.php' 와 'app/Listeners/CacheHandler.php' 파일이 만들어 진 것을 확인하자.\n\n```bash\n$ php artisan event:generate\n```\n\n이벤트 클래스는 단순한 DTO (== [Data Transfer Object](https://en.wikipedia.org/wiki/Data_transfer_object)) 로 클래스간 데이터를 주고 받기 위한 매개체이다. 해서, DTO의 클래스 변수들은 모두 public 으로 주어야 한다는 것을 주의하자.\n\n```php\n// app/Events/ModelChanged.php\n\n<?php\n\nnamespace App\\Events;\n\nuse Illuminate\\Queue\\SerializesModels;\n\nclass ModelChanged extends Event\n{\n    use SerializesModels;\n\n    public $cacheTags;\n\n    public function __construct($cacheTags)\n    {\n        $this->cacheTags = $cacheTags;\n    }\n}\n```\n\n리스너도 별 것 없다. `EventServiceProvider` 의 `$listen` 속성에서 이벤트에 연결된 리스너의 `handle()` 메소드를 기본적으로 호출하게 되어있고, 이 메소드에는 이벤트 객체를 인자로 넘겨 주게 되어 있다. \n\n`ModelChanged` 객체를 넘겨 받았으므로, 위헤서 정의한 `$cacheTags` 변수에 쉽게 접근할 수 있다. `taggable()` Helper 로 태그 기능이 없으면, 캐시 전체를 삭제하고 Early Return 을 하도록 하자.\n\n```php\n// app/Listeners/CacheHandler.php\n\n<?php\n\nnamespace App\\Listeners;\n\nuse App\\Events\\ModelChanged;\n\nclass CacheHandler\n{\n    public function handle(ModelChanged $event)\n    {\n        if (! taggable()) {\n            // Remove all cache store\n            return \\Cache::flush();\n        }\n\n        // Remove only cache that has the given tag(s)\n        return \\Cache::tags($event->cacheTags)->flush();\n    }\n}\n```\n\n> **`참고`** memcached 사용 관련... \n> 필자의 경우, memcache 사용을 위하여 'memcached(system library)', 'php-memcached(php module)' 을 모두 설치해 주어야 했다.\n> memcached 를 사용하려면 .env.php 에서 CACHE_DRIVER=memcached 로 수정하고, 아래 설치 및 실행 명령을 참고하자.\n\n```bash\n# Linux\n$ sudo apt-get install memcached php5-memcached\n# Mac OS\n$ brew install memcached homebrew/php/php5x-memcached\n# Run as daemon mode\n$ memcached -u memcached -d -m 30 -l 127.0.0.1 -p 11211\n```\n\n**`완전 잡담`** 가령, `Article::with('...')->where('...')->get()` 쿼리를 할 때, `with()` 가 붙는 순간 `Illuminate\\Database\\Eloquent\\Builder` 인스턴스로 변하고, `get()` 으로 최종 결과값을 가져오면 `Illuminate\\Database\\Eloquent\\Collection` 인스턴스가 된다.  \n\n### 이메일 알림\n\n별로 어렵지 않은데, 앞 전의 이벤트와 약간 다른 방식으로 이벤트와 핸들러를 등록할 것이다.\n\n```php\n// app/Providers/EventServiceProvider.php\n\nclass EventServiceProvider extends ServiceProvider\n{\n    // ...\n    \n    public function boot(DispatcherContract $events)\n    {\n        parent::boot($events);\n        $events->listen('comments.*', \\App\\Listeners\\CommentsHandler::class);\n    }\n}    \n```\n\n[22강 - 이벤트](22-events.md) 에서 배운 내용과 유사하다. 다만, `listen()` 메소드를 쓴 위치만, 글로벌 routes.php 에서 위 파일로 옮겨졌을 뿐이다. 'comments.*' 는 예상한대로, 'comments.' 로 시작하는 모든 이벤트를 `\\App\\Listeners\\CommentsHandler::handle()` 로 연결시키겠다는 의미이다.\n\n아래는 이벤트 핸들러 구현인데, 이메일을 보내는 일반적인 구현이다. 특이할만한 점은 `$comment->commentable()` 메소드를 이용하여 Comment 에 연결된 Article 객체를 가져와서 `author->email` 을 접근했다는 부분과, Comment 자신의 부모 Comment 의 `author->email` 도 같이 가져와서, 수신자에서 중복을 제거하고 메일을 발송하고 있다는 점이다.\n\n'emails.new-comment' 뷰는 설명을 생략한다.\n\n```php\n// app/Listeners/CommentsHandler.php\n\n<?php\n\nnamespace App\\Listeners;\n\nuse App\\Comment;\n\nclass CommentsHandler\n{\n    public function handle(Comment $comment)\n    {\n        $to[] = $comment->commentable->author->email;\n\n        if ($comment->parent) {\n            $to[] = $comment->parent->author->email;\n        }\n\n        $to = array_unique($to);\n        $subject = 'New comment';\n\n        return \\Mail::send('emails.new-comment', compact('comment'), function($m) use($to, $subject) {\n            $m->to($to)->subject($subject);\n        });\n    }\n}\n```\n\n### Markdown 컴파일러 확장\n\n[25강 - 컴포저](25-composer.md) 에서 가져온 `ParsedownExtra` 클래스를 이용하여, 사용자가 마크다운으로 작성한 포럼 글을 다시 보여줄 때 잘 사용하고 있었다. \n\n그런데, 갑자기 새로운 요구사항이 생겼다고 가정하자. 'a#포럼글id' 또는 'article#포럼글id' 식으로 마크다운 본문을 쓰면, 자동으로 해당 id로 이동하는 링크를 제공해야 한다고 하자.\n\n먼저, `ParsedownExtra` 상속받아 이 프로젝트만의 `Markdown` 클래스를 만들고, 여기에 해당 로직을 녹여 넣도록 하자. `preg_*()` 함수는 PHP 내장함수로 사용법에 대한 설명은 공식 문서를 참고하기 바란다. 다만, `public function text($text)` 의 마지막 줄 `return parent::text($text);` 에서 넘겨 받은 raw 문자열에서 필요한 컴파일 작업을 먼저 수행하여 얻은 결과물을 부모 클래스로 넘겨 데코레이션한 부분은 눈여겨 볼만하다. \n\n```php\n// app/Services/Markdown.php\n\n<?php\n\nnamespace App\\Services;\n\nuse ParsedownExtra;\n\nclass Markdown extends ParsedownExtra {\n\n    const PATTERN_ARTICLE = '/(article|a)\\#(?P<id>\\d+)/i';\n\n    public function text($text) {\n        if (preg_match(self::PATTERN_ARTICLE, $text, $matches) > 0) {\n            $text = preg_replace_callback(self::PATTERN_ARTICLE, function ($matches) {\n                return sprintf(\n                    \"<a href='%s'>%s</a>\",\n                    route('articles.show', $matches['id']),\n                    $matches[0]\n                );\n            }, $text);\n        }\n\n        return parent::text($text);\n    }\n}\n```\n\n### 베스트 답글 선택 구현\n \n#### UI 구성\n\n포럼 상세 보기 본문에 베스트 답글(== 댓글)이 있으면, 표시하도록 하였다.\n\n또, 댓글 뷰를 `@include` 할 때, `$solved`, `$owner` 란 새로운 변수도 넘겨 주도록 하였다.\n\n```html\n<!-- resources/views/articles/show.blade.php -->\n\n<div class=\"col-md-9\">\n  <article id=\"article__article\" data-id=\"{{ $article->id }}\">\n    <!-- ... -->\n    @if ($article->solution)\n      @include('comments.partial.best', ['comment' => $article->solution])\n    @endif\n  <!-- ... -->\n  \n  <article>\n    @include('comments.index', [\n      'solved' => $article->solution,\n      'owner'  => $currentUser && $article->isAuthor()\n    ])\n  </article>\n</div>\n```\n\n'comments.partial.best' 뷰는 특별한 내용이 없으므로 생략한다.\n \n포럼 글에 대해서 베스트 댓글이 없으면, 포럼 글 작성자가 베스트를 선택할 수 있도록 UI를 제공해야 한다. 'articles.show' 뷰에서 넘겨 받은, `$solved`, `$owner` 변수를 활용하고 있는 것을 확인할 수 있다.\n\n아래에서 `@parent` 란 블레이드 문법에 주목하자. 이는 부모 뷰에 동일한 이름의 `@section` 정의가 있으면, 둘을 합쳐서 `@yield` 할 수 있게 해 준다. 가령, 'comments.partial.commnet' 뷰에 `@section('script')` 가 있고, 부모 뷰인 'comments.index' 에도 `@section('script')` 가 있다면, `@parent` 키워드를 포함하지 않으면, 일반적인 클래스 상속과 동일하게 자식뷰의 섹션이 부모뷰를 오버라이드해 버린다.\n\n```html\n<!-- resources/views/comments/partial/comment.blade.php -->\n\n@if ($currentUser)\n<p class=\"text-right\" style=\"margin-top: 1rem;\">\n  @if (! $solved && $owner)\n    <button type=\"button\" class=\"btn btn-default btn-sm btn__pick\" title=\"Pick as the Best Answer\">\n      {!! icon('pick', false) !!}\n    </button>\n  @endif\n  <!-- Reply button here ... -->\n</p>\n@endif\n\n@section('script')\n  @parent\n  <script>\n    // Other javascript codes ...\n    $(\"button.btn__pick\").on(\"click\", function(e) {\n      var articleId = $(\"#article__article\").data(\"id\"),\n          commentId = $(this).closest(\".media__item\").data(\"id\");\n\n      if (confirm(\"Are you sure to select this comment as the 'Best'?\")) {\n        $.ajax({\n          type: \"POST\",\n          url: \"/articles/\" + articleId + \"/pick\",\n          data: {\n            _method: \"PUT\",\n            solution_id: commentId\n          }\n        }).success(function() {\n          flash('success', 'Updated ! The page will reload in 3 secs.', 2500);\n          reload(3000);\n        });\n      }\n    });\n  </script>\n@stop\n```\n\n![](./images/42-be-makeup-img-02.png)\n\n### 그 외 추가된 장식들\n\n- [22강 - 이벤트](22-events.md) 에서 썼던 users.last_login 필드를 살려서, 사용자가 로그인할 때마다 시각을 업데이트하였다. (database/migrations/create_users_table.php, app/Http/Controllers/SessionsController.php, app/Providers/EventServiceProvider.php, app/Listeners/UserEventsHandler.php)\n- 포럼 상세 보기 페이지가 로드될 때마다 articles.view_count 값을 올려 조회수를 표시하는 기능을 추가하였다. (database/migrations/create_articles_table.php, app/Providers/EventServiceProvider.php, app/Listeners/ViewCountHandler.php, resources/views/articles/partial/article.blade.php)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [41강 - UI 개선](41-ui-makeup.md)\n- [43강 - 변경 사항 알림](43-change-note.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/43-change-note.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 45\n---\n\n# 실전 프로젝트 2 - Forum\n\n## 43강 - 변경 사항 알림\n\n2~3주 정도 다른 일로 쉬는 동안 강좌는 쓰지 못했지만, 코드 변경을 계속 해 왔다. 다음 실전 강좌로 넘어가기 전에, 모든 변경 내용을 설명하지는 못하겠지만, 큰 변경 내용은 정리해서 공유하고자 한다.\n\n1. Article Refactoring \n    - 포럼에서 \"상단 고정 게시물\" 기능을 구현했다. \n    - `Article`, `Comment` 모델에 [Soft Delete](http://laravel.com/docs/eloquent#soft-deleting) 기능을 추가하였다.\n    - 댓글에 투표 기능을 추가했다.\n2. Lesson Refactoring\n    - 'documents (문서)' 디렉토리, Route 엔드포인트, 뷰 등등을 'lessons (강좌)' 으로 변경했다. 아울러 모델 이름도 `Document` 에서 `Lesson` 으로 변경했다.\n    - 포럼 뿐 아니라 강좌에서도 댓글을 쓸 수 있도록 수정하였다. 이 과정에서 `Lesson` 모델 관련 [Repository Pattern](https://github.com/domnikl/DesignPatternsPHP/tree/master/More/Repository) 을 적용하는 등 몇 가지 관련 코드들의 수정이 있었다.\n    - 강좌에서도 \"이전\", \"다음\" 페이지네이션 기능을 추가하였다.\n    - 'lessons (강좌)' 디렉토리에 담긴 마크다운 파일의 내용이 바뀌었을 경우, `Lesson` 모델과 컨텐츠 동기화를 해 주는 커스텀 Artisan 코맨드를 추가했다. \n3. 라이브 데모 사이트 개설\n    - 이 강좌의 라이브 데모 사이트를 위해, 랜딩 페이지를 만들고, [Amazon Web Service](http://aws.amazon.com/) 에 코드를 배포하였다. \n    - 이 과정에서 [Envoy SSH Task Runner](http://laravel.com/docs/envoy) 를 사용하였다.\n    - 라이브 데모 사이트에서 발생하는 Exception 을 [\\# slack](https://slack.com/) 메시지로 받기 위한 기능을 추가했다. \n\n**`참고`** 상세한 변경사항은 [Laravel 5 Essential](https://github.com/appkr/l5essential/commit) 의 Commit History 에서 확인하시기 바란다.\n\n### 1. Article Refactoring\n\n#### 상단 고정 게시물 기능 구현\n`Article` 모델에 `$pin` 속성이 지정되어 있으면, 포럼 목록을 표시할 때 가장 위에 표시하는 식으로 포럼 \"상단 고정 게시물\" 기능을 구현했다.\n\n```php\n// DATE_create_articles_table.php\n\nclass CreateArticlesTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('articles', function (Blueprint $table) {\n            // ...\n            $table->boolean('pin')->default(0);\n        }\n    }\n}\n```\n\n아래 코드에서 `orderBy('pin', 'desc')`가 추가된 것을 확인하자.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    protected function filter($request, $query)\n    {\n        //...\n        return $query->orderBy('pin', 'desc')->orderBy($sort, $direction);\n    }\n```\n\n그리고, `$pin` 속성은 관리자만 지정하거나 해제할 수 있도록 하였다.\n\n```html\n<!-- resources/views/articles/partial/form.blade.php -->\n\n<!-- Other view codes... -->\n@if ($currentUser and $currentUser->isAdmin())\n  <div class=\"form-group\">\n    <div class=\"checkbox\">\n      <label>\n        <input type=\"checkbox\" name=\"pin\" {{ $article->pin ? 'checked=\"checked\"': ''}}>\n        {{ trans('forum.pin') }}\n      </label>\n    </div>\n  </div>\n@endif\n```\n\n#### Soft Delete 적용 및 댓글에 응용\n\n[Soft Delete](http://laravel.com/docs/eloquent#soft-deleting) 란 사용자가 삭제 요청을 하면, DB 에서 레코드를 완전히 삭제하는 것이 아니라, `deleted_at` 이란 필드에 삭제된 날짜를 넣어 놓는 식으로 동작한다. 마이그레이션에서 `deleted_at` 필드를 추가하고, Soft Delete 를 적용할 모델에서 라라벨에 제공하는 Trait 만 추가하면 된다.\n\n```php\n// DATE_create_articles_table.php\n\nclass CreateArticlesTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('articles', function (Blueprint $table) {\n            // ...\n            $table->softDeletes();\n        }\n    }\n}\n```\n\n아래에서 `$dates` 는 날짜 형식을 `Carbon\\Carbon` 인스턴스로 바꾸어서 보여주기 위한 Accessor 이다. 기본기 [22강 - 이벤트](22-events.md) 강좌에서 `$last_login` 속성을 추가할 때도 사용한 적이 있다. \n\n```php\n// app/Article.php\n\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\n\nclass Article extends Model\n{\n    use SoftDeletes;\n    \n    protected $dates = ['deleted_at'];\n    \n    // ...\n}\n```\n\nSoft Delete 가 적용되었더라도 엘로퀀트나 쿼리빌더에서는 이전과 동일하게 쿼리하면, 라라벨이 내부적으로 `deleted_at == null` 인 레코드들만 가져오게 되어 있다. 다만 삭제된 레코드까지도 가져오고 싶다면 `withTrashed()` 메소드를 체인하면 된다. 아래는 자식 댓글이 있음에도 불구하고, 작성자가 자신의 댓글을 삭제했을 때, \"삭제된 댓글\" 이라고 표시하기 위한 구현인데, `withTrashed()` 로 삭제된 댓글까지도 모두 가져오고 있음을 확인할 수 있다.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    public function show($id)\n    {\n        $article = Article::with('comments', 'tags', 'attachments', 'solution')->findOrFail($id);\n        $commentsCollection = $article->comments()->with('replies')\n            ->withTrashed()->whereNull('parent_id')->latest()->get();\n        // ...\n    }\n```\n\n아래는 `Comment` 모델의 삭제 구현이다. 자식 댓글이 없으면 `forceDelete()` 메소드로 DB 에서 완전히 삭제해 버리고, 그렇지 않으면 `delete()` 메소드로 Soft Delete 한다.\n\n```php\n// app/Http/Controllers/CommentsController.php\n\nclass CommentsController extends Controller\n{\n    public function destroy(Request $request, $id)\n    {\n        $comment = Comment::with('replies')->find($id);\n\n        if ($comment->replies->count() > 0) {\n            $comment->delete();\n        } else {\n            $comment->forceDelete();\n        }\n\n        // ...\n    }\n}\n```\n\n이제 뷰를 살펴보자. `$comment->trashed()` 는 Soft Delete 된 댓글일 경우 `true` 를 반환한다.\n\n```html\n<!-- resources/views/comments/index.blade.php -->\n\n@forelse($comments as $comment)\n@include('comments.partial.comment', [\n  // ...\n  'hasChild'  => count($comment->replies),\n  'isTrashed' => $comment->trashed()\n])\n@empty\n@endforelse\n```\n\n```html\n<!-- resources/views/comments/partial/comment.blade.php -->\n\n@if ($isTrashed and ! $hasChild)\n  <!-- 자식 댓글이 없는 상태에서 삭제된 댓글 -->\n@elseif ($isTrashed and $hasChild)\n  <!-- 자식 댓글이 있는데 삭제되었을 때 -->\n  <p class=\"text-danger\">삭제된 댓글입니다.</p>\n@else\n  <!-- 삭제되지 않은 댓글일 때 -->\n@endif\n```\n\n#### 댓글에 투표 기능 추가\n\n[Disqus](https://disqus.com/), [Stack Overflow](http://stackoverflow.com/) 의 댓글들은 투표시스템 (== 포인팅 시스템) 을 가지고 있고, 그 점수에 따라 댓글의 품질을 평가하고 있다. 여기서도 유사한 기능을 구현했다. 주의할 점은 특정 댓글에 이미 Up 또는 Down 투표를 한 사용자는 같은 댓글에 대해서는 다시 투표를 할 수 없어야 한다는 점이다.\n \n먼저 투표을 받기 위한 마이그레이션과 모델을 만들자. `user_id` 필드는 이미 투표한 사용자인지를 판단하기 위해서 사용한다. `up`, `down` 필드는 특정 `comment_id` 에 대한 투표 값 통계를 내기 위한 목적으로 각각 분리해서 필드를 생성했다.\n\n```php\n// DATE_create_votes_table.php\n\nclass CreateVotesTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('votes', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('user_id')->unsigned();\n            $table->integer('comment_id')->unsigned();\n            $table->tinyInteger('up')->nullable();\n            $table->tinyInteger('down')->nullable();\n            $table->timestamp('voted_at');\n\n            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');\n            $table->foreign('comment_id')->references('id')->on('comments')->onDelete('cascade');\n        });\n    }\n}\n```\n\n아래는 `Vote` 모델이다. `User`, `Comment` 모델에서의 Reverse Relationship 은 설명을 생략한다.\n\n```php\n// app/Vote.php\n\nclass Vote extends Model\n{\n    public $timestamps = false;\n\n    protected $fillable = [\n        'user_id',\n        'comment_id',\n        'up',\n        'down',\n        'voted_at',\n    ];\n\n    protected $dates = [\n        'voted_at',\n    ];\n\n    public function comment()\n    {\n        return $this->belongsTo(Comment::class);\n    }\n\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n}\n```\n\n이제 투표를 하기 위한 UI 를 만들자. 아래 코드에서 `<?php $voted = $comment->votes->contains('user_id', $currentUser->id); ?>` 부분을 주목해볼만 하다. 페이지가 로드될 때, 현재 로그인한 사용자가 이미 투표를 했는지 확인하는 부분인데, `\\Illuminate\\Database\\Eloquent\\Collection::contains(mixed $key, mixed $value = null)` API 를 이용하고 있다. 이미 투표했을 경우. `@if ($voted) {{ 'disabled=\"disabled\"' }} @endif` 에서 버튼을 비활성화시켰다.\n\n투표 값, 'up' 또는 'down' 전송은 Ajax 를 이용하고 있고, 서버에서 성공 응답을 받으면, 투표한 댓글의 투표 버튼을 비활성화 시키고 있다. \n\n```html\n<!-- resources/views/comments/partial/comment.blade.php -->\n\n@if ($currentUser)\n  <div class=\"btn-group\" role=\"group\">\n    <?php $voted = $comment->votes->contains('user_id', $currentUser->id); ?>\n    <button type=\"button\" class=\"btn btn-default btn-sm btn__vote\" data-vote=\"up\" title=\"Vote up\" @if ($voted) {{ 'disabled=\"disabled\"' }} @endif>\n      {!! icon('up', false) !!} <span>{{ $comment->up_count }}</span>\n    </button>\n    <button type=\"button\" class=\"btn btn-default btn-sm btn__vote\" data-vote=\"down\" title=\"Vote down\" @if ($voted) {{ 'disabled=\"disabled\"' }} @endif>\n      {!! icon('down', false) !!} <span>{{ $comment->down_count }}</span>\n    </button>\n  </div>\n  <!-- Other view codes... -->\n@endif\n\n@section('script')\n  @parent\n  <script>\n    $(\"button.btn__vote\").on(\"click\", function(e) {\n      var self = $(this),\n          commentId = $(this).closest(\".media__item\").data(\"id\");\n\n      $.ajax({\n        type: \"POST\",\n        url: \"/comments/\" + commentId + \"/vote\",\n        data: {\n          vote: self.data(\"vote\")\n        }\n      }).success(function(data) {\n        self.find(\"span\").html(data.value);\n        self.attr(\"disabled\", \"disabled\");\n        self.siblings().attr(\"disabled\", \"disabled\");\n      }).error(function() {\n        flash(\"danger\", \"{{ trans('common.msg_whoops') }}\", 2500);\n      });\n    });\n  </script>\n@stop\n```\n\n이제 뷰에서 Ajax 로 전송한 투표를 받고 처리할 수 있는 Route 와 컨트롤러 로직을 만들어야 한다.\n\n```php\n// app/Http/routes.php\n\nRoute::post('comments/{id}/vote', 'CommentsController@vote');\n```\n\n아래는 컨트롤러이다. 주석에 설명을 달았다.\n\n```php\n// app/Http/Controllers/CommentsController.php\n\nclass CommentsController extends Controller\n{\n    public function vote(Request $request, $id)\n    {\n        $this->validate($request, [\n            'vote' => 'required|in:up,down',\n        ]);\n\n        if(Vote::whereCommentId($id)->whereUserId($request->user()->id)->exists()) {\n            // 사용자가 브라우저의 Inspector 등을 이용해서 disabled 된 투표 버튼을 다시 활성화시켜\n            // 중복 투표를 하는 것을 방지하기 위한 조치이다.\n            return response()->json(['errors' => 'Already voted!'], 409);\n        }\n\n        $comment = Comment::findOrFail($id);\n        $up = $request->input('vote') == 'up' ? true : false;\n\n        $comment->votes()->create([\n            'user_id'  => $request->user()->id,\n            'up'       => $up ? 1 : null,\n            'down'     => $up ? null : 1,\n            'voted_at' => \\Carbon\\Carbon::now()->toDateTimeString(),\n        ]);\n\n        return response()->json([\n            // up, down 어떤 투표인지와 투표 후 총 투표 수를 반환하고,\n            // 뷰의 자바스크립트에서 총 투표 수를 업데이트한다.\n            'voted' => $request->input('vote'),\n            'value' => $comment->votes()->sum($request->input('vote'))\n        ]);\n    }\n}\n```\n\n아래 `Comment` 모델에서 `$with` 속성은 모든 쿼리에서 포함할 Eager Loading 관계이다. 즉, `Comment::find(1)` 로만 쿼리해도 `Comment::with('author', 'votes')->find(1)` 과 같은 결과를 보여준다는 의미이다.\n\n```php\n// app/Comment.php\n\nclass Comment extends Model\n{\n    protected $with = [ 'author', 'votes', ];\n\n    protected $appends = [ 'up_count', 'down_count' ];\n\n    public function getUpCountAttribute()\n    {\n        return (int) static::votes()->sum('up');\n    }\n\n    public function getDownCountAttribute()\n    {\n        return (int) static::votes()->sum('down');\n    }\n    \n    // ...\n}\n```\n\n투표를 포함한 댓글 목록을 브라우저 쪽으로 던져 주는 부분은 `ArticlesController::show()` 메소드인데 설명은 생략한다. 대신, 사용자로 부터 얻은 댓글에 대한 통계를 어떻게 얻는지를 설명하기로 한다.\n \n`Comment` 모델에서 `up_count` 와 `down_count` 란 필드를 동적으로 생성하고 모델의 속성으로 Append 하였다. 이 속성들은 `getUpCountAttribute()`, `getDownCountAttribute()` 란 메소드에서 그 값이 채워지는데, `Comment::votes()->sum(up)` 처럼 엘로퀀트 컬렉션에서 제공하는 통계 메소드인 `sum()` 을 이용하고 있다. 앞 전에 `Vote` 모델을 채울 때, `up` 과 `down` 속성에 `null|1` 을 채운 것이 여기서 모두 합해 지는 것이다.\n\n```bash\n$ php artisan tinker\n>>> $comment = App\\Comment::find(22);\n=> App\\Comment {#835\n     content: \"저는 자식 댓글입니다.\",\n     #...,\n     author: App\\User {#840\n       name: \"Rowena Ferry\",\n       #...,\n     },\n     votes: Illuminate\\Database\\Eloquent\\Collection {#838\n       all: [\n         App\\Vote {#843\n           up: 1,\n           #...,\n         },\n         App\\Vote {#844\n           up: 1,\n           #...,\n         },\n       ],\n     },\n   }\n>>> $comment->up_count;\n=> 2\n>>> $comment->down_count;\n=> 0\n```\n\n![](./images/43-change-note-img-01.png)\n\n### 2. Lesson Refactoring\n\n#### Repository 구현\n\n강좌에서도 댓글을 쓸 수 있도록 하기 위해서, [28강 - Cache](28-cache.md) 에서 살펴본 바와 유사하게, 사용자의 마크다운 파일 요청이 있으면, 파일시스템에 있던 파일을 읽어서 바로 주는 것이 아니라 DB 에 넣었다. 즉, 파일의 내용을 DB 에 넣어서, 모델을 만들었다는 얘기다. 단, 매번 파일시스템 -> DB Insert 식으로 동작하는 것이 아니라, 캐시처럼 DB 를 먼저 탐색해서 없으면 파일시스템에서 읽어서 DB Insert 하는 식으로 구현했다.\n\n먼저 파일로 부터 읽어 들인 마크다운 파일의 내용을 담을 DB 마이그레이션을 만들어야 한다.\n\n```php\n// DATE_create_lessons_table.php\n\nclass CreateLessonsTable extends Migration\n{\n    public function up()\n    {\n        Schema::create('lessons', function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('author_id')->unsigned();\n            $table->string('name');\n            $table->text('content');\n            $table->timestamps();\n            $table->foreign('author_id')->references('id')->on('users');\n        });\n    }\n}\n```\n\n여러가지 구조를 고민하다가, 강좌 외에도 마크다운 형식의 파일을 서비스할 일이 더 있을 것을 고려해서 Repository 를 만들기로 했다. 아래 코드에서 `find()` 메소드를 보면, 사용자가 요청한 파일 이름으로 먼저 DB 쿼리를 하고, 쿼리 결과가 `null` 이면 파일 시스템에서 읽어서 `Lesson` 모델을 생성하고 있는 것을 확인할 수 있다.\n\n```php\n// app/Repositories/MarkdownRepository.php\n\nuse Exception;\nuse File;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nabstract class MarkdownRepository implements RepositoryInterface\n{\n    protected $model;\n    \n    protected $path;\n\n    public function __construct()\n    {\n        $this->initialize();\n    }\n\n    public abstract function model();\n\n    protected function initialize()\n    {\n        $model = app()->make($this->model());\n\n        if (! $model instanceof Model) {\n            throw new Exception(\n                'model() method must return a string name of an Eloquent Model.'\n            );\n        }\n\n        if (! property_exists($this->model(), 'path')) {\n            throw new Exception(\n                \"{$this->model()} should have a property named 'path'\"\n            );\n        }\n\n        $path  = base_path($model::$path);\n\n        if (! File::isDirectory($path)) {\n            throw new Exception(\n                \"Something went wrong with the path property of {$this->model()} model.\"\n            );\n        }\n\n        $this->model = $model;\n        $this->path  = $path;\n    }\n\n    public function find($id, $columns = ['*'])\n    {\n        return $this->model->whereName($id)->first()\n            ?: $this->model->create([\n                // Bad!! Avoid hard code, b.c, admin may change.\n                'author_id' => 1, \n                'name'      => $id,\n                'content'   => File::get($this->getPath($id)),\n            ]);\n    }\n\n    public function image($file) { // ... }\n\n    public function etag($file) { // ... }\n\n    protected function getPath($file)\n    {\n        $path = $this->path . DIRECTORY_SEPARATOR . $file;\n\n        if (!File::exists($path)) {\n            abort(404, 'File not exist');\n        }\n\n        return $path;\n    }\n}\n```\n\n이 추상 클래스를 상속하는 클래스는 `public abstract function` 으로 지정한 `model()` 메소드를 반드시 구현해야 한다. 그리고, 해당 Repository 와 연결된 모델에서는 `$path` 속성을 제공해야 한다. 이 클래스를 상속하게 되는 `LessonRepository` 와 `Lesson` 모델을 차례로 볼 것이다.\n \n```php\n// app/Repositories/LessonRepository.php\n\nclass LessonRepository extends MarkdownRepository\n{\n    public function model()\n    {\n        return \\App\\Lesson::class;\n    }\n}\n```\n\n```php\n// app/Lesson.php\n\nclass Lesson extends Model\n{\n    public static $path = 'lessons';\n    \n    // ...\n}\n```\n\n`MarkdownRepository` 추상 클래스에서 `initialize()` 메소드의 구동을 살펴보자.\n\n- 먼저 `app()->make(string $abstract)` Helper 를 이용해서, `Lesson` 모델을 생성한다. `LessonRepository::model()` 메소드에서 `\\App\\Lesson` 이란 스트링을 반환하게 되어 있으므로, 당연히 전술한 코드는 `app()->make('\\App\\Lesson')` 와 같이 된다.\n- 좀 전에 만든 클래스가 엘로퀀트 모델이 맞는지를 체크하여 아닐 경우 `\\Exception` 을 던진다\n- [`property_exists(mixed $class, string $property)`](http://php.net/manual/kr/function.property-exists.php) PHP 내장 함수로, `Lesson` 모델에 `$path` 속성이 지정되어 있지 않을 경우, `\\Exception` 을 던진다.\n- 또, `Lesson` 모델에서 `$path` 속성으로 지정한 디렉토리가 존재하지 않을 경우 `\\Exception` 을 던진다.\n- 모든 체크 과정이 완료되면, 이 추상 클래스가 동작하기 위해 필요한 `$model`, `$path` 속성이 모두 준비된다.\n\n이제 `LessonsController` 에서 만들어진 `LessonRepository` 를 사용하면 된다. \n\n```php\n// app/Controllers/LessonsController\n\nclass LessonsController extends Controller\n{\n    protected $repo;\n\n    public function __construct(LessonRepository $repo)\n    {\n        // LessonRepository 를 Injection 하고 $repo 속성에 할당한다.\n        $this->repo = $repo;\n    }\n\n    public function show($file = '01-welcome.md')\n    {\n        $lesson = $this->repo->find($file);\n\n        $commentsCollection = $lesson->comments()->with('replies')\n            ->withTrashed()->whereNull('parent_id')->latest()->get();\n\n        return view('lessons.show', [\n            'index'           => $this->repo->index(),\n            'lesson'          => $lesson,\n            'comments'        => $commentsCollection,\n            'commentableType' => $this->repo->model(),\n            'commentableId'   => $lesson->id,\n        ]);\n    }\n    \n    // ...\n}\n```\n\n강좌에서도 댓글을 사용하기 위해 `$comments` 변수를 뷰로 넘기는 것이 보일 것이다.\n\n#### Pagination\n\n포럼 목록보기에서 `\\Illuminate\\Database\\Eloquent\\Collection` 을 이용해서 페이지네이션을 보여주었다면, 강좌에서는 단일 강좌 상세보기를 보여주고 있으므로 \"다음\" 또는 \"이전\" 강좌로 이동하는 페이지네이션이 적절할 것으로 생각된다. \n\n`MarkdownRepository` 에 페이지네이션에 필요한 기능을 구현하였다. `$toc` 는 전체 강좌 목록을 가진 배열이다. `$current` 는 현재 선택된 강좌의 배열 값 (== 파일이름) 이다. `$toc` 는 `initialize()` 과정에서 셋팅이되며, `$current` 는 `find()` 메소드에서 셋팅이 된다. \n\n`$toc` 를 셋팅하는 과정에 [`glob()`](http://php.net/manual/kr/function.glob.php), [`array_diff()`](http://php.net/manual/kr/function.array-diff.php), [`array_map()`](http://php.net/manual/kr/function.array-map.php), [`pathinfo()`](http://php.net/manual/kr/function.pathinfo.php) 등의 PHP 내장 함수를 사용하는데, 공식 문서들을 참고하자.\n\n`prev(string $current)`, `next(string $current)` 메소드는 모두 `$current` 를 인자로 받는데, 이는 현재 화면에 표시된 강좌의 마크다운 파일이름이다. 이 메소드들에서는 [`array_search()`](http://php.net/manual/kr/function.array-search.php) PHP 내장 함수를 이용해서, 인자로 넘겨 받은 `$current` 에 해당하는 배열 인덱스를 `$toc` 에서 찾은 후, +1 또는 -1 해서 원하는 인덱스에 해당하는 파일이름을 반환하게 구현되어 있다. [`array_key_exists()`](http://php.net/manual/kr/function.array-key-exists.php) 도 찾아보기 바란다.\n\n```php\n// app/Repositories/MarkdownRepository.php\n\nabstract class MarkdownRepository implements RepositoryInterface\n{\n    protected $toc;\n\n    protected $current;\n    \n    public function __construct() {// ...}\n    \n    protected function initialize()\n    {\n        if (! $this->toc) {\n            $all    = glob(base_path($model::$path . DIRECTORY_SEPARATOR . '*.md'));\n            $except = glob(base_path($model::$path . DIRECTORY_SEPARATOR . '*INDEX.md'));\n            // $files 는 INDEX.md 를 제외한 나머지 *.md 파일들을 담고 있는 배열이다.\n            $files  = array_diff($all, $except);\n\n            $this->toc = array_map(function($file) {\n                // $files 배열을 순회하면서, $this->toc 에 담는다.\n                return pathinfo($file, PATHINFO_BASENAME);\n            }, $files);\n        }\n    }\n    \n    public function find($id, $columns = ['*'])\n    {\n        // $id 는 '01-welcome.md' 와 같은 파일 이름을 담고 있다.\n        $this->current = $id;\n        \n        // ...\n    }\n\n    public function prev($current) {\n        // $current 가 '01-welcome.md' 라면,\n        // array_search 의 결과는 이 파일의 index 인 0 이 된다.\n        // $prev 에는 -1 이 할당된다.\n        $prev = array_search($current, $this->toc) - 1;\n\n        // $this->toc[-1] 은 존재하지 않으므로 false 가 리턴될 것이다.\n        return array_key_exists($prev, $this->toc) ? $this->toc[$prev] : false;\n    }\n\n    public function next($current) {\n        // $current 가 '01-welcome.md' 라면,\n        // array_search 의 결과는 이 파일의 index 인 0 이 된다.\n        // $next 에는 2 가 할당된다.\n        $next = array_search($current, $this->toc) + 1;\n\n        // $this->toc[2] 에 해당하는 값은 '02-hello-laravel.md' 이다.\n        return array_key_exists($next, $this->toc) ? $this->toc[$next] : false;\n    }\n    \n    // ...\n}\n\n```\n\n이제 쉽다. 컨트롤러에서 뷰에다 \"이전\", \"다음\" 에 해당하는 파일이름을 넘겨주기만 하면 되니까..\n\n```php\n// app/Http/Controllers/LessonsController.php\n\nclass LessonsController extends Controller\n{\n    public function show($file = '01-welcome.md')\n    {\n        // ...\n        \n        return view('lessons.show', [\n            // ...\n            'prev'            => $this->repo->prev($file),\n            'next'            => $this->repo->next($file),\n        ]);\n    }\n}\n```\n\n뷰를 보자.\n\n```html\n// resources/views/lessons/show.blade.php\n\n<article>\n  @include('lessons.partial.pager')\n  <!-- ... -->\n</article>\n```\n\n컨트롤러에서 넘겨 받은 `$prev`, `$next` 값이 `false` 일 경우, 즉 처음 페이지 또는 마지막 페이지일 경우, `class=\"disabled\"` 속성을 지정하고 있다. 반면 값이 있을 경우에는, `route('lessons.show', '파일이름')` 으로 \"이전\" 또는 \"다음\" 으로 이동하는 링크를 만드는 것을 볼 수 있다.\n\n```\n// resources/views/lessons/partial/pager.blade.php\n\n<nav>\n  <ul class=\"pager\">\n    <li class=\"previous {{ $prev === false ? 'disabled' : ''}}\">\n      <a href=\"{{ $prev !== false ? route('lessons.show', $prev) : '#'}}\">\n        {{ trans('pagination.previous') }}\n      </a>\n    </li>\n    <li class=\"next {{ $next === false ? 'disabled' : ''}}\">\n      <a href=\"{{ $next !== false ? route('lessons.show', $next) : '#' }}\">\n        {{ trans('pagination.next') }}\n      </a>\n    </li>\n  </ul>\n</nav>\n```\n\n기존 강좌에서 넣어 두었던 마크다운을 이용한 이전 강좌, 다음 강좌 링크와 이번에 구현한 페이지네이션간의 중복을 피하기 위해, 기존 강좌의 마크다운 파일에 &lt;!--@start--&gt; &lt;!--@end--&gt; 와 같은 커스텀 마크다운 컴파일 규칙을 정의하고, 그것을 이해하고 처리하기 위해 'app/Services/Markdown.php' 도 약간 수정했다.\n\n![](./images/43-change-note-img-02.png)\n\n#### Custom Artisan Command\n\n사용자의 요청이 없으면 강좌의 내용은 DB 에 Insert 되지 않는다. 그렇지만, 이미 DB 에 들어간 강좌의 마크다운 파일을, 다음 릴리즈 때 수정해서 올려야 한다면 어떻게 할까? 당연히 기존에 DB 에 들어가 있는 강좌 엔트리를 모두 업데이트해 줘야 한다. 사실 'lessons' 테이블을 truncate 하면 모든게 리셋되고, 새로 파일에서 읽어 DB Insert 를 하겠지만, 이렇게 하면 문제가 생긴다. 무슨 문제이고 하니, 댓글의 'commentable_id' 값이 이미 DB 에 들어간 강좌의 'id' 와 연결되어 있다는 점이다. 강좌의 변경 내용을 효율적으로 반영하기 위해 [커스텀 Artisan 코맨드](http://laravel.com/docs/5.2/artisan) 를 만들자.\n\n```bash\n$ php artisan make:console UpdateLessonsTable\n```\n\n기본적으로 알고 있어야 할 것은 이 정도다. `$this->argument()` 로 콘솔에서 사용자가 입력한 인자를 얻을 수 있다. `$this->option()` 으로 콘솔에서 사용자가 입력한 옵션 값을 얻을 수 있다. `$this->info()`, `$this->error()`, `$this->warning()`, `$this->line()`, `$this->table()` 등으로 사용자에게 코맨드 실행결과를 알려 줄 수 있다. 사실 가장 중요한 것은 코맨드의 인자와 옵션을 지정하는 `$signature` 속성이다. 더 상세한 내용은 공식문서를 살펴볼 것을 권장한다. \n\n```php\n// app/Console/Commands/UpdateLessonsTable.php\n\nclass UpdateLessonsTable extends Command\n{\n    protected $signature = 'my:update-lessons';\n\n    protected $description = 'Update the content of the lessons table.';\n\n    public function handle()\n    {\n        $lessons = \\App\\Lesson::all();\n\n        foreach($lessons as $lesson) {\n            $path = base_path(\\App\\Lesson::$path . DIRECTORY_SEPARATOR . $lesson->name);\n            $lesson->content = \\File::get($path);\n            $lesson->save();\n            $lesson->touch();\n\n            $this->info(sprintf('Success updating %d: %s', $lesson->id, $lesson->name));\n        }\n\n        return $this->warn('Finished.');\n    }\n}\n```\n\nArtisan 명령을 작성했으면 반드시 'app/Console/Kernel.php' 에 등록해 주어야 한다.\n\n```php\n// app/Console/Kernel.php\n\nclass Kernel extends ConsoleKernel\n{\n    protected $commands = [\n        \\App\\Console\\Commands\\UpdateLessonsTable::class,\n    ];\n    \n    // ...\n}\n```\n\n실행해 보면 아래 그림과 같은 결과를 얻을 수 있다.\n\n![](./images/43-change-note-img-03.png)\n\n**`참고`** 라라벨은 서버의 Crontab 정의를 직접 손대지 않고도, PHP 코드 레벨에서 작업 스케쥴을 정의할 수 있게 도와 준다. 공식 문서의 [Task Scheduling](https://laravel.com/docs/5.2/scheduling) 부분을 살펴볼 것을 권장한다. 아래는 이 서비스에 적용되어 있는 월 단위 라라벨 로그를 삭제하는 스케쥴이다. 매일 3시에 DB 를 백업하는 코맨드도 넣어 두었다.\n\n```php\n// app/Console/Commands/ClearLog.php\n\nclass ClearLog extends Command\n{\n    protected $signature = 'my:clear-log';\n\n    protected $description = 'Clear Laravel log.';\n\n    public function handle()\n    {\n        $path = storage_path('logs/laravel.log');\n        system('cat /dev/null > ' . $path);\n\n        $now = \\Carbon\\Carbon::now()->toDateTimeString();\n        $result = \"{$this->getName()} command done at {$now}\";\n        \\Log::info($result);\n\n        return $this->info($result);\n    }\n}\n```\n\n```php\n// app/Console/Kernel.php\n\nclass Kernel extends ConsoleKernel\n{\n    // ...\n    \n    protected function schedule(Schedule $schedule)\n    {\n        $schedule->command('inspire')->hourly();\n        $schedule->command('my:clear-log')->monthly();\n        $schedule->command(\n                sprintf('my:backup-db %s %s', env('DB_USERNAME'), env('DB_PASSWORD'))\n            )->dailyAt('03:00');\n    }\n}\n```\n\n### 3. 라이브 데모 사이트 개설\n\n#### 라이브 데모 사이트\n\nAWS 에 오픈했다.\n\n![](./images/43-change-note-img-04.png)\n\n#### Envoy SSH Task Runner\n\n[Envoy](http://laravel.com/docs/envoy) 는 라라벨에서 제공하는 Remote Task Runner 이다. 원격 서버에 SSH 로 직접 로그인하지 않고도, 스크립트로 써 놓은 Task 를 **\"로컬\"** 에서 실행할 수 있는 기능이다. Envoy 는 [Puppet](http://www.puppetlabs.com/), [Chef](https://www.chef.io/) 와 같은 프로비저닝 툴도 아니고, [Capistrano](https://github.com/capistrano/capistrano/wiki), [Deployer](https://github.com/deployphp/deployer) 와 같은 배포 툴과도 결이 다르다. 앞서 나열한 목적이 명확한 고차원적인 애들 보다는 훨신 더 저수준 (== Low Level) 이고, 그만큼 자유도가 높다는 뜻이다. 이야기인 즉, 프로비저닝 용도로도 쓸 수 있고, 배포 용도로도 쓸 수 있고, 일반적인 관리 작업 용도로도 쓸 수 있다는 말이다. 파이썬으로 만들어진 [fabric/fabric](https://github.com/fabric/fabric) 과 가장 유사하다고 할 수 있다.\n\nEnvoy 를 사용하기 위해 가장 먼저 해야 하는 일은 Envoy 를 설치하는 일이다.\n\n```bash\n$ composer global require \"laravel/envoy=~1.0\"\n```\n\n```bash\n# 사용하는 Shell 에 따라 Profile 파일 이름은 다를 수 있다. \n# 필자는 Zshell 을 쓰므로, .zshrc 이다. e.g. .profile, .bashrc\n$ nano ~/.zshrc\n\n# composer global 로 설치한 패키지들의 실행파일을 경로에 넣어 준다.\n# 이 과정이 없다면 $ ~/.composer/vendor/bin/envoy 와 같이 전체 경로를 써주어야 한다.\nexport PATH=\"$PATH:$HOME/.composer/vendor/bin\"\n\n# 수정했다면 ctrl + X, \"Y\" 를 눌러 변경 내용을 저장하고, 엔터를 한번 더 눌러 기존 파일을 덮어 쓴다.\n \n# 그리고, 수정 내용을 현재 콘솔에 적용해 준다. 콘솔을 껐다가 다시 실행해도 된다.\n$ source ~/.zshrc\n```\n\n로컬에 설치된 Ubuntu VM을 원격 서버라 가정하고, 여기에 접속해서 터미널에서 'hello' 를 찍는 간단한 스크립트만 짜 볼 것이다. 독자들께서는 사용하시는 원격 서버의 정보를 직접 입력하여 테스트해 보시기 바란다. 여기서 재밌는 부분은 블레이드와 유사한 문법을 이용할 수 있다는 점이다.\n\n```bash\n// Envoy.blade.php\n\n@servers(['homestead' => 'homestead.vm'])\n\n@task('hello', ['on' => 'homestead'])\n  echo \"Hello Envoy!\";\n@endtask\n```\n\n필자는 원격 서버에 사용자 이름 및 키 파일 지정없이 `$ ssh 원격서버주소` 만으로 접속할 수 있도록 아래와 같이 '~/.ssh/config' 를 항상 지정한다. 이 과정이 없다면 `$ ssh -i 키파일위치 사용자이름@원격서버주소` 식으로 로그인해야 한다. '~/.ssh/config' 를 정의하자.\n\n```bash\n$ nano ~/.ssh/config\n\nHost homestead.vm\n    HostName homestead.vm\n    User vagrant\n    IdentityFile ~/.ssh/id_rsa\n    \n# 수정을 완료한 후 ctrl + X -> Y -> Enter.\n```\n\n`$ envoy run hello` 를 실행하면 아래 그림과 같이 원격 서버에 접속해서 명령을 수행하고 결과를 로컬로 다시 돌려준 것을 확인할 수 있을 것이다.\n\n![](./images/43-change-note-img-05.png)\n\n#### \\# slack 을 활용한 Error Reporting\n\n[BugSnag](https://bugsnag.com/) 과 같은 에러 관리 도구를 이용하면 좋겠지만 관리 도구는 항상 비용을 수반하게 된다. 소속한 개발팀에서 슬랙, 힙챗, 텔레그램과 같이 수시로 들여다 보는 커뮤니케이션 도구가 있다면, 원격 서버에서 발생하는 에러를 모니터링 하기에는 더 없이 좋은 도구이다. 여기서는 필자가 사용하는 [\\# slack](https://slack.com/) 을 이용할 것이다.\n\nPHP 자체는 Fatal Error 가 발생하지 않는 한 실행을 멈추지 않고 다음 코드를 실행하는 식으로 예외에 대해 관대한 편이다. 심지어 변수가 정의되지 않았을 때도 Warning 만 발생시키고 죽지 않는다. 하지만, 라라벨은 모든 Error 를 Exception 으로 던지게 구조화되어 있고, 기본기 강좌 [24강 - 예외 처리](24-exception-handling.md) 에서 살펴본 바와 같이 'app/Exceptions/Handler.php' 에서 이들을 캐치하고 있다. 즉 \\# slack 으로 예외를 보고하기 위해서는 'Handler.php' 에서 관련 코드를 추가하면 된다는 의미이다. \n\n```php\n// app/Exceptions/Handler.php\n\nclass Handler extends ExceptionHandler\n{\n    public function report(Exception $e)\n    {\n        if ($this->shouldReport($e) and app()->environment('production')) {\n            app(\\App\\Reporters\\ErrorReport::class, [$e])->send();\n        }\n        \n        //...\n    }\n}\n```\n\n그 다음은 \\# slack 메시지를 보내는 방법을 찾아야 하는데, [maknz/slack](https://github.com/maknz/slack) 와 같은 외부 라이브러리를 이용하는 방법과, 라라벨에 기본 내장된 [monolog/monolog](https://github.com/Seldaek/monolog) 를 이용하는 방법이 있다. 여기서는 maknz/slack 을 이용했다. monolog 를 이용한 구현도 'app/Reporters/MonologSlackReport.php' 에 있다.\n\n```bash\n$ composer require \"maknz/slack:1.*\"\n\n# ServiceProvider, Facade, config 등은 패키지의 문서를 참고하자.\n```\n\n위 'Handler.php' 코드에서 본 바와 같이 `ErrorReport` 란 클래스를 만들고, 거기에 `send()` 라는 API 를 정의한 것을 알 수 있다.\n \n```php\n// app/Reporters/ErrorReport.php\n\n<?php\n\nnamespace App\\Reporters;\n\nuse ...\n\nclass ErrorReport\n{\n    private $client;\n\n    private $primitive;\n\n    public function __construct(\\Exception $e, $webhook = '', $settings = [])\n    {\n        $this->primitive = $e;\n        $webhook = $webhook ?: env('SLACK_WEBHOOK');\n        $this->createClient($webhook, $settings);\n    }\n\n    public function send()\n    {\n        return $this->client->createMessage()->attach($this->buildPayload())->send();\n    }\n\n    protected function buildPayload()\n    {\n        return new Attachment([\n            'fallback' => 'Error Report',\n            'text'     => $this->primitive->getMessage() ?: \"Something broken :(\",\n            'color'    => 'danger',\n            'fields'   => [\n                new AttachmentField([\n                    'title' => 'localtime',\n                    'value' => Carbon::now('Asia/Seoul')->toDateTimeString(),\n                ]),\n                // ...\n            ],\n        ]);\n    }\n\n    protected function createClient($webhook, $overrides = [])\n    {\n        $settings = array_merge([\n            'channel'                 => '#l5essential',\n            'username'                => 'aws-demo',\n            'link_names'              => true,\n            'unfurl_links'            => true,\n            'markdown_in_attachments' => ['title', 'text', 'fields'],\n        ], $overrides);\n\n        return $this->client = new Client($webhook, $settings);\n    }\n}\n```\n\n테스트를 위해 'Handler.php' 에서 `APP_ENV == 'production'` 일 때만 리포팅 하도록 한 `if ($this->shouldReport($e) and app()->environment('production')) {` 부분을 잠깐 주석 처리 하고, `App\\Http\\Controllers\\WelcomeController::index()` 메소드에서 없는 뷰를 반환하도록 하고 홈 페이지를 방문하였다. 결과는 아래 그림과 같다.\n\n![](./images/43-change-note-img-06.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [42강 - 서버 사이드 개선](42-be-makeup.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/44-api-basic.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 46\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n**\"실전 프로젝트 2 - Forum\"** 에서 생성된 게시글/댓글을 JSON API 로 외부에 노출하여, 다양한 앱에서 \"포럼\" 을 이용할 수 있도록 서비스를 확장해 보자.\n\n## 44강 - API 기본기 및 기획\n\nRESTful API 의 이론에 대해 이해하는 시간을 가져보자.\n\n### RESTful API\n\n#### 먼저 REST 가 무엇인지 알아보자.\n\n- **RE**presentational **S**tate **T**ransfer. 대응되는 한국말 번역이 없어, 대부분 \"레스트\" 라 그냥 읽는다.\n- HTTP 의 특성을 잘 살려서 사용하는 방법에 대해, 그 창시자들이 제안한 **\"이종(異種, heterogeneous) 시스템간의 네트워크 통신 구조\"**다. 엄격하게 지켜야 하는 스펙은 아니지만, 남들, 특히 이름만 대면 아는 웹 거물들은 모두 쓰므로 꼭 써야 한다.\n- RESTful, \"레스트\" 스러운 HTTP 사용법은 [13강 - RESTful 리소스 컨트롤러](13-restful-resource-controller.md) 를 필두로 앞선 실전 프로젝트에서도 계속 사용했었다. 이 강좌를 잘 따라오신 분이라면 알게 모르게 쓰고 있었고 이미 알고 있는 개념이다.\n- REST 는 **1) Command** *(==Method. HEAD/GET, POST, PUT, ...)*, **2) Things** *(==Resource. articles, comments, ...)*, **3) Response** *(==Message. 200, 422 등의 HTTP 상태 코드와 text/html, application/json 등의 메시지 본문)*, 총 세 가지 큰 덩어리로 구성된다. \n\n#### (HTTP) API 가 무엇인지 알아보자.\n\n- API 는 시스템간의 커뮤니케이션에 사용된다. 가령, 우리가 만든 앱/서비스는 Laravel 에서 제공하는 API (e.g. `Route::resource()`) 를 이용해서 상호동작한다.\n- 이종(異種) 시스템, 가령 Ruby 로 작성된 라이브러리(==API)를 PHP 에서 쓰려면, 양쪽 언어를 다 아는 번역사, 즉 Wrapping 이 필요하다. 사람 세상이랑 참 비슷하다.\n- HTTP API 는 서로 다른 시스템간에도 커뮤니케이션을 할 수 있게 한다. 가령, iOS, Android, PC 등 다양한 플랫폼에서 다양한 언어로 구현된 클라이언트가 우리 API 와 데이터를 주고 받을 수 있다. \n\n#### 종합해 보면. \n\n영어가 공용어인것 처럼, HTTP 가 다양한 시스템에서 워낙 많이 쓰이기 때문에 거의 공용어 처럼 통한다라고 보면 된다. 모두 종합해 보면, **\"서로 다른 시스템간에 네트워크를 경유해서 데이터를 교환할 때 HTTP API 라는 것을 이용하는데, 아무렇게나 짜는 게 아니라, 기계 뿐 아니라 사람이 이해하기 쉽도록, 모두가 사용하고 권장하는 형태인 REST 원칙을 따르도록 짠 API\"** 가 **\"RESTful API\"** 인 것이다.\n\n### RESTful API 베스트 프랙티스\n\n아래는 [10 Best Practices for Better RESTful API](http://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/) 및 필자의 [RESTful API 제대로 개발하기](http://www.slideshare.net/ssuser7887b3/restful-api) 를 종합해서 정리한 내용이다. 실전 프로젝트를 진행하면서 하나씩 다시 보겠지만, 여기서 한번 정리하고 필요할 때 마다 돌아와서 잘 지키고 있는지 점검하기 위한 목적으로 나열해 본다.\n\n1.  Resource 는 명사를 쓴다. \n\n    [13강 - RESTful 리소스 컨트롤러](13-restful-resource-controller.md) 에서 배운 내용을 다시 한번 리마인드 하자. 대신 테이블 형태를 약간 바꾸었다. 여기서 Resource 란 클라이언트 사이드에서 보이는 요소인 URI Endpoint 를 의미한다. 물론 URI 뒤에는 모델이 있는데 클라이언트에게 보이진 않는다.\n    \n    Type|Resource|GET(Read)|POST(Store)|PUT(Update)|DELETE(Destroy)\n    ---|---|---|---|---|---\n    콜렉션|/articles|Article 목록|새 Article 만들기|`405 MethodNotAllowed`|`405 MethodNotAllowed`\n    인스턴스|/articles/{id}|id 를 가진 Article 상세 보기|`405 MethodNotAllowed`|id 를 가진 Article 수정|id 를 가진 Article 삭제\n    \n    **`참고`** API 에서는 HTML 뷰를 응답하는 경우가 없으므로, 'GET /articles/create', 'GET /articles/{id}/edit', 2 개의 Endpoint 는 필요 없다.\n    \n    **`ANTI-PATTERN`** Rosource 이름 (==Endpoint) 에 동사를 쓰지 않는 것이 좋다.\n    \n    ```\n    GET /getAllArticles\n    GET /getArticles?id={id}  \n    POST /createArticles\n    POST /updateArticle?id={id}\n    POST /deleteArticles?id={id}\n    ```\n    \n2.  적절한 HTTP 동사 (==Method) 를 사용한다.\n\n    Resource 의 상태를 변경할 때는 `POST`, `PUT`, `DELETE` 메소드를 사용한다.\n     \n    **`ANTI-PATTERN`** 잘못된 메소드 사용이 불러올 재앙.\n     \n    > My favorite WTF story is using a GET verb to delete resources. Which was interesting when Google crawled the API. <small>by Jamie Hannaford</small><br>\n    > 리소스 삭제를 위한 API Endpoint 를 DELETE 대신 GET 메소드로 정의했다. 구글 검색엔진 크롤러가 방문할 때 마다, 서비스는 안드로메다로 간다.\n     \n3. Resource 이름은 복수를 사용하고, 일관된 대소문자 규칙을 적용할 것을 권장한다.\n \n    1 번의 예에서 article 보다는 articles 가 더 낫다. Resource 이름 뿐 아니라, 필드명에서도 Snake case (e.g. snake_case), Camel case (e.g. camelCase), Dash case (e.g. dash-case) 를 일관되게 사용하자. \n    \n    ```\n    /article 보다는 /articles\n    /comment 보다는 /comments\n    ```\n    \n    **`ANTI-PATTERN`** 대소문자 혼용 사례.\n    \n    ```javascript\n    // GET /push_messages\n    {\n      \"total\": 1540,\n      \"perPage\": 10,\n      \"current-page\": 1,\n      \"data\": [\"...\"]\n    }\n    ```\n\n4.  Resource 간 관계를 노출해야 할 경우에는 Resource 를 중첩 (==Nesting) 한다.\n    \n    ```\n    GET /tags/{id}/articles\n    ```\n\n5.  복잡한 것들은 모두 물음표 (?) 뒤에 둔다.\n      \n    -   필터\n        \n        ```\n        GET /articles?filter=notsolved\n        ```\n        \n    -   정렬\n    \n        ```\n        GET /articles?sort=view_count&direction=asc\n        ```\n        \n    -   페이징\n    \n        ```\n        GET /articles?page=2\n        ```\n        \n    -   필드 선택\n    \n        모바일에서 트래픽은 곧 사용자의 돈이다. 클라이언트가 꼭 필요한 필드만 요청할 수 있는 방법을 제공하는 것은 좋은 API 디자인이다.\n    \n        ```\n        GET /articles?fields=id,title\n        ```\n                \n6.  Content/Language Negotiation\n\n    응답을 받고자 하는 데이터 형태 (==Content-Type) 와 언어는 HTTP 헤더를 이용해서 주고 받는다.\n    \n    ```\n    // Request\n    GET /articles<br/>\n    Accept: application/json\n    Accept-Language: ko-KR\n    ```\n    \n    ```\n    // Response\n    HTTP/1.1 200 OK\n    Content-Type: application/json\n    ```\n    \n    **`참고`** Resource 이름 뒤에 확장자를 붙여 Content Negotiation 을 하는 프레임웍도 있다 (e.g. /articles.json, /articles.xml). Anti-pattern 이라고는 할 수 없지만, 이 경우 API Endpoint 자체가 프레임웍에 의존성을 가지게 된다. 가령 /articles.json 을 그대로 두고, 백엔드 프레임웍을 다른 것으로 변경하고자 한다면, 확장자에 따른 Content Negotiation 로직을 별도로 구현해 주어야 한다. \n    \n7.  하위 또는 관련 리소스를 쉽게 찾을 수 있는 링크를 제공한다. (==HATEOAS)\n    \n    HTML 의 경우 메뉴나 링크로 다른 페이지로 이동할 수 있는 방법을 제공하고 있다. 반면에, API 는 달랑 데이터만 제공하기 때문에, API 를 사용하는 사람이나 기계가 다음에 무엇을 해야 하고, 어디로 가야할 지 전혀 알 수가 없다. 이를 해결하기 위한 방안으로 제시된 것이 HATEOAS (Hypermedia as the Engine of Application State) 이다.\n    \n    ```javascript\n    // GET /articles\n    {\n      data: [\n        {\n          id: 1,\n          title: \"...\",\n          links: [\n            rel: \"self\",\n            href: \"http://api.example.com/v1/articles\"\n          ]\n          author: {\n            id: 5,\n            name: \"...\",\n            links: [\n              rel: \"self\",\n              href: \"http://api.example.com/v1/users/5\"\n            ]\n          }\n        },\n        {\"...\"}\n      ]\n    }\n    ```\n\n8.  API 버전\n    \n    HTML 페이지의 경우에는 코드 배포만 하면, 사용자는 언제든지 최신 코드를 이용하게 된다. 반면, API 의 경우에는 클라이언트와 서버가 완전히 분리 (==Decoupling) 된다. 즉, 서버 사이드에서 API 를 변경하더라도, 클라이언트는 여전히 **정상적인 동작을 기대하면서** 변경 전 API 를 이용할 수 있다는 의미이다. 점진적 마이그레이션을 위해서 API 버저닝은 꼭 필요하고, 처음에 '/articles' 로 Endpoint 를 만든후, 변경되면 '/v2/articles' 로 가지 말고, 반드시 처음 부터 '/v1/articles' 로 만들 것을 권장한다.\n       \n    ```\n    GET http://api.example.com/v1/articles\n    GET http://example.com/api/v1/articles\n    ```\n   \n9.  적절한 HTTP 응답 코드를 사용하자.\n    \n    꽤 큰 회사/서비스 임에도 불구하고 에러일 경우에도 200 응답 코드를 사용하는 경우를 많이 봤다. HTTP 응답 코드는 괜히 있는 것이 아니며, 200 만 쓰는 것은 REST 원칙에도 어긋난다. 아래는 HTTP API 에서 주로 사용하는 응답 코드이다.\n    \n    ```\n    200 - Ok                                // 성공\n    201 - Created                           // 새로운 리소스 생성 요청에 대한 응답                     \n    204 - No Content                        // 리소스 삭제 요청 성공 등에 사용\n    304 - Not Modified                      // 클라이언트에 캐시된 리소스 대비 서버 리소스의 변경이 없을 때 \n    400 - Bad Request                       // 클라이언트 쪽에서 뭔가 잘못했을 때\n    401 - Unauthorized                      // 인증 필요 (실제로는 Unauthenticated 의 의미)\n    403 - Forbidden                         // 권한 부족 (실제로는 Unauthorized 의 의미)\n    404 - Not Found                         // 요청한 리소스가 없을 때\n    405 - Method Not Allowed                // 서버에 없는 Endpoint 일 때\n    406 - Not Acceptable                    // Accept* 헤더 또는 본문의 내용이 수용할 수 없을 경우 \n    409 - Conflict                          // 기존 리소스와 충돌\n    410 - Gone                              // 404 가 아니라, 리소스가 삭제되어 응답을 줄 수 없을 경우\n    422 - Unprocessable Entity,             // 유효성 검사 오류 등에 사용\n    429 - Too Many Requests,                // Rate Limit 에 걸렸을 경우\n    500 - Internal Server Error             // 서버 쪽 오류\n    503 - Service Unavailable               // 점검 등으로 서버가 일시적으로 응답할 수 없는 경우\n    ```\n    \n    클라이언트 측 개발자가 잘 이해할 수 있는 에러 내용도 같이 담아 주는 것이 좋다.\n    \n    ```javascript\n    {\n      \"errors\": {\n        \"code\": 422,\n        \"message\": [\n          \"title\": \"The title filed is required\" \n        ]\n        \"dict\": http://api.example.com/v1/docs#errors422\n      }\n    }\n    ```\n\n10. HTTP 메소드 오버라이드\n    \n    [13강 - RESTful 리소스 컨트롤러](13-restful-resource-controller.md) 에서 이미 설명한 바 있는 내용이다. 모던 브라우저 또는 네트워크 프록시들이 GET, POST 메소드만 이해하기 때문에 PUT, DELETE 메소드를 사용할 때는 `_method=put` 과 같이 사용해야 한다고.. 라라벨은 `X-HTTP-Method-Override` HTTP 헤더를 이용한 메소드 오버라이드도 지원한다.\n    \n    ```\n    POST /articles\n    ---payload---\n    _method=PUT&title=...&content=...\n    ```\n    \n    or\n    \n    ```\n    POST /articles\n    X-HTTP-Method-Override=PUT\n    ---payload---\n    title=...&content=...\n    ```\n\n### 어떤 기능을 가질 것인가?\n    \n- 앞서 베스트 프랙티스라고 나열한 기능은 모두 구현해 보자.\n- 기존과 다른 것은 응답의 형태 뿐이다. 앞 강에서 구현한 컨트롤러를 최대한 활용하자.\n- 뷰 뒤에 숨은 데이터가 아니다. 여기서는 데이터가 서비스이다. 데이터 Transform/Serialization 을 지원한다.\n- JWT (==JSON Web Token) 을 이용한 사용자 인증을 지원한다.\n- Rate Limit 를 구현한다.\n- 보안 목적으로 Auto-increment ID 를 숨길 것이다.\n- 브라우저 클라이언트를 위해 CORS (Cross Origin Resource Sharing) 기능을 지원한다.\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [45강 - 기본 구조 잡기](45-api-big-picture.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/45-api-big-picture.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 47\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 45강 - 기본 구조 잡기\n\n앞 강좌에서 기획한 내용을 가장 잘 수용할 수 있는 기본 구조를 잡아보자. 한 방에 완벽할 수는 없기에, 진행하면서 구조는 변경될 수도 있음을 감안하자.\n\n### 단일 서버 vs. 복수 서버\n\n대형 서비스의 경우, API 를 위해 물리적으로 분리된 별도의 서버를 두고, 데이터베이스를 공유하는 식의 아키텍처를 사용하기도 한다. 예를 들면, 서버 A 에 HTML 뷰와 RedirectResponse 를 응답하는 라라벨 어플리케이션을 구동하고, 서버 B 에 API 요청에 응답하는 라라벨 어플리케이션을 두는 식이다. 이 구조에서는 데이터 무결성 확보 등 신경 쓸 일이 굉장히 많아진다.\n\n이 실전 프로젝트에서는 단일 서버, 단일 라라벨 프레임웍을 사용하되, API 를 위한 엔트포인트만 별도의 도메인인 `api.myproject.dev` 로 분리하도록 하자. \n\n### 도메인 설정\n\n앞서 얘기했듯이 `myproject.dev` 와 `api.myproject.dev` 란 도메인을 만들어 보자. 실제로 도메인 서비스에 등록하는 것은 아니고, 로컬에서 'hosts' 파일을 변경하도록 하자. \n\n**`참고`** 운영체제에 포함된 'hosts' 파일은 DNS 로 api.myproject.dev 또는 myproject.dev 에 대한 ip 주소 Resolution 요청이 나가기 전에 요청을 낚아 채서, 'hosts' 파일 안에서 찾는다. 사용자가 요청한 도메인에 해당하는 레코드가 있으면 지정된 ip 주소로 이동할 것이다. 쓸데 없는 얘기긴한데... 보통 인터넷을 통해 라이센스 인증을 받는 상용소프트웨어의 경우, 이 hosts 파일을 이용해서 인증 서버에 해당하는 도메인을 로컬 주소로 바꾸고, 로컬 서버에서 인증된 것 처럼 꾸며 어둠의 소프트웨어를 사용할 수 있게 한다.\n\n```bash\n# Mac/Linux\n$ sudo nano /etc/hosts\n\n# Windows (코맨드프롬프트를 관리자 권한으로 실행해야 한다.)\n\\> notepad %SystemRoot%\\System32\\drivers\\etc\\hosts\n```\n\n```bash\n# /etc/hosts\n\n127.0.0.1   myproject.dev\n127.0.0.1   api.myproject.dev\n\n# ctrl + x, Y, Enter 순으로 변경 내용 저장\n# Homestead 를 쓰신다면, 192.168.10.10 으로 해 주어야 한다.\n```\n\n로컬 서버를 띄울 때, 이전과는 명령이 달라졌으니 잘 기억해 두자. 어떻게 알았냐고? `$ php artisan help serve`.\n\n```bash\n$ php artisan serve --host=myproject.dev\n```\n\n브라우저를 열고 'http://myproject.dev:8000' 으로 접근해서 앞 강좌에서 개발한 페이지가 보이는 지 확인하자.\n\n### Routing\n\n도메인이 만들어 졌으니 신나게 Routing 을 정의해 보자. `Route::group()` 의 첫번째 배열 인자 안에 `domain`, `namespace`, `as` 를 썼다. `domain` 에 매칭되는 요청이 들어오면 이 Routing 블럭이 응답하게 된다. `Route::group()` 내부에서 컨트롤러를 연결시킬 때 매번 `'Api\\WelcomeController@index'` 식으로 네임스페이스를 붙여주어야 하는 번거로움을 덜기 위해, `namespace` 라는 키워드를 사용한다. `'as' => 'api.'` 은 Route 이름 앞에 'api.' 을 붙이기 위해 사용하였다.\n\n도메인 이름을 '.env' 파일의 `API_DOMAIN` 값으로 지정했는데, 이는 프로덕션으로 배포할 때마다 Route 파일을 고쳐서 배포해야 하는 번거로움을 피하기 위해서다.\n\n`Route::group()` 안에 또 다른 `Route::group()` 이 중첩되어 있다. 두번 째 `Route::group()` 은 'http://api.myproject.dev:8000/v1' 요청에 응답하기 위한 것이다. 그래서 `'prefix' => 'v1'`, `'namespace' => 'V1'` 을 정의하고 있다.\n\n```php\n// app/Http/routes.php\n\nRoute::group(['domain' => env('API_DOMAIN'), 'as' => 'api.', namespace' => 'Api'], function() {\n    Route::get('/', [\n        'as'   => 'index',\n        'uses' => 'WelcomeController@index'\n    ]);\n    \n    Route::group(['prefix' => 'v1', 'namespace' => 'V1'], function() {\n        /* Landing page */\n        Route::get('/', [\n            'as'   => 'v1.index',\n            'uses' => 'WelcomeController@index'\n        ]);\n    ]);\n}\n\n// 기존 Routing ...\nRoute::group(['domain' => env('APP_DOMAIN')], function() {\n    Route::get('/', [\n        'as'   => 'index',\n        'uses' => 'WelcomeController@index',\n    ]);\n});\n```\n\n사용자 인증을 위한 Routing 들인, 'auth/register', 'auth/login', 'auth/remind' 들도 정의하도록 하자. 유의할 점은 API 클라이언트와 데이터만으로 통신을 하기 때문에, 뷰를 반환하는 Route 는 필요없다는 점이다. 그리고, 비밀번호 초기화 기능에서는 사용자의 이메일 주소를 받아서 Reset 토큰을 메일로 보내는 Route 만 제공하고, 그 이후 프로세스는 API 클라이언트와 분리된 메일 클라이언트에서 이루어 지므로 Route 를 제외 했다.\n\n### 컨트롤러\n\n앞 절에서 봤듯이 `Api` 란 네임스페이스를 이용하고 있다. 'app/Http/Controllers/Api' 디렉토리를 만들자. 방금 만든 디렉토리에 기존에 만들었던 'WelcomeController.php' 를 복사하고 아래와 같이 내용을 변경하자.\n\n'/v1' 요청에 응답하기 위한 'WelcomeController.php' 도, 아래 내용을 참고해서 'app/Http/Controllers/Api/V1' 디렉토리 아래에 만들도록 하자.\n\n```php\n// app/Http/Controllers/Api/WelcomeController.php\n\n<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Http\\Controllers\\Controller;\n\nclass WelcomeController extends Controller\n{\n    public function index()\n    {\n        return response()->json([\n            'name'    => 'myProject Api',\n            'message' => 'Welcome to myProject Api. This is a base endpoint.',\n            'version' => 'n/a',\n            'links'   => [\n                [\n                    'rel'  => 'self',\n                    'href' => route(\\Route::currentRouteName())\n                ],\n                [\n                    'rel'  => 'api.v1.index',\n                    'href' => route('api.v1.index')\n                ],\n            ],\n        ]);\n    }\n}\n```\n\n브라우저로 테스트를 해도 되는데, API 이니까 [PostMan 크롬 확장 프로그램](https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop) 을 이용하자. 'GET http://api.myproject.dev:8000' 요청을 해 보자. 현재 컨트롤러는 무조건 JSON 만 응답하기 때문에 `Accept` HTTP Header 는 필요없지만, 좋은 습관이니 `application/json` 으로 지정하도록 하자. \n\n![](./images/45-api-big-picture-img-01.png)\n\n### DRY 구조 설계\n\nDRY (==Don't Repeat Yourself) 는 코드의 재사용을 의미한다. \n\n우리는 기존에 개발한 컨트롤러들을 재활용할 것이다. 잘 생각해 보면, 기존에 개발한 컨트롤러 로직에서 API 서비스를 위해 변경되어야 하는 부분은 HTTP 응답 부분 뿐이다. 기존 컨트롤러에서는 뷰 (`\\Illuminate\\Contracts\\View\\Factory`) 또는 Redirect (`\\Illuminate\\Http\\RedirectResponse`) 를 응답했다면, API 컨트롤러들에서는 JSON 응답 (`\\Illuminate\\Http\\JsonResponse`) 을 반환하는 부분만 달라진다. 그래서, 기존 컨트롤러에서 뷰 또는 Redirect 를 응답하는 부분을 별도 메소드로 빼내고, API 컨트롤러들은 기존 컨트롤러를 일대일로 상속받되, 방금 추출한 응답 메소드만 오버라이드하면 깔끔할 것 같다. \n\n**`참고`** PHP 에서는 오버로딩을 지원하지 않는다. 오버로딩은 부모 메소드와 같은 이름을 가지지만, 인자도 다를 수 있고 내부에서 완전히 다른 동작을 하고 완전히 다른 결과를 반환하는 반면, 오버라이드는 인자의 타입과 갯수가 부모와 정확히 같아야 하고, 내부의 동작만 다른 것을 의미한다. 대신 PHP에서는 반환값에 대한 타입 정의가 없어서 부모를 오버라이드한 자식 클래스의 메소드에서 반환값의 타입을 다르게 쓸 수 있다. (PHP 7에서는 부모 클래스에 반환값 타입이 선언되어 있으면, 자식 클래스에서 반환값 타입을 오버로딩을 할 수 없다.)\n\n#### abstract 컨트롤러\n\n기존 컨트롤러들이 상속을 받고 있는 abstract 컨트롤러인 `App\\Http\\Controllers\\Controller` 에서 뷰에 공용 변수를 셋팅하는 부분은 Api 컨트롤러에서는 필요 없다.\n\n```php\n// app/Http/Controllers/Controller.php\n\nabstract class Controller extends BaseController\n{\n    public function __construct() {\n        if (! is_api_request()) {\n            $this->setSharedVariables();\n        }\n    }\n\n    // ...\n}\n```\n\n`is_api_request()` 란 Helper 는 쓰일 일이 많을 것 같아서 만들었다.\n\n```php\n// app/helpers.php\n\nfunction is_api_request()\n{\n    return starts_with(Request::getHttpHost(), env('API_DOMAIN'));\n}\n```\n \n#### 기존 컨트롤러 리팩토링\n\n기존 컨트롤러에서 뷰 또는 Redirect 를 응답하는 부분을 메소드로 추출 (==Extract) 해 내자. 'routes.php' 에 정의한 대로 오늘 강좌의 대상이 되는 컨트롤러는 `UsersController`, `SessionsController`, `PasswordsController` 등이다. 몇 개만 같이 살펴보고, 나머지는 코드를 참조하기 바란다.\n\n```php\n// app/Http/Controllers/UsersController.php\n\nnamespace App\\Http\\Controllers;\n\nclass UsersController extends Controller\n{\n    protected function syncAccountInfo(Request $request, User $user)\n    {\n        // ...\n\n        if ($validator->fails()) {\n            return $this->respondValidationError($validator);\n        }\n\n        // ...\n\n        return $this->respondCreated($user);\n    }\n    \n    protected function respondValidationError(Validator $validator)\n    {\n        return back()->withInput()->withErrors($validator);\n    }\n\n    protected function respondCreated(User $user)\n    {\n        \\Auth::login($user);\n        flash(trans('auth.welcome', ['name' => $user->name]));\n\n        return redirect(route('home'));\n    }\n}\n```\n\n```php\n// app/Http/Controllers/Api/UsersController.php\n\nnamespace App\\Http\\Controllers\\Api;\n\nclass UsersController extends ParentController\n{\n    protected function respondValidationError(Validator $validator)\n    {\n        return response()->json([\n            'code' => 422,\n            'errors' => $validator->errors()->all()\n        ], 422);\n    }\n\n    protected function respondCreated(User $user)\n    {\n        // Todo 로그인 하는 대신 JSON Web Token 을 응답할 것이다.\n        return response()->json([\n            'code' => 201,\n            'message' => 'success',\n            'token' => 'token here',\n        ], 201);\n    }\n}\n```\n\n![](./images/45-api-big-picture-img-02.png)\n\n대충 감이 잡히는가? 하나만 더 살펴 보자.\n\n```php\n// app/Http/Controllers/SessionsController.php\n\nnamespace App\\Http\\Controllers;\n\nclass SessionsController extends Controller\n{\n    public function store(Request $request)\n    {\n        // ...\n        \n        if ($validator->fails()) {\n            return $this->respondValidationError($validator);\n        }\n\n        // API 에서는 쿠키를 이용한 세션 유지 (로그인)을 하지 않기에\n        // attempt() 메소드를 쓰지 않고 once() 메소드를 이용하였다.\n        // Auth::once() 는 JWT 인증으로 대체될 것이다.\n        $valid = is_api_request()\n            ? Auth::once($request->only('email', 'password'))\n            : Auth::attempt($request->only('email', 'password'), $request->has('remember'));\n\n        if (! $valid) {\n            return $this->respondLoginFailed();\n        }\n\n        event('users.login', [Auth::user()]);\n\n        return $this->respondCreated($request->input('return'));\n    }\n    \n    // ...\n        \n    protected function respondValidationError(Validator $validator)\n    {\n        return back()->withInput()->withErrors($validator);\n    }\n\n    protected function respondLoginFailed()\n    {\n        flash()->error(trans('auth.failed'));\n\n        return back()->withInput();\n    }\n\n    protected function respondCreated($return = '')\n    {\n        flash(trans('auth.welcome', ['name' => Auth::user()->name]));\n\n        return ($return) ? redirect(urldecode($return)) : redirect()->intended();\n    }\n}\n```\n\n```php\n// app/Http/Controllers/Api/SessionsController.php\n\nnamespace App\\Http\\Controllers\\Api;\n\nclass SessionsController extends ParentController\n{\n    protected function respondValidationError(Validator $validator)\n    {\n        return response()->json([\n            'code' => 422,\n            'errors' => $validator->errors()->all()\n        ], 422);\n    }\n\n    protected function respondLoginFailed()\n    {\n        return response()->json([\n            'code' => 401,\n            'errors' => 'invalid_credentials'\n        ], 401);\n    }\n\n    protected function respondCreated($return = '')\n    {\n        // Todo 로그인 하는 대신 JSON Web Token 을 응답할 것이다.\n        return response()->json([\n            'code' => 201,\n            'message' => 'success',\n            'token' => 'token here',\n        ], 201);\n    }\n}\n```\n\n대충 보기에도, `respondValidationError()`, `respondCreated()` 등등 엄청난 중복이 보인다. 앞으로 진행될 강좌에서 중복들은 제거할 것이다. \n\n**`참고`** API 클라이언트에서 소셜 로그인은 각 클라이언트 플랫폼에 맞는 SDK 를 이용해야 한다. 가령, Android 에서 Github 로그인을 지원한다면 [`wuman/android-oauth-client`](https://github.com/wuman/android-oauth-client) 와 같은 라이브러리를 이용하여 소셜 로그인을 구현한다. 그런데, Github 에서 받은 Oauth access_token 으로 Github 리소스에 접근하는 것이 아니다. 즉, 소셜 로그인은 소위 말하는 실명 확인 정도, 사용자 등록에 대한 거부감을 좀 덜어 주는 정도의 용도로만 사용하고 있다. 우리 서버의 리소스에 접근하기 위해서는 우리 서버에서 클라이언트 요청의 유효성을 인증 받을 수 있는 방법이 있어야 한다. Android Native SDK 를 이용한 소셜 인증은 받되, 가령 `onSuccess` Callback 을 받는 부분에서 서버와 인터랙션을 해야 할 것으로 생각된다. 어쩌면, 서버 측에서 이를 위한 새로운 Route 를 제공해야 할 수도 있을 것 같다. 진행하면서 같이 고민해 보자.\n \n**`참고`** `logout()` 메소드/기능은 API 클라이언트에서는 필요하지 않다. 정당한 사용자로 부터의 API 요청인지를 서버 사이드에서 인증하는 방법으로 Oauth 또는 JWT 를 주로 사용하는데, 두 방법 모두 token 을 HTTP 요청에 포함해서 보낸다. token 이 없으면 로그인 과정을 거치지 않은 것으로 간주되고, token 이 만료되면 역시 로그인하지 않은 것으로 간주되므로 로그아웃이 필요하지 않다는 의미이다. 물론, `logout()` 기능을 제공하고, 정해진 토큰 만료 시간 이전에 토근을 강제로 삭제하거나 블랙리스트에 넣어 놓는 방법이 있기는 하지만, 필자 생각에 지금 당장은 필요성을 못 느끼겠다.  \n\n### CSRF\n\n사용자 인증을 위해 JSON Web Token 을 사용할 것이다. 앞으로 곧 보겠지만, 모든 API 요청의 HTTP 헤더에는 `Authorization: Bearer {header.payload.signature}` 형태의 JWT 를 붙여서 보내야 하고, 이를 통해 사용자를 인식할 뿐 아니라, CSRF 와 같은 악의적인 공격으로 부터 방어할 것이다. 바꾸어 말하면 API 에서 CSRF 토큰 사용은 적절하지 않다는 말. 왜일까 잘 생각해 보면, API 에서는 HTML \"폼\"를 서버에서 클라이언트에 내려 주지 않기 때문에 서버에서 생성한 CSRF 토큰을 전달할 방법이 없다.\n\n역시 [13강 - RESTful 리소스 컨트롤러](13-restful-resource-controller.md) 에서, 특정 Route 에 대해서 글로벌 미들웨어로 등록된 CSRF 를, `$except = []` 속성을 이용해서 제외시키는 방법을 살펴본 바 있다. 그런데, 이번에는 조금 특수하다. 기존 Route 와 API Route 가 동일한 형태이기 때문이다. 가령 로그인의 경우 'http://myproject.dev:8000/auth/login', 'http://api.myproject.dev:8000/auth/login' 으로 Route 에 정의된 'auth/login' Path 는 동일하기 때문이다. 둘 간에 서로 다른 부분은 도메인이라는 점에 착안해서, 필자는 아래 처럼 API 요청일 경우 CSRF 토큰 검사를 넘어가는 식으로 구현했다.\n  \n```php\n// app/Http/Middlewares/VerifyCsrfToken.php\n\nclass VerifyCsrfToken extends BaseVerifier\n{\n    public function handle($request, Closure $next)\n    {\n        if (is_api_request()) {\n            return $next($request);\n        }\n\n        return parent::handle($request, $next);\n    }\n}\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [44강 - API 기본기 및 기획](44-api-basic.md)\n- [46강 - JSON Web Token 을 이용한 인증](46-jwt.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/46-jwt.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 48\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 46강 - JWT 를 이용한 인증\n\n### HTTP Stateless 특성에 대한 이해\n\nHTTP 의 가장 큰 특징은 무상태 (==Stateless) 이다. 무슨 의미냐하면, 클라이언트 A 에서 Request A 와 Request B 를 했을 때, 서버 입장에서는 Request A 와 B 가 같은 클라이언트 A 로 부터의 요청인지 알 수 없다는 것이다. 공용 컴퓨터가 아닌 이상 \"클라이언트\"는 \"사용자\"랑 동일한 의미이다. 그럼, 서버에서 사용자를 어떻게 인식하는가? 라는 의문이 생긴다.\n  \nRequest A 와 B 가 같은 클라이언트라는 것을 서버에게 말하는 방법은 Cookie 를 이용하거나 Url Paremeter (http:://example.com/?user=foo) 를 이용하는 방법 등이 있을 것이다. 그런데, 문제는 클라이언트 쪽에서 사용자의 신분을 조작하기가 너무 쉽다는 것이다.\n\n이 문제를 해결하기 위해, HTTP 를 다루는 웹 서버 및 웹 프레임웍에서는 세션이라는 개념을 사용한다. 서버에서 Request A 에 대해서 고유한 세션 'key=foo' 를 생성하고, 클라이언트 A 에게 알려주면, 클라이언트 A 는 Request B 를 날릴 때 'key=foo' 를 달아서 \"난 Request A 를 했던 클라이언트와 같은 놈이요\" 라고 서버에게 말하는 식이다. 클라이언트 A 에서 사용자 'john@example.com' 이 자신의 신분을 서버에게 밝히면, 서버는 자신의 저장장치에서 사용자 'john@example.com' 의 신분을 확인하고 세션 정보에 기록해 두어 사용자까지도 인식하는 것이다. 이 과정을 우리는 흔히 \"로그인\"이라 한다.\n\n실전에서 세션은 서버에서 생성되고, 클라이언트와 HTTP Cookie 메커니즘을 이용해서 교환된다. 아래 그림을 보자. \n\n![](./images/46-jwt-img-01.png)\n\n### API 인증 방법\n\n위 그림은 브라우저의 경우이다. 브라우저는 쿠키를 파싱하여 내부 저장소에 보관하고, 다음 요청때 저장된 쿠키가 만료되지 않았다면 달아서 보내는 동작을 한다. \n\n그런데, API 컨텍스트에서는 클라이언트가 꼭 브라우저라 할 수 없다. Android/iOS/PC 와 같은 다양한 플랫폼이 API 서버에 접속하게 되며, 심지어는 CURL 과 같은 콘솔형 HTTP Client 가 될 수도 있는데, 위에서 설명한 쿠키 메카니즘이 동작한다고 보장할 수 없다.\n\n그래서, 일반적으로 아래와 같은 방법으로 API 클라이언트로 부터의 요청에 대한 유효성 검사를 수행한다.\n \n1.  HTTP Basic 인증\n    \n    클라이언트에서 API 서버에 리소스 요청을 할 때, `Authorization: Basic xyz` 를 달아서 보내는 식이다. 여기서 'xyz' 는 `base64_encode('john@example.com:password')` 처럼, 사용자 인증을 위한 username:password 를 Base64 인코딩한 문자열이다. 이 방식의 좋은 점은 사용하기 쉽다는 점인데, 나쁜점은 보안에 굉장히 취약하다는 점이다. 네트워크 구간에서 탈취되면 그냥 빵 털리고, 서비스는 안드로메다로 가게 된다. https 를 이용하여 HTTP Header 의 탈취를 원천 봉쇄하는 방법이 있기는 하나, username 및 password 대한 만료 기간도 없고, 클라이언트 앱이 사용자 인증을 위한 정보를 어딘가에 저장을 해야한다는 위협도 존재한다.  \n      \n    ```bash\n    $ php artisan tinker\n    >>> base64_encode('john@example.com:password');\n    => \"am9obkBleGFtcGxlLmNvbTpwYXNzd29yZA==\"\n    >>> base64_decode('am9obkBleGFtcGxlLmNvbTpwYXNzd29yZA==');\n    => \"john@example.com:password\"\n    ```\n\n    **`참고`** 따지고 보면, HTML 폼을 이용한 사용자 인증도 마찬가지다. 따라서, 보안 전문가들은 https 를 항상 권장한다. 다만, API 와 달리 HTML 폼에서는 로그인을 위한 POST 요청때만 사용자 정보가 평문으로 날아간다. https 을 위한 SSL 인증서가 돈이기 때문에, 보안과 비용 사이에서 의사결정을 해야 한다. 해커들 입장에서도 사용자가 좀 되어야 털 이유가 있으니, SSL 인증서 도입 시기를 적절하게 결정해야 한다. \n\n2.  Oauth 인증\n\n    조대협님의 [REST API 의 이해와 설계 #3 API 보안](http://bcho.tistory.com/955) 편을 읽어 보자. 이 강좌에서 Github 를 이용한 소셜 인증에 적용된 기술이 Oauth2 이다. API 사용자 인증을 위해 자체 Oauth 인증 서버를 구축하고자 한다면 [`league/oauth2-server`](https://github.com/thephpleague/oauth2-server) 를 이용하자. 단점은 복잡하고 무겁다는 점이다. 이름만 대면 아는 대형 서비스들은 대부분 Oauth 를 이용한다는 점을 기억하자. 사용자가 많아 지면, 1 번이나 3 번으로 부터 적절한 시기에 Oauth 로 마이그레이션을 해야 한다.\n\n\n3.  JWT 인증\n\n    역시 조대협님의 [REST JWT 소개 #1 개념 소개](http://bcho.tistory.com/999) 을 읽어 보시기 바란다. 한마디로 말하자면, 사용자를 인식하기 위한 정보 (e.g. 사용자 ID) 가 이미 담겨 있는 변조가 불가능한 토큰이라 할 수 있다. 클라이언트가 API 서버에 리소스를 요청할 때 이 토큰을 `Authorization: Bearer header.payload.signature` 와 같은 HTTP Header 로 전달하고, 서버는 이 값을 해독하여 사용자를 인식하는 방식이다. 1 번과 2 번 사이에 있는, 즉, 무겁지 않지만 보안에도 강한 방식이라 할 수 있다.\n\n\n### JWT 패키지 \n\n스펙을 이해하고 JWT 를 직접 구현한다는 것은 엄청난 일이다. 이미 만들어진, 그리고 커뮤니티에서도 검증된 [`tymon/jwt-auth`](https://github.com/tymondesigns/jwt-auth) 패키지를 끌어 와서 사용하자.\n \n#### 설치\n \n```bash\n$ composer require \"tymon/jwt-auth:0.5.*\"\n```\n\n패키지 매뉴얼에 써진대로 서비스 프로바이더와 Facade 를 추가하자.\n\n```php\n// config/app.php\n\n'providers' => [\n    // ...\n    Tymon\\JWTAuth\\Providers\\JWTAuthServiceProvider::class,\n],\n\n'aliases' => [\n    // ...\n    'JWTAuth' => Tymon\\JWTAuth\\Facades\\JWTAuth::class,\n    'JWTFactory' => Tymon\\JWTAuth\\Facades\\JWTFactory::class,\n];\n```\n\n패키지에서 제공하는 config 파일을 배포하고, 암호화 알고리즘에 사용할 씨드 키를 생성하자.\n\n```bash\n$ php artisan vendor:publish --provider=\"Tymon\\JWTAuth\\Providers\\JWTAuthServiceProvider\"\n$ php artisan jwt:generate\n```\n\n#### 설정\n\n설정 파일을 열어 보면..\n\n```php\n// config/jwt.php\n\nreturn [ \n    'ttl' => 120,\n    'refresh_ttl' => 20160,\n    'identifier' => 'id',\n    // ...\n];\n```\n\n중요한 설정만 살펴 보자.\n\n-   `ttl` 은 토큰의 유효 기간을 위한 설정이다. 120 이라고 한 것은 2 시간을 뜻하며, 토큰을 발행하고 난 이후 2 시간 동안 클라이언트와 서버간에 한번이라도 성공적인 인증이 없었다면 토큰은 만료된다는 의미이다. 바꾸어 말하면, 2시간 내에 한번이라도 서버에서 발급한 토큰을 이용하여 클라이언트가 서버 측에 `Authorization: Bearer header.payload.signature` HTTP Header 를 달아서 리소스 요청을 했고, 인증에 성공했다면 그 시점으로 부터 다시 2 시간 동안 토큰이 유효해진다는 의미이다.\n\n-   `refresh_ttl` 은 처음 발급 받은 토큰을 새 토큰으로 교체 발행 (==Token Refresh) 받을 수 있는 기간에 대한 설정이다. 가령 2 주 동안 클라이언트와 서버가 인터랙션이 없었다면, 처음 발급 받은 토큰을 이용해서 새 토큰을 교체 받을 수 없게 되며, 사용자이름과 비밀번호를 이용해서 새로 로그인하고 토큰을 발급 받아야 한다. `ttl` 로 지정한 2 시간을 지나서 API 서버에 리소스 요청을 하면, 401 응답을 받게 되고, 이 때 클라이언트는 토큰 교체를 위한 Endpoint 로 요청해서 토큰을 교체 받은 후, 교체 받은 토큰으로 리소스 요청을 계속 하면 된다. `refresh_ttl` 역시 토큰을 한번 교체하면 토큰의 교체 가능 기간은 다시 2주로 리셋된다.\n\n    보안 전문가들은 `ttl` 을 짧게 가져가고, Token Refresh 할 것을 권장한다. Token 이 털리더라도 `ttl` 로 지정한 시간이 지나면, 해커의 노력이 허무해지기 때문이다. \n    \n-   `identifier` 는 토큰의 Subject 필드 값이며, 사용자 인증에 사용되는 필드 값이다. 아래는 User 1 번에 대한 토큰을 디코딩한 것인데, `Subject` 부분을 살펴 보자. 가령 `identifier => email` 로 지정했다면 `Subject::$value` 는 '1' 이 아니라 'john@example.com' 이었을 것이다.\n\n    ```php\n    Payload {#283\n      -claims: array:6 [\n        0 => Subject {#251\n          #name: \"sub\"\n          -value: 1\n        }\n        1 => Issuer {#252\n          #name: \"iss\"\n          -value: \"http://api.myproject.dev:8000/auth/login\"\n        }\n        2 => IssuedAt {#250\n          #name: \"iat\"\n          -value: 1451288973\n        }\n        3 => Expiration {#280\n          #name: \"exp\"\n          -value: 1451296173\n        }\n        4 => NotBefore {#281\n          #name: \"nbf\"\n          -value: 1451288973\n        }\n        5 => JwtId {#282\n          #name: \"jti\"\n          -value: \"e7e045b1c2f5c716b0ec19ac184344e6\"\n        }\n      ]\n    }\n    ```\n\n### JWT Integration\n\n앞서도 얘기했다시피 꼭 기억해야할 점은, API 서비스는 HTTP Cookie 메커니즘을 이용할 수 없는 진정한 Stateless 라는 것이다. 그래서, 매번 리소스 요청시마다 서버 측에서는 HTTP Header 에 달린 token 에 해당하는 User 를 Resolve 해야 한다.\n\n#### 미들웨어\n\n`tymon/jwt-auth` 의 Integration 가이드에 제시된 패키지 내장 `Tymon\\JWTAuth\\Middlewar\\GetUserFromToken`미들웨어를 사용하지 말고, 나름의 미들웨어를 만들 것이다. 왜냐하면, JSON 응답 포맷을 마음대로 변경할 수 없어서 이다.\n\n```php\n// app/Http/Middleware/GetUserFromToken.php\n\n<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Tymon\\JWTAuth\\Exceptions\\JWTException;\nuse Tymon\\JWTAuth\\Middleware\\BaseMiddleware;\n\nclass GetUserFromToken extends BaseMiddleware\n{\n    public function handle($request, \\Closure $next)\n    {\n        if (! $token = $this->auth->setRequest($request)->getToken()) {\n            // HTTP Header 나 URL Parameter 에 token 값이 없으면 400 JWTException 을 던진다. \n            throw new JWTException('token_not_provided', 400);\n        }\n\n        if (! $user = $this->auth->authenticate($token)) {\n            // token 값으로 사용자 로그인을 한다. 해당 사용자가 없으면 404 JWTException 을 던진다. \n            throw new JWTException('user_not_found', 404);\n        }\n\n        $this->events->fire('tymon.jwt.valid', $user);\n        \n        // 미들웨어는 Chain of Responsibility 디자인 패턴의 구현이다\n        // @see https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern\n        return $next($request);\n    }\n}\n```\n\n혹시, 필자가 꼭 설명할 내용을 빼먹고 개떡같이 말해도, 이제 독자 여러분들은 찰떡같이 이해할 수 있다고 생각한다. 다행히 빼먹지 않았다, 'Kernel.php' 에 방금 만들 미들웨어를 등록해주는 일 말이다.\n \n```php\n// app/Http/Kernel.php\n\nclass Kernel extends HttpKernel\n{\n    protected $routeMiddleware = [\n        // ...\n        'jwt.auth'    => \\App\\Http\\Middleware\\GetUserFromToken::class,\n        'jwt.refresh' => \\App\\Http\\Middleware\\RefreshToken::class,\n    ];\n}\n```\n\n`jwt.auth` 란 별칭은 곧 써야 하니 잘 기억해 두자. `RefreshToken` 미들웨어도 만들었지만 지금 당장은 사용할 계획은 없다. 강좌를 진행하면서 필요할 일이 있기를..\n  \n#### 컨트롤러\n\n앞 강에서 JWT 관련 Todo 주석만 달아놓고 구현하지 않은 부분을 구현할 것이다.\n \n```php\n// app/Http/Controllers/SessionsController.php\n\nclass SessionsController extends Controller\n{\n    public function store(Request $request)\n    {\n        // ...\n        \n        $token = is_api_request()\n            // Auth::once() 를 JWTAuth::attempt() 로 변경했다.\n            // 이 메소드는 HTTP Request Header 의 token 을 파싱하여 일회용 로그인을 하는 역할을 한다.\n            ? \\JWTAuth::attempt($request->only('email', 'password'))\n            : Auth::attempt($request->only('email', 'password'), $request->has('remember'));\n            \n        if (! $token) {\n            return $this->respondLoginFailed();\n        }\n\n        return $this->respondCreated($request->input('return'), $token);\n    }\n    \n    // $token 인자가 추가 되었다.\n    protected function respondCreated($return = '', $token = '') {/*...*/}\n}\n```\n\n`ParentController` 의 생성자에서 지정한 미들웨어를, API 인증 관련 모든 컨트롤러에서 `$this->middleware = [];` 로 무효화 시켰다. 이후 이 문서에 포함된 코드에서 생성자는 생략한다.\n\n```php\n// app/Http/Controllers/Api/SessionsController.php\n\nclass SessionsController extends ParentController\n{\n    public function __construct()\n    {\n        parent::__construct();\n        // ParentController 의 미들웨어 정의 무력화.\n        $this->middleware = [];\n    }\n    \n    // ...\n    \n    protected function respondCreated($return = '', $token = '')\n    {\n        return response()->json([\n            'code' => 201,\n            'message' => 'success',\n            // 인자로 넘겨 받은 token (JSON Web Token) 을 반환한다.\n            // 클라이언트 사이드에서는 이 토큰을 저장하고 있다가 \n            // Resource 요청시 Authorization Header 에 사용해야 한다.\n            'token' => $token,\n        ], 201);\n    }\n```\n\n`UsersController` 에서는 `JWTAuth::fromUser()` 메소드를 사용하고 있다.\n\n```php\n// app/Http/Controllers/Api/UsersController.php\n\nclass UsersController extends ParentController\n{\n    // ...\n    \n    protected function respondCreated(User $user)\n    {\n        return response()->json([\n            'code' => 201,\n            'message' => 'success',\n            'token' => \\JWTAuth::fromUser($user),\n        ], 201);\n    }\n}\n```\n\nPostman 을 구동하고 로그인을 해 보자. 응답으로 받은 `token` 은 곧 사용해야 하니, 어딘가에 저장해 두자, 마치 API 클라이언트가 자체 저장소에 token 을 저장해 놓는 것 처럼.\n\n![](./images/46-jwt-img-02.png)\n\n#### Exception 처리\n\n`tymon/jwt` 는 라라벨의 철학을 따라, 여러가지 Exception 을 던지게 구현되어 있다, 우리가 자체 구현한 미들웨어에서도 그렇고. 척하면 착, 'app/Exceptions/Handler.php' 가 생각나야 한다.\n\n```php\n// app/Exceptions/Handler.php\n\nclass Handler extends ExceptionHandler\n{\n    protected $dontReport = [\n        // ...\n        // 이 부분이 없으면 storage/logs/laravel.log 에 기록될 뿐 아니라,\n        // production 환경에서는 Slack 으로 Exception 이 리포트된다.\n        TokenExpiredException::class,\n        TokenInvalidException::class,\n        JWTException::class,\n    ];\n    \n    public function render($request, Exception $e)\n    {\n        // ...\n        \n        if (is_api_request()) {\n            $code = method_exists($e, 'getStatusCode')\n                ? $e->getStatusCode()\n                : $e->getCode();\n        \n            // Exception 별로 메시지를 다르게 처리한다.\n            // 특히, 같은 400, 401 이라도 클라이언트가 이해하고 다음 액션을 취할 수 있는\n            // 메시지를 주는 것이 중요하다. 해서 xxx_yyy 식의 영어 메시지를 쓰고 있다.\n            if ($e instanceof TokenExpiredException) {\n                $message = 'token_expired';\n            } else if ($e instanceof TokenInvalidException) {\n                $message = 'token_invalid';\n            } else if ($e instanceof JWTException) {\n                $message = $e->getMessage() ?: 'could_not_create_token';\n            } else if ($e instanceof NotFoundHttpException) {\n                $message = $e->getMessage() ?: 'not_found';\n            } else if ($e instanceof Exception){\n                $message = $e->getMessage() ?: 'Something broken :(';\n            }\n\n            return response()->json([\n                'code' => $code ?: 400,\n                'errors' => $message,\n            ], $code ?: 400);\n        }\n\n        return parent::render($request, $e);\n    }\n}\n```\n\n### JWT 적용 및 테스트\n\n실제 Resource 를 처리 하는 'GET /v1/articles' Route 와 `ArticlesController` 를 만들고, JWT 미들웨어를 적용해 보자. \n\n```php\n// app/Http/routes.php\n\nRoute::group(['domain' => $domain, 'as' => 'api.', 'namespace' => 'Api'], function() {\n    // ...\n    \n    Route::group(['prefix' => 'v1', 'namespace' => 'V1'], function() {\n        // ...\n\n        Route::resource('articles', 'ArticlesController', ['only' => ['index']]);\n    });\n});\n```\n\n`__construct()` 생성자에서 `$this->middleware('jwt.auth');` 를 적용한 것을 눈여겨 봐야 한다. 우선 테스트를 위한 임시 컨트롤러이므로 아래와 같이 작성한 것이고, 나중에 기존에 만들었던 컨트롤러를 상속하고 수정할 것이다.\n\n```php\n// app/Http/Controller/Api/V1/ArticlesController.php\n\n<?php\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Controllers\\Controller;\n\nclass ArticlesController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('jwt.auth');\n\n        parent::__construct();\n    }\n\n    public function index()\n    {\n        return \\App\\Article::all();\n    }\n}\n```\n\ntoken 없이 'GET /v1/articles' 요청을 하거나, token 이 틀리면 아래와 같이 된다.\n\n![](./images/46-jwt-img-03.png)\n\n테스트를 위해 좀 전에 저장해 두었던 토큰이 필요하다.\n\n![](./images/46-jwt-img-04.png)\n\n인증이 완료되었으니, 다음 강좌에서는 지저분한 코드들을 좀 정리하도록 하자.\n\n**`주의`** Apache 웹 서버를 사용한다면 `tymon/jwt-auth` 패키지의 가이드 대로 아래 내용을 꼭 추가하자. 필자의 라이브 데모 서버에서도 방금 겪은 문제이다.\n \n```bash\n# public/.htaccess\n\n<IfModule mod_rewrite.c>\n    # ...\n\n    # Handle Authorization Header...\n    RewriteCond %{HTTP:Authorization} ^(.*)\n    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]\n</IfModule>\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [45강 - 기본 구조 잡기](45-api-big-picture.md)\n- [47강 - 중복 제거 리팩토링](47-dry-refactoring.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/47-dry-refactoring.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 49\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 47강 - 중복 제거 리팩토링\n\n앞 강에서 기존 컨트롤러의 HTTP 응답 메소드 부분을 API 관련 컨트롤러에서 오버라이드하는 과정에서, 상당히 많은 중복을 보았을 것이다. 이 중복을 제거하는 작업을 이번 강좌에서 해 볼 것이다.  \n\n### API Response 패키지\n\nAPI Response 에서 중복을 피하고 Response Payload 를 좀 더 편리하게 만들 수 있는, 이 실전 프로젝트 규모에 적절한 패키지를 찾아 봤지만.. 못 찾았다. `App\\Http\\Controllers\\Controller` 나 별도 Trait 로 API Response 를 위한 공용 메소드를 정의하는 방법이 있기도 하지만, 필자가 [Packagist](https://packagist.org/) 에 올려 놓은 [`appkr/api`](https://github.com/appkr/api) 패키지를 이용하도록 하자. \n\n**`참고`** Laravel/Lumen 월드에서 API 관련 패키지 중에서는 [`dingo/api`](https://github.com/dingo/api) 가 갑 (甲) 인데, 라라벨의 네이티브 클래스들을 꽤 많이 오버라이드하고 있어서 사용법을 다시 익혀야 하는 단점이 있다. [45강 - 기본 구조 잡기](45-api-big-picture.md) 서두에서 같이 고민했던 \"단일 서버 vs. 복수 서버\" 섹션을 기억할 것이다. `dingo/api` 는 API 전용 독립 서버, 즉 복수 서버 구조에 더 적합하다고 생각된다. 거의 라라벨 프레임웍 수준의 큰 프로젝트로 API 관련 a-Z 를 모두 담고 있고, 베스트 프랙티스를 실천하고 있으므로 꼭 한번 설치해서 사용해 보기 바란다.\n\n#### 설치\n\n```bash\n$ composer require \"appkr/api:0.1.*\"\n```\n\nServiceProvider 를 설정하고 config 파일을 우리 프로젝트 안으로 끌고 오자. \n\n```php\n// config/app.php\n\n'providers' => [\n    // ...\n    Appkr\\Api\\ApiServiceProvider::class,\n],\n```\n\n```bash\n$ php artisan vendor:publish --provider=\"Appkr\\Api\\ApiServiceProvider\"\n```\n\n#### 설정\n\n설정 파일을 확인해 보자.\n\n```php\n// config/fractal.php\n\nreturn [\n    'pattern' => 'v1/*',\n    'domain'  => 'api.myproject.dev',\n    \n    // ...\n    \n    'successFormat' => [\n        'success' => [\n            'code'    => ':code',\n            'message' => ':message',\n        ]\n    ],\n    \n    'errorFormat' =>  [\n        'error' => [\n            'code'    => ':code',\n            'message' => ':message',\n        ]\n    ],\n];\n```\n\n`pattern`, `domain`\n:   이 패키지에서도 `is_api_request()` 란 Helper 를 포함하고 있는데, 이 Helper 에서 사용하는 설정 값들이다. 주의할 점은 이 패키지가 먼저 로드되고 난후, 우리가 정의한 Helper 가 로드되는데, 이 때 `function_exists()` 에 걸려서 우리 Helper 가 로드되지 않고,이 패키지의 `is_api_request()` 가 동작하게 된다는 점이다. PHP 네임스페이스가 필요한 이유를 방금 봤다.\n    \n`successFormat`\n:   200 번 대의 성공 응답을 할 때, 이 포맷이 사용된다. `:code`, `:message` 는 `Appkr\\Api\\Response` 클래스의 HTTP 응답 메소드에서 HTTP Status Code 와 메소드에 넘긴 메시지로 치환된다.\n    \n`errorFormat`\n:   400 번 이상의 에러 응답을 할 때, 이 포맷이 사용된다.\n\n### 리팩토링\n\n방금 끌어온 `appkr/api` 패키지에서는 `json(array $payload)` Helper 를 제공한다. 또, `json()` Helper 는 인자 없이 호출할 때는 `Appkr\\Api\\Response` 인스턴스를 리턴하기 때문에, 해당 클래스에 정의된 \n\n- `success(string $message)`\n- `error(string|array|\\Exception $message)`\n- `respond***(string $message)`\n- `setStatusCode(int $statusCode)`\n- `setMeta(array $meta)` \n- `...`\n\n등 다양한 메소드를 `json()->success()` 처럼 체인해서 사용할 수 있다. `set*()` 메소드는 다른 응답 메소드보다 먼저 체인되어야 한다는 점을 주의하자. \n\n#### 컨트롤러\n\n하나씩 적용해 보자. `json(array $payload)` Helper 는 `response()->json(array $payload)` 와 같은 역할을 한다.\n\n```php\n// app/Http/Controllers/Api/WelcomeController.php\n\nclass WelcomeController extends Controller\n{\n    /**\n     * Get the index page\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function index()\n    {\n        return json([\n            'name'    => 'myProject Api',\n            'message' => 'Welcome to myProject Api. This is a base endpoint.',\n            'version' => 'n/a',\n            'links'   => [/* ... */],\n        ]);\n    }\n}\n```\n\n`unprocessableError(mixed $message)` 메소드는 HTTP 응답 코드를 422 로 설정하고, 인자로 넘겨 받은 `$message` 를, `config('fractal.errorFormat')` 으로 정의한 형태로 치환해서 HTTP 응답을 내 보내는 역할을 한다.\n\n`setMeta(array $meta)` 는 HTTP 응답을 위한 Payload 에 `['meta' => $meta]` 를 추가해 준다. \n\n`created(string|array|Illuminate\\Database\\Eloquent\\Model $primitive)` 는 HTTP 응답 코드를 201 로 설정하고, 인자로 넘겨 받은 `$primitive` 의 형태에 따라 적절하게 포맷팅하여 HTTP 응답을 내보내는 일을 한다.\n\n```php\n// app/Http/Controllers/Api/UsersController.php\n\nclass UsersController extends ParentController\n{\n    // ...\n\n    protected function respondValidationError(Validator $validator)\n    {\n        return json()->unprocessableError($validator->errors()->all());\n    }\n\n    protected function respondCreated(User $user)\n    {\n        return json()->setMeta(['token' => \\JWTAuth::fromUser($user)])->created();\n    }\n}\n```\n\n![](./images/47-dry-fefactoring-img-01.png)\n\n`SessionsController` 에서 위와 중복된 메소드는 설명을 생략했다.\n\n`unauthorizedError(mixed $message)` 는 HTTP 응답 코드를 401로 설정하고, 넘겨 받은 `$message` 를 포맷팅해서 HTTP 응답을 반환한다.\n\n```php\n// app/Http/Controllers/Api/SessionsController.php\n\nclass SessionsController extends ParentController\n{\n    // ...\n    \n    protected function respondLoginFailed()\n    {\n        return json()->unauthorizedError('invalid_credentials');\n    }\n}\n```\n\n![](./images/47-dry-fefactoring-img-02.png)\n\n`PasswordsController::respondError()` 는 어떤 에러가 넘어올 지 모르기 때문에, `notFoundError(mixed $message)` 를 쓰지 않고, 좀 더 일반적인 `error()` 메소드를 사용하였다. \n\n`setStatusCode(int $statusCode)` 는 HTTP 응답 코드를 셋팅하는 역할을 한다. `error()` 메소드에는 'not_found' 란 스트링을 인자로 넘겨 주었다. \n\n```php\n// app/Http/Controllers/Api/PasswordsController.php\n\nclass PasswordsController extends ParentController\n{\n    // ...\n    \n    protected function respondError($message, $statusCode = 400)\n    {\n        return json()->setStatusCode($statusCode)->error('not_found');\n    }\n}\n```\n\n![](./images/47-dry-fefactoring-img-03.png)\n\n`App\\Http\\Controllers\\Api\\V1\\ArticlesController` 는 좀 더 다른 형태의 메소드를 사용해야 하기에, 다음 강좌에서 살펴 보기로 하자.\n\n#### Handler\n\n이번에는 라라벨의 글로벌 Exception Handling 을 하는 'App\\Exceptions\\Handler' 클래스에 끌어온 Response 의 메소드들을 적용하자.\n\n```php\nclass Handler extends ExceptionHandler\n{\n    public function render($request, Exception $e)\n    {\n        // ...\n        \n        if (is_api_request()) {\n            // ...\n            \n            return json()->setStatusCode($code ?: 400)->error($message);\n        }\n    }\n}\n```\n\n![](./images/47-dry-fefactoring-img-04.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [46강 - JWT 를 이용한 인증](46-jwt.md)\n- [48강 - all() is bad](48-all-is-bad.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/48-all-is-bad.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 50\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 48강 - `all()` is bad\n\n앞 강에서 작성한 `App\\Http\\Controllers\\Api\\V1\\ArticlesController::index()` 메소드를 살펴 보자.\n\n```php\nclass ArticlesController extends Controller\n{\n    // ...\n    \n    public function index()\n    {\n        return \\App\\Article::all();\n    }\n}\n```\n\n`all()` 이란 메소드를 이용해서, 리소스를 반환 하고 있다. `all|get|first\\find|...` 등의 메소드를 이용하여, 컨트롤러에서 엘로퀀트 모델을 직접 반환하면, 라라벨이 자동으로 Json 으로 캐스팅해 주긴 한다. 그러나, 이렇게 엘로퀀트 모델을 직접 반환하면 다음과 같은 문제가 있다. \n\n### Why `all()` is bad.\n\n1.  페이징\n    가령 레코드가 10만개라고 생각해 보자. 응답 속도는 당연히 느릴 테고, 엄청난 네트워크 대역폭을 사용할 것이다. 그런데, 정작 클라이언트가 필요로 하는 레코드는 단 몇 개라면... 클라이언트가 필요한 데이터가 속한 구간을 탐색해서 사용할 수 있도록 API 에서 Pagination 은 필수이다.\n    \n2.  추가 데이터를 포함할 수 없다.\n    엘로퀀트 모델을 그대로 반환한다면, 앞 강에서 보았던 JSON Web Token, HATEOAS 를 위한 링크, 페이지네이션을 위한 정보들을 어떻게 추가할 것인가? 엘로퀀트 모델에서 [Accessor](https://laravel.com/docs/5.2/eloquent-mutators#accessors-and-mutators) 를 사용할 수 있지만 한계가 있고, API 응답만 분리하기도 쉽지 않다.\n      \n3.  API 응답에 DB 의 구조가 그대로 드러난다.\n    엘로퀀트 모델의 속성 중에는 API 클라이언트에게 필요하지 않은 필드가 있을 수 있다. 또, 클라이언트에게 DB 의 필드 이름이 아닌 다른 필드 이름을 반환하고 싶을 수 도 있다. DB 필드가 그대로 노출되는 것은 보안 측면에서도 좋지 않고, 혹, 나중에 DB 리모데링을 하게 될 경우, 모든 API 클라이언트가 갑자기 동작하지 않고, 변경된 API 로 마이그레이션하는데 오랜 시간이 걸릴 수 있다.\n    \n4.  HTTP 헤더와 응답 코드\n    엘로퀀트 모델을 그대로 반환하게 되면, 200, 404, 500 3 가지 응답 코드 밖에 쓸 수 없다. 뿐만 아니라, 커스텀 HTTP 헤더를 붙이기도 쉽지 않다.\n    \n그럼, 어쩌라고? `Response::make()` 또는 `response()` Helper 를 이용해서 잘 포맷팅 해서 내 보내야 하는데, 앞 강에서 끌어온 `appkr/api` 패키지가 그 역할을 해 준다.\n  \n### Transformer\n\n앞 강에서 계속 봤듯이, 컨트롤러에서 뷰를 반환할 때 뷰에 바인딩할 데이터를 모델로 부터 뽑아서 전달한다. 그런데, 뷰에서 모델의 모든 속성 값을 표시하던가? 그리고 필요에 따라서는, 가령 `$model->created_at->diffForHumans()` 처럼 값의 형태를 변경하기여 뷰에 뿌리기도 한 것을 기억할 것이다. \n \n그런데, API 에서는 뷰라는 것이 없다. 우리가 응답하는 JOSN, 즉 데이터 자체가 뷰 (==Presentation Layer) 라고 생각하면 되는데, 여기서도 필요한 데이터만을 표시하거나, 데이터 형태를 변경하는 일이 필요하다. 이 때 필요한 것이 Data Transformer (데이터 변환기) 이다. \n\nTransformer (데이터 변환기) 를 이용함으로써, API 클라이언트에게 전달되는 데이터를 완벽하게 제어할 수 있다. 다시 말하면, 데이터 타입/포맷을 마음대로 변경할 수 있을 뿐더러, 필드를 추가하거나 숨기는 일이 가능해 진다. 앞 절의 3 번에서 언급한 데이터베이스 필드가 바뀌었을 때도, 이 Transformer 가 완충 역할을 할 수 있다. 우리 프로젝트의 `Article` 모델을 반환할 때, `author` 관계를 중첩 (Nesting) 하는 등의 조작도 쉬워진다.\n \nTransformer 는 아래 'Simple Trasformer' 의 예처럼 배열을 순회하면서 간단히 구현할 수 있기는 하지만, 지난 강좌에서 가져온 `appkr/api` 패키지가 의존하는 `league/fractal` 패키지에서 제공하는 [Transformer](http://fractal.thephpleague.com/transformers/) 를 이용할 것이다.\n\n#### Simple Transformer\n\n우리의 실전 프로젝트에서 쓰지는 않을 것이지만, 기본은 이렇다 정도로 알아 두자.\n\n`Transformer` 라는 추상 클래스에 `transformCollection()`, `transform()` 등의 메소드를 정의하고 있다. 자세히 보면 `transformCollection()` 메소드는 인자로 넘겨 받은 `$collection` 을 `array_map()` PHP 내장 함수를 이용해서 순회하면서 같은 클래스에 있는 `transform()` 메소드를 호출하는 것을 볼 수 있다. 그리고, `transform()` 메소드 자체는 이름만 있고, 내용이 없는 `abstract` 로 정의되어 있다.\n \n`ArticleTransformer` 는 `Transformer` 추상 클래스를 상속하고 있기 때문에, 부모 클래스에서 `abstract` 로 정의한 `transform()` 메소드를 반드시 구현해야 한다. 여기서, 앞서 언급했던 필요한 필드명을 바꾼다거나, 데이터 타입을 변경하는 등의 작업을 수행한다.\n  \n`ArticlesController::index()` 메소드에서 JSON 을 응답할 때, 앞서 구현한 `ArticleTransformer::transformCollection()` 메소드를 이용하는 것을 볼 수 있다. 모델을 쿼리해서 얻은 엘로퀀트 Collection 을 메소드 인자로 넘기고 있는 것을 확인할 수 있다. 엘로퀀트 Collection 은 PHP 의 ArrayAccess 와 ArrayIterator 를 구현하고 있기에, 배열처럼 순회하면서 우리가 원하는 일들을 할 수 있는 것이다.\n\n```php\n// Transformer.php\n\nabstract class Transformer\n{\n    public function transformCollection(\\Illuminate\\Database\\Eloquent\\Collection $collection)\n    {\n        return array_map([$this, 'transform'], $collection);\n    }\n    \n    public function transformPagination() { /* ... */ }\n    \n    public abstract function transform($item);\n}\n```\n\n```php\n// ArticleTransformer.php\n\nclass ArticleTransformer extends Transformer\n{\n    public function transform($article)\n    {\n        return [\n            'id' => (int) $article->id,\n            // ...\n            'created' => $article->created_at->toISO8601String(),\n            'author' => [\n                'name' => $article->author->name,\n                 // ...\n            ],\n        ];\n    }\n}\n```\n\n```php\n// ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    public function index()\n    {\n        return response()->json([\n            'data' => (new ArticleTransformer)->transformCollection(App\\Article::get())    \n        ]);\n    }\n}\n```\n\n#### Advanced Transformer\n\n이제 이 프로젝트에서 사용할 Transformer 를 artisan CLI 로 만들것이다. CLI 사용법은 [`appkr/api` 문서](https://github.com/appkr/api) 를 참고하자.\n\n```bash\n$ php artisan make:transformer App\\\\Article --includes=App\\\\Comment:comments:true,App\\\\Author:author,App\\\\Tag:tags:true,App\\\\Attachment:attachments:true\n$ php artisan make:transformer App\\\\Comment --includes=App\\\\Author:authors\n$ php artisan make:transformer App\\\\Tag --includes=App\\\\Article::articles:true\n$ php artisan make:transformer App\\\\Attachment\n$ php artisan make:transformer App\\\\User --includes=App\\\\Article:articles:true,App\\\\Comment:comments:true\n```\n\n`ArticleTransformer` 하나만 살펴 보도록 하자.\n\n```php\n// app/Transformers/ArticleTransformer.php\n\n<?php\n\nnamespace App\\Transformers;\n\nuse App\\Article;\nuse Appkr\\Api\\TransformerAbstract;\nuse League\\Fractal\\ParamBag;\n\nclass ArticleTransformer extends TransformerAbstract\n{\n    // 클라이언트에서 /v1/articles?include=comments:limit(2|0):order(created_at|desc) 처럼\n    // Nesting 된 하위 리소스를 JSON 응답에 포함할 때, 응답할 갯수와 정렬을 정의할 수 있다.\n    protected $availableIncludes = ['comments', 'author', 'tags', 'attachments'];\n\n    public function transform(Article $article)\n    {\n        $payload = [\n            'id'           => (int) $article->id, // 정수형으로 캐스팅\n            'title'        => $article->title,\n            'content_raw'  => strip_tags($article->content), // HTML 태그를 모두 제거 \n            'contant_html' => markdown($article->content), // 마크다운으로 컴파일\n            'created'      => $article->created_at->toIso8601String(),\n            'view_count'   => (int) $article->view_count,\n            'link'         => [\n                'rel'  => 'self',\n                'href' => route('api.v1.articles.show', $article->id), // URL\n            ],\n            'comments'     => (int) $article->comments->count(), // 댓글 수\n            'author'       => sprintf('%s <%s>', $article->author->name, $article->author->email), \n            'tags'         => $article->tags->pluck('slug'), // ['laravel', 'eloquent', '...']\n            'attachments'  => (int) $article->attachments->count(), // 첨부파일 수\n        ];\n        \n        if ($fields = $this->getPartialFields()) {\n            $payload = array_only($payload, $fields);\n        }\n\n        return $payload;\n    }\n\n    // $availableIncludes 에 정의된 값들에 대응되는 includeXxx 이름의 메소드를 모두 정의해 주어야 한다.\n    // 이 메소드가 있어야 /v1/articles?include=comments 처럼 쿼리스트링을 통해서 하위 리소스를 포함하는 것이 가능해 진다.\n\n    // /v1/articles?include=comments 처럼 QueryString 이 달려 있으면, \n    // config('api.params.limit'), config('api.params.order') 에 정의한 개수와 정렬방식의 Collection 으로 응답된다.\n    // Article 와 Comment 의 관계는 morphMany() 로 정의되어 있어, \n    // Article 컨텍스트에서 Comment 는 항상 Collection 이 되어야 한다는 점을 상기하자.\n    public function includeComments(Article $article, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\CommentTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $comments = $article->comments()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($comments, $transformer);\n    }\n\n    // 얘는 belongsTo() 관계라 Item 을 응답한다.\n    // Simple Transformer 구현에서 봤던 내용과 크게 다르지 않다.\n    public function includeAuthor(Article $article, ParamBag $params = null)\n    {\n        return $this->item($article->author, new \\App\\Transformers\\UserTransformer($params));\n    }\n\n    // 역시 마찬가지. 위에서 Transform 한대로 배열 형태의 Tag Slug 들만 나가지만,\n    // ?include=tags 이 있다면 Tag Collection 이 JSON 배열로 반환될 것이다.\n    public function includeTags(Article $article, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\TagTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $tags = $article->tags()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($tags, $transformer);\n    }\n\n    // Article 과 Attachment 는 hasMany 관계로 연결되어 있기 때문에 Collection 을 응답하는게 맞다. \n    public function includeAttachments(Article $article, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\AttachmentTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        $attachments = $article->attachments()->limit($parsed['limit'])->offset($parsed['offset'])->orderBy($parsed['sort'], $parsed['order'])->get();\n\n        return $this->collection($attachments, $transformer);\n    }\n}\n```\n\n### Serializer\n\n`league/fractal` 의 개발자인 Phil Sturgeon 의 포스트 ['The Importance of Serializing API Output'](https://philsturgeon.uk/api/2015/05/30/serializing-api-output/) 을 꼭 읽어 보자. \n\nMSDN 정의에 따르면,\n\n> 직렬화 (==Serialization) 란 객체를 메모리 데이터베이스, 또는 파일 등에 저장하기 위한 목적으로 바이트 스트림으로 변환하는 행위를 말한다. 직렬화를 하는 이유는, 현재 객체의 상태를 그대로 저장했다가 필요할 때 다시 꺼내 쓰기 위한 목적이다. 반대 개념은 역직렬화 (==Deserialization) 이다.\n\n![](https://i-msdn.sec.s-msft.com/dynimg/IC20067.jpeg)\n\n가령 객체의 속성이 변경된 상태에서 나중에 이전 상태 그대로 다시 꺼내 쓰고 싶으면 어떻게 할것인가? 객체를 `new` 키워드로 다시 생성하고, 속성값을 변경해서 사용할 것인가? 아니다, 이때 필요한 것이 직렬화이다. 쉽게 직렬화란 객체를 스트링 형태로 변환해서 저장했다가, 부활시키는 것이라고 보면 된다.\n\nAPI 에서 직렬화란 Transformer 에서 변경된 모델/데이터의 상태에서의 직렬화를 의미한다. API 에서 직렬화란 위에서 얘기한 상태의 재복원 보다는 데이터를 전달하는 형태에 더 의미를 둔다. (그럼 직렬화가 맞나요? 라고 따지지 말고 그냥 그렇다고 수용하자.) `league/fractal` 에서도 여러가지 직렬화 방식 (==[Serializer](http://fractal.thephpleague.com/serializers/)) 을 지원하는데,\n\n-   `ArraySerializer`\n    : Collection 을 응답할 경우에만 `data` 필드를 사용한다.\n    \n-   `DataArraySerializer`\n    : Item 이든 Collection 이든 무조건 `data` 필드를 사용한다.\n    \n-   `JsonApiSerializer`\n    : [JSON API](http://jsonapi.org/) 스펙에 정의된 응답 형식을 따른다. `type`, `id`, `attributes` 란 필드를 필수적으로 사용한다.\n    \n우리 실전 프로젝트에서는 가장 간단한 `ArraySerializer` 를 사용할 것이다. `config/api.php` 에서 원하는 다른 Serializer 로 바꿀 수도 있고, 이미 정의된 Serializer 형식을 넘어서서 자신만의 Custom Serializer 를 만들 수도 있다.\n\n### Controller\n\n이제 이론을 배웠으니, 우리의 `ArticleController` 를 변경하자.\n \n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    public function __construct()\n    {\n        $this->middleware('author:article', ['only' => ['update', 'destroy', 'pickBest']]);\n\n        if (! is_api_request()) {\n            // \\App\\Http\\Controllers\\Api\\V1\\ArticlesController 에서 이 컨트롤러를 상속할 것이므로,\n            // API 에 필요 없는 부분은 (! is_api_request()) 로 제외 시켰다.\n            $this->middleware('auth', ['except' => ['index', 'show']]);\n\n            $allTags = taggable()\n                ? Tag::with('articles')->remember(5)->cacheTags('tags')->get()\n                : Tag::with('articles')->remember(5)->get();\n\n            view()->share('allTags', $allTags);\n        }\n\n        parent::__construct();\n    }\n    \n    public function index(FilterArticlesRequest $request, $slug = null)\n    {\n        // ...\n\n        return $this->respondCollection($articles);\n    }\n    \n    public function store(ArticlesRequest $request)\n    {\n        // ...\n        \n        return $this->respondCreated($article);\n    }\n    \n    public function show($id)\n    {\n        // ...\n\n        return $this->respondItem($article, $commentsCollection);\n    }\n    \n    public function update(ArticlesRequest $request, $id)\n    {\n        // ...\n\n        return $this->respondUpdated($article);\n    }\n    \n    public function destroy(Request $request, $id)\n    {\n        // ...\n\n        return $this->respondDeleted($article);\n    }\n    \n    // ...\n    \n    protected function respondCollection(LengthAwarePaginator $articles)\n    {\n        return view('articles.index', compact('articles'));\n    }\n\n    protected function respondCreated(Article $article)\n    {\n        flash()->success(trans('common.created'));\n\n        return redirect(route('articles.index'));\n    }\n\n    protected function respondItem(Article $article, Collection $commentsCollection = null)\n    {\n        return view('articles.show', [\n            'article'         => $article,\n            'comments'        => $commentsCollection,\n            'commentableType' => Article::class,\n            'commentableId'   => $article->id,\n        ]);\n    }\n\n    protected function respondUpdated(Article $article)\n    {\n        flash()->success(trans('common.updated'));\n\n        return redirect(route('articles.show', $article->id));\n    }\n\n    protected function respondDeleted(Article $article)\n    {\n        flash()->success(trans('common.deleted'));\n\n        return redirect(route('articles.index'));\n    }\n}\n```\n\n앞선 강의에서 언급했다시피, Web Response 랑 API Response 부분은 로직에서 큰 차이가 없다, 다행시 아직까지는... 다만 차이가 나는 부분은 HTML 을 응답하냐?, JSON 을 응답하느냐? 의 차이만 있을 뿐이다. DRY (Don't Repeat Yourself) 원칙에 따라 로직을 최대한 사용하면서, `respondCollection()`, `respondCreated`, `...` 의 응답 메소드만 다르게 정의한 것을 볼 수 있다.\n\n이제 위 클래스의 응답 메소들을 Override 하는 API 응답 메소드들을 만들어 보자. 응답에 사용한 메소드들은 `appkr/api` 의 `Appkr\\Api\\Http\\Response` 클래스의 메소드들이다.\n\n-   `withPagination(\\Illuminate\\Pagination\\LengthAwarePaginator $paginator, $transformer = null)`\n    인자로 넘겨 받은 `Paginator` 객체와 `Transformer` 객체를 이용하여, 페이징이 포함된 JSON 콜렉션을 응답한다.\n\n-   `withItem(\\Illuminate\\Pagination\\LengthAwarePaginator $paginator, $transformer = null)`\n    역시, 인자로 넘겨 받은 `Paginator` 객체와 `Transformer` 객체를 이용하여, 단일 아이템에 대한 JSON 을 응답한다.\n    \n-   `created(\\Illuminate\\Database\\Eloquent\\Model|array\\String $primitive = 'Created')`\n    201 응답을 반환한다. 엘로퀀트 모델을 받으면 엘로퀀트 모델을 JSON 캐스팅해서 Response Body 에 덧붙이고, 문자열을 넘기면 'config/api.php' 의 `successFormat` 키에 지정된 형태로 JSON 응답을 한다.  \n    \n-   `success(array|string $message = 'Success')`\n    200 응답을 반환한다. `created` 와 유사하다.\n\n-   `noContent()`\n    204 응답을 반환한다.\n    \n```php\n// app/Http/Controllers/Api/V1/ArticlesController.php\n\nclass ArticlesController extends ParentController\n{\n    public function __construct()\n    {\n        // 'auth' 대신 'jwt.auth' 미들웨어를 사용하는데, 미들웨어를 적용시키지 않을 메소드는 동일하다.\n        // 읽기 요청인 'index' 와 'show' 를 제외했는데, 나중에 Rate Limit 로 시간당 요청 가능 횟수를 제한할 것이다.\n        $this->middleware('jwt.auth', ['except' => ['index', 'show']]);\n\n        parent::__construct();\n    }\n\n    // 부모 클래스를 Override 해서 JSON 응답을 반환한다.\n    protected function respondCollection(LengthAwarePaginator $articles)\n    {\n        return json()->withPagination($articles, new ArticleTransformer);\n    }\n\n    protected function respondCreated(Article $article)\n    {\n        return json()->created();\n    }\n\n    protected function respondItem(Article $article, Collection $commentsCollection = null)\n    {\n        return json()->withItem($article, new ArticleTransformer);\n    }\n\n    protected function respondUpdated(Article $article)\n    {\n        return json()->success('Updated');\n    }\n\n    protected function respondDeleted(Article $article)\n    {\n        return json()->noContent();\n    }\n}\n```\n\n### Test\n\n어떻게 나오는 지 보자. Article Collection 을 먼저 요청해 본다.\n\n```HTTP\nGET /v1/articles HTTP/1.1\nHost: api.myproject.dev:8000\nAccept: application/json\n```\n\n![](./images/48-all-is-bad-img-01.png)\n\nArticle 개별 인스턴스를 요청한다. 그런데, 여기서는 `?include=comments:limit(2|0):order(id|desc),tags` 쿼리스트링을 덧 붙였다. 해석하자면, Comment 를 네스팅하되 0 개를 건너 뛰고 총 2개만, Tag 는 전체 콜렉션을 전부 응답해 달라는 요청이다.\n\n```HTTP\nGET /v1/articles/1?include=comments:limit(2|0):order(id|desc),tags HTTP/1.1\nHost: api.myproject.dev:8000\nAccept: application/json\n```\n\n![](./images/48-all-is-bad-img-02.png)\n\n이번에는 Article 을 생성하는 요청을 한다. 먼저 API_DOMAIN/auth/login 을 방문하여 JWT Token 을 얻어서, 이번 테스트 요청의 Authorization 헤더에 붙인다. title, content, tags[] 등의 내용을 입력하고 요청해 보자. 아무 내용 없는 상태로도 요청해 보면, 아마 422 Unprocessable Entity 에 에러가 있는 필드에 대한 설명이 담긴 JSON 응답을 받았을 것이다.\n\n```HTTP\nPOST /v1/articles HTTP/1.1\nHost: api.myproject.dev:8000\nAccept: application/json\nAuthorization: bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEsImlzcyI6Imh0dHA6XC9cL2FwaS5teXByb2plY3QuZGV2OjgwMDBcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNDUyNDM0MjU4LCJleHAiOjE0NTI0NDE0NTgsIm5iZiI6MTQ1MjQzNDI1OCwianRpIjoiNWM4ZjRhOTAxZWQ2YzljYTkxMjQ5NzU2NjVmZTMyODEifQ.bsLX0u5ZvAX2ZD3w1SSSGyhk6tg0F5q_C6nzR2Ez5Tg\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW\n\n----WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"title\"\n\nNew Title\n----WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"content\"\n\nNew Content\n----WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"tags[]\"\n\n1\n----WebKitFormBoundary7MA4YWxkTrZu0gW\nContent-Disposition: form-data; name=\"tags[]\"\n\n5\n----WebKitFormBoundary7MA4YWxkTrZu0gW\n```\n\n![](./images/48-all-is-bad-img-03.png)\n\n나머지들은 스스로 테스트해 보자.\n\n### Form Request\n\n`App\\Http\\Controllers\\ArticlesController::store()` 메소드에서 입력값 유효성 검사를 위해서 `App\\Http\\Requests\\ArticlesRequest` 라는 [Form Request](https://laravel.com/docs/5.2/validation#form-request-validation) 인스턴스를 주입하고 있다 ([37강 - Article 기능 구현](37-articles.md)). 그런데, 이 Form Request 는 입력값 유효성 검사에 실패하면 422 JSON 응답을 반환하긴 하지만, 우리가 원하는 모양의 JOSN 포맷이 아니다. `App\\Http\\Requests\\ArticlesRequest` 의 부모 클래스를 계속 따라가다 적절한 포인트를 찾아서 기존 응답 형식을 우리 형식에 맞도록 메소드 오버라이딩을 해 주자.\n\n```php\n// app/Http/Requests/Reqeust.php\n\nabstract class Request extends FormRequest\n{\n    // ...\n    \n    public function response(array $errors)\n    {\n        if (is_api_request()) {\n            // API 요청인데, 입력값 유효성 검사에 실패했을 때, 그래서 response() 메소드에 왔을 때는  \n            // 부모 클래스인 Illuminate\\Foundation\\Http\\FormRequest::response() 를\n            // Override 해서 여기서 바로 JSON 응답을 우리 API 응답 포맷에 맞도록 내 보낸다.\n            return json()->unprocessableError($errors);\n        }\n\n        // parent::response() 를 사용하지 않고, 완전히 Overwriting 하였다.\n        return $this->redirector->to($this->getRedirectUrl())\n            ->withInput($this->except($this->dontFlash))\n            ->withErrors($errors, $this->errorBag);\n    }\n\n    public function forbiddenResponse()\n    {\n        if (is_api_request()) {\n            // 역시 위와 동일하다.\n            return json()->forbiddenError();\n        }\n\n        return response('Forbidden', 403);\n    }\n}\n```\n\n### Integration Test\n\n특히 API 의 경우에는 UI 가 없어서 육안 테스트가 번거로울 뿐 아니라, 수정할 일도 많아서 통합 테스트를 작성하는 것이 좋다. 이번 강좌에서 테스트 코드 구현에 대한 내용은 설명하지 않지만, tests 디렉토리 아래에 있는 테스트 코드들을 살펴보도록 하자.\n\n```bash\n$ phpunit\n```\n\n![](./images/48-all-is-bad-img-04.png)\n\n테스트 코드를 짜는 과정에서 `App\\Http\\Controllers\\ArticlesController::update()` 동작 관련 몇가지 버그를 잡았다.\n\n```php\n// app/Http/Requests/ArticlesRequest.php\n\npublic function rules()\n{\n    $rules = [];\n\n    if ($this->isUpdate()) {\n        // update 요청일 때와 아닐 때로 유효성 검사 규칙을 분리했다.\n        $rules = ['tags' => ['array']];\n    } else {\n        $rules = [\n            'title'   => 'required',\n            'content' => 'required',\n            'tags'    => 'required|array'\n        ];\n    }\n\n    return $rules;\n}\n```\n\n```php\n// app/Http/Requests/Request.php\n\nprotected function isUpdate()\n{\n    $needle = ['put', 'patch'];\n\n    return in_array(strtolower($this->input('_method')), $needle)\n        or in_array(strtolower($this->header('x-http-method-override')), $needle)\n        // _method=PUT 등으로 메소드 오버로딩을 하지 않아도 되는 클라이언트를 위해 아래 한줄을 보강했다.\n        or in_array(strtolower($this->method()), $needle);\n}\n```\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\npublic function update(ArticlesRequest $request, $id)\n{\n    // If Check 가 추가되었다. tags 필드를 넘기지 않으면 에러가 나므로...\n    if ($request->has('tags')) {\n        $article->tags()->sync($request->input('tags'));\n    }\n    // ...\n}\n```\n\n또, Article 모델에 접근제한하는 부분에서도, API 요청일 경우에 적절한 JSON 응답을 하도록 고쳤다.\n\n```php\n// app/Http/Middleware/AuthorOnly.php\n\npublic function handle(Request $request, Closure $next, $param)\n{\n    //...\n    if (! $model::whereId($modelId)->whereAuthorId($user->id)->exists() and ! $user->isAdmin()) {\n        if (is_api_request()) {\n            return json()->forbiddenError();\n        }\n\n        return back();\n    }\n\n    return $next($request);\n}\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [47강 - 중복 제거 리팩토링](47-dry-refactoring.md)\n- [49강 - API Rate Limit](49-rate-limit.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/49-rate-limit.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 51\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 49강 - API Rate Limit\n\n### Why?\n\nAPI 엔드포인트의 사용량을 제한하는 이유는 여러가지이다.\n\n-   DDoS 공격으로 부터 서비스를 보호한다.\n-   API 클라이언트 간에 API Resource 의 사용에 공평성을 제공한다. 가령, 소수의 Heavy 클라이언트로 인해 다른 선량한 클라이언트가 피해를 입지 않도록 말이다.\n-   API 를 통해 받는 데이터 자체가 돈과 직결되는 경우, 그 Business Model 로서의 역할을 한다.\n\n### 적용\n\n라라벨 5.2 를 사용하고 있다면, `\\Illuminate\\Routing\\Middleware\\ThrottleRequests` 라는 HTTP Middleware 가 이미 내장되어 있다. 우리의 `ArticlesController` 에 적용하기 전에 Route Middleware 로 잘 등록되어 있나 확인해 보자.\n\n```php\n// app/Http/Kernel.php\n\nclass Kernel extends HttpKernel\n{\n    // ...\n    \n    protected $routeMiddleware = [\n        // ...\n        'throttle' => \\Illuminate\\Routing\\Middleware\\ThrottleRequests::class,\n    ];\n}\n```\n\n적용하자.\n\n```php\n// app/Http/Controllers/Api/V1/ArticlesController.php\n\n\nclass ArticlesController extends ParentController\n{\n    public function __construct()\n    {\n        $this->middleware('jwt.auth', ['except' => ['index', 'show']]);\n        $this->middleware('throttle:60,1');\n\n        parent::__construct();\n    }\n    \n    // ...\n}\n```\n\n아주 간단하다. `throttle:60,1` 이란, 클라이언트당 1 분에 60번 요청을 허용하겠다는 의미이다. `throttle:3,1` 정도로 수정하고 GET /v1/articles 요청을 여러번 연달아 해 보자. 네번째 요청에서 아래와 같은 응답을 받고, 1분 후에 다시 사용 가능한 상태가 되는 것을 확인할 수 있다.  \n  \n```HTTP\nHTTP/1.1 429 Too Many Requests\nHost: api.myproject.dev:8000\n# ...\nRetry-After: 60\nX-RateLimit-Limit: 3\nX-RateLimit-Remaining: 0\n```\n\n### 다듬기\n\nAPI 응답 포맷의 일관성을 위해, `text/application` 이 아니라 `application/json` 으로 응답하도록 수정하자. 라라벨 내장 `\\Illuminate\\Routing\\Middleware\\ThrottleRequests` 를 상속 받아 `\\App\\Http\\Middleware\\ThrottleApiRequests` 를 만들고 여기서 Rate Limit 에 걸렸을 경우 JSON 을 응답하게 수정하면 될 것이다.\n\n```php\n<?php\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Routing\\Middleware\\ThrottleRequests;\n\nclass ThrottleApiRequests extends ThrottleRequests\n{\n    public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)\n    {\n        $key = $this->resolveRequestSignature($request);\n\n        if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {\n            return json()->setHeaders([\n                'Retry-After' => $this->limiter->availableIn($key),\n                'X-RateLimit-Limit' => $maxAttempts,\n                'X-RateLimit-Remaining' => 0,\n            ])->tooManyRequestsError();\n        }\n\n        // ...\n    }\n}\n```\n\n새로 만들어진 HTTP Middleware 를 등록하고, `ArticlesController` 에 적용하자.\n\n```php\n// app/Http/Kernel.php\n\nclass Kernel extends HttpKernel\n{\n    // ...\n    \n    protected $routeMiddleware = [\n        // ...\n        'throttle.api' => \\App\\Http\\Middleware\\ThrottleApiRequests::class,\n    ];\n}\n```\n\n```php\n// app/Http/Controllers/Api/V1/ArticlesController.php\n\n\nclass ArticlesController extends ParentController\n{\n    public function __construct()\n    {\n        $this->middleware('jwt.auth', ['except' => ['index', 'show']]);\n        $this->middleware('throttle.api:60,1');\n\n        parent::__construct();\n    }\n    \n    // ...\n}\n```\n\n이제 `throttle.api:3,1` 정도로 수정하고 테스트해 보면, 우리의 일관된 포맷의 JSON 응답을 볼 수 있을 것이다.\n  \n```HTTP\nHTTP/1.1 429 Too Many Requests\nHost: api.myproject.dev:8000\nContent-Type: application/json\n# ...\nRetry-After: 60\nX-RateLimit-Limit: 3\nX-RateLimit-Remaining: 0\n\n{\n  \"error\": {\n    \"code\": 429,\n    \"message\": \"Too Many Requests\"\n  }\n}\n```\n\n### 추가 적용\n\nAPI 컨트롤러들, `SessionsController`, `UsersController`, `PasswordsController` 등에도 적용하자. 필자의 경우 `throttle.api:10,1` 로 정의했다. 상용에서는 서비스를 하면서 여러가지 통계 정보들에 기반해서 클라이언트 당 허용할 적절한 Rate Limit 값을 정해야 한다. \n\n**`참고`** Laravel 5.2 를 이용하지 않는다면, [`graham-campbell/throttle`](https://github.com/GrahamCampbell/Laravel-Throttle) 패키지를 이용하자. \n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [48강 - all() is bad](48-all-is-bad.md)\n- [50강 - 리소스 id 난독화](50-id-obfuscation.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/50-id-obfuscation.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 52\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 50강 - 리소스 id 난독화\n\n### Why?\n\n엘로퀀트는 기본적으로 자동 증가 ID 를 PRIMARY KEY 로 사용한다. 대부분의 서비스들이 아무런 문제없이 이렇게 사용한다. 그런데, 어떨 때는 PRIMARY KEY 가 예측이 불가능한 것이 더 나은 경우가 있다. 아래 예를 생각해 보자.\n\n예를 들어 식당을 예약하고 예약 내용을 얻어 오는 API 를 서비스한다고 가정하자. API 클라이언트가 예약 API 를 호출했고, 해당 클라이언트를 소유한 사용자의 예약 id 인 15 번을 담은 JSON 을 응답했다고 가정해 보자. 인증이나 권한 부여가 없는 API 서비스였다면... 이 클라이언트는 14 번 예약을 읽어 볼 수도 있고, 16 번 예약을 변경하거나 삭제할 수도 있게 된다.\n\n또 이건 어떤가? `$id++` 이용해서 API 데이터 전체를 훔칠 수 있다. 가령, `/users/{id}` 처럼 사용자 profile 에 대해 API 요청을 할 수 있다면 사용자 정보를 훔칠수도 있고, 경쟁자가 우리 서비스의 전체 사용자 수도 카운트할 수 있다. 대형 서비스에서 자동 증가 ID 를 절대 사용하면 안되는 이유이다. \n\n```php\nclass Scraper\n{\n    protected $base;\n    protected $client;\n    protected $failCount;\n\n    public function __construct($base)\n    {\n        $this->base = $base;\n        $this->client = new \\GuzzleHttp\\Client;\n    }\n\n    public function steal($id)\n    {\n        try {\n            $response = $this->client->get($this->base . DIRECTORY_SEPARATOR . $id);\n\n            if ($response->getStatusCode() !== 200) {\n                throw new \\Exception('Failed');\n            }\n\n            $this->failCount = 0;\n\n            return \\File::put(storage_path(\"stealed/{$id}.json\"), $response->getBody()->getContents());\n        } catch (\\Exception $e) {\n            $this->failCount++;\n\n            if ($this->failCount !== 0 and $this->failCount <= 3) {\n                $this->steal($id);\n            }\n\n            return false;\n        }\n    }\n}\n\n$scraper = new Scraper('http://your-api-host/articles');\n$id = 1;\n\nwhile ($scraper->steal($id) !== false) {\n    $i++;\n}\n```\n \n### How?\n\n두가지 방법이 있다.\n\n1.  DB 에 기록할 때 Auto-increment ID 를 사용하지 않고, 난수화된 ID 로 기록하는 방법\n2.  DB 기록은 Auto-increment ID 를 사용하되, 사용자에게 전달될 때는 난수화하여 전달하는 방법\n\n우리의 실전 프로젝트가 처음부터 MongoDB 와 같은 NoSQL Document DB 를 선택했다면, 이 문제는 처음부터 없었을 것이다. 우리 프로젝트는 MySql 을 사용하고 있으므로 두번째 방법을 이용할 것이다. \n\n**`참고`** Auto-increment ID 를 사용하지 않을 경우, 각 모델에서 `public $incrementing = false;` 로 설정해 주고, 모델을 만들 때 마다 id 값을 직접 넣어 주어야 한다. \n\n**`참고`** 라라벨에서 MongoDB 를 사용하고자 할 때는, `$ brew install homebrew/php/phpXX-mongodb` 명령으로 MongoDB 확장 모듈을 설치한 후, 라라벨용 [`jenssegers/mongodb`](https://github.com/jenssegers/laravel-mongodb) 드라이버 패키지를 설치해서 이용하자.\n\n### 난독화 패키지 선택 및 설치\n\n이 강좌에서는 [`jenssegers/optimus`](https://github.com/jenssegers/optimus) 패키지를 이용한다.\n\n```bash\n$ composer require jenssegers/optimus\n```\n\n난독화에 사용할 소수 (素數, Prime number) 를 만들자. 생성된 값은 곧 사용해야 하니 잘 기록해 두자.\n\n```bash\n$ vendor/bin/optimus spark\n# Prime: 132961291\n# Inverse: 1484265379\n# Random: 37817169\n```\n\nTinker 코맨드로 방금 설치한 패키지를 사용해 보자. 어떤 원리로 동작하는 지 쉽게 감을 잡을 수 있을 것이다.\n\n```bash\n$ php artisan tinker\n>>> $optimus = new Jenssegers\\Optimus\\Optimus(132961291, 1484265379, 37817169);\n=> Jenssegers\\Optimus\\Optimus {#805}\n>>> $optimus->encode(1);\n=> 95280986\n>>> $optimus->decode(95280986);\n=> 1\n```\n\n**`참고`** base62 를 이용한 [zackkitzmiller/tiny-php](https://github.com/zackkitzmiller/tiny-php) 난독화 패키지도 추천한다. \n**`참고`** 또 하나의 옵션은 UUID 패키지, [`ramsey/uuid`](https://github.com/ramsey/uuid), [`webpatser/laravel-uuid`](https://github.com/webpatser/laravel-uuid) 를 이용하는 것이다. 다만 UUID 를 사용할 경우, 문자, 숫자, 대시가 포함된 36 Byte 가 id 값으로 사용되므로, 그에 맞게 `App\\Providers\\RouteServiceProviders` 에서 `$router->pattern()` 부분을 손 봐 주어야 한다.\n\n### 난독화 패키지 정합\n\n#### 디자인\n\n우리 프로젝트의 요구에 맞도록 아래와 같이 동작 구조를 디자인 해 보자.\n\n-   난독화 기능을 쉽게 사용할 수 있도록 Service Provider 를 만들자. \n-   API 에서만 난독화를 적용하자.\n-   JSON 응답을 내 보낼 때, [48강 - all() is bad](48-all-is-bad.md) 에서 만든 Transformer 에서 id 를 난독화하자.\n-   URL 을 통해서 넘어온 난독화된 id 값을 Route Middleware 에서 해독하자.\n\n#### Service Provider and Helper\n\n매번 `new` 키워드와 좀 전에 만든 소수를 넣어서 Optimus 를 깨울 수 없으니, Service Provider 를 만들자. \n\n```php\n// app/Providers/AppServiceProvider.php\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function register()\n    {\n        $this->app->singleton(\\Jenssegers\\Optimus\\Optimus::class, function () {\n            return new Optimus(132961291, 1484265379, 37817169);\n        });\n\n        // ...\n    }\n}\n```\n\n내친 김에 `optimus()` Helper 도 만들자.\n\n```php\n// app/helpers.php\n\nfunction optimus($id = null)\n{\n    $factory = app(\\Jenssegers\\Optimus\\Optimus::class);\n\n    if (func_num_args() === 0) {\n        return $factory;\n    }\n\n    return $factory->encode($id);\n}\n```\n\n#### Transformer\n\n적용 방법은 모두 동일하니 `ArticleTransformer` 하나만 살펴 보자.\n \n```php\n// app/Transformers/ArticleTransformer.php\n\nclass ArticleTransformer extends TransformerAbstract\n{\n    public function transform(Article $article)\n    {\n        $id = optimus((int) $article->id);\n    \n        return [\n            'id' => $id,\n            // ...\n            'link'         => [\n                'rel'  => 'self',\n                'href' => route('api.v1.articles.show', $id),\n            ],\n            // ...\n        ];\n    }\n}\n```\n\n**`참고`** API 뿐아니라 서비스 전체에 걸쳐 난독화된 ID 를 사용하고 싶다면, Transformer 보다는 모든 Model 들이 상속 받고 있는 추상 부모 클래스에 Accessor 를 구현하는 것이 더 적절한 방법이라 생각된다. 아래 예처럼 말이다.\n\n```php\n// app/Model.php\n\nabstract class Model extends Eloquent\n{\n    public function getIdAttribute($value)\n    {\n        return optimus($value);\n    }\n}\n```\n\n#### Route Middleware\n\n앞 절에서 Transformer 를 이용해서 API 응답에만 난독화된 ID 를 제공하는 것으로 구현했으므로, API 컨트롤러에서 모델에 대한 쿼리를 하기 전에 난독화된 ID 를 해독해 주면 된다. 최선의 방법인지는 모르겠지만, API 요청일 경우에만 적용하기에 가장 적절한 방법을 필자는 Route Middleware 라고 생각했다.  \n\n```bash\n$ php artisan make:middleware ObfuscateId\n```\n\n[37강 - Article 기능 구현](37-articles.md) 에서 소유자가 아닌 경우, Article 모델을 변경하거나 삭제할 수 없도록 하기 위해서 미들웨어 파라미터를 받을 수 있는 `CanAccess` 미들웨어를 만든 기억을 더듬어 보자. `$ php artisan route:list` 로 봤을 때, `Route::resource()` 를 이용한 URL Endpoint 에서 Route Parameter 는 {id} 가 아니라, {articles} 와 같이 이름이 지어진다는 점을 확인할 수 있었다. 여기서도 미들웨어 파라미터 `$param` 으로 넘긴 값을 이용해서 Route Parameter 키 값을 계산하고 있다. 여기서 `$routeParamName = 'articles'` 가 된다.\n \n Route Parameter 가 {articles} 라는 것을 알았다. 값을 받아 보면 난독화되어 있을 것이다. 이 값을 `optimus()` 로 해독하여, 기존 Route Parameter 값을 오버라이드하는 작업을 해 주어야 한다. 여기서 `$routeParamValue = 1026009865` 와 같은 값이고, `optimus()->decode(1026009865) = 8` 처럼 처리된다. `getParameter()`, `setParameter()` 는 Request 인스턴스에 바인딩되어 있는 Route 인스턴스의 메소들이다.\n\n```php\n// app/Http/Middleware/ObfuscateId.php\n\nclass ObfuscateId\n{\n    public function handle(Request $request, Closure $next, $param = null)\n    {\n        $routeParamName = $param ? str_plural($param) : 'id';\n\n        if ($routeParamValue = $request->route()->getParameter($routeParamName)) {\n            $request->route()->setParameter($routeParamName, optimus()->decode($routeParamValue));\n        }\n\n        return $next($request);\n    }\n}\n```\n\n'app/Http/Kernel.php' 의 `$routeMiddleware` 섹션에 등록하는 것을 잊지 말자. 필자는 `obfuscate` 별칭으로 등록하였다. \n\n**`참고`** 서비스 전체에 ID 난독화를 적용하고 싶다면, 방금 만든 미들웨어를 글로벌 미들웨어로 등록하면 될 것이다. 이 경우 Route 나 컨트롤러에서 `$this->middleware()` 를 정의할 필요가 없어지게 된다.\n\n#### Controller\n\n미들웨어를 적용하자. `obfuscate:article` 과 같이 Middleware Parameter 를 넘겨 준 것을 확인하자.\n\n```php\n// app/Http/Controllers/Api/V1/ArticlesController.php\n\nclass ArticlesController extends ParentController\n{\n    public function __construct()\n    {\n        $this->middleware('obfuscate:article');\n        // ...\n    }\n    \n    // ...\n}\n```\n\n### 테스트\n\n![](./images/50-id-obfuscation-img-01.png)\n\nIntegration Test 코드도 약간 수정되었다. \n\n```bash\n$ phpunit\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [49강 - API Rate Limit](49-rate-limit.md)\n- [51강 - CORS](51-cors.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/51-cors.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 53\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 51강 - CORS\n\n이번 강좌에서는 [CORS (Cross Origin Resource Sharing)](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) 에 대해 공부해 보자. 개념적으로는 굉장히 어려운 내용이지만, 해결 방법 자체는 엄청 간단하다. \n\n### CORS 란?\n\n개념을 알고 넘어 가야 한다. 어려운 개념을 복잡하게 설명하면 고수가 아니다. 필자도 잘 모르기 때문에 딱 눈 높이에 맟추어 설명하자면... \n\n-   일단 CORS 이슈는 JavaScript 를 이용하는 API Client 에서만 발생한다. \n\n    Android, iOS 에서는 신경쓸 필요가 없다. 왜냐하면, 브라우저를 통한 Ajax (== `XMLHttpRequest`) 요청을 할 때만, Same Origin Security Policy 가 적용되기 때문이다. XSS (== Cross Site Script) 공격을 방지하기 위해, W3C 와 브라우저 벤더들이 그렇게 하기로 오래전에 약속했다.\n    \n-   Same Origin Security Policy (== 동일 출처 보안 정책) 란...\n\n    foo.com 에서 동작하는 JavaScript 가 bar.com 에 있는 API 서버에 Ajax 요청을 할 수 없다는 것이다. 심지어 http://foo.com -> https://foo.com 뿐 아니라, http://foo.com -> http://foo.com:8080 도 동작하지 않는다. 왜냐하면, JavaScript 는 태생적으로 클라이언트에 다운로드 되어 사용되는 프로그램이라, JavaScript 코드를 사용자가 임의로 변경할 수 있기 때문이다. \n\n아래는 이번 강좌를 위해 개발한 JavaScript 기반의 [`appkr/api-client-demo`](https://github.com/appkr/api-client-demo) 코드를 http://localhost:3000 에서 구동하고, http://api.myproject.dev:8000 API 서버에 리소소를 요청하는 그림이다. \n \n![](./images/51-cors-img-01.png)\n\nJavaScript 기반의 SPA (== Single Page Application) 들이 계속 늘어나고 있고, 클라이언트와 서버는 API 로 데이터만 주고 받고, 뷰/UI 는 클라이언트 쪽에 모두 맡기는 것이 모던 웹 개발의 베스트 프렉티스라는 점을 감안한다면, API 서버를 개발하는 백엔드 개발자 입장에서 Same Origin Security Policy 문제는 반드시 해결해야 할 숙제이다. \n\n### 해결방안\n\n여러가지 방법이 있다.\n\n1.  `JSONP` 를 이용하는 방법. \n\n    Legacy 이다. CORS 이슈가 대두된게 10년이 넘었고, W3C 스펙이 확정된지 5년이 넘었다. 쓰면 안된다는 얘기다. 게다가 JSONP 는 HTTP GET 요청만 적용할 수 있다는 한계도 있다.\n    \n2.  Reverse Proxy 를 이용하는 방법. \n\n    Reverse Proxy (또는 L4) 가 클라이언트의 HTTP 요청을 보고, Reverse Proxy 내부에 위치한 web 또는 api 적절한 서버로 요청을 분기하는 방법이다. 클라이언트가 Reverse Proxy 주소로 요청하고, 서버오 Reverse Proxy 뒤에 있기에 문제가 발생하지 않는다. 다만, 자기 서비스에만 적용할 수 있다는 단점이 있다.\n    \n3.  HTTP `Options` Pre-flight Request 를 이용해 White-list 하는 방법. \n\n    클라이언트가 HTTP `OPTIONS` 요청을 먼저 한 후, 응답을 해석한 후, 본 요청을 해야 한다. 서버 쪽에서도 로직이 복잡하다.\n    \n4.  `Origin` 및 `Access-Control-*` HTTP 헤더를 이용하는 방법. \n\n우리는 가장 간단한 4 번 방법을 이용할 것이다.\n\n### 패키지 설치\n\n[`barryvdh/laravel-cors`](https://github.com/barryvdh/laravel-cors) 패키지를 이용할 것이다.\n\n이 패키지가 의존하는 [`asm89/stack-cors`](https://github.com/asm89/stack-cors) 패키지의 Git Tagging 이 늦어, Composer 설치시 충돌이 발생한다. 우리는 아래와 같이 우회해서 설치할 것이다.\n\n```javascript\n// composer.json\n\n{\n  // ...\n  \n  \"require\": {\n    // ...\n    \"asm89/stack-cors\": \"dev-master as 0.2.2\",\n    \"barryvdh/laravel-cors\": \"^0.7.3\"\n  }\n  \n  // ...\n}\n```\n\n```bash\n$ composer update\n```\n\n공식 문서에 나온대로 ServiceProvider 를 활성화 해 준다.\n \n```php\n// config/app.php\n\nreturn [\n    // ...\n    \n    'providers' => [\n        // ...\n        Barryvdh\\Cors\\ServiceProvider::class,\n    ],\n    \n    // ...\n];\n```\n\n### CORS 기능 정합\n\n서두에 구현이 굉장히 간단하고 얘기했다. `barryvdh/laravel-cors` 패키지를 설치하고 나면, `cors` 라는 별칭을 가진 Route Middleware 를 사용할 수 있다. API 에만 이 미들웨어를 적용할 것이므로 가장 적절한 위치는 Route 정의 파일인 듯 하다.\n\n```php\n// app/Http/routes.php\n\nRoute::group(['domain' => env('API_DOMAIN'), /* ... */, 'middleware' => 'cors'], function() {\n    // ...\n}\n```\n\n이걸로 끝이다.\n\n**`참고`** Laravel 5.2 부터 Middleware Group 을 이용할 수 있다. 기본으로 `web`, `api` 두개의 그룹이 가용하다. 요는 여러개의 미들웨어를 모아 `api` 등의 별칭으로 한번에 적용할 수 있다는 것이다.\n\n### 살펴 보기\n\n설치한 `barryvdh/laravel-cors` 패키지와 `cors` 미들웨어는 어떤 일을 할까? \n\n![](./images/51-cors-img-02.png)\n\nJavaScript 클라이언트에서 Ajax 요청을 할 때 `Origin` HTTP Header 를 달아서 보내면, API 서버에서 응답할 때 `Access-Control-Allow-Origin` HTTP Header 를 내려주는 식이다. 그림을 보면, \"JavaScript 엔진아! 나 API 서버인데... http://localhost:3000 은 나랑 scheme:://host:port 가 달라도 내가 허용해 줄라니까, Same Origin Security Policy 적용하지 말고 내 Client 한테 데이터 좀 넘겨 줘~\" 라고 부탁하는 식이다. 왼쪽 클라이언트 화면을 보면, API 서버로 데이터를 받아 뷰를 정상적으로 렌더링한 것을 볼 수 있다. 요약하자면, `Origin` 요청 헤더를 검사하고, `Access-Control-*` 응답 헤더를 붙여 주는 역할을 한다. \n\n이 패키지는 `Access-Control-*` 헤더 방식을 이용한 CORS Handling 만 하는 것이 아니라, 앞서 언급한 Pre-flight 방식도 지원한다.\n\n### api-client-demo\n\n전체 코드는 [`appkr/api-client-demo`](https://github.com/appkr/api-client-demo) 에서 확인하기로 하자. 앞 강에서와 달리 [Vue.js](http://vuejs.org/) 프레임웍을 이용하고 있고, API 서버에 Ajax 요청을 하는 부분은 아래와 같다.\n\n```javascript\n// @appkr/api-client-demo\n// app/scripts/main.js\n\n(function(Vue, moment) {\n  'use strict';\n\n  var base = 'http://api.myproject.dev:8000';\n\n  var vm = new Vue({\n    el: '#demo',\n\n    data: {\n      articles: {}\n    },\n\n    ready: function() {\n      var resource = this.$resource(base + '/v1/articles');\n\n      resource.get('').then(function(response) {\n        this.$set('articles', response.data.data);\n      }, function(response) {\n        console.log(response);\n      });\n    },\n\n    filters: {\n      // ...\n    },\n\n    http: {\n      headers: {\n        Accept: 'application/json'\n      }\n    }\n  });\n})(Vue, moment);\n```\n\n[`appkr/api-client-demo`](https://github.com/appkr/api-client-demo) 에서 뷰는 Bootstrap 대신 [Google Material Design Lite](http://www.getmdl.io/) 를 사용하고 있다. [Cordova](https://cordova.apache.org/) 를 이용하면 Android, iOS 모바일 앱으로도 패키징해서 사용해 볼 수 있다. \n\n```html\n<!-- @appkr/api-client-demo -->\n<!-- app/index.html -->\n\n<!-- ... -->\n\n<main class=\"mdl-layout__content\">\n  <div class=\"page-content\" id=\"demo\">\n    <div v-for=\"article in articles\" class=\"mdl-card ...\"><!--repeat start-->\n      <div class=\"mdl-card__title\">\n        <h2 class=\"mdl-card__title-text\">\n          {{ article.title }}\n        </h2>\n        <div class=\"mdl-layout-spacer\"></div>\n        <span class=\"material-icons mdl-badge\" data-badge=\"{{ article.view_count }}\">\n          done\n        </span>\n        <span class=\"material-icons mdl-badge\" data-badge=\"{{ article.comments }}\" v-if=\"article.comments\">\n          chat\n        </span>\n        <span class=\"material-icons mdl-badge\" data-badge=\"{{ article.attachments }}\" v-if=\"article.attachments\">\n          attachment\n        </span>\n      </div>\n      <div class=\"mdl-card__supporting-text\">\n        <img src=\"images/user.jpg\" class=\"avatar\">\n        {{{ article.content_raw }}}\n        <span class=\"composed-by\">\n          - Composed by {{ article.author.name }}, {{ article.created | formatDate }}\n        </span>\n      </div>\n      <div class=\"mdl-card__actions mdl-card--border\">\n        <a class=\"mdl-button ...\" v-for=\"tag in article.tags\"> <!--sub repeat start-->\n          {{ tag }}\n        </a> <!--sub repeat end-->\n      </div>\n    </div> <!--repeat end-->\n  \n    <!-- ... -->\n  \n  </div>\n</main>\n\n<!-- ... -->\n```\n\n![](./images/51-cors-img-03.png)\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [50강 - 리소스 id 난독화](50-id-obfuscation.md)\n- [52강 - Caching](52-caching.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/52-caching.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 54\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 52강 - Caching\n\n강좌를 시작하기 전에 \"적정 기술\" 이란 개념에 대해 먼저 잡담을 좀 하자. \n\n원래 의미와 약간 다를 수 있지만, 필자는 자신이 속한 환경, 즉 비즈니스/서비스의 성숙도나 규모에 따라 적합한 기술을 선택하는 행위로 해석한다. 스타트업이 MVP (==Minimum Viable Product) 를 개발하는 데, Caching 까지 고려해서 할 필요는 없다는 얘기다. 일 Page View 가 몇 천, 피크 타임에 동시 사용자가 수십 명 정도인 서비스에 Caching 까지 고려해서 API 서버와 API 클라이언트를 개발할 필요는 없다는 얘기다. \n\n바꾸어 얘기하면, 트래픽이 많은 서비스는 서버 사이드 및 클라이언트 사이드 모두에서 캐시를 구현해야 한다는 얘기다. 좀 더 나아가서 서버 팜에는 L4, Web, DB, Cache 등 서버가 모두 분리되어 있고 오토스케일링 할 수 있도록 설정되어 있어야 하며, Session 이나 Cache 등 공용 저장소는 클러스터링이 되어 있어야 한다. 규모가 되었는데 이렇게 안하면, 사용자는 떠나고 사업은 망한다.\n\n지금 내가 처한 상황에서 Caching 이 적정기술이 아니더라도, 이 강좌는 일단 학습 목적으로 배워 두자. 그리고, \"아, 그거 거기에 있었지~\" 정도로 기억해 두자, 필요할 때 꺼내 쓸 수 있도록. \"페이스북 하니까..\", \"구글이 하니까..\" 라고 하는 오류를 범하지 말자. \n\n### Why?\n\nPagination, Transformer, Cache, Partial Response (원하는 필드만 골라 요청하고 응답하는 것) 등의 장치들은 모두 다음을 위한 것들이다.\n \n1.  **네트워크 사용량을 줄인다.**\n\n    가령, 전체 목록 요청에 응답되는 데이터량이 1 MByte 라고 가정해 보자. 모든 오버헤드를 무시하고, 1 초 내에 응답을 받으려면 적어도 네트워크 속도가 8 Mbps 가 되어야 한다. 다행히 대부분의 환경에서 그 이상 나온다. 그런데, 그렇지 않을 환경도 있다는 것을 염두해 두어야 한다. 만원 지하철 Wi-Fi , Lte 엣지, 강남역 처럼 사용자가 붐비는 곳의 Lte 등의 환경에 있는 API Client 도 있을 수 있기 때문이다. 가령, 200 Kbps 속도로 가정하면, 총 16 초가 소요되며, 그 사용자는 다시 방문하지 않을 것이다.\n     \n    뿐만 아니다. API 클라이언트와 서버가 Lte 와 같은 유료 네트워크를 이용한다면 그 비용은 누가 내는가? 훌륭한 서비스라면 사용자의 비용을 아껴주어야 한다. \n    \n    정리하자면, API 호출로 인한 데이터 사용량은 **서비스 품질** 뿐 이나라 **비용** 두 가지 모두에 영향을 미친다. 이 강좌에서는 **Etag/If-None-Match** HTTP Header 를 이용해 네트워크 사용량을 최소화하는 구현을 할 것이다. \n    \n2.  **컴퓨팅 파워를 절약한다.**\n\n    PHP 7 이 나왔다. 외국 블로그들 보면, 동일 조건으로 PHP 5.6 과 비교하여, 몇 ms 가 더 빨라졌다고 비교 실험들을 하고 있다. Facebook 의 HHVM 과 실행 속도 면에 큰 차이가 없다는 기사도 보았다. 그런데, 서비스하는 입장에서 PHP Executable 에서 발생하는 몇 ms 는 큰 의미가 없다. 왜냐하면, 사실상의 병목은 파일, DB, 네트워크 등의 IO 에서 발생하기 때문이다. 경험이 있는 개발자라면 DB 에서 병목이 심하다는 것을 알고 있을 것이다.\n     \n    서버 사이드 캐시는 DB 쿼리를 결과를, 상대적으로 병목이 덜한 파일이나 메모리에 일정 시간 동안 담아 놓아, DB 쿼리로 인한 컴퓨팅 파워 절약과 반응속도를 향상시키는 역할을 한다. 이 강좌에서는 **서버 사이드 캐싱** 을 구현할 것이다.\n    \n\"폭탄 떠넘기기\" 라고 필자는 자주 얘기하는데, 서버 개발자와 클라이언트 개발자가 어렵고 귀찮은 캐싱 기능 구현을 상대편으로 떠넘기는 것을 묘사한 것이다. 이 강좌에서는 서버 사이드에서 HTTP 표준을 이용해 캐싱 기능을 구현하고, HTTP 표준을 이용하는 클라이언트가 거부감 없이 캐싱 기능을 사용하도록 할 것이다.\n  \n### 서버 사이드 캐싱\n\n#### 구현\n\n[42강 - 서버 사이드 개선](42-be-makeup.md) 에서 모델 쿼리에다 `remember()` 메소드를 바로 체인하기 위해서 [watson/rememberable](https://github.com/dwightwatson/rememberable) 를 끌어 온 적이 있다. 이번에는 이 패키지를 걷어 내고 [라라벨 표준 방식](https://laravel.com/docs/cache#cache-usage)으로 구현할 것이다.\n\n```bash\n$ composer remove watson/rememberable\n```\n\n```php\n// app/Model.php\n\n// use Watson\\Rememberable\\Rememberable;\n\nabstract class Model extends Eloquent\n{\n    // use Rememberable;\n}\n```\n\n`ArticlesController::index()`, `ArticlesController::show()` 에서 모델 쿼리 하는 부분에 캐싱 기능을 부여하자.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    protected $cache;\n\n    public function __construct()\n    {\n        // taggable() Helper 를 이용하여 기본 쿼리를 만든다.\n        // .env 에 CACHE_DRIVER= 값이 file 이나 database 이면 Cache Tag 를 쓸 수 없다.\n        $this->cache = taggable() ? app('cache')->tags('articles') : app('cache');\n\n        // ...\n    }\n    \n    public function index(FilterArticlesRequest $request, $slug = null)\n    {\n        // ...\n\n        // cache_key() Helper 를 이용해 캐시에 사용할 고유한 key 를 만든다.\n        $cacheKey = cache_key('articles.index');\n\n        $articles = $this->cache->remember($cacheKey, 5, function() use($query, $request) {\n            return $this->filter($query)->paginate($request->input('pp', 5));\n        });\n        \n        // ...\n    }\n \n    public function show($id)\n    {\n        $cacheKey = cache_key(\"articles.show.{$id}\");\n        $secondKey = cache_key(\"articles.show.{$id}.comments\");\n\n        $article = $this->cache->remember($cacheKey, 5, function() use($id) {\n            return Article::with('comments', 'tags', 'attachments', 'solution')->findOrFail($id);\n        });\n\n        $commentsCollection = $this->cache->remember($secondKey, 5, function() use($article){\n            return $article->comments()->with('replies')->withTrashed()->whereNull('parent_id')->latest()->get();\n        });\n\n        // ...\n    }\n}\n```\n\n`cache_key()` 란 Helper 를 사용하고 있다. 쿼리스트링을 포함한 요청 URL 과 함수 인자를 연결하여 고유한 스트링을 만드는 간단한 함수이다. 캐시 키를 만드는 데 정해진 규칙은 없다. `Article::find(2)` 와 `Article::find(3)` 쿼리는 서로 다른 쿼리이고, 그 결과가 다르기에 다른 키로 저장되어야 하며, 그 구분자 역할을 이 캐시 키가 하는 것이다.\n\n```php\nfunction cache_key($base) {\n    $key = ($uri = request()->fullUrl()) ? $base . '.' . urlencode($uri) : $base;\n    \n    return md5($key);\n}\n```\n\n#### 이벤트\n\n앞 절에서 캐싱 기간을 5분으로 지정했다. 즉 5 분 내에 새로운 요청이 오면, DB 쿼리를 하지 않고 캐시 저장소에서 꺼내서 사용한다.\n \n그렇다면, 5 분 내에 모델에 새로운 레코드가 생성되거나, 수정되거나, 삭제되면 어떻게 해야 하나? 이 부분은 이미 [42강 - 서버 사이드 개선](42-be-makeup.md) 에서 이미 배운 바 있다. \n\n한번 더 상기해 보면, `ArticlesController::store()`, `ArticlesController::update()`, `ArticlesController::destroy()` 메소드에는 해당 작업이 성공했을 때 `App\\Events\\ModelChanged` 이벤트를 던지도록 되어 있다. 이 이벤트를 받은 `App\\Listeners\\CacheHandler` 가 넘겨 받은 캐시를 찾아서 삭제하도록 되어 있다. \n\n이제 캐시 저장소는 비워졌고, 첫 사용자에게는 `ArticlesController` 에서 DB 쿼리를 통해 서비스를 제공하고 캐시 저장소에 다시 5 분간 캐싱할 수 있게 된다. \n\n#### 테스트\n\n쿼리를 찍어 보는 방법 외에 딱히 좋은 테스트 방법은 없다.\n\nRoute 정의 파일에 아래 내용을 넣고, 로컬 서버를 기동한 후, '/v1/articles' 를 방문해 보자. 다시 한 번 더 방문해서 쿼리 개수가 줄어든 것을 확인하자.\n\n```php\n// app/Http/routes.php\n\nDB::listen(function($event){\n    var_dump($event->sql);\n});\n```\n\n### Etag 와 304 Not Modified\n\n#### 웹 서버\n\n아래 그림을 보자.\n\n우선, 우리가 사용하는 Apache 또는 Nginx 서버는 Html, Javascript, CSS, Image 등 Static Resource 에 대해서는 Etag 와 304 Not Modified 를 이용한 응답을 처리해 주고 있다. Static Resource 란 Content-Length 가 매 요청시 마다 변하지 않는 파일들을 말한다. \n\n![](./images/52-caching-img-02.png)\n\n반면, 확장자가 php 이거나 쿼리 스트링이 달린 경우에 웹 서버는 해당 요청에 대한 응답 형식을 Dynamic Resource 라 생각한다. Dynamic Resource 란 매 요청시마다 Content-Length 가 변할 수 있는 파일이다. 가령, /abc.php 요청했을 경우, abc.php 내에서 응답할 컨텐츠를 만들기 때문에, 설령 그 응답값이 지난 번과 동일하다 할 지라도, 웹 서버 입장에서는 응답의 크기를 미리 알 수 없다. 그래서, 304 응답을 자동으로 처리해 줄 수 없는 것이다.\n\n![](./images/52-caching-img-01.png)\n\n**참고** 우리는 .php 로 요청하지 않고, '/v1/articles' 로 요청했는데 웹 서버가 어떻게 알지? 라고 궁금증이 생길 수 있다. 이 내용은 [2강 - 라라벨 5 설치하기](02-hello-laravel.md) 에서 라라벨의 동작 시퀀스라는 그림으로 설명한 바 있다. 웹 서버의 설정에 의해 '/v1/articles' 라 해도 무조건 'public/index.php' 로 들어가게 되고, 'index.php' 가 URL 을 Router 에 넘겨 적절한 컨트롤러로 작업을 위임하기 때문이다. 즉, 웹 서버는 확장자가 php 인 요청인지 안다는 얘기다.\n\n#### Etag 생성\n\n일단, 모델과 베이스 컨트롤러에 필요한 메소드를 추가하는 구조로 구현해 보자. Repository 패턴을 구현했다면 그 쪽에 위치하는 것이 더 좋을 것 같긴 하다만, 우리 강좌에서는 오버인 듯 하다.\n\n`Article::etag()` Helper 메소드를 보면, `$cacheKey` 를 인자로 받아, 테이블 이름, 모델 id, 모델의 수정 시각 등을 모두 스트링으로 연결한 뒤 `md5()` 내장 함수로 Hashing 하는 것을 볼 수 있다.\n \n```php\n// app/Articles.php\n\nclass Article extends Model\n{\n    public function etag($cacheKey = null)\n    {\n        $etag = $this->getTable() . $this->getKey();\n\n        if ($this->usesTimestamps()) {\n            $etag .= $this->updated_at->timestamp;\n        }\n\n        return md5($etag.$cacheKey);\n    }\n}\n```\n\n위는 `ArticlesController::show()` 메소드에서 사용할 수 있는, 단일 모델에 대한 Etag 생성 로직이다. `ArticlesController::index()` 는 Collection 을 다루게 되는데 이때는 Etag 를 어떻게 하면 좋을까? Collection 에 속한 각 Item (==Article 모델) 을 순회하면서, 위에서 만든 `Article::etag()` 메소드로 얻은 개별 Article Etag 들을 전부 조합한후 `md5()` Hashing 을 하면 될 것 같다.\n\n```php\n// app/Http/Controllers/Controller.php\n\nclass Controller extends BaseController\n{\n    // ...\n    \n    public function etags($collection, $cacheKey = null)\n    {\n        $etag = '';\n\n        foreach($collection as $instance) {\n            $etag .= $instance->etag();\n        }\n\n        return md5($etag.$cacheKey);\n    }\n}\n```\n\n**참고** 3rd Party 에서 제공하는 Repository 패턴 구현체를 사용하려면, [`prettus/l5-repository`](https://github.com/prettus/l5-repository) 를 적극 권장한다. 위에서 살펴본 서버 사이드 캐싱 기능도 Ouf of Box 로 포함되어 있다. \n\n#### Controller 수정\n\n`ArticlesController::index()` 에서는 수정할 것이 없다. `ArticlesController::show()` 에서는 Etag 가 모델의 updated_at 필드 값에 의존하기 때문에, 조회수를 증가시키기 위한 이벤트를 API 요청일 경우에는 제외시키도록 하자.\n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    public function show($id)\n    {\n        // ...\n\n        if (! is_api_request()) {\n            event(new ArticleConsumed($article));\n        }\n\n        return $this->respondItem($article, $commentsCollection, $cacheKey.$secondKey);\n    }\n}\n```\n\nEtag 및 304 응답은 API 요청/응답 에만 적용할 것이다. 즉, 앞선 강좌에서 만든 응답 관련 메소드만 수정하면 된다. 설명은 코드 내 주석을 보자.\n\n```php\n// app/Http/Controllers/Api/V1/ArticlesController.php\n\nclass ArticlesController extends ParentController\n{\n    protected function respondCollection(LengthAwarePaginator $articles, $cacheKey = null)\n    {\n        // Request 붙어 온 If-None-Match Header 가져오기 \n        $reqEtag = request()->getETags();\n        // 베이스 클래스에 만든 Collection 에 대한 Etag 만들기\n        $genEtag = $this->etags($articles, $cacheKey);\n\n        if (isset($reqEtag[0]) and $reqEtag[0] === $genEtag) {\n            // $reqEtag = [\"65f8322657950bdccdc48df21dddfc33\"] 이기 때문에 Array Access 해야 함.\n            return $this->respondNotModified();\n        }\n\n        // 클라이언트가 If-None-Match Header 를 보내 오지 않았거나,\n        // 클라이언트가 보내온 Header 가 $genEtag 와 다를 경우. \n        // 즉, 모델이 수정되었을 경우.\n        return json()->setHeaders(['Etag' => $genEtag])->withPagination($articles, new ArticleTransformer);\n    }\n    \n    protected function respondItem(Article $article, Collection $commentsCollection = null, $cacheKey = null)\n    {\n        $reqEtag = request()->getETags();\n        // 단일 Instance 에 대한 Etag 만들기\n        $genEtag = $article->etag($cacheKey);\n\n        if (isset($reqEtag[0]) and $reqEtag[0] === $genEtag) {\n            return $this->respondNotModified();\n        }\n\n        return json()->setHeaders(['Etag' => $genEtag])->withItem($article, new ArticleTransformer);\n    }\n    \n    protected function respondNotModified()\n    {\n        return json()->notModified();\n    }\n}\n```\n\n#### 테스트\n\n브라우저로 쉽게 테스트해 볼 수 있다. \n\n![](./images/52-caching-img-03.png)\n\n개발자 도구의 'Disable Cache' 를 이용하면 차이점을 보기 쉬우니 참고하자. \n\n'Disable Cache' 를 켰다는 얘기는 Etag Header 를 클라이언트 측의 캐시 Key 로 해서 받은 컨텐츠를 브라우저 캐시 스토리지에 저장하지 않고, 다음 요청 때 If-Non-Match Header 를 보내지 않는다는 의미이다. 즉, 'Disable Cache' 를 켰다는 얘기는 API 클라이언트가 캐시 기능을 구현하지 않았다는 얘기이다. \n\n그런데, API 클라이언트 개발자가 HTTP 스펙을 다 이해하고 HTTP 스택을 직접 구현하지 않을 테고, 클라이언트의 플랫폼/프레임웍에 포함된 라이브라리를 가져다 쓸 것이다. 이 경우, 대부분이 Etag 기능을 지원하고, 위 브라우저 예에서 보듯이 클라이언트 사이드에서도 캐싱을 자동으로 하게 된다. API 클라이언트 개발자가 거부감이 들리 없다고 생각된다.   \n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [51강 - CORS](51-cors.md)\n- [53강 - Partial Response](53-partial-response.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/53-partial-response.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 55\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 53강 - Partial Response\n\n[52강 - Caching](lessons/52-caching.md) 에서 네트워크 대역폭을 줄이는 일이, 대형 서비스로 발전할 때 얼마나 중요한 일인지 배워 보았다. Partial Response 는 API 클라이언트가 필요한 필드만 골라서 받을 수 있도록 하는 장치로서 역시 동일한 이유로 API 서버에서 제공되면 좋은 기능이다.\n\n지난 강의에서 캐싱을 구현했는데, Production 환경에서 꼭 필요한 기능이지만, Development 환경에서는 수정한 결과가 캐싱때문에 바로 표시되지 않는 문제가 있다. 이번 강좌에서도 응답을 수정하고, 그 결과를 봐야 할 때 매번 `$ php artisan cache:clear` 명령으로 캐시를 버리는 개발 프로세스는 아주 비 효율적이다. 개발 환경에서 캐시를 끌 수 있도록 하는 Refactoring 을 먼저 하고, Partial Response 를 살펴 보도록 하자.\n\n### 리팩토링 I - 캐싱 기능 토글\n\n#### Config (설정)\n\n캐싱을 On/Off 할 수 있는 설정이 필요할 것 같다. 라라벨의 좋은 점 중에 하나가, config 폴더 아래에 만든 파일은 `config('파일명.키')` 로 값을 읽을 수 있다는 점이다. 'config/project.php' 를 만들자.\n \n```php\n// config/project.php\n\nreturn [\n    'cache' => ! env('APP_DEBUG', false),\n];\n```\n\n부정 연산자 (`!`) 를 이용해서, '.env' 파일에 정의된 `APP_DEBUG=true` 이면 캐싱을 끄고, 반대이면 켜도록 하였다. 이제 프로젝트의 코드 어디서든 `config('project.cache')` 로 설정 값을 읽을 수 있다.\n \n#### Controller\n\n지난 강의에서 캐싱 기능 구현을 위해 수정한 컨트롤러 부분을 모두 수정해야 한다. 캐싱은 아주 일반적이고 자주 사용하는 기능인데, 모든 컨트롤러의 캐싱이 필요한 메소드에서 조건문으로 설정 값을 확인하는 일은 DRY (==Don't Repeat Yourself) 원칙에 어긋난다. 추출하여 부모 클래스로 옮기자.\n\n새로운 기능을 추가할 때, 사용자 입장에서 어떻게 사용할지를 먼저 생각해 보고, 그에 맞게 기능을 개발하는 것은 좋은 습관이다. `ArticlesController` 에서 부모 클래스의 캐시 기능을 어떻게 사용할 지 먼저 작성해 보자. 참고로, 전 강좌에서도 지적한 바 있듯이 부모 클래스보다는 사실상 Repository 가 더 적절한 위치이다.\n\n`cache(string $key, int $minites, mixed $query, string $method, mixed ...$param)` 으로 사용하면 좋을 것 같다. \n\n-   `$key`\n    : 캐시키\n    \n-   `$minutes`\n    : 캐싱 유지 기간 (분)\n    \n-   `$query`\n    : 모델 (==데이터베이스) 쿼리\n\n-   `$args`\n    : 여기서는 `paginate`. 메소드를 떼낸 이유는 `$query` 에 `paginate()` 를 붙여 버리면 DB 쿼리를 해 버리기 때문이다. 이러면 캐싱을 할 수 없기 때문이다.\n\n-   `...$param`\n    : PHP 의 [Splat Operator](http://php.net/manual/kr/migration56.new-features.php#migration56.new-features.splat) (`...`) 를 사용한 `$method` 의 인자이다. `cache()` 메소드의 5번째 인자를 포함한 그 뒤에 추가되는 인자들은 모두 이 Splat Operator 로 처리된다. Splat Operator 를 받는 쪽에서 `$args` 는 배열로 인식된다. \n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller\n{\n    // ...\n    \n    public function index(FilterArticlesRequest $request, $slug = null)\n    {\n        $query = $slug ? Tag::whereSlug($slug)->firstOrFail()->articles() : new Article;\n        $cacheKey = cache_key('articles.index');\n        $query = $this->filter($query->orderBy('pin', 'desc'));\n        $param = $request->input(config('project.params.limit'), 5);\n        \n        // 기존 코드\n        // $articles = $this->cache->remember($cacheKey, 5, function() use($query, $request) {\n        //     return $this->filter($query->orderBy('pin', 'desc'))->paginate($request->input(config('project.params.limit'), 5));\n        // });\n        $articles = $this->cache($cacheKey, 5, $query, $method, $param);\n\n        return $this->respondCollection($articles, $cacheKey);\n    }\n    \n    // show() 메소드는 코드를 생략한다.\n}\n```\n\n`cache()` 메소드를 구현하자.\n\nSplat Operator 로 넘어온 값을 `implode(string $glue, array $pieces)` PHP 내장 함수로 조합했다. 캐싱 설정을 확인한 후, 꺼져 있으면 Early Return 을 하고 있다. `$this->cache->...` 로 시작하는 부분은 지난 강의에서 자식 클래스인 `ArticlesController` 에서 썼던 코드와 동일하다.\n\n```php\n// app/Http/Controllers/Controller.php\n\nclass Controller extends BaseController\n{\n    // ...\n\n    protected function cache($key, $minutes, $query, $method, ...$args)\n    {\n        $args = (! empty($args)) ? implode(',', $args) : null;\n\n        if (config('project.cache') === false) {\n            return $query->{$method}($args);\n        }\n\n        return $this->cache->remember($key, $minutes, function() use($query, $method, $args){\n            return $query->{$method}($args);\n        });\n    }\n```\n\n**`참고`** 코드 내에서 `else` 를 사용하고 있다면, 다시 한번 살펴 보자. 기술 용어로 [Code Smell](https://en.wikipedia.org/wiki/Code_smell) 이라 하는데, `else` 가 들어가면 나쁜 코드일 가능성이 크다. 위의 경우도 Early Return 을 통해서 `if(...) {...} else {...}` 를 쓸 것을 `if` 로만 사용하고 있다. Early Return 을 사용하는 방법은 에러나, 예외를 던져야 할 조건을 먼저 검사해서 빨리 반환값을 던져 버리는 것이다.\n\n**`참고`** `use` 키워드는 전역에 정의된 변수를 [`Closure`](http://php.net/manual/kr/class.closure.php) 컨텍스트로 넘길때 사용한다.\n \n**`참고`** `{$method}($args);` 에서 중괄호를 사용하고 있다. 우리 프로젝트의 이 코드 부분에서 중괄호 (==Curly Brace) 가 없어도 동작하지만, 중괄호를 쓰는 것이 좋은 습관이다. `$foo='bar; ${$foo}='baz';` 처럼 변수의 값을 변수의 이름으로 사용할 때, 변수의 값을 메소드 이름으로 사용할 때 등에 중괄호를 사용한다.  \n\n자식 컨트롤러인 `ArticlesController::__construct()` 에 있던 `$this->cache` 속성 선언은 더 이상 필요 없다. 대신 부모 클래스인 `Controller::__construct()` 에 필요하므로 옮기자. 그런데 문제가 있다.\n\n#### Interface\n\n`Controller::__construct()` 에 `$this->cache` 를 선언하려고 보니, 캐시 태그가 필요하다. 이는 각 컨트롤러마다 달라져야 하는 값이다. 다른 구조도 있겠지만, 여기서는 다음과 같이 해 보자.\n \n-  `Interface Cacheable` 을 만들고, `cacheTags` 메소드를 정의하자.\n-  캐싱이 필요한 컨트롤러는 `Cacheable` 인터페이스를 구현하도록 하자. 이렇게 함으로써, `Cacheable` 인터페이스를 구현한 컨트롤러는 `cacheTags` 메소드를 반드시 포함해야 한다.\n-  부모 컨트롤러의 생성자에서 이 클래스 인스턴스 (==오브젝트, `$this`) 가 `Cacheable` 인터페이스를 구현한 객체인지 검사하고, 검사에 통과할 경우 `cacheTags` 메소드를 호출하여 캐시 태그를 얻어 오자.\n\n인터페이스를 정의하자. \n\n참고로 라라벨 프레임웍 코드를 보면, `Illuminate\\Contracts` 라는 네임스페이스를 많이 접하게 된다. 여기에 라라벨 인터페이스들이 모두 정의되어 있다. 이름에서 보듯이 인터페이스는 계약 (==Contract) 이다. \"인터페이스: 클래스야, 나를 구현하려면 내가 정한 원칙/계약을 따라야 해\", \"클래스: 니가 정한 원칙을 지킬께\" 라고 서로 말하는 것이다. \n\n인터페이스에서 정의한 메소드를 클래스에서 구현하지 않거나, 메소드 인자의 타입이 다르면 PHP 는 실행 오류를 낸다.\n \n```php\n// app/Http/Controllers/Cacheable.php \n\n<?php\n\nnamespace App\\Http\\Controllers;\n\ninterface Cacheable\n{\n    public function cacheKeys();\n}\n```\n\n방금 만든 인터페이스를 `implements` 키워드를 사용 하여 `ArticlesController` 에 적용하자. \n\n```php\n// app/Http/Controllers/ArticlesController.php\n\nclass ArticlesController extends Controller implements Cacheable\n{\n    // ...\n    \n    public function cacheKeys()\n    {\n        return 'articles';\n    }\n}\n```\n\n자, 이제 `Cacheable` 인터페이스를 구현한 자식 컨트롤러에 `cacheTags()` 메소드가 무조건 있다는 것을 알고 있으니, 안전하게 부모 컨트롤러에서 `$this->cacheTags()` 를 실행할 수 있다.\n\n```php\n// app/Http/Controllers/Controller.php\n\nclass Controller extends BaseController\n{\n    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;\n\n    protected $cache;\n\n    public function __construct() {\n        // ...\n        \n        $this->cache = taggable() ? app('cache')->tags($this->cacheKeys()) : app('cache');\n    }\n    \n    // ...\n}\n```\n\n그런데, 여기서 또 문제가 있다.\n\n#### Reflection\n\n그럼, 모든 자식 컨트롤러가 `Cacheable` 인터페이스를 구현해야 하는가? \n\n이런 방법이 있긴 하다.\n\n```php\n// NotExistingChildController.php\n\npublic function cacheTags()\n{\n    throw new \\Exception('This class does\\'t require cache feature !!!');\n}\n```\n\n사용하지도 않을 메소드를 구현하게 하는 것은 잘못된 디자인일 뿐더러, 생성자에서 `cacheTags()` 를 호출하기 때문에 저렇게 하면 컨트롤러 전체를 쓸 수 없게 된다. \n\n캐싱 기능이 필요 없는 `CommentsController` 등은 인터페이스를 구현하지 않아도 되도록 하자. 다시 말하면, `CommentsController` 가 생성될 때 부모 클래스에서 `cacheTags` 가 호출되지 않도록 한다는 얘기다.\n\n이를 위해 [`class_implements(mixed $class)`](http://php.net/manual/en/function.class-implements.php) PHP 내장함수를 응용할 수도 있지만, 우리는 여기서 OOP 의 꽃이라 불리우는 [`ReflectionClass`](http://php.net/manual/en/book.reflection.php) 기능을 이용해 볼 것이다. 무엇인지에 대해서는 [What is Reflection in PHP?](http://culttt.com/2014/07/02/reflection-php/) 포스트를 참고하도록 하자.\n\n```php\n// app/Http/Controllers/Controller.php\n\nclass Controller extends BaseController\n{\n    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;\n\n    protected $cache;\n\n    public function __construct() {\n        // ...\n        \n        $this->cache = app('cache');\n\n        if ((new \\ReflectionClass($this))->implementsInterface(\\App\\Http\\Controllers\\Cacheable::class) and taggable()) {\n            $this->cache = app('cache')->tags($this->cacheTags());\n        }\n    }\n    \n    // ...\n}\n```\n\n잠깐 객체 지향 프로그랭의 기본 몇가지만 짚고 넘어가자.\n\nreflection 은 투영, 반사를 의미하는 영어단어이다. `ReflectionClass` 는 인자로 받은 인스턴스의 모습을 투영해 준다. 대부분의 OOP 언어들이 가지고 있는 기능이며, 일종의 Hack 이라 할 수 있다. 꽃이라 한 이유는, 이 기능을 잘 사용하면 `private` 로 정의된 메소드도 끌어내서 사용할 수 있을 만큼 강력하기 때문이다.  \n\n`$this` 키워드는 Instantiate 된 Object 를 의미한다. 아래 코드를 가정해 보자. \n\n```php\n1 $foo = new Bear; \n2 $this->color = 'white';\n3\n4 $bar = new Bear; \n5 $this->color = 'black';\n```\n\n`$foo` 라는 흰색 곰과 `$bar` 라는 검정색 곰을 만들었다. 이 둘은 모두 `Bear` 란 클래스의 인스턴스이다. 여기서 `$this` 는 `Bear` 클래스를 의미하는 것이 아니다. 2 라인의 `$this` 는 `$foo` 라는 `Bear` 클래스의 인스턴스, 5 라인은 `$bar` 라는 `Bear` 클래스의 인스턴스를 의미한다. \n\n우리 코드의 `ReflectionClass($this)` 에서 `$this` 는 이 부모 클래스를 상속 받은 자식 클래스인 `ArticlesController` 의 인스턴스를 의미한다.   \n\n이제 코드가 깔끔해 졌다. 앞 강에서 DB 쿼리 부분에 대한 서버사이드 캐싱 뿐 아니라, 클라이언트를 위한 Etag/304 기능도 구현했다. 요것도 개발 중에는 상당히 불편하다.\n\n#### Etag & 304\n\n요 부분은 특별히 추출할 것이 없어 쉽다.\n\n```php\n// app/Http/Controllers/Api/V1/ArticlesController.php\n\nclass ArticlesController extends ParentController\n{\n    protected function respondCollection(LengthAwarePaginator $articles, $cacheKey = null)\n    {\n        $reqEtag = request()->getETags();\n        $genEtag = $this->etags($articles, $cacheKey);\n\n        if (config('project.cache') === true and isset($reqEtag[0]) and $reqEtag[0] === $genEtag) {\n            return $this->respondNotModified();\n        }\n\n        // return json()->...\n    }\n    \n    // respondItem() 메소드는 코드를 생략한다.\n}\n```\n\n#### 테스트\n\n브라우저 개발자 도구를 켜 놓은 상태에서 'project.php' 의 `cache` 설정 값을 `true`, `false` 로 바꾸어 가며, 같은 엔드포인트로 여러번 반복 요청을 했을 때, 응답 코드가 어떻게 바뀌는지 눈으로 확인해 보자. 또, 쿼리 개수에는 어떤 영향을 미치는 지도 실험해 보자.\n\n### 리팩토링 II - 캐싱 기능\n\n아주 오래전 앞 강의에서 쿼리를 위한 필드를 만들 때, `f`, `s`, `d`, `...` 등 짧은 필드명을 이용한 것은 Github 의 필드명을 참조한 것이다. 그런데, API 클라이언트, 즉 컴퓨터가 보기엔 `l` 이나 `limit` 나 같은 녀석이겠지만, 클라이언트를 개발하는 사람이 보기에는 가독성과 이해도가 너무 떨어 지는 것 같아, 필드명을 바꾸기로 결심했다.\n\n또, 필드명이 나중에 바뀔 수도 있고 해서, API 를 사용하는 클라이언트 측과, 서버의 코드 사이에 완충 레이어를 하나 더 두기로 했다. 설령, 클라이언트가 사용해야 하는 필드명이 바뀌 더라도, 서버의 코드는 수정할 일이 없도록 말이다.\n \n앞 절에서 만든 'project.php' 는 우리 서비스 전체를 위한 설정들을 저장하기에 가장 좋은 장소이다. 이용하자.\n\n```php\n// config/project.php\n\nreturn [\n    // ...\n    \n    'params'      => [\n        'page'   => 'page',\n        'filter' => 'filter',\n        'limit'  => 'limit',\n        'sort'   => 'sort',\n        'order'  => 'order',\n        'search' => 'q',\n        'select' => 'fields',\n    ],\n    \n    'filters' => [\n        'article' => [\n            'no_comment' => 'No Comment',\n            'not_solved' => 'Not Solved'\n        ]\n    ],\n];\n```\n\n> **`주의`** API 버전을 정의하는 부분에서 한번 설명했지만, 한번 더 강조한다. <br/><br/>\n> API 를 탑재한 클라이언트 앱이 사용자에게 뿌려지는 순간, 앞서 말한 필드명이 바뀌는 등, API 스펙을 바꾸는 행위는 자제해야 한다. 바뀐 API 스펙을 탑재하여 클라이언트 앱을 업데이트하였다 해도, 이를 사용하는 사용자가 즉시 업데이트를 할지는 전혀 알 수 없는 일이다. 갑작스런 API 스펙 변경에, 예전 스펙대로 동작하는 클라이언트 앱들은 전혀 동작하지 않게 될 것이고, 여러번 말했지만 서비스는 망한다.<br/><br/> \n> 클라이언트 코드를 서버 개발자가 언제든 배포할 수 있는 웹 (물론 웹도 클라이언트 측의 캐싱이 만료될 때 까지는 문제가 있을 수 있다.) 과는 차원이 다르다는 점을 기억하자. 그뿐인가, API 서버에 어떤 녀석 (User Agent) 이 요청을 할지.. CURL CLI 일 수도, `fsockopen(string $hostname, int $port)` PHP 내장 함수를 이용한 앱일 수도 있다는 점을 염두해 두자. <br/><br/>\n> 코드 에디터를 열기 전에, API 스펙을 설계하는 일이 먼저다. 바로 다음 강좌에서 다루려고 한다. \n\n적용되는 부분이 여러군데 있는데 그 중 한군데만 살펴보자.\n\n```php\n// app/Http/Requests/FilterArticlesRequest.php\n\nclass FilterArticlesRequest extends Request\n{\n    // ...\n    \n    public function rules()\n    {\n        $params = config('project.params');\n        $filters = implode(',', array_keys(config('project.filters.article')));\n\n        return [\n            $params['filter'] => \"in:{$filters}\",\n            $params['limit']  => 'size:1,10',\n            $params['sort']   => 'in:created_at,view_count,created',\n            $params['order']  => 'in:asc,desc',\n            $params['search'] => 'alpha_dash',\n            $params['page']   => '',\n        ];\n    }\n}\n```\n\n주제에 조금 벗어난 얘기지만, 없는 필드에 대해서 DB 쿼리를 하면 `Illuminate\\Database\\QueryException` 이 발생하기 때문에, API 클라이언트에게 허용할 필드들을 미리 지정해 주고, DB 쿼리 까지 도달하기 전에 미리 걸러내는 것이 좋은 디자인이라 할 수 있다. \n\n그 외 `App\\Http\\Controllers\\ArticlesController::filter()` 메소드를 추상화해서 `App\\Http\\Controllers\\Controller::filter()` 로 옮겼고, 'config/project.php' 의 설정을 이용해서 HTML 뷰의 내용을 수정하는 작업을 좀 더 했으나, 설명과 코드는 생략한다. [Github Commit 로그](https://github.com/appkr/l5essential/commits/master) 에서 확인해 보자.\n\n### Partial Response\n\n#### 패키지 업데이트\n\nPartial Response 를 위해 특별히 더 구현할 것은 없다. 왜냐하면, 우리 프로젝트에서 사용하는 [`appkr/api`](https://github.com/appkr/api) 패키지에 이미 포함되어 있기 때문이다. 사용법만 살펴 볼 것이다. \n\n해당 기능은 필자가 최근에 추가했으므로, 최신 버전이 아니라면 아래와 같이 업그레이드 하자.\n \n```sh\n$ composer update\n\n# 수정한 설정이 있다면 수동으로 머지하자. \n$ rm config/api.php\n$ php artisan vendor:publish --provider=\"Appkr\\Api\\ApiServiceProvider\"\n```\n\n기존에 artisan CLI 의 `make:transformer` 를 이용해 Transformer 를 만들었다면, 이번 강좌의 코드를 참조해서 수정하도록 하자.\n\n```php\n// app/Transformers/ArticleTransformer.php\n\nclass ArticleTransformer extends TransformerAbstract\n{\n    public function transform(Article $article)\n    {\n        $payload = [/* ... */];\n        \n        if ($fields = $this->getPartialFields()) {\n            $payload = array_only($payload, $fields);\n        }\n\n        return $payload;\n    }\n    \n    public function includeComments(Article $article, ParamBag $params = null)\n    {\n        $transformer = new \\App\\Transformers\\CommentTransformer($params);\n\n        $parsed = $this->getParsedParams();\n\n        // ...\n    }\n    \n    public function includeAuthor(Article $article, ParamBag $params = null)\n    {\n        return $this->item($article->author, new \\App\\Transformers\\UserTransformer($params));\n    }\n    \n    // ...\n}\n```\n\n#### 테스트\n\nPartial Response 를 구현하는 방법은 여러 가지가 있을 텐데, 왜 Transformer (~=Presentation Layer) 에 구현했는가 라는 의문이 들 수 있다. 가령, fields 라는 쿼리스트링 필드명을 쓴다면, 모델 쿼리할 때 `Article::select($request->input('fields'))->...` 처럼 구현할 수도 있다. 그런데 이렇게 쿼리 레이어에서 수정해 버리면, 쿼리 결과에 의존하는 나머지 코드들이 모두 망가질 가능성이 크다.\n\n우리가 HTML 뷰를 응답할 때, 모델에서 모든 속성값들을 쿼리해서 가져온 후, 뷰에서 필요한 속성들만 바인딩해서 썼다. 그거랑 동일한 개념이라고 보면 된다.\n\n우선 테스트를 위해 앞 절에서 구현한 기능을 설정하자.\n \n```php\n// config/project.php\n\nreturn [\n    'cache' => false, // ! env('APP_DEBUG', false),\n    \n    // ...\n];\n```\n\n서버를 부트업하고, 브라우저나 PostMan 에서 아래 주소를 방문해 보자.\n\n```http\nGET /v1/articles?fields=id,content_raw,link&include=comments:limit(1|0):fields(id|content_raw|author)\n```\n\n![](./images/53-partial-response-img-01.png)\n\n부모 리소스를 선택할 때는 `fields` 값의 구분자로 콤마 (`,`) 를 사용하고, 자식 리소스에 대해서는 파이프 (`|`) 문자를 사용한다는 점을 주의하자.\n\nPresentation Layer 에서 응답할 내용을 제어해서 좋은 점 또 한가지는, API 클라이언트로 부터 넘겨 받은 필드들이 DB 쿼리에 사용되지 않으므로 `QueryException` 이 발생할 염려가 없다는 점이다. 없는 필드가 넘어오면 그냥 무시된다.\n\n#### 설정\n\n'config/api.php' 를 열어 어떤 설정을 수정할 수 있는 지 확인해 보자.\n\n```php\n// config/api.php\n\nreturn [\n    'include' => [\n        // 자식 리소스를 포함할 때 사용할 쿼리스트링의 필드 이름을 바꿀 수 있다.\n        // 기본 값은 'include' 이다.\n        'key' => 'include',\n        'params' => [\n            // limit, sort 의 기본값을 정의할 수 있다.\n            'limit' => [3, 0],\n            'sort' => ['created_at', 'desc'],\n        ],\n    ],\n\n    'partial' => [\n        // Partial Response 에 사용할 쿼리스트링의 필드 이름을 바꿀 수 있다.\n        // 기본 값은 'fields' 이다.\n        'key' => 'fields',\n    ],\n    \n    // ...\n];\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [52강 - Caching](52-caching.md)\n- [54강 - API Documents](54-api-docs.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/54-api-docs.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 56\n---\n\n# 실전 프로젝트 3 - RESTful API\n\n## 54강 - API Documents\n\n### 잡담\n\n필자의 경험에 비추어 보면 대기업이 좋은 점도 있었다.\n\n-   실무에서 실수를 하더라도 결재 라인을 타는 과정에서 걸러질 가능성이 크다.\n-   문제가 걸러지지 않아 세상에 제품이나 서비스 뿌려졌더라도 그로 인해 회사가 망할 지경에 이르지는 않는다.\n-   업무 프로세스가 잘 갖추어져 있다.\n\n바꾸어, 중소기업믜 문제점을 지적해 보자.\n\n-   말단 신입 사원의 작은 실수 하나도 사업에 치명타를 입힌다. (e.g. 신입 사원에게 Production 서버의 root 권한을 줬는데, 실수로 `# rm -rf *`)  \n-   이런 걸 걸러 줄 시스템적인 장치가 탄탄하지 않다. \n-   업무 프로세스가 잘 정리되지 않았다. (e.g. 개업날 식당에 가면, 허둥지둥 대기만 하고, 대접은 못받는 거랑 마찬가지~)\n\n대신 대기업의 문제점은 업무 속도가 짜증날 정도로 늦다는 점이고, 중소기업은 반대다. [52강 - Caching](52-caching.md) 에서 \"적정기술\" 이란 잡담을 나누었는데, 어른이 되는 꿈을 품고 사업을 하는 것이고, 또 대기업으로 성장하기 위해서는 적정 수준에서 규모에 적합한 업무 프로세스를 개발하고 적용해야 한다.\n\n그런데, 규모에 상관없이 아래 프로세스는 꼭 했으면 좋겠다. (기업마다 용어는 다를 수 있다)\n\n-   PRD (==Product/Service Require Document)\n\n    스펙이다. 가령 우리가 [31강 - 포럼 요구사항 기획](31-forum-features.md) 에서 봤던 내용을 좀 더 구체화해서, \"사용자는 이메일과 비밀번호를 이용해 로그인한다\" 처럼 상위 설계를 하는 것이다.\n    \n    이 문서를 기반으로 개발팀이 Functional 스펙 과 개발 계획을 수립합니다. 이 문서를 보고 경영진이나 투자자는 회사가 기획한 제품/서비스가 무엇이고 어떤 기대효과가 있을 지를 이해할 수 있고, 그에 따라 필요한 의사결정을 할 수 있다. 영업이나 재무하시는 분들은 이 문서를 보고 장기 영업/자금 예측을 할 수 있고, 인사는 성과 평가의 기초 자료로 활용할 수 있다. PRD 는 한번에 완성되는 것이 아니라, 프로젝트를 진행하면서 여러 이해관계자가 지속적으로 논의하고 다듬어야 한다.\n    \n-   Story board\n\n    PRD 를 기초로 제품/서비스를 좀 더 구체화한 화면 설계와 동작 시나리오이다. 스토리 보드는 업무량을 가늠하는 척도가 된다. UI 개발자들은 스토리보드를 참고해서 마크업을 작성하고, 서버 개발자는 백엔드 코드를 작성하게 된다.\n      \n-   API Documentation\n\n    이번 강좌의 주제이다. 우리 강좌에서는 코드를 먼저 구현하고 문서를 작성하는 순으로 순서가 뒤집어 졌지만... 실무에서는 항상 문서를 먼저 만들 것을 권장한다. API 문서만 가지고 클라이언트 개발자는 작업을 시작할 수 있고, API 문서를 가지고 서버 개발자는 구현을 하게된다. 이런 이유로 API 문서가 반드시 먼저 개발되어야 한다.\n\n-   Testing\n\n    제품/서비스의 특징이 달라 집집마다 천차만별인게 테스팅이다. 유닛이나 통합테스트가 불가한 시나리오도 있어, 사람이 직접 필드를 돌거나 해야 하는 제품 이나 기능들도 있다. 상황이 어떻든 테스팅 프로세스가 있어야, 개발자는 발 뻗고 편히 잠자리에 누울 수 있다. 특히 테스트 코드가 있다면 코드 리팩토링이나 신규 기능 추가시 테스트에 소요되는 시간을 상당히 단축할 수 있다.  \n\n위 프로세스의 소유자는 누구냐? 라고 질문할 수 있다. 필자는 이 부분도 \"폭탄 떠넘기기\"라 생각한다. 작은 회사에 기획자, 개발자 구분이 어디 있으랴? 심지어 구글이나 페이스북에는 기획팀이 없고 개발팀이 a-Z, 다시 말하면 기획~개발~마케팅 까지 다 한다는 점을 타산지석으로 삼아야 한다. 시쳇말로 월급 받으면 다 할 수 있는 일이다. 디자인은 예술 영역이라 조금 다르다는 생각이 든다. \n\n### 플랫폼 선택\n\n잡담이 길었다. 본론으로 들어가서... API 문서 만드는 데 왜 플랫폼 선택이 필요하냐고 반문할 수 있다.\n\nAPI 문서는 그냥 워드프로세서나 코드에디터 열고 쓰면 된다. API 를 만든다는 것은 API 문서를 만든다는 내용을 포함하고 있다. API 강좌 시작하면서 얘기했지만, API 를 잘 만드는 방법은 인터넷 공룡들을 따라하는 것이다. API 문서도 마찬가지이다.\n\n-   [Github API v3](https://developer.github.com/v3/)\n-   [YouTube Data API (v3)](https://developers.google.com/youtube/v3/docs/)\n-   [Twitter API](https://dev.twitter.com/rest/public)\n\n이들의 공통적인 특징은 아래와 같다. \n\n-   REST 원칙을 따른다.\n-   API 베스트 프랙티스를 실천한다.\n-   (클라이언트 개발자가 바로 실험해 볼 수 있도록) Tester/Playground 를 제공한다.\n-   (클라이언트 개발자가 복붙해서 사용할 수 있도록) cURL 포함 다양한 플랫폼을 위한 샘플 코드를 제공한다.\n\n워드프로세서로 만드는 것은 누구든 할 수 있으니 생략하고, 인터넷 공룡들의 API 의 장점을 모두 흡수하기 위해, 이 강좌에서는 API 문서를 만드는 플랫폼을 이용할 것이다.\n\n선택 가능한 옵션은 아래와 같다.\n\n-   API Blueprint ([Project site](https://apiblueprint.org/), [Github](https://github.com/apiaryio/api-blueprint))\n-   [Apiary](https://apiary.io/) (==API Blueprint 의 SaaS 버전)\n-   RAML ([Project site](http://raml.org/), [Github](https://github.com/raml-org/raml-spec))\n-   Swagger ([Project site](http://swagger.io/), [Github](https://github.com/swagger-api))\n\n### Apiary 가입 및 프로젝트 생성\n\nSwagger 는 Java 라 패스, RAML 은 YAML 문법으로 스펙을 써야 해서 패스. 개발자라면 누구나 친숙한 마크다운 (아닌가요? 익숙해 지시길.) 문법으로 스펙을 쉽게 쓸 수 있고, 호스팅까지 제공되는 Apiary 로 선택하자. 필자는 에이피아이어리 라고 읽는데, 매일 쓰라고 다이어리라는 단어를 합성한 것 같아, 이름도 잘 지었다고 생각한다. \n\n참고로 가입 후 30 일 동안 무료로 모든 기능을 사용해 볼 수 있지만, 이후 부터는 요금이 꽤 나온다. 신용카드 없이 가입할 수 있고, 계속 쓰지 않을 것이라면 신용카드 정보를 입력하지 않으면 되기에 걱정없이 사용하자.   \n\n[Apiary](https://apiary.io/) 에 가입하고, 첫 프로젝트를 만들자.\n\n![](./images/54-api-docs-img-01.png)\n\n프로젝트 이름을 입력한다. 처음 가입했다면 무조건 하나를 만들라는 창이 뜨는데, 거기서 이름을 입력하면 된다.\n\n![](./images/54-api-docs-img-02.png)\n\n에디터 창이 떴을 것이다. 이 에디터는 문법 오류를 잡아주고 미리 보기도 보여 주므로, 첫 프로젝트는 여기서 API 문서를 쓰자. 익숙해지면 로컬 프로젝트 디렉토리에서 `apiary.apib` 파일을 만들어 스펙을 쓰고, Github 에 배포하면 자동으로 API 문서가 업데이트되도록 하자.\n\n![](./images/54-api-docs-img-03.png)\n\n### API Blueprint 문법\n\nApiary 는 API Bluepint 문법을 구현한 호스팅 서비스의 이름이다. \n\n[API Blueprint 문법](https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md) 은 기본적으로 그냥 마크다운이다. [예약어](https://github.com/apiaryio/api-blueprint/blob/master/API%20Blueprint%20Specification.md#def-keywords) 는 문서의 타이틀 (`# title`, `## title`, `### title`) 영역이나, 목록 (`- list item`) 영역에 사용하지 말아야 한다. 이 약속만 지키면, 타이틀이나 목록을 자유롭게 쓸 수 있고, 최종 API 문서의 본문에 잘 렌더링되어 표출된다.\n\n아래는 꼭 알아야 할 기본적인 API Blueprint 문법이다.\n\n**`알림`** 이해도를 높이기 위해 블레이드의 `{{}}` 문법을 차용해서 String Interpolation 을 표기하였다. `{{}}` 를 제외한 나머지 기호 (e.g. `` ` ``, `{}`, `[]`, `()`, `-`, `#`) 들은 그대로 써야 하는 것들이다.\n**`알림`** 리스트 표현을 위해 Dash (`-`) 를 썼는데, Asterisk (`*`), Plus (`+`) 기호도 쓸 수 있다. \n\n-   문서의 가장 첫 줄은 `FORMAT: 1A` 로 시작한다.\n-   두번째 줄은 `HOST: http://your-host` 를 쓴다.\n-   세번째 줄은 사용자에게 표출될 API 이름, `# Welcome to Blah Blah API` 와 같은 타이틀과 그 아래에 설명을 자유롭게 담는다.\n-   그 이후 내용들은 모두 본문으로 간주된다.\n    -   본문은 `# group {{Group Name}}`, `## {{Resource Name}} [{{Endpoint}}]`, `### {{Action Name}} [HEAD|GET|POST|PUT\\PATCH|DELETE {{Endpoint override, if any...}}]` 순으로 진행된다.\n    -   `### {{Action Name}}` 은 다시 `- request {{Optional Request Name}}`, `- response {{HTTP Status Code}} ({{Content Type}})` 와 같은 하위 요소를 포함할 수 있다.\n    -   `- request` 는 `- headers`, `- body` 하위 요소를 가질 수 있다.\n    -   `- response` 도 `- headers`, `- body` 하위 요소를 가질 수 있다.\n    -   `- headers`, `- body` 의 내용은 `            Accept: application/json` 처럼, 12 space 들여쓰기 해야 한다.\n    -   `- headers`, `- body` 키워드 없이 `- request`, `- response` 아래에 바로 Request 또는 Response Payload 를 쓰면 `- body` 의 내용으로 해석된다.\n-   Url Endpoint\n    -   `/v1/articles/{id}` 처럼 Route Parameter 가 있을 때는,  `### {{Action Name}}` 또는 `- request` 하위에 `- parameters` 를 정의할 수 있다.\n    -   `- parameters` 는 `` - id: `{{example id}}` `` 처럼 Route Parameter 값을 정의할 수 있다.\n    -   쿼리스트링은 `/v1/articles{?field,another}` 식으로 쓸 수 있다.\n\n이 정도만 알아도 훌륭한 Apiary 서비스에서 훌륭한 API 를 작성할 수 있다. 같이 해 보자.\n \n### Hello Apiary\n\nApiary 를 방문하여 프로젝트를 생성한 후, 열린 에디터 창에서 아래와 같이 입력한 후 <kbd>Save & Publish</kbd> 버튼을 누르자. Resource 가 없는 정말 간단한 예제이다.\n\n```apib\nFORMAT: 1A\n\n# The Simplest API\n\n마크다운 영역 - jXUqC9KaU9Zr5ZIM\n\n# GET /\n\n마크다운 영역 - 8FgmhqJ6JmiboL0Q\n\n-   Response 200 (text/plain)\n\n        Hello World!\n```\n\n![](./images/54-api-docs-img-04.png)\n\n### Apiary with Resource\n\n아래 예제를 꼼꼼이 읽어 보자. 에디터에 붙여 넣고 어떻게 표현되지는 확인하자. <kbd>Save & Publish</kbd> 버튼을 누른 후 시험해 보자.\n\n```apib\nFORMAT: 1A\nHOST: http://api.appkr.kr\n\n# myProject API\n\nmyProject API 에 오신 것을 환영합니다.\n\n# group Authentication\n\n마크다운 영역 - 0QUzt3lZmM6SNg13\n\n## User Registration [/auth/register]\n\n마크다운 영역 - unRx5VBYJloH8ZVi\n\n### 예약어가 포함되지 않은 타이틀은 그냥 HTML <H3> Element 로 렌더링 된다.\n\n마크다운 영역 - K7C7ZjOTwxB5OlFi\n\n-   list - N1DGocGMwgHdy2c3\n-   list - yXuAdYAurN74hH4W\n\n\\```php\n// fenced code block 도 안될리 없다.\n\necho 'Hello Apiary';\n\\```\n\n### User Registration [POST]\n\n-   request\n\n    -   headers\n        \n            Accept: application/json\n            Content-type: application/json\n        \n    -   body\n    \n            {\n                \"name\": \"John Doe\",\n                \"email\": \"john@example.com\",\n                \"password\": \"password\",\n                \"password_confirmation\": \"password\"\n            }\n        \n-   response 201 (application/json)\n\n    -   body\n    \n            {\n                \"success\": {\n                    \"code\": 201,\n                    \"message\": \"Created\"\n                },\n                \"meta\": {\n                    \"token\": \"header.payload.signature\"\n                }\n            }\n```\n\n위 예제에서 사용한 서버는 이 강좌의 [라이브 데모 API 서버](http://api.appkr.kr) 이다. 즉, Production 으로 실험을 해 볼 수 있다는 의미이다.\n\n**`참고`** API 설계 과정, 즉 API 가 구현되기 전에는, Apiary 에서 제공하는 Mock Server 를 이용해서 설계와 시험을 할 수 있다. **클라이언트 개발자가 이것만 가지고 개발을 시작할 수 있다는 의미이다.** \n\n![](./images/54-api-docs-img-05.png)\n\n이 강좌의 라이브 데모 서버에 john@example 사용자는 이미 있으므로 아래와 같은 422 응답을 받았을 것이다.\n\n### Payload Content Type\n\n라라벨은 정말 스마트하다. API 요청의 Payload 를 Form data 로 보내든 JSON 으로 보내든 라라벨은 다 잡아 낸다. 가령, 요청 Payload 를 `{\"name\": \"John Doe\"}` 로 보내면, 라라벨에서는 `Request::input('name') // 'John Doe'` 로 Form Data 와 동일하게 사용자 요청 값을 읽을 수 있다. PostMan 에서는 `raw` 버튼을 선택하고 JSON 을 직접 입력해서 실험해 볼 수 있다.\n \n![](./images/54-api-docs-img-06.png)\n \n클라이언트에서 Form data 로 보내야 한다면, 아래 처럼 보내야 한다. Javascript Ajax 클라이언트는 Form data 를 아래와 같이 자동으로 포맷팅하는 기능을 가지고 있다. 요점은 API 클라이언트에게 요청 Content-type 에 대한 선택 자유도를 주었다는 점이다. \n\n참고로 `Content-type: application/x-www-form-urlencoded` 으로 지정하고 Ampersand (`&`) 로 Payload 를 이어붙여 인코딩한 후 보낼 수도 있다. 자세한 내용은 [rfc1341](https://www.w3.org/Protocols/rfc1341/4_Content-Type.html) 을 참고.\n\n```http\nPOST /auth/register HTTP/1.1\nHost: api.appkr.kr\nContent-Type: multipart/form-data; boundary=MultipartBoundryYQUn4B08rTQtuN4O\n\n------MultipartBoundryYQUn4B08rTQtuN4O\nContent-Disposition: form-data; name=\"name\"\n\njohn\n------MultipartBoundryYQUn4B08rTQtuN4O\nContent-Disposition: form-data; name=\"email\"\n\njohn@example.com\n\n# ...\n```\n\n### Final Product\n\n문법을 익혔으니 됐다. Apiary 의 모든 기능을 다룬 것이 아니므로, 문서도 읽어 보고 에디터에서 이것 저것 가지고 놀아 보길 권장한다. 그리고 스펙 작성시 중복을 줄여 주는 [MSON](https://github.com/apiaryio/mson) 도 공부해 보시기 바란다. \n\n필자가 작성한 스펙의 소스와 최종 결과물은 여기에 있다. (JWT 가 꼭 있어야 하는 일부는 Apiary Console 이 동작하지 않는다)\n\n-   https://github.com/appkr/l5essential/blob/master/apiary.apib (우상단에 Raw 버튼을 눌러서 보자.)\n-   http://docs.forumv1.apiary.io\n\n## 변경 사항 알림\n\nJWT 리프레시 하는 부분이 빠져서 추가했다.\n\n```php\n// app/Http/routes.php\n\nRoute::group(['domain' => env('API_DOMAIN'), 'as' => 'api.', 'namespace' => 'Api', 'middleware' => 'cors'], function() {\n    Route::post('auth/refresh', [\n        'as'   => 'sessions.refresh',\n        'uses' => 'SessionsController@refresh'\n    ]);\n    \n    // ...\n});\n```\n\n```php\n//app/Http/Controllers/Api/V1/SessionsController.php\n\nclass SessionsController extends ParentController\n{\n    public function __construct()\n    {\n        $this->middleware('jwt.refresh', ['only' => 'refresh']);\n        \n        // ...\n    }\n\n    public function refresh()\n    {\n        // 미들웨어에서 응답을 던지므로 이 메소드는 빈 메소드이다.\n        return true;\n    }\n}\n```\n\n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n- [53강 - Partial Response](53-partial-response.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/999-code-release.md",
    "content": "---\nextends: _layouts.master\nsection: content\ncurrent_index: 59\n---\n\n# 코드 배포 \n\n웹 프로그래머의 삶이 여유롭지는 않다. 왜냐하면, 사용자와 접하게 되는 UI/UX 요소인 CSS/JS 부터 시작해서, 서버 설치 및 운영까지 다 할 줄 알아야 될 뿐 아니라, 하루가 다르게 쏟아져 나오는 새로운 기술과 툴들을 익혀야 하기 때문이다. 그 뿐인가, 개발에 필요한 디자인 패턴이며, 컴퓨터 네트워크의 동작 원리 등등 배워야 할 것이 산적해 있기도 하다. 운이 좋아 FE (==Front End), BE (==Back End), SE (==Systems Engineer) 로 업무가 모두 나뉘어 있는 큰 회사에 소속되어 있다면 좋을텐데... 모두가 그런 행운아의 주인공일 수는 없일 일. 참고로, FE, BE, SE 의 영역을 모두 아우르는 프로그래머를 [풀 스택 프로그래머](https://speakerdeck.com/driesvints/the-laravel-ecosystem?slide=17) 라고 한다.\n\n꼭 웹 프로그래머가 아니더라도, 프로그래머의 삶이 좋은 이유가 있긴 하다. \"배움에 소홀하지 않다면\", 동네 내과 병원의 백발이 성성한 70대 원장님 처럼, 계속 프로그래밍으로 생계를 유지할 수도 있기 때문이다. **\"배움에 소홀하지 않다면...\"**\n\n서론이 길었다. 이번 강좌에서는 코드 배포하는 것을 배울 것이다. 아무리 훌륭한 웹 어플리케이션 또는 서비스를 만들었다고 해도 서버에 올라가서 사용자들에게 서비스가 되지 않는다면, 만들지 않은 서비스 또는 존재하지 않는 서비스나 마찬가지이다. 즉, 코드 배포는 (웹) 프로그래머로서 꼭 알아야 할 주제라고 강조하고 싶다.\n\n## 학습 목표\n  \n1.  **Amazon Web Service 에 웹 서버를 생성해 본다.**\n\n    이 강좌를 쓰고 있는 시점이 2016년 1월 11일(월)인데, 2016년 1월 7일(목)에 Amazon Web Service 의 12번째 Region 인 Seoul Region 이 새롭게 추가되었다. Seoul Region 의 속도나 가격 비교는 [정창훈님의 블로그 포스트](http://blog.iamseapy.com/archives/250) 를 참고하면 되는데, 결론은 빠르고 싸다는 것이다. 필자도 Seoul Region 오픈 다음날, 이 강좌의 라이브 데모 사이트를 Seoul 로 옮겼다.\n    \n2.  **Envoy (SSH Task Runner) 사용법을 익힌다.**\n\n    이 강좌를 통해서 FE 리소스를 관리하고 빌드하는 [Elixir](29-elixir.md), 팀 내 개발 환경을 표준화할 수 있는 [Homestead](02-install-homestead-osx.md) 등의 사용법을 살펴 보았다. 라라벨에서는 원격 서버에서의 복잡하고 반복되는 작업을 편리하게 할 수 있도록 도와 주는 [Envoy](https://laravel.com/docs/envoy) 라는 툴도 제공하고 있다. **Envoy 는 Non-Laravel, Non-PHP 프로젝트에서도 사용할 수 있다** 는 점을 강조하고 싶다.\n    \n3.  **Envoy 와 Git 을 이용하여 코드를 배포해 본다.**\n\n    Envoy 는 코드 배포를 위한 도구가 아니다. Git 도 코드 배포를 위한 도구는 아니다. 하지만, 우리는 이 둘을 결합하여 깔끔하게 동작하는 코드 배포 도구를 만들것이다.\n    \n## Hello AWS Seoul\n\n### 회원 가입 및 Free Tier 사용하기\n\nAmazon 에 신규로 회원 가입을 하면 1년 동안 무료로 [Free Tier 서비스](http://aws.amazon.com/ko/free/) 를 이용할 수 있다. 가입 과정에서 해외 결재가 가능한 신용카드가 필요하니 미리 준비해야 한다. 신용카드는 신분 확인만을 위한 장치일 뿐, 당장 결재가 되는 것은 아니니 거부감을 가질 필요는 없다. 매해 신용카드를 바꾸어 가며, Free Tier 를 옮겨 다니는 분들도 봤다. Shared 호스팅이 아니라, 자신만의 독립서버를 1년 동안 무료로 쓸 수 있는데, 쓰지 않을 이유는 없지 않는가? \n\n\"개발 기간동안은 맘껏 써 봐라. 대신 서비스가 커지고 수익을 창출하면 돈을 좀 내 줘~ 장사 하루 이틀 할 것도 아닌데...\". Amazon 을 갓마존 또는 대인배라고 하는 이유가 있다.\n\n### EC2 인스턴스 생성\n\n회원 가입을 하고 나서 로그인을 하면, AWS 의 모든 제품군이 나열된 AWS Management Console 화면을 볼 수 있을 것이다. 우리는 Compute 섹션의 EC2 만 사용할 것이다. **네비게이션 메뉴 오른쪽 위에 Region 선택 드롭다운에서 반드시 Seoul 로 선택하자.**  \n\n![](./images/999-code-release-img-01.png)\n\nEC2 제품을 눌러 표시된 화면에서, 중앙에 위치한 **\"Launch Instance\"** 버튼을 눌러 새로운 서버 인스턴스를 만들자. 총 7 단계를 거치는데 거의 대부부분이 그냥 **\"Next\"** 로 넘어가면 된다. 이 강좌 작성 이후, Amazon 의 화면 구성이나 UI 는 시간이 지남에 따라 언제든 달라질 수 있으니, 아래 설명을 참고해서 적응적으로 적용하도록 하자.\n\n**Step 1: Choose an Amazon Machine Image (AMI)** 화면에서 `Free Tier Eligible` 이라고 표시된 `Ubuntu Server 14.04 LTS (HVM), SSD Volume Type` 을 선택하자. \n\n![](./images/999-code-release-img-02.png)\n\n2 ~5 단계는 특별한 것이 없다. **Step 6: Configure Security Group** 화면에서 **\"Add Rule\"** 버튼을 눌러, `HTTP` 와 `MYSQL` 을 추가해 주자. 아래 그림의 보안 경고에 보이듯이, HTTP 를 제외하고는 IP 를 지정하는 것이 보안 측면에서 좋다. 참고로, 앞으로 진행하는 과정 중에 자연스럽게 OpenSSL 기반의 Self-signed 인증서가 설치되므로, HTTPS 를 상용으로 쓸 예정이라면 개발 과정에 HTTPS 룰도 추가해 주자. \n\n![](./images/999-code-release-img-03.png)\n\n**Step 6: Configure Security Group** 화면에서 **\"Review and Launch\"** 버튼, **Step 7: Review Instance Launch** 화면에서 **\"Launch\"** 버튼 순으로 진행한다. Step 7 에서 버튼을 누르는 순간, 서버에 SSH 로 접속하기 위한 Private Key 를 만드는 화면이 뜨는데, 키 이름을 입력하고, **\"다운로드\"** 버튼을 눌러 '~/.ssh' 디렉토리 아래에 저장하자. **\"Launch\"** 버튼을 한번 더 누르면 서버 생성이 시작된다. 대략 30초 이내로 끝난다.\n\n**`참고`** AWS 에서 SSH Key 는 인스턴스가 생성될 때 딱 한번 발급/지정할 수 있다. Key 를 잊어 버리면, 서버를 지우고 다시 생성해야 하니, Key 관리를 잘 해야 한다.\n \n![](./images/999-code-release-img-04.png)\n\n콘솔 화면에 다시 돌아오면, 생성된 서버 인스턴스를 확인할 수 있다. IP 와 DNS 는 곧 써야 하니, 어떤 화면 어디 쯤에 위치해 있는지 잘 봐 두자.\n\n![](./images/999-code-release-img-05.png)\n\n### 서버에 접속\n\nSSH 로 접속하기 위한 기본 설정을 수정한다.\n\n좀 전에 다운로드 받은 키 파일은 나 (==소유자) 만 읽기 가능하도록 해야 한다.\n\n```bash\n$ chmod 400 ~/.ssh/aws-demo.pem\n```\n\n매번 `$ ssh ubuntu@52.79.54.81 -i ~/.ssh/aws-demo.pem` 을 쳐야 하는 번거로움을 피하기 위해 SSH config 를 작성한다.\n\n```bash\n$ nano ~/.ssh/config\n```\n\nconfig 파일에 아래 내용을 넣고 <kbd>Ctrl</kbd> + <kbd>x</kbd>, <kbd>Y</kbd> 를 눌러 저장한다. \n\n```bash\nHost aws-demo\n    Hostname 52.79.54.81              # AWS Console 에 표시된 IP 또는 DNS 주소\n    User ubuntu                       # 기본  계정은 'ubuntu' 이다.\n    IdentityFile ~/.ssh/aws-demo.pem  # 좀 전에 다운로드 받은 Private Key 지정\n```\n\n서버로 접속해 보자.\n\n```bash\n# 로컬 컴퓨터에서\n\n$ ssh aws-demo\n# The authenticity of host '52.79.54.81 (52.79.54.81)' can't be established.\n# ECDSA key fingerprint is SHA256:+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.\n# Are you sure you want to continue connecting (yes/no)?\n# \"yes\" 를 타이핑하고 엔터.\n\nubuntu@ip-xxx-xx-x-xx:~$\n```\n\n**`참고`** 앞으로 진행될 내용에서 `ubuntu@ip-xxx-xx-x-xx:~$` 라고 표시되면 원격 서버의 SSH 접속된 콘솔을 의미하며, `...$` 는 사용자 계정, `...#` 는 root 계정을 의미한다. 로컬 컴퓨터의 콘솔은 `$` 로 구분된다.  \n\n## Hello Web Server\n\n### 배포 사용자 계정 준비\n\nSSH 로 서버에 접속되었다. 먼저 이 서버에 코드를 배포하고, 웹 서버의 사용자로 사용될 계정을 만들것이다.\n\n```bash\n$ ssh aws-demo\n\n# sudo 를 계속 쳐야 하는 번거로움을 피하기 위해 아래 명령으로 root 로 로그인한다.\nubuntu@ip-xxx-xx-x-xx:~$ sudo -s\n```\n\n코드 배포에 사용할 `deployer` 란 계정을 만들고, 이 계정을 `www-data` 그룹에 추가하자.\n\n```bash\nroot@ip-xxx-xx-x-xx:~# adduser deployer\n# Enter new UNIX password:      # deployer 계정이 사용할 비밀번호\n# Retype new UNIX password:     # 비밀번호 확인\n# ...\n# Enter the new value, or press ENTER for the default\n#     Full Name []: Deployer\n# Is the information correct? [Y/n] Y\n\nroot@ip-xxx-xx-x-xx:~# usermod -G www-data deployer\n```\n\n`deployer` 계정이 `sudo` 입력 없이 쉘 (==콘솔) 명령을 수행할 수 있는 권한을 주자.\n\n```bash\nroot@ip-xxx-xx-x-xx:~# visudo\n```\n\n열린 파일 마지막에 아래 내용을 추가하자.\n\n```bash\n# deployer 계정에 대한 권한 부여\ndeployer ALL=(ALL:ALL) NOPASSWD: ALL\n\n# www-data 그룹에 대한 권한 부여\n%www-data ALL=(ALL:ALL) NOPASSWD:/usr/sbin/service php5-fpm restart,/usr/sbin/service nginx restart\n```\n\n*참고로 필자는 SE 나 서버 보안 전문가가 아니므로, 이 강좌의 내용이 완벽한 서버 보안을 보장할 수 없다는 점을 양해해 주기 바란다.*\n\n### 서버 프로비저닝\n\n이제 LNMP (==`Linux` + `Nginx` + `MySql` + `PHP`) 스택을 설치하고 웹 서버로 기동할 준비를 해 보자.\n\n필요한 모듈을 한줄씩 쳐서 설치하는 번거로움을 피하기 위해 [appkr/envoy](https://github.com/appkr/envoy) 리포지토리에서 제공하는 스크립트들을 이용할 것이다. 얘네들은 `Git`, `Build Tool`, `Nginx`, `PHP & required Modules`, `Composer`, `MySql`, `...` 등을 한번에 설치하는 역할을 하는 Bash Script 이다. 설치에 5 ~ 10 분 정도 소요된다.\n\n```bash\nroot@ip-xxx-xx-x-xx:~# wget https://raw.githubusercontent.com/appkr/envoy/master/scripts/provision.sh \n\n# 첫번째 인자는 배포 계정 이름, 두번째 인자는 MySql 로그인에 사용할 비밀번호 \nroot@ip-xxx-xx-x-xx:~# bash provision.sh deployer secret\n\n# 작업이 완료된 후, 필요한 모듈들이 잘 설치되었나 확인해 보자.\nroot@ip-xxx-xx-x-xx:~# which nginx\nroot@ip-xxx-xx-x-xx:~# which php5-fpm\nroot@ip-xxx-xx-x-xx:~# which mysql\nroot@ip-xxx-xx-x-xx:~# git --version\nroot@ip-xxx-xx-x-xx:~# php --version\nroot@ip-xxx-xx-x-xx:~# composer --version\nroot@ip-xxx-xx-x-xx:~# ...\n```\n\nNginx Sites 를 빠르게 만들기 위한 `serve.sh` Bash Script 도 다운로드 받아 이용하자. 다행히 요건 순식간에 끝난다.\n\n```bash\nroot@ip-xxx-xx-x-xx:~# wget https://raw.githubusercontent.com/appkr/envoy/master/scripts/serve.sh\n\n# 첫번째 인자는 도메인 이름, 두번째 인자는 Document Root 경로\nroot@ip-xxx-xx-x-xx:~# bash serve.sh ec2-52-79-54-81.ap-northeast-2.compute.amazonaws.com /home/deployer/www/aws-demo/public\n\n# 작업이 완료된 후 잘 설정되었나 확인해 보자. 특히 server_name 과 root 지시자가 정확한지 눈여겨 보자.\nroot@ip-xxx-xx-x-xx:~# cat /etc/nginx/sites-enabled/ec2-52-79-54-81.ap-northeast-2.compute.amazonaws.com\n```\n\n### `deployer` 계정으로 로그인하기\n\n`deployer` 계정으로 로그인하기 위해서 로컬에서 `ssh-keygen` 으로 Key Pair 를 생성하고, 서버에 Public Key 를 등록하는 방법도 있지만, 편의상 여기서는 `ubuntu` 계정의 Public Key 를 그대로 사용하기로 하자.\n\n```bash\n# deployer 계정에 .ssh 디렉토리 생성\nroot@ip-xxx-xx-x-xx:~# mkdir /home/deployer/.ssh\nroot@ip-xxx-xx-x-xx:~# chown deployer:deployer /home/deployer/.ssh\n\n# ubuntu 계정에 등록된 public key 레지스트리를 deployer 계정에 복사\nroot@ip-xxx-xx-x-xx:~# cp /home/ubuntu/.ssh/authorized_keys /home/deployer/.ssh/\n\n# /home/deployer/.ssh 디렉토리 전체에 대한 소유권 부여 \nroot@ip-xxx-xx-x-xx:~# chown deployer:deployer -R /home/deployer/.ssh\n```\n\n이제 로컬로 돌아와서, 생성한 `deployer` 계정으로 서버에 접속할 수 있도록 설정하자. 서버에서 로그아웃 할 때는, 로컬로 돌아올 때 까지 `exit` 를 여러 번 입력하면 된다.\n\n`$ nano ~/.ssh/config` 명령으로 기존 'aws-demo' 외에 'aws-demo-deploy' 란 레코드를 하나 더 만들자. \n\n```bash\nHost aws-demo-deploy\n    Hostname 52.79.54.81\n    User deployer\n    IdentityFile ~/.ssh/aws-demo.pem\n```\n\nSSH 로그인을 해보자.\n\n```bash\n$ ssh aws-demo-deploy\ndeployer@ip-xxx-xx-x-xx:~$\n```\n\n### MySql 서버 접속\n\nMySql 로그인을 해보자.\n\n![](./images/999-code-release-img-08.png)\n\n이제 서버 쪽에 모든 준비는 완료된 상태이다. Envoy 에 대해 배워 보고, 배포 스크립트를 만들어 보자.\n\n## Hello Envoy\n\n### Envoy Executable 설치\n\nEnvoy 문법에 대한 자세한 설명은 [공식 문서](https://laravel.com/docs/envoy) 와 필자의 [슬라이드](http://www.slideshare.net/ssuser7887b3/envoy-56730937) 를 참고하도록 하자.\n\n요약하자면 Envoy 는 로컬 컴퓨터에서 원격 서버에 미리 정의된 작업을 시키는 도구라고 할 수 있다. Envoy Executable 을 로컬 컴퓨터에 설치하자.\n\n```bash\n# 로컬 컴퓨터에서\n\n$ composer global require \"laravel/envoy=~1.0\"\n$ envoy --version\n```\n\n자신의 콘솔 프로파일 (`.zshrc`, `bash_profile`, `.bashrc`, `...`) 에 Composer Global 컴포넌트에 대한 경로 설정 (`export PATH=\"$PATH:$HOME/.composer/vendor/bin\"`) 이 되어 있지 않다면, 추가해 줘야, `$ envoy` 명령을 경로 지정없이 어떤 디렉토리에서든 실행할 수 있다.\n\n**`참고`** Envoy 는 Global 로 설치하지 않고 프로젝트 단위로 설치해도 된다. 단, 이 경우에는 프로젝트 디렉토리에서 `$ vendor/bin/envoy` 로 명령을 실행해야 한다.\n\n### Envoy Script\n\nEnvoy 는 항상 `envoy.blade.php` 가 위치한 프로젝트 디렉토리에서 실행해야 한다. `appkr/envoy` 리포지토리에서 예제 Envoy Script 를 다운로드 받아 수정하여 사용하도록 하자.\n\n```bash\n# 로컬 컴퓨터에서\n\n$ cd myProject\n$ wget https://raw.githubusercontent.com/appkr/envoy/master/envoy.blade.php\n# wget 또는 curl 이 없다면 브라우저로 해당 주소를 방문해서, 본문 내용을 복붙한 envoy.blade.php 파일을 만들고 저장해도 된다.\n```\n\n일단 서버 주소만 수정하고, 첫 Envoy 명령을 수행해 보자. `aws-demo-deploy` 란 이름은 앞 절에서 '~/.ssh/config' 에서 정의한 Hostname 에 대한 별칭임을 기억하자. '~/.ssh/config' 정의가 없었다면 `deployer@52.79.54.81` 로 쓸 수도 있다.\n\n```php\n// envoy.blade.php\n\n@servers(['web' => 'aws-demo-deploy'])\n```\n\n```bash\n# 로컬 컴퓨터에서\n\n$ envoy run hello\n[aws-demo-deploy]: Hello Envoy! Responding from ip-xxx-xx-x-xx\n```\n\n와우~!!! 로컬 컴퓨터에서 SSH 로 접속하지 않고도, 명령 한줄으로 원격 서버에 지정된 계정으로 들어가서 `hello` Task 를 수행하고, 그 수행 결과를 로컬로 다시 되돌려 준 것이다.\n\n### Envoy Script II\n\n배포를 위한 설정들을 변경하자.\n\n```php\n// envoy.blade.php\n\n@setup\n  $path = [\n    // release Task 수행 중에 변수로 사용할 디렉토리 경로들.\n    'base' => '/home/deployer/www',\n    'docroot' => '/home/deployer/www/aws-demo',\n    'shared' => '/home/deployer/www/shared',\n    'release' => '/home/deployer/www/releases',\n  ];\n\n  $required_dirs = [\n    // release Task 수행 중에 없으면 만들어야 할 디렉토리 목록들.\n    $path['base'],\n    $path['shared'],\n    $path['release'],\n  ];\n\n  $shared_item = [\n    // release Task 수행 중에 Symlink 로 연결되어야 할 공유 디렉토리/파일들.\n    '/home/deployer/www/shared/.env' => '.env',\n    '/home/deployer/www/shared/storage' => 'storage',\n    '/home/deployer/www/shared/cache' => 'cache',\n  ];\n\n  $distribution = [\n    // 그냥 두자.\n    // 매 release Task 수행시 마다 아래 정의한 디렉토리에 Git Clone 을 하게 된다.\n    'name' => 'release_' . date('YmdHis'),\n  ];\n\n  $git = [\n    // release Task 에서 Git Clone 을 할 대상이 되는 Git Repo 의 주소.\n    'repo' => 'git@github.com:vendor/project',\n  ];\n@endsetup\n```\n\n서버에 접속한 후, `$shared_item` 에 정의한 디렉토리/파일은 생성해 놓자. 없으면 Symlink 에러날 수 있으니..\n\n```bash\n# $shared_item 디렉토리/파일 목록은 라라벨 프로젝트를 가정하고 설정한 것이다.\n# 다른 프레임웍이라면 공유될 리소스를 알맞게 지정하도록 하자.\n\n$ ssh aws-demo-deloy\n\ndeployer@ip-xxx-xx-x-xx:~$ mkdir www\ndeployer@ip-xxx-xx-x-xx:~$ mkdir www/shared\ndeployer@ip-xxx-xx-x-xx:~$ mkdir www/shares/storage www/shared/cache\ndeployer@ip-xxx-xx-x-xx:~$ touch www/shared/.env\n# .env 에 환경 설정 내용을 채워 놓도록 하자. 내용이 없다면 release Task 의 Composer Install 과정에서 에러가 날 가능성이 있다.\n```\n\n## 코드 배포\n\n### Git Clone 을 위한 Key 설치\n\n우리의 원격 서버가 Github 서버와 통신할 수 있기 위해서는, aws-demo 서버에 Github 접속을 위한 SSH Private Key 가 있어야 한다. 아래 내용은 [Github 공식 문서](https://help.github.com/articles/generating-ssh-keys/) 를 그대로 따라한 것이다.\n\n```bash\n$ ssh aws-demo-deloy\n\ndeployer@ip-xxx-xx-x-xx:~$ ssh-keygen -t rsa -b 4096 -C \"your_email@example.com\"\n# Key 이름과 passphrase 를 넣는 질문이 나오는데 필요하다면 입력하자. 필자의 경우에는 그냥 엔터했다.\n\ndeployer@ip-xxx-xx-x-xx:~$ cat .ssh/id_rsa.pub\n# 콘솔에 출력된 내용을 블럭으로 잡아 복사해 두자.\n```\n\n복사한 내용을 [Github Setting 의 SSH keys 페이지](https://github.com/settings/ssh) 를 방문하여 **\"Add SSH Key\"** 버튼을 눌러 붙여 넣는다.\n \n![](./images/999-code-release-img-07.png)\n\n그러고나서, 아래 과정을 꼭 한번은 거쳐 주어야 한다. Github 서버가 aws-demo 서버를 인식하게 하는 과정이다.\n\n```bash\ndeployer@ip-xxx-xx-x-xx:~$ ssh -T git@github.com\n# Are you sure you want to continue connecting (yes/no)?\n# yes 치고 엔터\n```\n\n### Release\n\n이걸 할려고 이제까지 복잡한 과정을 수행했다. 모든 준비가 완료되었다. 보통 요 앞의 과정까지 숙달된 사람의 경우 스크립트 없이 4시간, 숙달되지 않은 사람의 경우 짧게는 이틀, 좀 헤메면 일주일 걸린다.  \n\n코드를 배포하자.\n\n```bash\n# 로컬 컴퓨터에서\n\n$ envoy run release\n```\n\n![](./images/999-code-release-img-06.png)\n\n앞으로 코드가 변경되어 `$ git push` 를 하고, 서버에 릴리즈해야 할 일이 있다면... 위 명령 한번으로 끝난다. 스크린샷이 aws-demo 가 아니라 필자가 라이브 데모로 사용하는 aws-seoul-deploy 로 되어 있는 점 양해 바란다. 필자의 라이브 데모 사이트의 경우, `release` Task 수행에 총 30 초 정도 소요되었다.\n\n### `release` Task 의 동작 원리\n\n`@servers(['web' => 'aws-demo-deploy'])` 와 `@task('release', ['on' => 'web'])` 에 지정된 서버에 백그라운드에서 SSH 로그인한 후 아래 작업을 순차적으로 진행하고, 그 수행 결과를 로컬 컴퓨터 터미널에 표시해 준다.\n\n1.  `$required_dirs` 에서 정의한 디렉토리가 없다면 생성한다.\n2.  `$path['release'] . '/' . $distribution['name']` 디렉토리에 `$git['repo']` 로 정의한 코드 베이스를 Clone 한다.\n3.  방금 Clone 한 디렉토리에서 Composer Component 를 설치한다.\n4.  방금 Clone 한 디렉토리에 `$shared_item` 에 정의한 공유 디렉토리와 파일을 Symbolic Link 로 연결한다.\n5.  방금 Clone 한 디렉토리를 Nginx 의 Document Root 로 Symbolic Link 한다.\n6.  방금 Clone 한 디렉토리 및 그 하위에 연결된 Symbolic Link 들에 대한 그룹 권한을 `www-data` 로 변경한다.\n\nGit 과 Envoy 를 응용한 이 배포 스크립트의 장점은, \n\n1.  **Zero Conflict**\n    \n    매번 Git Clone 하는 전략을 취함으로써 `$ git push --force` 를 했을 경우, 서버에서 발생할 수 있는 Code Conflict 를 없애준다.\n     \n2.  **Zero Downtime**\n    \n    DB, 캐시/세션 스토리지, 환경설정등은 릴리즈 디렉토리 밖에 존재하면서 릴리즈에 Symlink 로 연결되며, 코드, 의존 모듈 등 모든 준비가 완료된 후, 이번 릴리즈 디렉토리를 Document Root 로 Symlink 하기 때문에, 서비스의 다운 타임이 발생하지 않는다.\n     \n3.  **Release 이력 관리 및 빠른 롤백**\n    \n    매번 기존 코드를 엎어 쓰는 Git Checkout, Git Pull 전략이 아니라, Git Clone 전략을 이용하므로, 이전 릴리즈들도 바로 사용이 가능한 상태로 서버에 그대로 남아 있게 된다. 즉, 릴리즈에 문제가 있을 경우, 이전 릴리즈로 롤백이 가능하단 얘기다. 이 참고용 `envoy.blade.php` 스크립트에는 `release` Task 외에도 `list`, `checkout`, `prune` 등의 추가 Task 를 포함하고 있다. 사용법은 [`appkr/envoy` 문서](https://github.com/appkr/envoy) 또는 코드를 참고하자.  \n    \n<!--@start-->\n---\n\n- [목록으로 돌아가기](../readme.md)\n<!--@end-->\n"
  },
  {
    "path": "lessons/INDEX.md",
    "content": "-   **입문코스-기본기**\n    -   [1강 - 처음 만나는 라라벨](/lessons/01-welcome.md)\n    -   [2강 - 라라벨 5 설치하기](/lessons/02-hello-laravel.md)\n    -   [2강 - 라라벨 5 설치하기 (on Windows)](/lessons/02-install-on-windows.md)\n    -   [3강 - 글로벌 설정 살펴보기](/lessons/03-configuration.md)\n    -   [4강 - Routing 기본기](/lessons/04-routing-basics.md)\n    -   [5강 - 뷰에 데이터 바인딩하기](/lessons/05-pass-data-to-view.md)\n    -   [6강 - 블레이드 101](/lessons/06-blade-101.md)\n    -   [7강 - 블레이드 201](/lessons/07-blade-201.md)\n    -   [8강 - 날 쿼리 :(](/lessons/08-raw-queries.md)\n    -   [9강 - 쿼리 빌더](/lessons/09-query-builder.md)\n    -   [10강 - 엘로퀀트 ORM](/lessons/10-eloquent.md)\n    -   [11강 - DB 마이그레이션](/lessons/11-migration.md)\n    -   [12강 - 컨트롤러](/lessons/12-controller.md)\n    -   [13강 - RESTful 리소스 컨트롤러](/lessons/13-restful-resource-controller.md)\n    -   [14강 - 이름 있는 Route](/lessons/14-named-routes.md)\n    -   [15강 - 중첩된 리소스](/lessons/15-nested-resources.md)\n    -   [16강 - 사용자 인증 기본기](/lessons/16-authentication.md)\n    -   [17강 - 라라벨에 내장된 사용자 인증](/lessons/17-authentication-201.md)\n    -   [18강 - 모델간 관계 맺기](/lessons/18-eloquent-relationships.md)\n    -   [19강 - 데이터 심기](/lessons/19-seeder.md)\n    -   [20강 - Eager 로딩](/lessons/20-eager-loading.md)\n    -   [추가 - 페이징](/lessons/20-1-pagination.md)\n    -   [21강 - 메일 보내기](/lessons/21-mail.md)\n    -   [22강 - 이벤트](/lessons/22-events.md)\n    -   [23강 - 입력 값 유효성 검사](/lessons/23-validation.md)\n    -   [24강 - 예외 처리](/lessons/24-exception-handling.md)\n    -   [25강 - 컴포저](/lessons/25-composer.md)\n-   **중급코스1-Markdown Viewer**\n    -   [26강 - Document 모델](/lessons/26-document-model.md)\n    -   [27강 - Document 컨트롤러](/lessons/27-document-controller.md)\n    -   [28강 - Cache](/lessons/28-cache.md)\n    -   [29강 - Elixir, 만병통치약?](/lessons/29-elixir.md)\n    -   [30강 - Debug & Final Touch](/lessons/30-final-touch.md)\n-   **중급코스2-Forum**\n    -   [31강 - 포럼 요구사항 기획](/lessons/31-forum-features.md)\n    -   [32강 - 사용자 로그인](/lessons/32-login.md)\n    -   [33강 - 소셜 로그인](/lessons/33-social-login.md)\n    -   [34강 - 사용자 역할](/lessons/34-role.md)\n    -   [35강 - 다국어 지원](/lessons/35-locale.md)\n    -   [36강 - 마이그레이션과 모델](/lessons/36-models.md)\n    -   [37강 - Article 기능 구현](/lessons/37-articles.md)\n    -   [38강 - Tag 기능 구현](/lessons/38-tags.md)\n    -   [39강 - Attachment 기능 구현](/lessons/39-attachments.md)\n    -   [32/33 보충 - 인증 리팩토링](/lessons/32n33-auth-refactoring.md)\n    -   [40강 - Comment 기능 구현](/lessons/40-comments.md)\n    -   [41강 - UI 개선](/lessons/41-ui-makeup.md)\n    -   [42강 - 서버 사이드 개선](/lessons/42-be-makeup.md)\n    -   [43강 - 변경 사항 알림](/lessons/43-change-note.md)\n-   **중급코스3-RESTFul API**\n    -   [44강 - API 기본기 및 기획](/lessons/44-api-basic.md)\n    -   [45강 - 기본 구조 잡기](/lessons/45-api-big-picture.md)\n    -   [46강 - JWT 를 이용한 인증](/lessons/46-jwt.md)\n    -   [47강 - 중복 제거 리팩토링](/lessons/47-dry-refactoring.md)\n    -   [48강 - all() is bad](/lessons/48-all-is-bad.md)\n    -   [49강 - API Rate Limit](/lessons/49-rate-limit.md)\n    -   [50강 - 리소스 id 난독화](/lessons/50-id-obfuscation.md)\n    -   [51강 - CORS](/lessons/51-cors.md)\n    -   [52강 - Caching](/lessons/52-caching.md)\n    -   [53강 - Partial Response](/lessons/53-partial-response.md)\n    -   [54강 - API Documents](/lessons/54-api-docs.md)\n-   **번외-기타 잡다한 것들**\n    -   [Homestead 설치 (on Mac)](/lessons/02-install-homestead-osx.md)\n    -   [Homestead 설치 (on Windows)](/lessons/02-install-homestead-windows.md)\n    -   [코드 배포](/lessons/999-code-release.md)\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"devDependencies\": {\n    \"gulp\": \"^3.8.8\"\n  },\n  \"dependencies\": {\n    \"laravel-elixir\": \"^3.0.0\"\n  }\n}\n"
  },
  {
    "path": "phpunit.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         bootstrap=\"bootstrap/autoload.php\"\n         colors=\"true\"\n         convertErrorsToExceptions=\"true\"\n         convertNoticesToExceptions=\"true\"\n         convertWarningsToExceptions=\"true\"\n         processIsolation=\"false\"\n         stopOnFailure=\"false\">\n    <testsuites>\n        <testsuite name=\"Integration Test Suite\">\n            <directory suffix=\".php\">./tests/integration/</directory>\n            <exclude>./tests/integration/Http/Controllers/AuthTest.php</exclude>\n            <exclude>./tests/integration/Http/Controllers/Api/ApiTest.php</exclude>\n        </testsuite>\n    </testsuites>\n    <filter>\n        <whitelist>\n            <directory suffix=\".php\">app/</directory>\n        </whitelist>\n    </filter>\n    <php>\n        <env name=\"APP_ENV\" value=\"testing\"/>\n        <env name=\"CACHE_DRIVER\" value=\"array\"/>\n        <env name=\"SESSION_DRIVER\" value=\"array\"/>\n        <env name=\"QUEUE_DRIVER\" value=\"sync\"/>\n        <env name=\"DB_CONNECTION\" value=\"sqlite\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "public/.htaccess",
    "content": "<IfModule mod_rewrite.c>\n    <IfModule mod_negotiation.c>\n        Options -MultiViews\n    </IfModule>\n\n    RewriteEngine On\n\n    # Redirect to new domain\n    RewriteCond \"%{HTTP_HOST}\"   \"^ec2-52-193-67-224\\.ap-northeast-1\\.compute\\.amazonaws\\.com$\"\n    RewriteRule \"^/?(.*)\"        \"http://l5.appkr.kr/$1\"\n\n    # Redirect Trailing Slashes If Not A Folder...\n    RewriteCond %{REQUEST_FILENAME} !-d\n    RewriteRule ^(.*)/$ /$1 [L,R=301]\n\n    # Handle Front Controller...\n    RewriteCond %{REQUEST_FILENAME} !-d\n    RewriteCond %{REQUEST_FILENAME} !-f\n    RewriteRule ^ index.php [L]\n\n    # Handle Authorization Header...\n    RewriteCond %{HTTP:Authorization} ^(.*)\n    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]\n</IfModule>\n"
  },
  {
    "path": "public/attachments/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "public/build/css/app-4cd4d601dd.css",
    "content": "/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */dfn,span.form-error{font-style:italic}.label,sub,sup{vertical-align:baseline}.btn,.btn-group,.btn-group-vertical,.caret,.checkbox-inline,.radio-inline,img{vertical-align:middle}.fa,.glyphicon{-moz-osx-font-smoothing:grayscale}body,figure{margin:0}.btn-group>.btn-group,.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.dropdown-menu{float:left}.img-responsive,.img-thumbnail,.table,label{max-width:100%}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.pre-scrollable{max-height:340px}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}b,optgroup,strong{font-weight:700}h1{margin:.67em 0}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;margin-top:20px;margin-bottom:20px}pre,textarea{overflow:auto}code,kbd,pre,samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}.glyphicon,.popover,.tooltip,address{font-style:normal}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{blockquote,img,pre,tr{page-break-inside:avoid}*,:after,:before{background:0 0!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:\" (\" attr(href) \")\"}abbr[title]:after{content:\" (\" attr(title) \")\"}a[href^=\"javascript:\"]:after,a[href^=\"#\"]:after{content:\"\"}blockquote,pre{border:1px solid #999}thead{display:table-header-group}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}.btn,.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active,.btn.active,.btn:active,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover,.form-control,.navbar-toggle,.open>.btn-danger.dropdown-toggle,.open>.btn-default.dropdown-toggle,.open>.btn-info.dropdown-toggle,.open>.btn-primary.dropdown-toggle,.open>.btn-success.dropdown-toggle,.open>.btn-warning.dropdown-toggle,div.dropzone,div.preview__forum{background-image:none}.img-thumbnail,body{background-color:#fff}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/bootstrap/glyphicons-halflings-regular.eot);src:url(../fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix) format(\"embedded-opentype\"),url(../fonts/bootstrap/glyphicons-halflings-regular.woff2) format(\"woff2\"),url(../fonts/bootstrap/glyphicons-halflings-regular.woff) format(\"woff\"),url(../fonts/bootstrap/glyphicons-halflings-regular.ttf) format(\"truetype\"),url(../fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format(\"svg\")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-weight:400;line-height:1;-webkit-font-smoothing:antialiased}.glyphicon-asterisk:before{content:\"\\2a\"}.glyphicon-plus:before{content:\"\\2b\"}.glyphicon-eur:before,.glyphicon-euro:before{content:\"\\20ac\"}.glyphicon-minus:before{content:\"\\2212\"}.glyphicon-cloud:before{content:\"\\2601\"}.glyphicon-envelope:before{content:\"\\2709\"}.glyphicon-pencil:before{content:\"\\270f\"}.glyphicon-glass:before{content:\"\\e001\"}.glyphicon-music:before{content:\"\\e002\"}.glyphicon-search:before{content:\"\\e003\"}.glyphicon-heart:before{content:\"\\e005\"}.glyphicon-star:before{content:\"\\e006\"}.glyphicon-star-empty:before{content:\"\\e007\"}.glyphicon-user:before{content:\"\\e008\"}.glyphicon-film:before{content:\"\\e009\"}.glyphicon-th-large:before{content:\"\\e010\"}.glyphicon-th:before{content:\"\\e011\"}.glyphicon-th-list:before{content:\"\\e012\"}.glyphicon-ok:before{content:\"\\e013\"}.glyphicon-remove:before{content:\"\\e014\"}.glyphicon-zoom-in:before{content:\"\\e015\"}.glyphicon-zoom-out:before{content:\"\\e016\"}.glyphicon-off:before{content:\"\\e017\"}.glyphicon-signal:before{content:\"\\e018\"}.glyphicon-cog:before{content:\"\\e019\"}.glyphicon-trash:before{content:\"\\e020\"}.glyphicon-home:before{content:\"\\e021\"}.glyphicon-file:before{content:\"\\e022\"}.glyphicon-time:before{content:\"\\e023\"}.glyphicon-road:before{content:\"\\e024\"}.glyphicon-download-alt:before{content:\"\\e025\"}.glyphicon-download:before{content:\"\\e026\"}.glyphicon-upload:before{content:\"\\e027\"}.glyphicon-inbox:before{content:\"\\e028\"}.glyphicon-play-circle:before{content:\"\\e029\"}.glyphicon-repeat:before{content:\"\\e030\"}.glyphicon-refresh:before{content:\"\\e031\"}.glyphicon-list-alt:before{content:\"\\e032\"}.glyphicon-lock:before{content:\"\\e033\"}.glyphicon-flag:before{content:\"\\e034\"}.glyphicon-headphones:before{content:\"\\e035\"}.glyphicon-volume-off:before{content:\"\\e036\"}.glyphicon-volume-down:before{content:\"\\e037\"}.glyphicon-volume-up:before{content:\"\\e038\"}.glyphicon-qrcode:before{content:\"\\e039\"}.glyphicon-barcode:before{content:\"\\e040\"}.glyphicon-tag:before{content:\"\\e041\"}.glyphicon-tags:before{content:\"\\e042\"}.glyphicon-book:before{content:\"\\e043\"}.glyphicon-bookmark:before{content:\"\\e044\"}.glyphicon-print:before{content:\"\\e045\"}.glyphicon-camera:before{content:\"\\e046\"}.glyphicon-font:before{content:\"\\e047\"}.glyphicon-bold:before{content:\"\\e048\"}.glyphicon-italic:before{content:\"\\e049\"}.glyphicon-text-height:before{content:\"\\e050\"}.glyphicon-text-width:before{content:\"\\e051\"}.glyphicon-align-left:before{content:\"\\e052\"}.glyphicon-align-center:before{content:\"\\e053\"}.glyphicon-align-right:before{content:\"\\e054\"}.glyphicon-align-justify:before{content:\"\\e055\"}.glyphicon-list:before{content:\"\\e056\"}.glyphicon-indent-left:before{content:\"\\e057\"}.glyphicon-indent-right:before{content:\"\\e058\"}.glyphicon-facetime-video:before{content:\"\\e059\"}.glyphicon-picture:before{content:\"\\e060\"}.glyphicon-map-marker:before{content:\"\\e062\"}.glyphicon-adjust:before{content:\"\\e063\"}.glyphicon-tint:before{content:\"\\e064\"}.glyphicon-edit:before{content:\"\\e065\"}.glyphicon-share:before{content:\"\\e066\"}.glyphicon-check:before{content:\"\\e067\"}.glyphicon-move:before{content:\"\\e068\"}.glyphicon-step-backward:before{content:\"\\e069\"}.glyphicon-fast-backward:before{content:\"\\e070\"}.glyphicon-backward:before{content:\"\\e071\"}.glyphicon-play:before{content:\"\\e072\"}.glyphicon-pause:before{content:\"\\e073\"}.glyphicon-stop:before{content:\"\\e074\"}.glyphicon-forward:before{content:\"\\e075\"}.glyphicon-fast-forward:before{content:\"\\e076\"}.glyphicon-step-forward:before{content:\"\\e077\"}.glyphicon-eject:before{content:\"\\e078\"}.glyphicon-chevron-left:before{content:\"\\e079\"}.glyphicon-chevron-right:before{content:\"\\e080\"}.glyphicon-plus-sign:before{content:\"\\e081\"}.glyphicon-minus-sign:before{content:\"\\e082\"}.glyphicon-remove-sign:before{content:\"\\e083\"}.glyphicon-ok-sign:before{content:\"\\e084\"}.glyphicon-question-sign:before{content:\"\\e085\"}.glyphicon-info-sign:before{content:\"\\e086\"}.glyphicon-screenshot:before{content:\"\\e087\"}.glyphicon-remove-circle:before{content:\"\\e088\"}.glyphicon-ok-circle:before{content:\"\\e089\"}.glyphicon-ban-circle:before{content:\"\\e090\"}.glyphicon-arrow-left:before{content:\"\\e091\"}.glyphicon-arrow-right:before{content:\"\\e092\"}.glyphicon-arrow-up:before{content:\"\\e093\"}.glyphicon-arrow-down:before{content:\"\\e094\"}.glyphicon-share-alt:before{content:\"\\e095\"}.glyphicon-resize-full:before{content:\"\\e096\"}.glyphicon-resize-small:before{content:\"\\e097\"}.glyphicon-exclamation-sign:before{content:\"\\e101\"}.glyphicon-gift:before{content:\"\\e102\"}.glyphicon-leaf:before{content:\"\\e103\"}.glyphicon-fire:before{content:\"\\e104\"}.glyphicon-eye-open:before{content:\"\\e105\"}.glyphicon-eye-close:before{content:\"\\e106\"}.glyphicon-warning-sign:before{content:\"\\e107\"}.glyphicon-plane:before{content:\"\\e108\"}.glyphicon-calendar:before{content:\"\\e109\"}.glyphicon-random:before{content:\"\\e110\"}.glyphicon-comment:before{content:\"\\e111\"}.glyphicon-magnet:before{content:\"\\e112\"}.glyphicon-chevron-up:before{content:\"\\e113\"}.glyphicon-chevron-down:before{content:\"\\e114\"}.glyphicon-retweet:before{content:\"\\e115\"}.glyphicon-shopping-cart:before{content:\"\\e116\"}.glyphicon-folder-close:before{content:\"\\e117\"}.glyphicon-folder-open:before{content:\"\\e118\"}.glyphicon-resize-vertical:before{content:\"\\e119\"}.glyphicon-resize-horizontal:before{content:\"\\e120\"}.glyphicon-hdd:before{content:\"\\e121\"}.glyphicon-bullhorn:before{content:\"\\e122\"}.glyphicon-bell:before{content:\"\\e123\"}.glyphicon-certificate:before{content:\"\\e124\"}.glyphicon-thumbs-up:before{content:\"\\e125\"}.glyphicon-thumbs-down:before{content:\"\\e126\"}.glyphicon-hand-right:before{content:\"\\e127\"}.glyphicon-hand-left:before{content:\"\\e128\"}.glyphicon-hand-up:before{content:\"\\e129\"}.glyphicon-hand-down:before{content:\"\\e130\"}.glyphicon-circle-arrow-right:before{content:\"\\e131\"}.glyphicon-circle-arrow-left:before{content:\"\\e132\"}.glyphicon-circle-arrow-up:before{content:\"\\e133\"}.glyphicon-circle-arrow-down:before{content:\"\\e134\"}.glyphicon-globe:before{content:\"\\e135\"}.glyphicon-wrench:before{content:\"\\e136\"}.glyphicon-tasks:before{content:\"\\e137\"}.glyphicon-filter:before{content:\"\\e138\"}.glyphicon-briefcase:before{content:\"\\e139\"}.glyphicon-fullscreen:before{content:\"\\e140\"}.glyphicon-dashboard:before{content:\"\\e141\"}.glyphicon-paperclip:before{content:\"\\e142\"}.glyphicon-heart-empty:before{content:\"\\e143\"}.glyphicon-link:before{content:\"\\e144\"}.glyphicon-phone:before{content:\"\\e145\"}.glyphicon-pushpin:before{content:\"\\e146\"}.glyphicon-usd:before{content:\"\\e148\"}.glyphicon-gbp:before{content:\"\\e149\"}.glyphicon-sort:before{content:\"\\e150\"}.glyphicon-sort-by-alphabet:before{content:\"\\e151\"}.glyphicon-sort-by-alphabet-alt:before{content:\"\\e152\"}.glyphicon-sort-by-order:before{content:\"\\e153\"}.glyphicon-sort-by-order-alt:before{content:\"\\e154\"}.glyphicon-sort-by-attributes:before{content:\"\\e155\"}.glyphicon-sort-by-attributes-alt:before{content:\"\\e156\"}.glyphicon-unchecked:before{content:\"\\e157\"}.glyphicon-expand:before{content:\"\\e158\"}.glyphicon-collapse-down:before{content:\"\\e159\"}.glyphicon-collapse-up:before{content:\"\\e160\"}.glyphicon-log-in:before{content:\"\\e161\"}.glyphicon-flash:before{content:\"\\e162\"}.glyphicon-log-out:before{content:\"\\e163\"}.glyphicon-new-window:before{content:\"\\e164\"}.glyphicon-record:before{content:\"\\e165\"}.glyphicon-save:before{content:\"\\e166\"}.glyphicon-open:before{content:\"\\e167\"}.glyphicon-saved:before{content:\"\\e168\"}.glyphicon-import:before{content:\"\\e169\"}.glyphicon-export:before{content:\"\\e170\"}.glyphicon-send:before{content:\"\\e171\"}.glyphicon-floppy-disk:before{content:\"\\e172\"}.glyphicon-floppy-saved:before{content:\"\\e173\"}.glyphicon-floppy-remove:before{content:\"\\e174\"}.glyphicon-floppy-save:before{content:\"\\e175\"}.glyphicon-floppy-open:before{content:\"\\e176\"}.glyphicon-credit-card:before{content:\"\\e177\"}.glyphicon-transfer:before{content:\"\\e178\"}.glyphicon-cutlery:before{content:\"\\e179\"}.glyphicon-header:before{content:\"\\e180\"}.glyphicon-compressed:before{content:\"\\e181\"}.glyphicon-earphone:before{content:\"\\e182\"}.glyphicon-phone-alt:before{content:\"\\e183\"}.glyphicon-tower:before{content:\"\\e184\"}.glyphicon-stats:before{content:\"\\e185\"}.glyphicon-sd-video:before{content:\"\\e186\"}.glyphicon-hd-video:before{content:\"\\e187\"}.glyphicon-subtitles:before{content:\"\\e188\"}.glyphicon-sound-stereo:before{content:\"\\e189\"}.glyphicon-sound-dolby:before{content:\"\\e190\"}.glyphicon-sound-5-1:before{content:\"\\e191\"}.glyphicon-sound-6-1:before{content:\"\\e192\"}.glyphicon-sound-7-1:before{content:\"\\e193\"}.glyphicon-copyright-mark:before{content:\"\\e194\"}.glyphicon-registration-mark:before{content:\"\\e195\"}.glyphicon-cloud-download:before{content:\"\\e197\"}.glyphicon-cloud-upload:before{content:\"\\e198\"}.glyphicon-tree-conifer:before{content:\"\\e199\"}.glyphicon-tree-deciduous:before{content:\"\\e200\"}.glyphicon-cd:before{content:\"\\e201\"}.glyphicon-save-file:before{content:\"\\e202\"}.glyphicon-open-file:before{content:\"\\e203\"}.glyphicon-level-up:before{content:\"\\e204\"}.glyphicon-copy:before{content:\"\\e205\"}.glyphicon-paste:before{content:\"\\e206\"}.glyphicon-alert:before{content:\"\\e209\"}.glyphicon-equalizer:before{content:\"\\e210\"}.glyphicon-king:before{content:\"\\e211\"}.glyphicon-queen:before{content:\"\\e212\"}.glyphicon-pawn:before{content:\"\\e213\"}.glyphicon-bishop:before{content:\"\\e214\"}.glyphicon-knight:before{content:\"\\e215\"}.glyphicon-baby-formula:before{content:\"\\e216\"}.glyphicon-tent:before{content:\"\\26fa\"}.glyphicon-blackboard:before{content:\"\\e218\"}.glyphicon-bed:before{content:\"\\e219\"}.glyphicon-apple:before{content:\"\\f8ff\"}.glyphicon-erase:before{content:\"\\e221\"}.glyphicon-hourglass:before{content:\"\\231b\"}.glyphicon-lamp:before{content:\"\\e223\"}.glyphicon-duplicate:before{content:\"\\e224\"}.glyphicon-piggy-bank:before{content:\"\\e225\"}.glyphicon-scissors:before{content:\"\\e226\"}.glyphicon-bitcoin:before,.glyphicon-btc:before,.glyphicon-xbt:before{content:\"\\e227\"}.glyphicon-jpy:before,.glyphicon-yen:before{content:\"\\00a5\"}.glyphicon-rub:before,.glyphicon-ruble:before{content:\"\\20bd\"}.glyphicon-scale:before{content:\"\\e230\"}.glyphicon-ice-lolly:before{content:\"\\e231\"}.glyphicon-ice-lolly-tasted:before{content:\"\\e232\"}.glyphicon-education:before{content:\"\\e233\"}.glyphicon-option-horizontal:before{content:\"\\e234\"}.glyphicon-option-vertical:before{content:\"\\e235\"}.glyphicon-menu-hamburger:before{content:\"\\e236\"}.glyphicon-modal-window:before{content:\"\\e237\"}.glyphicon-oil:before{content:\"\\e238\"}.glyphicon-grain:before{content:\"\\e239\"}.glyphicon-sunglasses:before{content:\"\\e240\"}.glyphicon-text-size:before{content:\"\\e241\"}.glyphicon-text-color:before{content:\"\\e242\"}.glyphicon-text-background:before{content:\"\\e243\"}.glyphicon-object-align-top:before{content:\"\\e244\"}.glyphicon-object-align-bottom:before{content:\"\\e245\"}.glyphicon-object-align-horizontal:before{content:\"\\e246\"}.glyphicon-object-align-left:before{content:\"\\e247\"}.glyphicon-object-align-vertical:before{content:\"\\e248\"}.glyphicon-object-align-right:before{content:\"\\e249\"}.glyphicon-triangle-right:before{content:\"\\e250\"}.glyphicon-triangle-left:before{content:\"\\e251\"}.glyphicon-triangle-bottom:before{content:\"\\e252\"}.glyphicon-triangle-top:before{content:\"\\e253\"}.glyphicon-console:before{content:\"\\e254\"}.glyphicon-superscript:before{content:\"\\e255\"}.glyphicon-subscript:before{content:\"\\e256\"}.glyphicon-menu-left:before{content:\"\\e257\"}.glyphicon-menu-right:before{content:\"\\e258\"}.glyphicon-menu-down:before{content:\"\\e259\"}.glyphicon-menu-up:before{content:\"\\e260\"}*,:after,:before{box-sizing:border-box}body{font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.img-responsive{display:block;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.428571429;border:1px solid #ddd;border-radius:4px;transition:all .2s ease-in-out;display:inline-block;height:auto}.img-circle{border-radius:50%}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}dl,ol,ul{margin-top:0}.lead,address,dl{margin-bottom:20px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{font-size:16px;font-weight:300;line-height:1.4}.badge,.label,dt,kbd kbd,label{font-weight:700}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child,ol ol,ol ul,ul ol,ul ul{margin-bottom:0}address,blockquote .small,blockquote footer,blockquote small,dd,dt,pre{line-height:1.428571429}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{background-color:#fcf8e3;padding:.2em}.list-inline,.list-unstyled{padding-left:0;list-style:none}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.initialism,.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}pre code,table{background-color:transparent}.page-header{padding-bottom:9px;border-bottom:1px solid #eee}ol,ul{margin-bottom:10px}.list-inline{margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dd{margin-left:0}.dl-horizontal dd:after,.dl-horizontal dd:before{content:\" \";display:table}.dl-horizontal dd:after{clear:both}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.container{width:750px}}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dropdown-menu>li>a,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;color:#777}legend,pre{color:#333}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\\2014 \\00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}code,kbd{padding:2px 4px;font-size:90%}caption,th{text-align:left}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\\00A0 \\2014'}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,\"Courier New\",monospace}code{color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;box-shadow:none}pre{display:block;margin:0 0 10px;font-size:13px;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5}.container-fluid:after,.container-fluid:before,.container:after,.container:before,.row:after,.row:before{display:table;content:\" \"}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;border-radius:0}.container,.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.pre-scrollable{overflow-y:scroll}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.row{margin-left:-15px;margin-right:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1{width:8.3333333333%}.col-xs-2{width:16.6666666667%}.col-xs-3{width:25%}.col-xs-4{width:33.3333333333%}.col-xs-5{width:41.6666666667%}.col-xs-6{width:50%}.col-xs-7{width:58.3333333333%}.col-xs-8{width:66.6666666667%}.col-xs-9{width:75%}.col-xs-10{width:83.3333333333%}.col-xs-11{width:91.6666666667%}.col-xs-12{width:100%}.col-xs-pull-0{right:auto}.col-xs-pull-1{right:8.3333333333%}.col-xs-pull-2{right:16.6666666667%}.col-xs-pull-3{right:25%}.col-xs-pull-4{right:33.3333333333%}.col-xs-pull-5{right:41.6666666667%}.col-xs-pull-6{right:50%}.col-xs-pull-7{right:58.3333333333%}.col-xs-pull-8{right:66.6666666667%}.col-xs-pull-9{right:75%}.col-xs-pull-10{right:83.3333333333%}.col-xs-pull-11{right:91.6666666667%}.col-xs-pull-12{right:100%}.col-xs-push-0{left:auto}.col-xs-push-1{left:8.3333333333%}.col-xs-push-2{left:16.6666666667%}.col-xs-push-3{left:25%}.col-xs-push-4{left:33.3333333333%}.col-xs-push-5{left:41.6666666667%}.col-xs-push-6{left:50%}.col-xs-push-7{left:58.3333333333%}.col-xs-push-8{left:66.6666666667%}.col-xs-push-9{left:75%}.col-xs-push-10{left:83.3333333333%}.col-xs-push-11{left:91.6666666667%}.col-xs-push-12{left:100%}.col-xs-offset-0{margin-left:0}.col-xs-offset-1{margin-left:8.3333333333%}.col-xs-offset-2{margin-left:16.6666666667%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-4{margin-left:33.3333333333%}.col-xs-offset-5{margin-left:41.6666666667%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-7{margin-left:58.3333333333%}.col-xs-offset-8{margin-left:66.6666666667%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-10{margin-left:83.3333333333%}.col-xs-offset-11{margin-left:91.6666666667%}.col-xs-offset-12{margin-left:100%}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-1{width:8.3333333333%}.col-sm-2{width:16.6666666667%}.col-sm-3{width:25%}.col-sm-4{width:33.3333333333%}.col-sm-5{width:41.6666666667%}.col-sm-6{width:50%}.col-sm-7{width:58.3333333333%}.col-sm-8{width:66.6666666667%}.col-sm-9{width:75%}.col-sm-10{width:83.3333333333%}.col-sm-11{width:91.6666666667%}.col-sm-12{width:100%}.col-sm-pull-0{right:auto}.col-sm-pull-1{right:8.3333333333%}.col-sm-pull-2{right:16.6666666667%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.3333333333%}.col-sm-pull-5{right:41.6666666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.3333333333%}.col-sm-pull-8{right:66.6666666667%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.3333333333%}.col-sm-pull-11{right:91.6666666667%}.col-sm-pull-12{right:100%}.col-sm-push-0{left:auto}.col-sm-push-1{left:8.3333333333%}.col-sm-push-2{left:16.6666666667%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.3333333333%}.col-sm-push-5{left:41.6666666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.3333333333%}.col-sm-push-8{left:66.6666666667%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.3333333333%}.col-sm-push-11{left:91.6666666667%}.col-sm-push-12{left:100%}.col-sm-offset-0{margin-left:0}.col-sm-offset-1{margin-left:8.3333333333%}.col-sm-offset-2{margin-left:16.6666666667%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.3333333333%}.col-sm-offset-5{margin-left:41.6666666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.3333333333%}.col-sm-offset-8{margin-left:66.6666666667%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.3333333333%}.col-sm-offset-11{margin-left:91.6666666667%}.col-sm-offset-12{margin-left:100%}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-1{width:8.3333333333%}.col-md-2{width:16.6666666667%}.col-md-3{width:25%}.col-md-4{width:33.3333333333%}.col-md-5{width:41.6666666667%}.col-md-6{width:50%}.col-md-7{width:58.3333333333%}.col-md-8{width:66.6666666667%}.col-md-9{width:75%}.col-md-10{width:83.3333333333%}.col-md-11{width:91.6666666667%}.col-md-12{width:100%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.3333333333%}.col-md-pull-2{right:16.6666666667%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.3333333333%}.col-md-pull-5{right:41.6666666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.3333333333%}.col-md-pull-8{right:66.6666666667%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.3333333333%}.col-md-pull-11{right:91.6666666667%}.col-md-pull-12{right:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.3333333333%}.col-md-push-2{left:16.6666666667%}.col-md-push-3{left:25%}.col-md-push-4{left:33.3333333333%}.col-md-push-5{left:41.6666666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.3333333333%}.col-md-push-8{left:66.6666666667%}.col-md-push-9{left:75%}.col-md-push-10{left:83.3333333333%}.col-md-push-11{left:91.6666666667%}.col-md-push-12{left:100%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.3333333333%}.col-md-offset-2{margin-left:16.6666666667%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.3333333333%}.col-md-offset-5{margin-left:41.6666666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.3333333333%}.col-md-offset-8{margin-left:66.6666666667%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.3333333333%}.col-md-offset-11{margin-left:91.6666666667%}.col-md-offset-12{margin-left:100%}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-1{width:8.3333333333%}.col-lg-2{width:16.6666666667%}.col-lg-3{width:25%}.col-lg-4{width:33.3333333333%}.col-lg-5{width:41.6666666667%}.col-lg-6{width:50%}.col-lg-7{width:58.3333333333%}.col-lg-8{width:66.6666666667%}.col-lg-9{width:75%}.col-lg-10{width:83.3333333333%}.col-lg-11{width:91.6666666667%}.col-lg-12{width:100%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.3333333333%}.col-lg-pull-2{right:16.6666666667%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.3333333333%}.col-lg-pull-5{right:41.6666666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.3333333333%}.col-lg-pull-8{right:66.6666666667%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.3333333333%}.col-lg-pull-11{right:91.6666666667%}.col-lg-pull-12{right:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.3333333333%}.col-lg-push-2{left:16.6666666667%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.3333333333%}.col-lg-push-5{left:41.6666666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.3333333333%}.col-lg-push-8{left:66.6666666667%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.3333333333%}.col-lg-push-11{left:91.6666666667%}.col-lg-push-12{left:100%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.3333333333%}.col-lg-offset-2{margin-left:16.6666666667%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.3333333333%}.col-lg-offset-5{margin-left:41.6666666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.3333333333%}.col-lg-offset-8{margin-left:66.6666666667%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.3333333333%}.col-lg-offset-11{margin-left:91.6666666667%}.col-lg-offset-12{margin-left:100%}}caption{padding-top:8px;padding-bottom:8px;color:#777}.table{width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover,.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset,legend{padding:0;border:0}fieldset{margin:0;min-width:0}legend{display:block;width:100%;margin-bottom:20px;font-size:21px;line-height:inherit;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px}input[type=search]{box-sizing:border-box;-webkit-appearance:none}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\\9;line-height:normal}.form-control,div.dropzone,div.preview__forum,output{font-size:14px;line-height:1.428571429;color:#555;display:block}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}output{padding-top:7px}.form-control,div.dropzone,div.preview__forum{width:100%;height:34px;padding:6px 12px;background-color:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075);transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus,div.dropzone:focus,div.preview__forum:focus{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder,div.dropzone::-moz-placeholder,div.preview__forum::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder,div.dropzone:-ms-input-placeholder,div.preview__forum:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder,div.dropzone::-webkit-input-placeholder,div.preview__forum::-webkit-input-placeholder{color:#999}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .form-control-feedback,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.form-control[disabled],.form-control[readonly],div[disabled].dropzone,div[disabled].preview__forum,div[readonly].dropzone,div[readonly].preview__forum,fieldset[disabled] .form-control,fieldset[disabled] div.dropzone,fieldset[disabled] div.preview__forum{background-color:#eee;opacity:1}.form-control[disabled],div[disabled].dropzone,div[disabled].preview__forum,fieldset[disabled] .form-control,fieldset[disabled] div.dropzone,fieldset[disabled] div.preview__forum{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],.input-group-sm>.input-group-btn>input[type=date].btn,.input-group-sm>.input-group-btn>input[type=datetime-local].btn,.input-group-sm>.input-group-btn>input[type=month].btn,.input-group-sm>.input-group-btn>input[type=time].btn,.input-group-sm>input[type=date].form-control,.input-group-sm>input[type=date].input-group-addon,.input-group-sm>input[type=datetime-local].form-control,.input-group-sm>input[type=datetime-local].input-group-addon,.input-group-sm>input[type=month].form-control,.input-group-sm>input[type=month].input-group-addon,.input-group-sm>input[type=time].form-control,.input-group-sm>input[type=time].input-group-addon,input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],.input-group-lg>.input-group-btn>input[type=date].btn,.input-group-lg>.input-group-btn>input[type=datetime-local].btn,.input-group-lg>.input-group-btn>input[type=month].btn,.input-group-lg>.input-group-btn>input[type=time].btn,.input-group-lg>input[type=date].form-control,.input-group-lg>input[type=date].input-group-addon,.input-group-lg>input[type=datetime-local].form-control,.input-group-lg>input[type=datetime-local].input-group-addon,.input-group-lg>input[type=month].form-control,.input-group-lg>input[type=month].input-group-addon,.input-group-lg>input[type=time].form-control,.input-group-lg>input[type=time].input-group-addon,input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-left:-20px;margin-top:4px\\9}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.checkbox-inline.disabled,.checkbox.disabled label,.radio-inline.disabled,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio label,fieldset[disabled] .radio-inline,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm,.input-group-lg>.form-control-static.form-control,.input-group-lg>.form-control-static.input-group-addon,.input-group-lg>.input-group-btn>.form-control-static.btn,.input-group-lg>div.form-control-static.dropzone,.input-group-lg>div.form-control-static.preview__forum,.input-group-sm>.form-control-static.form-control,.input-group-sm>.form-control-static.input-group-addon,.input-group-sm>.input-group-btn>.form-control-static.btn,.input-group-sm>div.form-control-static.dropzone,.input-group-sm>div.form-control-static.preview__forum{padding-left:0;padding-right:0}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn,.input-group-sm>div.dropzone,.input-group-sm>div.preview__forum,.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.input-group-sm>.input-group-btn>select.btn,.input-group-sm>select.form-control,.input-group-sm>select.input-group-addon,select.input-sm{height:30px;line-height:30px}.input-group-sm>.input-group-btn>select[multiple].btn,.input-group-sm>.input-group-btn>textarea.btn,.input-group-sm>select[multiple].form-control,.input-group-sm>select[multiple].input-group-addon,.input-group-sm>textarea.form-control,.input-group-sm>textarea.input-group-addon,select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control,.form-group-sm div.dropzone,.form-group-sm div.preview__forum{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn,.input-group-lg>div.dropzone,.input-group-lg>div.preview__forum,.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.input-group-lg>.input-group-btn>select.btn,.input-group-lg>select.form-control,.input-group-lg>select.input-group-addon,select.input-lg{height:46px;line-height:46px}.input-group-lg>.input-group-btn>select[multiple].btn,.input-group-lg>.input-group-btn>textarea.btn,.input-group-lg>select[multiple].form-control,.input-group-lg>select[multiple].input-group-addon,.input-group-lg>textarea.form-control,.input-group-lg>textarea.input-group-addon,select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control,.form-group-lg div.dropzone,.form-group-lg div.preview__forum{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control,.has-feedback div.dropzone,.has-feedback div.preview__forum{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.collapsing,.dropdown,.dropup{position:relative}.form-group-lg .form-control+.form-control-feedback,.form-group-lg div.dropzone+.form-control-feedback,.form-group-lg div.preview__forum+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-group-lg>.form-control+.form-control-feedback,.input-group-lg>.input-group-addon+.form-control-feedback,.input-group-lg>.input-group-btn>.btn+.form-control-feedback,.input-group-lg>div.dropzone+.form-control-feedback,.input-group-lg>div.preview__forum+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.form-group-sm div.dropzone+.form-control-feedback,.form-group-sm div.preview__forum+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-group-sm>.form-control+.form-control-feedback,.input-group-sm>.input-group-addon+.form-control-feedback,.input-group-sm>.input-group-btn>.btn+.form-control-feedback,.input-group-sm>div.dropzone+.form-control-feedback,.input-group-sm>div.preview__forum+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .form-control,.has-success div.dropzone,.has-success div.preview__forum{border-color:#3c763d;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus,.has-success div.dropzone:focus,.has-success div.preview__forum:focus{border-color:#2b542c;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .form-control-feedback,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control,.has-warning div.dropzone,.has-warning div.preview__forum{border-color:#8a6d3b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus,.has-warning div.dropzone:focus,.has-warning div.preview__forum:focus{border-color:#66512c;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .form-control-feedback,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control,.has-error div.dropzone,.has-error div.preview__forum{border-color:#a94442;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus,.has-error div.dropzone:focus,.has-error div.preview__forum:focus{border-color:#843534;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-control-static,.form-inline .form-group{display:inline-block}.form-inline .control-label,.form-inline .form-group{margin-bottom:0;vertical-align:middle}.form-inline .form-control,.form-inline div.dropzone,.form-inline div.preview__forum{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group div.dropzone,.form-inline .input-group div.preview__forum{width:auto}.form-inline .input-group>.form-control,.form-inline .input-group>div.dropzone,.form-inline .input-group>div.preview__forum{width:100%}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.btn-block,input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-group:after,.form-horizontal .form-group:before{content:\" \";display:table}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{outline:0;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.btn-default:hover,.open>.btn-default.dropdown-toggle{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.btn-default.dropdown-toggle.focus,.open>.btn-default.dropdown-toggle:focus,.open>.btn-default.dropdown-toggle:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary.active,.btn-primary:active,.btn-primary:hover,.open>.btn-primary.dropdown-toggle{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.btn-primary.dropdown-toggle.focus,.open>.btn-primary.dropdown-toggle:focus,.open>.btn-primary.dropdown-toggle:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success.active,.btn-success:active,.btn-success:hover,.open>.btn-success.dropdown-toggle{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.btn-success.dropdown-toggle.focus,.open>.btn-success.dropdown-toggle:focus,.open>.btn-success.dropdown-toggle:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info.active,.btn-info:active,.btn-info:hover,.open>.btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.btn-info.dropdown-toggle.focus,.open>.btn-info.dropdown-toggle:focus,.open>.btn-info.dropdown-toggle:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.btn-warning:hover,.open>.btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.btn-warning.dropdown-toggle.focus,.open>.btn-warning.dropdown-toggle:focus,.open>.btn-warning.dropdown-toggle:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger.active,.btn-danger:active,.btn-danger:hover,.open>.btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.btn-danger.dropdown-toggle.focus,.open>.btn-danger.dropdown-toggle:focus,.open>.btn-danger.dropdown-toggle:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:400;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block}.btn-block+.btn-block{margin-top:5px}.fade{opacity:0;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{height:0;overflow:hidden;transition-property:height,visibility;transition-duration:.35s;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;border-top:4px dashed;border-top:4px solid\\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.badge,.input-group-addon,.label,.pager,.progress-bar{text-align:center}.dropdown-menu-right,.dropdown-menu.pull-right{left:auto;right:0}.dropdown-header,.dropdown-menu>li>a{display:block;padding:3px 20px;line-height:1.428571429;white-space:nowrap}.btn-group-vertical>.btn:not(:first-child):not(:last-child),.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn,.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{font-weight:400;color:#333}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{font-size:12px;color:#777}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid\\9;content:\"\"}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar:after,.btn-toolbar:before{content:\" \";display:table}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn .caret,.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group-lg.btn-group>.btn+.dropdown-toggle,.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{box-shadow:none}.btn-group-lg>.btn .caret,.btn-lg .caret{border-width:5px 5px 0}.dropup .btn-group-lg>.btn .caret,.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before{content:\" \";display:table}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn,.input-group .form-control:not(:first-child):not(:last-child),.input-group div.dropzone:not(:first-child):not(:last-child),.input-group div.preview__forum:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group,.input-group-btn,.input-group-btn>.btn,.nav>li,.nav>li>a,.navbar{position:relative}.input-group{display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control,.input-group div.dropzone,.input-group div.preview__forum{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control,.input-group div.dropzone,.input-group div.preview__forum,.input-group-addon,.input-group-btn{display:table-cell}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group div.dropzone:first-child,.input-group div.preview__forum:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group div.dropzone:last-child,.input-group div.preview__forum:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{font-size:0;white-space:nowrap}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav:after,.nav:before{content:\" \";display:table}.nav>li,.nav>li>a{display:block}.nav>li>a{padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-pills>li{float:left}.nav-justified>li,.nav-stacked>li,.nav-tabs.nav-justified>li{float:none}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified,.nav-tabs.nav-justified{width:100%}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}.nav-tabs-justified,.nav-tabs.nav-justified{border-bottom:0}.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-justified>li,.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{margin-bottom:0}.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before{content:\" \";display:table}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar{border-radius:4px}.navbar-header{float:left}.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-left:0;padding-right:0}}.embed-responsive,.modal,.modal-open,.progress{overflow:hidden}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}.navbar-static-top{z-index:1000;border-width:0 0 1px}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;font-size:18px;line-height:20px;height:50px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}.progress-bar-striped,.progress-striped .progress-bar,.progress-striped .progress-bar-danger,.progress-striped .progress-bar-info,.progress-striped .progress-bar-success,.progress-striped .progress-bar-warning{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}@media (min-width:768px){.navbar-toggle{display:none}.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin:8px -15px}@media (min-width:768px){.navbar-form .form-control-static,.navbar-form .form-group{display:inline-block}.navbar-form .control-label,.navbar-form .form-group{margin-bottom:0;vertical-align:middle}.navbar-form .form-control,.navbar-form div.dropzone,.navbar-form div.preview__forum{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group div.dropzone,.navbar-form .input-group div.preview__forum{width:auto}.navbar-form .input-group>.form-control,.navbar-form .input-group>div.dropzone,.navbar-form .input-group>div.preview__forum{width:100%}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;box-shadow:none}.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.breadcrumb>li,.pagination{display:inline-block}.btn .badge,.btn .label{top:-1px;position:relative}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-radius:4px 4px 0 0}.navbar-btn{margin-top:8px;margin-bottom:8px}.btn-group-sm>.navbar-btn.btn,.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.btn-group-xs>.navbar-btn.btn,.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#090909}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#090909;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li+li:before{content:\"/ \";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.badge,.label{line-height:1;white-space:nowrap}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none}.pager:after,.pager:before{content:\" \";display:table}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;color:#fff;border-radius:.25em}.label:empty{display:none}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;color:#fff;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.media-object,.thumbnail{display:block}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.jumbotron,.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;background-color:#eee}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.alert .alert-link,.close{font-weight:700}.alert,.thumbnail{margin-bottom:20px}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}.thumbnail .caption{padding:9px;color:#333}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.alert{padding:15px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.modal,.modal-backdrop{top:0;right:0;bottom:0;left:0}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;background-color:#337ab7;box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-bar-info{background-color:#5bc0de}.progress-bar-warning{background-color:#f0ad4e}.progress-bar-danger{background-color:#d9534f}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{text-decoration:none;color:#555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.panel-heading>.dropdown .dropdown-toggle,.panel-title,.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-title,.panel>.list-group,.panel>.panel-collapse>.list-group,.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel-body{padding:15px}.panel-body:after,.panel-body:before{content:\" \";display:table}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-title{margin-top:0;font-size:16px}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel-group .panel-heading,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-responsive:last-child>.table:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.table-responsive:first-child>.table:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.list-group+.panel-footer,.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-left:15px;padding-right:15px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.popover,.tooltip{font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.428571429;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;text-decoration:none}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-content,.popover{background-clip:padding-box}.modal{display:none;position:fixed;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);transform:translate(0,-25%);transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.carousel-control,.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.43px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:after,.modal-footer:before{content:\" \";display:table}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}.tooltip.top-left .tooltip-arrow,.tooltip.top-right .tooltip-arrow{bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;text-align:left;text-align:start;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px}.tooltip.top-right .tooltip-arrow{left:5px}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow{border-width:0 5px 5px;border-bottom-color:#000;top:0}.tooltip.bottom .tooltip-arrow{left:50%;margin-left:-5px}.tooltip.bottom-left .tooltip-arrow{right:5px;margin-top:-5px}.tooltip.bottom-right .tooltip-arrow{left:5px;margin-top:-5px}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;text-align:left;text-align:start;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2)}.carousel-caption,.carousel-control{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.6);text-align:center}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.carousel,.carousel-inner{position:relative}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:\"\"}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:\" \";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.left>.arrow:after,.popover.right>.arrow:after{content:\" \";bottom:-10px}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{left:1px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:\" \";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;border-right-width:0;border-left-color:#fff}.carousel-inner{overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{display:block;max-width:100%;height:auto;line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;font-size:20px}.carousel-control.left{background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:focus,.carousel-control:hover{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\\2039'}.carousel-control .icon-next:before{content:'\\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000\\9;background-color:transparent}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px}.carousel-caption .btn,.text-hide,::selection{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:after,.clearfix:before{content:\" \";display:table}.center-block{display:block;margin-left:auto;margin-right:auto}.fa.fa-pull-left,.fa.pull-left{margin-right:.3em}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.hidden,.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;background-color:transparent;border:0}.affix{position:fixed}@-ms-viewport{width:device-width}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}.visible-xs-block{display:block!important}.visible-xs-inline{display:inline!important}.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}.visible-sm-block{display:block!important}.visible-sm-inline{display:inline!important}.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}.visible-md-block{display:block!important}.visible-md-inline{display:inline!important}.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}.visible-lg-block{display:block!important}.visible-lg-inline{display:inline!important}.visible-lg-inline-block{display:inline-block!important}.hidden-lg{display:none!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}.hidden-print{display:none!important}}/*!\n *  Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n */@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot?v=4.4.0);src:url(../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0) format(\"embedded-opentype\"),url(../fonts/fontawesome-webfont.woff2?v=4.4.0) format(\"woff2\"),url(../fonts/fontawesome-webfont.woff?v=4.4.0) format(\"woff\"),url(../fonts/fontawesome-webfont.ttf?v=4.4.0) format(\"truetype\"),url(../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular) format(\"svg\");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased}.fa-lg{font-size:1.3333333333em;line-height:.75em;vertical-align:-15%}.fa-stack,.select2-container{display:inline-block;vertical-align:middle}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857em;text-align:center}.fa-ul{padding-left:0;margin-left:2.1428571429em;list-style-type:none}.fa.fa-pull-right,.fa.pull-right{margin-left:.3em}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.1428571429em;width:2.1428571429em;top:.1428571429em;text-align:center}.fa-li.fa-lg{left:-1.8571428571em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0);-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{-webkit-filter:none;filter:none}.fa-stack{position:relative;width:2em;height:2em;line-height:2em}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:\"\"}.fa-music:before{content:\"\"}.fa-search:before{content:\"\"}.fa-envelope-o:before{content:\"\"}.fa-heart:before{content:\"\"}.fa-star:before{content:\"\"}.fa-star-o:before{content:\"\"}.fa-user:before{content:\"\"}.fa-film:before{content:\"\"}.fa-th-large:before{content:\"\"}.fa-th:before{content:\"\"}.fa-th-list:before{content:\"\"}.fa-check:before{content:\"\"}.fa-close:before,.fa-remove:before,.fa-times:before{content:\"\"}.fa-search-plus:before{content:\"\"}.fa-search-minus:before{content:\"\"}.fa-power-off:before{content:\"\"}.fa-signal:before{content:\"\"}.fa-cog:before,.fa-gear:before{content:\"\"}.fa-trash-o:before{content:\"\"}.fa-home:before{content:\"\"}.fa-file-o:before{content:\"\"}.fa-clock-o:before{content:\"\"}.fa-road:before{content:\"\"}.fa-download:before{content:\"\"}.fa-arrow-circle-o-down:before{content:\"\"}.fa-arrow-circle-o-up:before{content:\"\"}.fa-inbox:before{content:\"\"}.fa-play-circle-o:before{content:\"\"}.fa-repeat:before,.fa-rotate-right:before{content:\"\"}.fa-refresh:before{content:\"\"}.fa-list-alt:before{content:\"\"}.fa-lock:before{content:\"\"}.fa-flag:before{content:\"\"}.fa-headphones:before{content:\"\"}.fa-volume-off:before{content:\"\"}.fa-volume-down:before{content:\"\"}.fa-volume-up:before{content:\"\"}.fa-qrcode:before{content:\"\"}.fa-barcode:before{content:\"\"}.fa-tag:before{content:\"\"}.fa-tags:before{content:\"\"}.fa-book:before{content:\"\"}.fa-bookmark:before{content:\"\"}.fa-print:before{content:\"\"}.fa-camera:before{content:\"\"}.fa-font:before{content:\"\"}.fa-bold:before{content:\"\"}.fa-italic:before{content:\"\"}.fa-text-height:before{content:\"\"}.fa-text-width:before{content:\"\"}.fa-align-left:before{content:\"\"}.fa-align-center:before{content:\"\"}.fa-align-right:before{content:\"\"}.fa-align-justify:before{content:\"\"}.fa-list:before{content:\"\"}.fa-dedent:before,.fa-outdent:before{content:\"\"}.fa-indent:before{content:\"\"}.fa-video-camera:before{content:\"\"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:\"\"}.fa-pencil:before{content:\"\"}.fa-map-marker:before{content:\"\"}.fa-adjust:before{content:\"\"}.fa-tint:before{content:\"\"}.fa-edit:before,.fa-pencil-square-o:before{content:\"\"}.fa-share-square-o:before{content:\"\"}.fa-check-square-o:before{content:\"\"}.fa-arrows:before{content:\"\"}.fa-step-backward:before{content:\"\"}.fa-fast-backward:before{content:\"\"}.fa-backward:before{content:\"\"}.fa-play:before{content:\"\"}.fa-pause:before{content:\"\"}.fa-stop:before{content:\"\"}.fa-forward:before{content:\"\"}.fa-fast-forward:before{content:\"\"}.fa-step-forward:before{content:\"\"}.fa-eject:before{content:\"\"}.fa-chevron-left:before{content:\"\"}.fa-chevron-right:before{content:\"\"}.fa-plus-circle:before{content:\"\"}.fa-minus-circle:before{content:\"\"}.fa-times-circle:before{content:\"\"}.fa-check-circle:before{content:\"\"}.fa-question-circle:before{content:\"\"}.fa-info-circle:before{content:\"\"}.fa-crosshairs:before{content:\"\"}.fa-times-circle-o:before{content:\"\"}.fa-check-circle-o:before{content:\"\"}.fa-ban:before{content:\"\"}.fa-arrow-left:before{content:\"\"}.fa-arrow-right:before{content:\"\"}.fa-arrow-up:before{content:\"\"}.fa-arrow-down:before{content:\"\"}.fa-mail-forward:before,.fa-share:before{content:\"\"}.fa-expand:before{content:\"\"}.fa-compress:before{content:\"\"}.fa-plus:before{content:\"\"}.fa-minus:before{content:\"\"}.fa-asterisk:before{content:\"\"}.fa-exclamation-circle:before{content:\"\"}.fa-gift:before{content:\"\"}.fa-leaf:before{content:\"\"}.fa-fire:before{content:\"\"}.fa-eye:before{content:\"\"}.fa-eye-slash:before{content:\"\"}.fa-exclamation-triangle:before,.fa-warning:before{content:\"\"}.fa-plane:before{content:\"\"}.fa-calendar:before{content:\"\"}.fa-random:before{content:\"\"}.fa-comment:before{content:\"\"}.fa-magnet:before{content:\"\"}.fa-chevron-up:before{content:\"\"}.fa-chevron-down:before{content:\"\"}.fa-retweet:before{content:\"\"}.fa-shopping-cart:before{content:\"\"}.fa-folder:before{content:\"\"}.fa-folder-open:before{content:\"\"}.fa-arrows-v:before{content:\"\"}.fa-arrows-h:before{content:\"\"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:\"\"}.fa-twitter-square:before{content:\"\"}.fa-facebook-square:before{content:\"\"}.fa-camera-retro:before{content:\"\"}.fa-key:before{content:\"\"}.fa-cogs:before,.fa-gears:before{content:\"\"}.fa-comments:before{content:\"\"}.fa-thumbs-o-up:before{content:\"\"}.fa-thumbs-o-down:before{content:\"\"}.fa-star-half:before{content:\"\"}.fa-heart-o:before{content:\"\"}.fa-sign-out:before{content:\"\"}.fa-linkedin-square:before{content:\"\"}.fa-thumb-tack:before{content:\"\"}.fa-external-link:before{content:\"\"}.fa-sign-in:before{content:\"\"}.fa-trophy:before{content:\"\"}.fa-github-square:before{content:\"\"}.fa-upload:before{content:\"\"}.fa-lemon-o:before{content:\"\"}.fa-phone:before{content:\"\"}.fa-square-o:before{content:\"\"}.fa-bookmark-o:before{content:\"\"}.fa-phone-square:before{content:\"\"}.fa-twitter:before{content:\"\"}.fa-facebook-f:before,.fa-facebook:before{content:\"\"}.fa-github:before{content:\"\"}.fa-unlock:before{content:\"\"}.fa-credit-card:before{content:\"\"}.fa-feed:before,.fa-rss:before{content:\"\"}.fa-hdd-o:before{content:\"\"}.fa-bullhorn:before{content:\"\"}.fa-bell:before{content:\"\"}.fa-certificate:before{content:\"\"}.fa-hand-o-right:before{content:\"\"}.fa-hand-o-left:before{content:\"\"}.fa-hand-o-up:before{content:\"\"}.fa-hand-o-down:before{content:\"\"}.fa-arrow-circle-left:before{content:\"\"}.fa-arrow-circle-right:before{content:\"\"}.fa-arrow-circle-up:before{content:\"\"}.fa-arrow-circle-down:before{content:\"\"}.fa-globe:before{content:\"\"}.fa-wrench:before{content:\"\"}.fa-tasks:before{content:\"\"}.fa-filter:before{content:\"\"}.fa-briefcase:before{content:\"\"}.fa-arrows-alt:before{content:\"\"}.fa-group:before,.fa-users:before{content:\"\"}.fa-chain:before,.fa-link:before{content:\"\"}.fa-cloud:before{content:\"\"}.fa-flask:before{content:\"\"}.fa-cut:before,.fa-scissors:before{content:\"\"}.fa-copy:before,.fa-files-o:before{content:\"\"}.fa-paperclip:before{content:\"\"}.fa-floppy-o:before,.fa-save:before{content:\"\"}.fa-square:before{content:\"\"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:\"\"}.fa-list-ul:before{content:\"\"}.fa-list-ol:before{content:\"\"}.fa-strikethrough:before{content:\"\"}.fa-underline:before{content:\"\"}.fa-table:before{content:\"\"}.fa-magic:before{content:\"\"}.fa-truck:before{content:\"\"}.fa-pinterest:before{content:\"\"}.fa-pinterest-square:before{content:\"\"}.fa-google-plus-square:before{content:\"\"}.fa-google-plus:before{content:\"\"}.fa-money:before{content:\"\"}.fa-caret-down:before{content:\"\"}.fa-caret-up:before{content:\"\"}.fa-caret-left:before{content:\"\"}.fa-caret-right:before{content:\"\"}.fa-columns:before{content:\"\"}.fa-sort:before,.fa-unsorted:before{content:\"\"}.fa-sort-desc:before,.fa-sort-down:before{content:\"\"}.fa-sort-asc:before,.fa-sort-up:before{content:\"\"}.fa-envelope:before{content:\"\"}.fa-linkedin:before{content:\"\"}.fa-rotate-left:before,.fa-undo:before{content:\"\"}.fa-gavel:before,.fa-legal:before{content:\"\"}.fa-dashboard:before,.fa-tachometer:before{content:\"\"}.fa-comment-o:before{content:\"\"}.fa-comments-o:before{content:\"\"}.fa-bolt:before,.fa-flash:before{content:\"\"}.fa-sitemap:before{content:\"\"}.fa-umbrella:before{content:\"\"}.fa-clipboard:before,.fa-paste:before{content:\"\"}.fa-lightbulb-o:before{content:\"\"}.fa-exchange:before{content:\"\"}.fa-cloud-download:before{content:\"\"}.fa-cloud-upload:before{content:\"\"}.fa-user-md:before{content:\"\"}.fa-stethoscope:before{content:\"\"}.fa-suitcase:before{content:\"\"}.fa-bell-o:before{content:\"\"}.fa-coffee:before{content:\"\"}.fa-cutlery:before{content:\"\"}.fa-file-text-o:before{content:\"\"}.fa-building-o:before{content:\"\"}.fa-hospital-o:before{content:\"\"}.fa-ambulance:before{content:\"\"}.fa-medkit:before{content:\"\"}.fa-fighter-jet:before{content:\"\"}.fa-beer:before{content:\"\"}.fa-h-square:before{content:\"\"}.fa-plus-square:before{content:\"\"}.fa-angle-double-left:before{content:\"\"}.fa-angle-double-right:before{content:\"\"}.fa-angle-double-up:before{content:\"\"}.fa-angle-double-down:before{content:\"\"}.fa-angle-left:before{content:\"\"}.fa-angle-right:before{content:\"\"}.fa-angle-up:before{content:\"\"}.fa-angle-down:before{content:\"\"}.fa-desktop:before{content:\"\"}.fa-laptop:before{content:\"\"}.fa-tablet:before{content:\"\"}.fa-mobile-phone:before,.fa-mobile:before{content:\"\"}.fa-circle-o:before{content:\"\"}.fa-quote-left:before{content:\"\"}.fa-quote-right:before{content:\"\"}.fa-spinner:before{content:\"\"}.fa-circle:before{content:\"\"}.fa-mail-reply:before,.fa-reply:before{content:\"\"}.fa-github-alt:before{content:\"\"}.fa-folder-o:before{content:\"\"}.fa-folder-open-o:before{content:\"\"}.fa-smile-o:before{content:\"\"}.fa-frown-o:before{content:\"\"}.fa-meh-o:before{content:\"\"}.fa-gamepad:before{content:\"\"}.fa-keyboard-o:before{content:\"\"}.fa-flag-o:before{content:\"\"}.fa-flag-checkered:before{content:\"\"}.fa-terminal:before{content:\"\"}.fa-code:before{content:\"\"}.fa-mail-reply-all:before,.fa-reply-all:before{content:\"\"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:\"\"}.fa-location-arrow:before{content:\"\"}.fa-crop:before{content:\"\"}.fa-code-fork:before{content:\"\"}.fa-chain-broken:before,.fa-unlink:before{content:\"\"}.fa-question:before{content:\"\"}.fa-info:before{content:\"\"}.fa-exclamation:before{content:\"\"}.fa-superscript:before{content:\"\"}.fa-subscript:before{content:\"\"}.fa-eraser:before{content:\"\"}.fa-puzzle-piece:before{content:\"\"}.fa-microphone:before{content:\"\"}.fa-microphone-slash:before{content:\"\"}.fa-shield:before{content:\"\"}.fa-calendar-o:before{content:\"\"}.fa-fire-extinguisher:before{content:\"\"}.fa-rocket:before{content:\"\"}.fa-maxcdn:before{content:\"\"}.fa-chevron-circle-left:before{content:\"\"}.fa-chevron-circle-right:before{content:\"\"}.fa-chevron-circle-up:before{content:\"\"}.fa-chevron-circle-down:before{content:\"\"}.fa-html5:before{content:\"\"}.fa-css3:before{content:\"\"}.fa-anchor:before{content:\"\"}.fa-unlock-alt:before{content:\"\"}.fa-bullseye:before{content:\"\"}.fa-ellipsis-h:before{content:\"\"}.fa-ellipsis-v:before{content:\"\"}.fa-rss-square:before{content:\"\"}.fa-play-circle:before{content:\"\"}.fa-ticket:before{content:\"\"}.fa-minus-square:before{content:\"\"}.fa-minus-square-o:before{content:\"\"}.fa-level-up:before{content:\"\"}.fa-level-down:before{content:\"\"}.fa-check-square:before{content:\"\"}.fa-pencil-square:before{content:\"\"}.fa-external-link-square:before{content:\"\"}.fa-share-square:before{content:\"\"}.fa-compass:before{content:\"\"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:\"\"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:\"\"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:\"\"}.fa-eur:before,.fa-euro:before{content:\"\"}.fa-gbp:before{content:\"\"}.fa-dollar:before,.fa-usd:before{content:\"\"}.fa-inr:before,.fa-rupee:before{content:\"\"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:\"\"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:\"\"}.fa-krw:before,.fa-won:before{content:\"\"}.fa-bitcoin:before,.fa-btc:before{content:\"\"}.fa-file:before{content:\"\"}.fa-file-text:before{content:\"\"}.fa-sort-alpha-asc:before{content:\"\"}.fa-sort-alpha-desc:before{content:\"\"}.fa-sort-amount-asc:before{content:\"\"}.fa-sort-amount-desc:before{content:\"\"}.fa-sort-numeric-asc:before{content:\"\"}.fa-sort-numeric-desc:before{content:\"\"}.fa-thumbs-up:before{content:\"\"}.fa-thumbs-down:before{content:\"\"}.fa-youtube-square:before{content:\"\"}.fa-youtube:before{content:\"\"}.fa-xing:before{content:\"\"}.fa-xing-square:before{content:\"\"}.fa-youtube-play:before{content:\"\"}.fa-dropbox:before{content:\"\"}.fa-stack-overflow:before{content:\"\"}.fa-instagram:before{content:\"\"}.fa-flickr:before{content:\"\"}.fa-adn:before{content:\"\"}.fa-bitbucket:before{content:\"\"}.fa-bitbucket-square:before{content:\"\"}.fa-tumblr:before{content:\"\"}.fa-tumblr-square:before{content:\"\"}.fa-long-arrow-down:before{content:\"\"}.fa-long-arrow-up:before{content:\"\"}.fa-long-arrow-left:before{content:\"\"}.fa-long-arrow-right:before{content:\"\"}.fa-apple:before{content:\"\"}.fa-windows:before{content:\"\"}.fa-android:before{content:\"\"}.fa-linux:before{content:\"\"}.fa-dribbble:before{content:\"\"}.fa-skype:before{content:\"\"}.fa-foursquare:before{content:\"\"}.fa-trello:before{content:\"\"}.fa-female:before{content:\"\"}.fa-male:before{content:\"\"}.fa-gittip:before,.fa-gratipay:before{content:\"\"}.fa-sun-o:before{content:\"\"}.fa-moon-o:before{content:\"\"}.fa-archive:before{content:\"\"}.fa-bug:before{content:\"\"}.fa-vk:before{content:\"\"}.fa-weibo:before{content:\"\"}.fa-renren:before{content:\"\"}.fa-pagelines:before{content:\"\"}.fa-stack-exchange:before{content:\"\"}.fa-arrow-circle-o-right:before{content:\"\"}.fa-arrow-circle-o-left:before{content:\"\"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:\"\"}.fa-dot-circle-o:before{content:\"\"}.fa-wheelchair:before{content:\"\"}.fa-vimeo-square:before{content:\"\"}.fa-try:before,.fa-turkish-lira:before{content:\"\"}.fa-plus-square-o:before{content:\"\"}.fa-space-shuttle:before{content:\"\"}.fa-slack:before{content:\"\"}.fa-envelope-square:before{content:\"\"}.fa-wordpress:before{content:\"\"}.fa-openid:before{content:\"\"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:\"\"}.fa-graduation-cap:before,.fa-mortar-board:before{content:\"\"}.fa-yahoo:before{content:\"\"}.fa-google:before{content:\"\"}.fa-reddit:before{content:\"\"}.fa-reddit-square:before{content:\"\"}.fa-stumbleupon-circle:before{content:\"\"}.fa-stumbleupon:before{content:\"\"}.fa-delicious:before{content:\"\"}.fa-digg:before{content:\"\"}.fa-pied-piper:before{content:\"\"}.fa-pied-piper-alt:before{content:\"\"}.fa-drupal:before{content:\"\"}.fa-joomla:before{content:\"\"}.fa-language:before{content:\"\"}.fa-fax:before{content:\"\"}.fa-building:before{content:\"\"}.fa-child:before{content:\"\"}.fa-paw:before{content:\"\"}.fa-spoon:before{content:\"\"}.fa-cube:before{content:\"\"}.fa-cubes:before{content:\"\"}.fa-behance:before{content:\"\"}.fa-behance-square:before{content:\"\"}.fa-steam:before{content:\"\"}.fa-steam-square:before{content:\"\"}.fa-recycle:before{content:\"\"}.fa-automobile:before,.fa-car:before{content:\"\"}.fa-cab:before,.fa-taxi:before{content:\"\"}.fa-tree:before{content:\"\"}.fa-spotify:before{content:\"\"}.fa-deviantart:before{content:\"\"}.fa-soundcloud:before{content:\"\"}.fa-database:before{content:\"\"}.fa-file-pdf-o:before{content:\"\"}.fa-file-word-o:before{content:\"\"}.fa-file-excel-o:before{content:\"\"}.fa-file-powerpoint-o:before{content:\"\"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:\"\"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:\"\"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:\"\"}.fa-file-movie-o:before,.fa-file-video-o:before{content:\"\"}.fa-file-code-o:before{content:\"\"}.fa-vine:before{content:\"\"}.fa-codepen:before{content:\"\"}.fa-jsfiddle:before{content:\"\"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:\"\"}.fa-circle-o-notch:before{content:\"\"}.fa-ra:before,.fa-rebel:before{content:\"\"}.fa-empire:before,.fa-ge:before{content:\"\"}.fa-git-square:before{content:\"\"}.fa-git:before{content:\"\"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:\"\"}.fa-tencent-weibo:before{content:\"\"}.fa-qq:before{content:\"\"}.fa-wechat:before,.fa-weixin:before{content:\"\"}.fa-paper-plane:before,.fa-send:before{content:\"\"}.fa-paper-plane-o:before,.fa-send-o:before{content:\"\"}.fa-history:before{content:\"\"}.fa-circle-thin:before{content:\"\"}.fa-header:before{content:\"\"}.fa-paragraph:before{content:\"\"}.fa-sliders:before{content:\"\"}.fa-share-alt:before{content:\"\"}.fa-share-alt-square:before{content:\"\"}.fa-bomb:before{content:\"\"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:\"\"}.fa-tty:before{content:\"\"}.fa-binoculars:before{content:\"\"}.fa-plug:before{content:\"\"}.fa-slideshare:before{content:\"\"}.fa-twitch:before{content:\"\"}.fa-yelp:before{content:\"\"}.fa-newspaper-o:before{content:\"\"}.fa-wifi:before{content:\"\"}.fa-calculator:before{content:\"\"}.fa-paypal:before{content:\"\"}.fa-google-wallet:before{content:\"\"}.fa-cc-visa:before{content:\"\"}.fa-cc-mastercard:before{content:\"\"}.fa-cc-discover:before{content:\"\"}.fa-cc-amex:before{content:\"\"}.fa-cc-paypal:before{content:\"\"}.fa-cc-stripe:before{content:\"\"}.fa-bell-slash:before{content:\"\"}.fa-bell-slash-o:before{content:\"\"}.fa-trash:before{content:\"\"}.fa-copyright:before{content:\"\"}.fa-at:before{content:\"\"}.fa-eyedropper:before{content:\"\"}.fa-paint-brush:before{content:\"\"}.fa-birthday-cake:before{content:\"\"}.fa-area-chart:before{content:\"\"}.fa-pie-chart:before{content:\"\"}.fa-line-chart:before{content:\"\"}.fa-lastfm:before{content:\"\"}.fa-lastfm-square:before{content:\"\"}.fa-toggle-off:before{content:\"\"}.fa-toggle-on:before{content:\"\"}.fa-bicycle:before{content:\"\"}.fa-bus:before{content:\"\"}.fa-ioxhost:before{content:\"\"}.fa-angellist:before{content:\"\"}.fa-cc:before{content:\"\"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:\"\"}.fa-meanpath:before{content:\"\"}.fa-buysellads:before{content:\"\"}.fa-connectdevelop:before{content:\"\"}.fa-dashcube:before{content:\"\"}.fa-forumbee:before{content:\"\"}.fa-leanpub:before{content:\"\"}.fa-sellsy:before{content:\"\"}.fa-shirtsinbulk:before{content:\"\"}.fa-simplybuilt:before{content:\"\"}.fa-skyatlas:before{content:\"\"}.fa-cart-plus:before{content:\"\"}.fa-cart-arrow-down:before{content:\"\"}.fa-diamond:before{content:\"\"}.fa-ship:before{content:\"\"}.fa-user-secret:before{content:\"\"}.fa-motorcycle:before{content:\"\"}.fa-street-view:before{content:\"\"}.fa-heartbeat:before{content:\"\"}.fa-venus:before{content:\"\"}.fa-mars:before{content:\"\"}.fa-mercury:before{content:\"\"}.fa-intersex:before,.fa-transgender:before{content:\"\"}.fa-transgender-alt:before{content:\"\"}.fa-venus-double:before{content:\"\"}.fa-mars-double:before{content:\"\"}.fa-venus-mars:before{content:\"\"}.fa-mars-stroke:before{content:\"\"}.fa-mars-stroke-v:before{content:\"\"}.fa-mars-stroke-h:before{content:\"\"}.fa-neuter:before{content:\"\"}.fa-genderless:before{content:\"\"}.fa-facebook-official:before{content:\"\"}.fa-pinterest-p:before{content:\"\"}.fa-whatsapp:before{content:\"\"}.fa-server:before{content:\"\"}.fa-user-plus:before{content:\"\"}.fa-user-times:before{content:\"\"}.fa-bed:before,.fa-hotel:before{content:\"\"}.fa-viacoin:before{content:\"\"}.fa-train:before{content:\"\"}.fa-subway:before{content:\"\"}.fa-medium:before{content:\"\"}.fa-y-combinator:before,.fa-yc:before{content:\"\"}.fa-optin-monster:before{content:\"\"}.fa-opencart:before{content:\"\"}.fa-expeditedssl:before{content:\"\"}.fa-battery-4:before,.fa-battery-full:before{content:\"\"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:\"\"}.fa-battery-2:before,.fa-battery-half:before{content:\"\"}.fa-battery-1:before,.fa-battery-quarter:before{content:\"\"}.fa-battery-0:before,.fa-battery-empty:before{content:\"\"}.fa-mouse-pointer:before{content:\"\"}.fa-i-cursor:before{content:\"\"}.fa-object-group:before{content:\"\"}.fa-object-ungroup:before{content:\"\"}.fa-sticky-note:before{content:\"\"}.fa-sticky-note-o:before{content:\"\"}.fa-cc-jcb:before{content:\"\"}.fa-cc-diners-club:before{content:\"\"}.fa-clone:before{content:\"\"}.fa-balance-scale:before{content:\"\"}.fa-hourglass-o:before{content:\"\"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:\"\"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:\"\"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:\"\"}.fa-hourglass:before{content:\"\"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:\"\"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:\"\"}.fa-hand-scissors-o:before{content:\"\"}.fa-hand-lizard-o:before{content:\"\"}.fa-hand-spock-o:before{content:\"\"}.fa-hand-pointer-o:before{content:\"\"}.fa-hand-peace-o:before{content:\"\"}.fa-trademark:before{content:\"\"}.fa-registered:before{content:\"\"}.fa-creative-commons:before{content:\"\"}.fa-gg:before{content:\"\"}.fa-gg-circle:before{content:\"\"}.fa-tripadvisor:before{content:\"\"}.fa-odnoklassniki:before{content:\"\"}.fa-odnoklassniki-square:before{content:\"\"}.fa-get-pocket:before{content:\"\"}.fa-wikipedia-w:before{content:\"\"}.fa-safari:before{content:\"\"}.fa-chrome:before{content:\"\"}.fa-firefox:before{content:\"\"}.fa-opera:before{content:\"\"}.fa-internet-explorer:before{content:\"\"}.fa-television:before,.fa-tv:before{content:\"\"}.fa-contao:before{content:\"\"}.fa-500px:before{content:\"\"}.fa-amazon:before{content:\"\"}.fa-calendar-plus-o:before{content:\"\"}.fa-calendar-minus-o:before{content:\"\"}.fa-calendar-times-o:before{content:\"\"}.fa-calendar-check-o:before{content:\"\"}.fa-industry:before{content:\"\"}.fa-map-pin:before{content:\"\"}.fa-map-signs:before{content:\"\"}.fa-map-o:before{content:\"\"}.fa-map:before{content:\"\"}.fa-commenting:before{content:\"\"}.fa-commenting-o:before{content:\"\"}.fa-houzz:before{content:\"\"}.fa-vimeo:before{content:\"\"}.fa-black-tie:before{content:\"\"}.fa-fonticons:before{content:\"\"}.select2-container{box-sizing:border-box;margin:0;position:relative}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:#fff;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important}.select2-container--bootstrap .select2-results>.select2-results__options,.select2-container--classic .select2-results>.select2-results__options,.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:700}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent;border-style:solid;border-width:5px 4px 0;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir=rtl] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir=rtl] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888;border-width:0 4px 5px}.select2-container--default .select2-selection--multiple{background-color:#fff;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:700;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:700;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-search--inline,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__placeholder{float:right}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:1px solid #000;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple,.select2-container--default.select2-container--open.select2-container--above .select2-selection--single{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple,.select2-container--default.select2-container--open.select2-container--below .select2-selection--single{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:0 0;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:#fff}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:linear-gradient(to bottom,#fff 50%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:700;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:linear-gradient(to bottom,#eee 50%,#ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent;border-style:solid;border-width:5px 4px 0;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir=rtl] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir=rtl] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:4px 0 0 4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:0 0;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888;border-width:0 4px 5px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:linear-gradient(to bottom,#fff 0,#eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:linear-gradient(to bottom,#eee 50%,#fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:#fff;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:700;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--bootstrap .select2-search--dropdown .select2-search__field,.select2-container--bootstrap .select2-selection{box-shadow:inset 0 1px 1px rgba(0,0,0,.075);background-color:#fff;color:#555;font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-size:14px}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb}/*! Select2 Bootstrap Theme v0.1.0-beta.4 | MIT License | github.com/select2/select2-bootstrap-theme */.select2-container--bootstrap{display:block}.select2-container--bootstrap .select2-selection{border:1px solid #ccc;border-radius:4px;outline:0}.select2-container--bootstrap .select2-search--dropdown .select2-search__field{border:1px solid #ccc;border-radius:4px}.select2-container--bootstrap .select2-search__field{outline:0}.select2-container--bootstrap .select2-search__field::-webkit-input-placeholder{color:#999}.select2-container--bootstrap .select2-search__field:-moz-placeholder{color:#999}.select2-container--bootstrap .select2-search__field::-moz-placeholder{color:#999;opacity:1}.select2-container--bootstrap .select2-search__field:-ms-input-placeholder{color:#999}.select2-container--bootstrap .select2-results__option[role=group]{padding:0}.select2-container--bootstrap .select2-results__option[aria-disabled=true]{color:#777;cursor:not-allowed}.select2-container--bootstrap .select2-results__option[aria-selected=true]{background-color:#f5f5f5;color:#262626}.select2-container--bootstrap .select2-results__option--highlighted[aria-selected]{background-color:#337ab7;color:#fff}.select2-container--bootstrap .select2-results__option .select2-results__option{padding:6px 12px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option{margin-left:-12px;padding-left:24px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-24px;padding-left:36px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-36px;padding-left:48px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-48px;padding-left:60px}.select2-container--bootstrap .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-60px;padding-left:72px}.select2-container--bootstrap .select2-results__group{color:#777;display:block;padding:6px 12px;font-size:12px;line-height:1.428571429;white-space:nowrap}.select2-container--bootstrap.select2-container--focus .select2-selection,.select2-container--bootstrap.select2-container--open .select2-selection{box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;border-color:#66afe9}.select2-container--bootstrap.select2-container--open .select2-selection .select2-selection__arrow b{border-color:transparent transparent #999;border-width:0 4px 4px}.select2-container--bootstrap.select2-container--open.select2-container--below .select2-selection{border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom-color:transparent}.select2-container--bootstrap.select2-container--open.select2-container--above .select2-selection{border-top-right-radius:0;border-top-left-radius:0;border-top-color:transparent}.select2-container--bootstrap .select2-selection__clear{color:#999;cursor:pointer;float:right;font-weight:700;margin-right:10px}.select2-container--bootstrap .select2-selection__clear:hover{color:#333}.select2-container--bootstrap.select2-container--disabled .select2-selection{border-color:#ccc;box-shadow:none}.select2-container--bootstrap.select2-container--disabled .select2-search__field,.select2-container--bootstrap.select2-container--disabled .select2-selection{cursor:not-allowed}.select2-container--bootstrap.select2-container--disabled .select2-selection,.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice{background-color:#eee}.select2-container--bootstrap.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove,.select2-container--bootstrap.select2-container--disabled .select2-selection__clear{display:none}.select2-container--bootstrap .select2-dropdown{box-shadow:0 6px 12px rgba(0,0,0,.175);border-color:#66afe9;overflow-x:hidden;margin-top:-1px}.select2-container--bootstrap .select2-dropdown--above{margin-top:1px}.select2-container--bootstrap .select2-selection--single{height:34px;line-height:1.428571429;padding:6px 24px 6px 12px}.select2-container--bootstrap .select2-selection--single .select2-selection__arrow{position:absolute;bottom:0;right:12px;top:0;width:4px}.select2-container--bootstrap .select2-selection--single .select2-selection__arrow b{border-color:#999 transparent transparent;border-style:solid;border-width:4px 4px 0;height:0;left:0;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--bootstrap .select2-selection--single .select2-selection__rendered{color:#555;padding:0}.select2-container--bootstrap .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--bootstrap .select2-selection--multiple{min-height:34px}.select2-container--bootstrap .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;display:block;line-height:1.428571429;list-style:none;margin:0;overflow:hidden;padding:0;width:100%;text-overflow:ellipsis;white-space:nowrap}.select2-container--bootstrap .select2-selection--multiple .select2-selection__placeholder{color:#999;float:left;margin-top:5px}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice{color:#555;background:#fff;border:1px solid #ccc;border-radius:4px;cursor:default;float:left;margin:5px 0 0 6px;padding:0 6px}.back-to-top,.dropzone.dz-clickable,.tags__forum li,.tags__lessons li{cursor:pointer}.select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field{background:0 0;padding:0 12px;height:32px;line-height:1.428571429;margin-top:0;min-width:5em}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:700;margin-right:3px}.select2-container--bootstrap .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--bootstrap .select2-selection--multiple .select2-selection__clear{margin-top:6px}.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn,.input-group-lg>.select2-container--bootstrap.form-control,.input-group-lg>.select2-container--bootstrap.input-group-addon,.input-group-lg>div.select2-container--bootstrap.dropzone,.input-group-lg>div.select2-container--bootstrap.preview__forum,.input-group-sm>.input-group-btn>.select2-container--bootstrap.btn,.input-group-sm>.select2-container--bootstrap.form-control,.input-group-sm>.select2-container--bootstrap.input-group-addon,.input-group-sm>div.select2-container--bootstrap.dropzone,.input-group-sm>div.select2-container--bootstrap.preview__forum,.select2-container--bootstrap.input-lg,.select2-container--bootstrap.input-sm{border-radius:0;font-size:12px;height:auto;line-height:1;padding:0}.form-group-sm .select2-container--bootstrap .select2-selection--single,.input-group-sm .select2-container--bootstrap .select2-selection--single,.input-group-sm>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--single,.input-group-sm>.select2-container--bootstrap.form-control .select2-selection--single,.input-group-sm>.select2-container--bootstrap.input-group-addon .select2-selection--single,.input-group-sm>div.select2-container--bootstrap.dropzone .select2-selection--single,.input-group-sm>div.select2-container--bootstrap.preview__forum .select2-selection--single,.select2-container--bootstrap.input-sm .select2-selection--single{border-radius:3px;font-size:12px;height:30px;line-height:1.5;padding:5px 22px 5px 10px}.form-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-sm .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-sm>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--single .select2-selection__arrow b,.input-group-sm>.select2-container--bootstrap.form-control .select2-selection--single .select2-selection__arrow b,.input-group-sm>.select2-container--bootstrap.input-group-addon .select2-selection--single .select2-selection__arrow b,.input-group-sm>div.select2-container--bootstrap.dropzone .select2-selection--single .select2-selection__arrow b,.input-group-sm>div.select2-container--bootstrap.preview__forum .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap.input-sm .select2-selection--single .select2-selection__arrow b{margin-left:-5px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple,.input-group-sm .select2-container--bootstrap .select2-selection--multiple,.input-group-sm>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple,.input-group-sm>.select2-container--bootstrap.form-control .select2-selection--multiple,.input-group-sm>.select2-container--bootstrap.input-group-addon .select2-selection--multiple,.input-group-sm>div.select2-container--bootstrap.dropzone .select2-selection--multiple,.input-group-sm>div.select2-container--bootstrap.preview__forum .select2-selection--multiple,.select2-container--bootstrap.input-sm .select2-selection--multiple{min-height:30px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-sm>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple .select2-selection__choice,.input-group-sm>.select2-container--bootstrap.form-control .select2-selection--multiple .select2-selection__choice,.input-group-sm>.select2-container--bootstrap.input-group-addon .select2-selection--multiple .select2-selection__choice,.input-group-sm>div.select2-container--bootstrap.dropzone .select2-selection--multiple .select2-selection__choice,.input-group-sm>div.select2-container--bootstrap.preview__forum .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__choice{font-size:12px;line-height:1.5;margin:4px 0 0 5px;padding:0 5px}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm>.select2-container--bootstrap.form-control .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm>.select2-container--bootstrap.input-group-addon .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm>div.select2-container--bootstrap.dropzone .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-sm>div.select2-container--bootstrap.preview__forum .select2-selection--multiple .select2-search--inline .select2-search__field,.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-search--inline .select2-search__field{padding:0 10px;font-size:12px;height:28px;line-height:1.5}.form-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-sm .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-sm>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple .select2-selection__clear,.input-group-sm>.select2-container--bootstrap.form-control .select2-selection--multiple .select2-selection__clear,.input-group-sm>.select2-container--bootstrap.input-group-addon .select2-selection--multiple .select2-selection__clear,.input-group-sm>div.select2-container--bootstrap.dropzone .select2-selection--multiple .select2-selection__clear,.input-group-sm>div.select2-container--bootstrap.preview__forum .select2-selection--multiple .select2-selection__clear,.select2-container--bootstrap.input-sm .select2-selection--multiple .select2-selection__clear{margin-top:5px}.form-group-lg .select2-container--bootstrap .select2-selection--single,.input-group-lg .select2-container--bootstrap .select2-selection--single,.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--single,.input-group-lg>.select2-container--bootstrap.form-control .select2-selection--single,.input-group-lg>.select2-container--bootstrap.input-group-addon .select2-selection--single,.input-group-lg>div.select2-container--bootstrap.dropzone .select2-selection--single,.input-group-lg>div.select2-container--bootstrap.preview__forum .select2-selection--single,.select2-container--bootstrap.input-lg .select2-selection--single{border-radius:6px;font-size:18px;height:46px;line-height:1.3333333;padding:10px 31px 10px 16px}.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow,.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow,.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--single .select2-selection__arrow,.input-group-lg>.select2-container--bootstrap.form-control .select2-selection--single .select2-selection__arrow,.input-group-lg>.select2-container--bootstrap.input-group-addon .select2-selection--single .select2-selection__arrow,.input-group-lg>div.select2-container--bootstrap.dropzone .select2-selection--single .select2-selection__arrow,.input-group-lg>div.select2-container--bootstrap.preview__forum .select2-selection--single .select2-selection__arrow,.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow{width:5px}.form-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-lg .select2-container--bootstrap .select2-selection--single .select2-selection__arrow b,.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--single .select2-selection__arrow b,.input-group-lg>.select2-container--bootstrap.form-control .select2-selection--single .select2-selection__arrow b,.input-group-lg>.select2-container--bootstrap.input-group-addon .select2-selection--single .select2-selection__arrow b,.input-group-lg>div.select2-container--bootstrap.dropzone .select2-selection--single .select2-selection__arrow b,.input-group-lg>div.select2-container--bootstrap.preview__forum .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap.input-lg .select2-selection--single .select2-selection__arrow b{border-width:5px 5px 0;margin-left:-10px;margin-top:-2.5px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple,.input-group-lg .select2-container--bootstrap .select2-selection--multiple,.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple,.input-group-lg>.select2-container--bootstrap.form-control .select2-selection--multiple,.input-group-lg>.select2-container--bootstrap.input-group-addon .select2-selection--multiple,.input-group-lg>div.select2-container--bootstrap.dropzone .select2-selection--multiple,.input-group-lg>div.select2-container--bootstrap.preview__forum .select2-selection--multiple,.select2-container--bootstrap.input-lg .select2-selection--multiple{min-height:46px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__choice,.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple .select2-selection__choice,.input-group-lg>.select2-container--bootstrap.form-control .select2-selection--multiple .select2-selection__choice,.input-group-lg>.select2-container--bootstrap.input-group-addon .select2-selection--multiple .select2-selection__choice,.input-group-lg>div.select2-container--bootstrap.dropzone .select2-selection--multiple .select2-selection__choice,.input-group-lg>div.select2-container--bootstrap.preview__forum .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__choice{font-size:18px;line-height:1.3333333;border-radius:4px;margin:9px 0 0 8px;padding:0 10px}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg>.select2-container--bootstrap.form-control .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg>.select2-container--bootstrap.input-group-addon .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg>div.select2-container--bootstrap.dropzone .select2-selection--multiple .select2-search--inline .select2-search__field,.input-group-lg>div.select2-container--bootstrap.preview__forum .select2-selection--multiple .select2-search--inline .select2-search__field,.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-search--inline .select2-search__field{padding:0 16px;font-size:18px;height:44px;line-height:1.3333333}.form-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-lg .select2-container--bootstrap .select2-selection--multiple .select2-selection__clear,.input-group-lg>.input-group-btn>.select2-container--bootstrap.btn .select2-selection--multiple .select2-selection__clear,.input-group-lg>.select2-container--bootstrap.form-control .select2-selection--multiple .select2-selection__clear,.input-group-lg>.select2-container--bootstrap.input-group-addon .select2-selection--multiple .select2-selection__clear,.input-group-lg>div.select2-container--bootstrap.dropzone .select2-selection--multiple .select2-selection__clear,.input-group-lg>div.select2-container--bootstrap.preview__forum .select2-selection--multiple .select2-selection__clear,.select2-container--bootstrap.input-lg .select2-selection--multiple .select2-selection__clear{margin-top:10px}.input-group-lg .select2-container--bootstrap.select2-container--open .select2-selection--single .select2-selection__arrow b,.input-group-lg>.input-group-btn>.select2-container--bootstrap.select2-container--open.btn .select2-selection--single .select2-selection__arrow b,.input-group-lg>.select2-container--bootstrap.select2-container--open.form-control .select2-selection--single .select2-selection__arrow b,.input-group-lg>.select2-container--bootstrap.select2-container--open.input-group-addon .select2-selection--single .select2-selection__arrow b,.input-group-lg>div.select2-container--bootstrap.select2-container--open.dropzone .select2-selection--single .select2-selection__arrow b,.input-group-lg>div.select2-container--bootstrap.select2-container--open.preview__forum .select2-selection--single .select2-selection__arrow b,.select2-container--bootstrap.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #999;border-width:0 5px 5px}.select2-container--bootstrap[dir=rtl] .select2-selection--single{padding-left:24px;padding-right:12px}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:0;padding-left:0;text-align:right}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__clear{float:left}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__arrow{left:12px;right:auto}.select2-container--bootstrap[dir=rtl] .select2-selection--single .select2-selection__arrow b{margin-left:0}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__placeholder{float:right}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:0;margin-right:6px}.select2-container--bootstrap[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.has-warning .select2-dropdown,.has-warning .select2-selection{border-color:#8a6d3b}.has-warning .select2-container--focus .select2-selection,.has-warning .select2-container--open .select2-selection{box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;border-color:#66512c}.has-warning.select2-drop-active{border-color:#66512c}.has-warning.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#66512c}.has-error .select2-dropdown,.has-error .select2-selection{border-color:#a94442}.has-error .select2-container--focus .select2-selection,.has-error .select2-container--open .select2-selection{box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;border-color:#843534}.has-error.select2-drop-active{border-color:#843534}.has-error.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#843534}.has-success .select2-dropdown,.has-success .select2-selection{border-color:#3c763d}.has-success .select2-container--focus .select2-selection,.has-success .select2-container--open .select2-selection{box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;border-color:#2b542c}.has-success.select2-drop-active{border-color:#2b542c}.has-success.select2-drop-active.select2-drop.select2-drop-above{border-top-color:#2b542c}.input-group .select2-container--bootstrap{display:table;table-layout:fixed;position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group.select2-bootstrap-prepend .select2-container--bootstrap .select2-selection{border-bottom-left-radius:0;border-top-left-radius:0}.input-group.select2-bootstrap-append .select2-container--bootstrap .select2-selection{border-bottom-right-radius:0;border-top-right-radius:0}.select2-bootstrap-append .input-group-btn,.select2-bootstrap-append .input-group-btn .btn,.select2-bootstrap-append .select2-container--bootstrap,.select2-bootstrap-prepend .input-group-btn,.select2-bootstrap-prepend .input-group-btn .btn,.select2-bootstrap-prepend .select2-container--bootstrap{vertical-align:top}.form-control.select2-hidden-accessible,div.select2-hidden-accessible.dropzone,div.select2-hidden-accessible.preview__forum{position:absolute!important;width:1px!important}.form-inline .select2-container--bootstrap{display:inline-block}body,html{width:100%;color:#444;font-size:16px;font-weight:400;-webkit-font-smoothing:antialiased;line-height:24px;background:#f5f5f5;overflow-x:hidden;box-sizing:border-box}hr{display:block;height:1px;border:0;border-top:1px solid #e9e9e9;margin:1em 0;padding:0}::selection{background:#fff7a8;color:#444}::-moz-selection{background:#fff7a8;color:#444;text-shadow:none}.footer,.footer a{color:#98978B}body>div.container{margin-top:5rem}.navbar-brand{padding:10px 15px}.flash-message,.js-flash-message{display:inline-block;position:fixed;bottom:50px;right:15px;max-width:450px;opacity:.8;z-index:9999}.page-header{margin:20px 0}.footer{min-height:60px;padding:1rem;margin-top:48px;margin-bottom:24px;border-top:1px solid #e9e9e9;font-size:14px}.footer .locale li.active a,.footer a:hover{color:#444}.footer .locale li.active{background-color:#e9e9e9}i.icon{display:inline-block;width:10px;margin-right:10px}span.form-error{margin-top:5px;display:block;font-size:.8em;color:#d9534f;font-weight:100}.divider{display:block;margin:1rem auto;width:100%}.back-to-top{position:fixed;bottom:1px;right:1px;display:none;z-index:9998;transition:all .5s ease-in-out;padding:8px 10px}.landing{margin-top:50px}.landing hr{margin:4rem}.landing #laracroft{background:url(/images/459033.jpg) center 50px no-repeat fixed;background-size:cover;position:relative;transition:all .5s ease;margin-bottom:5rem}.landing #laracroft .container-fluid{color:#fff;padding:calc(100% / 4 - 125px) 0}.landing #laracroft .container-fluid .row{background:rgba(0,0,0,.5);text-align:center;padding-bottom:20px}.landing #laracroft span.selection{background:#fff7a8;color:#444;text-shadow:none}.landing #laracroft .credit{position:absolute;right:2rem;bottom:1rem;color:#fff;font-weight:700;font-size:.8rem}.landing #laracroft .credit a{color:#fff;text-decoration:underline}.container__lessons aside li.active a,.container__lessons aside li.active a:active,.container__lessons aside li.active a:focus,.container__lessons aside li.active a:hover,.tags__lessons li a{color:#444}.landing #feature h1,.landing #story h1{margin-bottom:2rem}.landing #feature blockquote,.landing #story blockquote{margin:2rem auto}.landing #feature pre{width:95%;margin:2rem auto}.landing #courses img{width:8rem;max-width:50%;display:block;margin:2rem auto}.landing #courses h1,.landing #courses h2,.landing #courses h3,.landing #courses h4,.landing #courses p{margin:1rem auto}.landing #courses .btn{display:inline-block;margin:1rem auto}.landing #mailing-list form{display:block;margin-left:auto;margin-right:auto}.form-auth{max-width:330px;width:100%;padding:15px;margin:0 auto}.form-auth .checkbox,.form-auth .form-signin-heading{margin-bottom:1rem}.form-auth .checkbox{font-weight:400}.form-auth .form-control,.form-auth div.dropzone,.form-auth div.preview__forum{position:relative;height:auto;box-sizing:border-box;padding:.6rem}.form-auth .form-control:focus,.form-auth div.dropzone:focus,.form-auth div.preview__forum:focus{z-index:2}.form-auth input{margin-bottom:10px}.container__lessons{margin-top:1rem}.container__lessons article{background-color:#fff;padding:1rem}.container__lessons .media{margin:24px 0}.container__lessons aside li{display:block}.container__lessons aside li a{display:block;padding:.5rem 1rem}.container__lessons aside li.active{background-color:#e9e9e9}.container__lessons .article__lessons article ul,.container__lessons aside ul{list-style:none;padding-left:1rem}.container__lessons dl{width:auto;margin:1rem auto;font-weight:300}.container__lessons dd,.container__lessons dt{padding:.5rem}.tags__lessons{display:inline-block;padding:0}.tags__lessons li a:active,.tags__lessons li a:focus,.tags__lessons li a:hover{color:#fff}.tags__lessons li.active,.tags__lessons li:focus,.tags__lessons li:hover{background-color:#2f7dc8;color:#fff;transition:all .3s ease}.tags__lessons .label{display:inline-block;margin-left:0!important;margin-right:5px;margin-bottom:5px;padding:5px 7px;font-weight:100;border-radius:1px;background-color:#e9e9e9;color:#444}.sidebar__lessons aside>ul>li>ul>li:first-child{margin-top:.5rem}.sidebar__lessons aside>ul>li{padding:0 0 1rem;margin-bottom:24px;border-bottom:1px solid #e9e9e9}.sidebar__lessons aside>ul>li:last-child{border-bottom:none}.article__lessons article:first-child{line-height:1.6rem}.article__lessons article:first-child li{padding:.5rem 0}.article__lessons article:first-child h2:before,.article__lessons article:first-child h3:before,.article__lessons article:first-child h4:before,.article__lessons article:first-child h5:before,.article__lessons article:first-child h6:before,.article__lessons article:first-child ul li:before{content:\"# \";padding-right:5px;opacity:.4;color:#2f7dc8}.article__lessons article:first-child pre{margin-bottom:24px}.article__lessons article:first-child h1{margin-bottom:.8rem;margin-top:.5rem}.article__lessons article:first-child h2{margin-top:1rem;margin-bottom:24px;padding-top:48px;border-top:1px solid #e9e9e9}.article__lessons article:first-child h4{font-size:1.2rem}.article__lessons article:first-child h2 a,.article__lessons article:first-child h3 a,.article__lessons article:first-child h4 a,.article__lessons article:first-child h5 a,.article__lessons article:first-child h6 a{transition:250ms linear all}.article__lessons article:first-child p>img,.container__forum img{line-height:1rem;transition:all .2s ease-in-out;max-width:100%;height:auto}.article__lessons article:first-child h2 a:active,.article__lessons article:first-child h2 a:focus,.article__lessons article:first-child h2 a:hover,.article__lessons article:first-child h3 a:active,.article__lessons article:first-child h3 a:focus,.article__lessons article:first-child h3 a:hover,.article__lessons article:first-child h4 a:active,.article__lessons article:first-child h4 a:focus,.article__lessons article:first-child h4 a:hover,.article__lessons article:first-child h5 a:active,.article__lessons article:first-child h5 a:focus,.article__lessons article:first-child h5 a:hover,.article__lessons article:first-child h6 a:active,.article__lessons article:first-child h6 a:focus,.article__lessons article:first-child h6 a:hover{outline:0}.article__lessons article:first-child p{margin-bottom:24px}.article__lessons article:first-child blockquote{background-color:#e9e9e9;font-size:1rem;border-radius:2px;box-sizing:border-box;margin-bottom:24px;max-width:100%;padding:1rem;opacity:.7}.article__lessons article:first-child blockquote p{margin-bottom:0}.article__lessons article:first-child p>img{display:inline-block;padding:4px;margin:0 auto;background-color:#fff}.article__lessons article:first-child table{width:100%;max-width:100%;overflow-y:hidden;overflow-x:auto;border-radius:2px;background-color:transparent;margin:24px auto}.article__lessons article:first-child table>tbody>tr>td,.article__lessons article:first-child table>tbody>tr>th,.article__lessons article:first-child table>tfoot>tr>td,.article__lessons article:first-child table>tfoot>tr>th,.article__lessons article:first-child table>thead>tr>td,.article__lessons article:first-child table>thead>tr>th{padding:.5rem;border-top:1px solid #eee}.article__lessons article:first-child table>tbody>tr:nth-child(odd)>td,.article__lessons article:first-child table>tbody>tr:nth-child(odd)>th{background-color:#efefef}.article__lessons article:first-child ul.pager li:before{content:\"\"!important;color:#2f7dc8;padding-right:5px;opacity:0}.container__forum aside li.active a,.container__forum aside li.active a:active,.container__forum aside li.active a:focus,.container__forum aside li.active a:hover,.tags__forum li a{color:#444}div.nav__lessons{display:none}.container__forum{margin-top:1rem}.container__forum .form__forum,.container__forum article{background-color:#fff;padding:1rem}.container__forum .media{margin:24px 0}.container__forum aside li{display:block}.container__forum aside li a{display:block;padding:.5rem 1rem}.container__forum aside li.active{background-color:#e9e9e9}.container__forum img{display:inline-block;padding:4px;margin:0 auto;background-color:#fff}.container__forum table{width:100%;max-width:100%;overflow-y:hidden;overflow-x:auto;border-radius:2px;background-color:transparent;margin:24px auto}.container__forum table>tbody>tr>td,.container__forum table>tbody>tr>th,.container__forum table>tfoot>tr>td,.container__forum table>tfoot>tr>th,.container__forum table>thead>tr>td,.container__forum table>thead>tr>th{padding:.5rem;border-top:1px solid #eee}.container__forum table>tbody>tr:nth-child(odd)>td,.container__forum table>tbody>tr:nth-child(odd)>th{background-color:#efefef}.sidebar__forum aside>ul>li{margin-bottom:1rem}.sidebar__forum aside form{padding-left:1rem;margin-bottom:1rem}.sidebar__forum aside p.lead{margin:0;padding:1rem}.sidebar__forum aside ul{padding-left:1rem}.tags__forum{display:inline-block;padding:0}.tags__forum li a:active,.tags__forum li a:focus,.tags__forum li a:hover{color:#fff}.tags__forum li.active,.tags__forum li:focus,.tags__forum li:hover{background-color:#2f7dc8;color:#fff;transition:all .3s ease}.tags__forum .label{display:inline-block;margin-left:0!important;margin-right:5px;margin-bottom:5px;padding:5px 7px;font-weight:100;border-radius:1px;background-color:#e9e9e9;color:#444}div.dropzone,div.nav__forum{display:none}div.preview__forum{display:none;margin-top:24px;height:auto}div.dropzone{height:auto}textarea.forum__content{width:100%;padding:1rem}pre{padding:0;border:none;border-radius:0}pre>code.hljs{padding:1rem}.login__forum{padding:1rem;border-radius:3px;border:1px solid #e9e9e9;width:100%}.border__item{padding:1rem;border-radius:3px;position:relative;overflow:visible;float:right;width:calc(100% - 80px);border:1px solid #e9e9e9}.border__item:before{content:\"\";display:block;position:absolute;top:21px;left:-6px;width:10px;height:10px;background:#fff;border-left:1px solid #e9e9e9;border-top:1px solid #e9e9e9;-moz-transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}@media screen and (max-width:991px){.landing h1{font-size:32px}.landing h2{font-size:26px}.landing p.lead{font-size:16px}.landing hr{margin:2rem auto}.sidebar__forum,.sidebar__lessons{display:none;overflow:hidden;margin-bottom:24px}.sidebar__forum li a,.sidebar__lessons li a{display:block}.sidebar__forum li a:hover,.sidebar__lessons li a:hover{background-color:#29ABE0;color:#fff}div.sort__forum{display:none}div.nav__forum,div.nav__lessons{position:fixed;bottom:1px;left:1px;z-index:9999;display:block;transition:all .5s ease-in-out}.border__item{width:100%}.border__item:before{content:none}}@media screen and (max-width:767px){.landing h1{font-size:29px}.landing h2{font-size:23px}.landing p.lead{font-size:13px}.landing #laracroft{background-size:contain}.landing #laracroft .container-fluid{padding:4rem 0}.landing button{white-space:normal!important;word-wrap:break-word!important;padding:6px 12px!important;line-height:1.42!important;border-radius:4px!important}.landing #feature pre{width:100%}}@media screen and (max-width:540px){.landing #laracroft{background-size:540px 342px}}@media screen and (max-width:480px){.landing h1{font-size:26px}.landing h2{font-size:20px}.landing p.lead{font-size:12px}.landing #laracroft{background-size:480px 300px}article img{display:block;width:100%;max-width:100%;height:auto}}@-webkit-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%,70%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-moz-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%,70%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%,70%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-webkit-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}@-moz-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}@keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-ms-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes pulse{0%,20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}}@-moz-keyframes pulse{0%,20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}}@keyframes pulse{0%,20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone{min-height:150px;border:2px solid rgba(0,0,0,.3);background:#fff;padding:20px}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:.5}.dropzone .dz-preview.dz-file-preview .dz-details,.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-message{text-align:center;margin:2em 0}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(to bottom,#eee,#ddd)}.dropzone .dz-preview.dz-image-preview{background:#fff}.dropzone .dz-preview.dz-image-preview .dz-details{-webkit-transition:opacity .2s linear;-moz-transition:opacity .2s linear;-ms-transition:opacity .2s linear;-o-transition:opacity .2s linear;transition:opacity .2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid rgba(200,200,200,.8);background-color:rgba(255,255,255,.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid transparent}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:rgba(255,255,255,.4);padding:0 .4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{-webkit-transform:scale(1.05,1.05);-moz-transform:scale(1.05,1.05);-ms-transform:scale(1.05,1.05);-o-transform:scale(1.05,1.05);transform:scale(1.05,1.05);-webkit-filter:blur(8px);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{-webkit-animation:passing-through 3s cubic-bezier(.77,0,.175,1);-moz-animation:passing-through 3s cubic-bezier(.77,0,.175,1);-ms-animation:passing-through 3s cubic-bezier(.77,0,.175,1);-o-animation:passing-through 3s cubic-bezier(.77,0,.175,1);animation:passing-through 3s cubic-bezier(.77,0,.175,1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;-webkit-animation:slide-in 3s cubic-bezier(.77,0,.175,1);-moz-animation:slide-in 3s cubic-bezier(.77,0,.175,1);-ms-animation:slide-in 3s cubic-bezier(.77,0,.175,1);-o-animation:slide-in 3s cubic-bezier(.77,0,.175,1);animation:slide-in 3s cubic-bezier(.77,0,.175,1)}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px}.dropzone .dz-preview .dz-error-mark svg,.dropzone .dz-preview .dz-success-mark svg{display:block;width:54px;height:54px}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;-webkit-transition:all .2s linear;-moz-transition:all .2s linear;-ms-transition:all .2s linear;-o-transition:all .2s linear;transition:all .2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;-webkit-transition:opacity .4s ease-in;-moz-transition:opacity .4s ease-in;-ms-transition:opacity .4s ease-in;-o-transition:opacity .4s ease-in;transition:opacity .4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{-webkit-animation:pulse 6s ease infinite;-moz-animation:pulse 6s ease infinite;-ms-animation:pulse 6s ease infinite;-o-animation:pulse 6s ease infinite;animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:16px;left:50%;top:50%;margin-top:-8px;width:80px;margin-left:-40px;background:rgba(255,255,255,.9);-webkit-transform:scale(1);border-radius:8px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#333;background:linear-gradient(to bottom,#666,#444);position:absolute;top:0;left:0;bottom:0;width:0;-webkit-transition:width .3s ease-in-out;-moz-transition:width .3s ease-in-out;-ms-transition:width .3s ease-in-out;-o-transition:width .3s ease-in-out;transition:width .3s ease-in-out}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;-webkit-transition:opacity .3s ease;-moz-transition:opacity .3s ease;-ms-transition:opacity .3s ease;-o-transition:opacity .3s ease;transition:opacity .3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#be2626;background:linear-gradient(to bottom,#be2626,#a92222);padding:.5em 1.2em;color:#fff}.dropzone .dz-preview .dz-error-message:after{content:'';position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #be2626}.hljs{display:block;padding:.5em;background:#12100f;color:#EBD1B7}.hljs-comment,.hljs-javadoc,.hljs-template_comment{color:#7A7267}.hljs-keyword,.hljs-request,.hljs-status,.nginx .hljs-title,.ruby .hljs-function .hljs-keyword{color:#DB784D}.hljs-function .hljs-keyword,.hljs-list .hljs-title,.hljs-sub .hljs-keyword,.method{color:#60A365}.apache .hljs-cbracket,.coffeescript .hljs-attribute,.hljs-attr_selector,.hljs-cdata,.hljs-date,.hljs-filter .hljs-argument,.hljs-string,.hljs-tag .hljs-value,.tex .hljs-command{color:#F8BB39}.hljs-subst{color:#DAEFA3}.hljs-regexp{color:#E9C062}.hljs-decorator,.hljs-pi,.hljs-prompt,.hljs-shebang,.hljs-sub .hljs-identifier,.hljs-tag,.hljs-tag .hljs-keyword,.hljs-title{color:#DB784D}.hljs-number,.hljs-symbol,.ruby .hljs-symbol .hljs-string{color:#F8BB39}.clojure .hljs-attribute,.hljs-params,.hljs-variable{color:#95CC5E}.css .hljs-tag,.hljs-pseudo,.hljs-rules .hljs-property,.tex .hljs-special{color:#DB784D}.css .hljs-class,.hljs-rules .hljs-keyword{color:#95CC5E}.hljs-rules .hljs-value{color:#DB784D}.css .hljs-id{color:#8B98AB}.apache .hljs-sqbracket,.hljs-annotation,.nginx .hljs-built_in{color:#9B859D}.hljs-pragma,.hljs-preprocessor{color:#8996A8}.css .hljs-value .hljs-number,.hljs-hexcolor{color:#DD7B3B}.css .hljs-function{color:#DAD085}.diff .hljs-header,.hljs-chunk,.tex .hljs-formula{background-color:#0E2231;color:#F8F8F8;font-style:italic}.diff .hljs-change{background-color:#4A410D;color:#F8F8F8}.hljs-addition{background-color:#253B22;color:#F8F8F8}.hljs-deletion{background-color:#420E09;color:#F8F8F8}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .css,.xml .hljs-cdata,.xml .javascript,.xml .vbscript{opacity:.5}"
  },
  {
    "path": "public/build/js/app-038b8ad709.js",
    "content": "/*!\n * jQuery JavaScript Library v2.1.4\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2015-04-28T16:01Z\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//\n\nvar arr = [];\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\tversion = \"2.1.4\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\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\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\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\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\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(null);\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: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, 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\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\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) || (copyIsArray = jQuery.isArray(copy)) ) ) {\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\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\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\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\treturn !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\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\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\t// Support: Android<4.0, iOS<6 (functionish RegExp)\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// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE9-11+\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\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\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\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\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\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\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\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 value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\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 tmp, args, proxy;\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: Date.now,\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// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(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 = \"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\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\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.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\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// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + 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 = \":(\" + characterEncoding + \")(?:\\\\((\" +\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( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\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 match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\tnodeType = context.nodeType;\n\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\tif ( !seed && documentIsHTML ) {\n\n\t\t// Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\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 (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\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} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType !== 1 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\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 = attrs.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// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\tparent = doc.defaultView;\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Support tests\n\t---------------------------------------------------------------------- */\n\tdocumentIsHTML = !isXML( doc );\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( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( doc.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 !doc.getElementsByName || !doc.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\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [ 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\" && elem.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 ( 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( doc.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 + \"-\\f]' 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.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\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 = doc.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 does not implement inclusive descendent\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 === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || 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 === doc ? -1 :\n\t\t\t\tb === doc ? 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 doc;\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( !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, outerCache, node, diff, 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\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 ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\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\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && 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\touterCache[ 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// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\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\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\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\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\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, 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 dir 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\t\t\t\t\t\tif ( (oldCache = outerCache[ 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\touterCache[ 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;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\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\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, 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// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\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 no seed and only one group\n\tif ( match.length === 1 ) {\n\n\t\t// Take a shortcut and set the context if the root 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\trsibling.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.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\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 ( indexOf.call( qualifier, elem ) >= 0 ) !== 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\tlen = this.length,\n\t\t\tret = [],\n\t\t\tself = this;\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 ) {\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// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[0] === \"<\" && selector[ selector.length - 1 ] === \">\" && selector.length >= 3 ) {\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// Option to run 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\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// Support: Blackberry 4.6\n\t\t\t\t\t// gEBID returns nodes no longer in the document (#6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// 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 || rootjQuery ).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 rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\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\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.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; 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\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.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\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 indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\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\twhile ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}\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 jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.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 jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = 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\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\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\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\nvar rnotwhite = (/\\S+/g);\n\n\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\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\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\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\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\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\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\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 && type !== \"string\" ) {\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\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\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});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\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 ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\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\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\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 ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\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\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\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\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.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\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\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\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\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 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. 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\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.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\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\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\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 * The ready event handler and self cleanup method\n */\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\twindow.removeEventListener( \"load\", completed, false );\n\tjQuery.ready();\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 after the browser event has already occurred.\n\t\t// We once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\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// 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 = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = 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\tjQuery.access( 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\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 < len; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\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\tlen ? fn( elems[0], key ) : emptyGet;\n};\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( owner ) {\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\t/* jshint -W018 */\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\nfunction Data() {\n\t// Support: Android<4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\nData.accepts = jQuery.acceptData;\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android<4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\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 = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\nvar data_priv = new Data();\n\nvar data_user = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\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\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\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\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\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend({\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\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// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\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\tdata_priv.set( elem, \"hasDataAttrs\", 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\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( 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 = data_priv.get( 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 = data_priv.access( 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 public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", 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\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 = data_priv.get( 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});\nvar pnum = (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\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\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Safari<=5.1\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\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, Android<4.2\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<=11+\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n})();\nvar strundefined = typeof undefined;\n\n\n\nsupport.focusinBubbles = \"onfocusin\" in window;\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\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\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( 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\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 !== strundefined && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\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 if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\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},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( 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] && new 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 || selector === \"**\" && 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 || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\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\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\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(\".\") >= 0 ) {\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.namespace_re = 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 = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\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 && jQuery.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 ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\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// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( 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\telem[ type ]();\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 = ( data_priv.get( 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++ ]) && !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.namespace_re || event.namespace_re.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 || handleObj.handler )\n\t\t\t\t\t\t\t.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// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( 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 ) >= 0 :\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\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase 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 offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\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 + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\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\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: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome<28\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\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\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\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\tthis.focus();\n\t\t\t\t\treturn false;\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\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\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\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\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\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\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\t\t\t\t// Support: 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\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\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\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 && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\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// Support: Chrome 15+\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 mousenter/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// Support: Firefox, Chrome, Safari\n// Create \"bubbling\" focus and blur events\nif ( !support.focusinBubbles ) {\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\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\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 = data_priv.access( 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\tdata_priv.access( 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 = data_priv.access( 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\tdata_priv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdata_priv.access( 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, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( 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\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 ? handleObj.origType + \".\" + handleObj.namespace : handleObj.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\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\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\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\n\t\t// Support: IE9\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE9\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: 1.x compatibility\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 = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!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\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\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, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], 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\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [],\n\t\t\ti = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type, key,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( jQuery.acceptData( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\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\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\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().each(function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( 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 this.domManip( 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 this.domManip( 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 this.domManip( 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\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\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\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\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 && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\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!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\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 arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\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\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\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\tjQuery.globalEval( node.textContent.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\t\t}\n\n\t\treturn this;\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\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\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// Support: QtWebKit\n\t\t\t// .get() because push.apply(_, arraylike) throws\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/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar style,\n\t\telem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?\n\n\t\t\t// Use of this method is a temporary fix (more like optimization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\tstyle.display : 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'/>\" )).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 ].contentDocument;\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 getStyles = function( elem ) {\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\tif ( elem.ownerDocument.defaultView.opener ) {\n\t\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t\t}\n\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// Support: IE9\n\t// getPropertyValue is only needed for .css('filter') (#12537)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\t}\n\n\tif ( computed ) {\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// Support: iOS < 6\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\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\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\n(function() {\n\tvar pixelPositionVal, boxSizingReliableVal,\n\t\tdocElem = document.documentElement,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE9-11+\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tcontainer.style.cssText = \"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;\" +\n\t\t\"position:absolute\";\n\tcontainer.appendChild( div );\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computePixelPositionAndBoxSizingReliable() {\n\t\tdiv.style.cssText =\n\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;\" +\n\t\t\t\"box-sizing:border-box;display:block;margin-top:1%;top:1%;\" +\n\t\t\t\"border:1px;padding:1px;width:4px;position:absolute\";\n\t\tdiv.innerHTML = \"\";\n\t\tdocElem.appendChild( container );\n\n\t\tvar divStyle = window.getComputedStyle( div, null );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\tdocElem.removeChild( container );\n\t}\n\n\t// Support: node.js jsdom\n\t// Don't assume that getComputedStyle is a property of the global object\n\tif ( window.getComputedStyle ) {\n\t\tjQuery.extend( support, {\n\t\t\tpixelPosition: function() {\n\n\t\t\t\t// This test is executed only once but we still do memoizing\n\t\t\t\t// since we can use the boxSizingReliable pre-computing.\n\t\t\t\t// No need to check if the test was already performed, though.\n\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\treturn pixelPositionVal;\n\t\t\t},\n\t\t\tboxSizingReliable: function() {\n\t\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\t}\n\t\t\t\treturn boxSizingReliableVal;\n\t\t\t},\n\t\t\treliableMarginRight: function() {\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// This support function is only executed once so no memoizing is needed.\n\t\t\t\tvar ret,\n\t\t\t\t\tmarginDiv = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\t\tmarginDiv.style.cssText = div.style.cssText =\n\t\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\t\tdiv.style.width = \"1px\";\n\t\t\t\tdocElem.appendChild( container );\n\n\t\t\t\tret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );\n\n\t\t\t\tdocElem.removeChild( container );\n\t\t\t\tdiv.removeChild( marginDiv );\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t});\n\t}\n})();\n\n\n// A method for quickly swapping in/out CSS properties to get correct calculations.\njQuery.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\n\t// Swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\trrelNum = 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\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// Check for vendor prefixed names\n\tvar capName = name[0].toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\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\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\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\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\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\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 = jQuery.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\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// 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\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 ] = data_priv.get( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\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 ] = data_priv.access( 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 !== \"none\" || !hidden ) {\n\t\t\t\tdata_priv.set( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\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\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\"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\t\t\"float\": \"cssFloat\"\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 ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// Gets hook for the prefixed version, then 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 = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\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 (#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, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// background-* props affect original clone's values\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) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\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 val, num, 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 ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// Try prefixed name followed by the unprefixed name\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// Make numeric 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 || jQuery.isNumeric( 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// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) && elem.offsetWidth === 0 ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\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\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\n// Support: Android 2.3\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\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 || \"swing\";\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\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || 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// 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\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\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if 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.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.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: IE9\n// Panic based approach to setting things on disconnected nodes\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};\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\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +target ) &&\n\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( start && start[ 3 ] !== unit ) {\n\t\t\t\t// Trust units reported by jQuery.css\n\t\t\t\tunit = unit || start[ 3 ];\n\n\t\t\t\t// Make sure we update the tween properties later on\n\t\t\t\tparts = parts || [];\n\n\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\tstart = +target || 1;\n\n\t\t\t\tdo {\n\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t// Adjust and apply\n\t\t\t\t\tstart = start / scale;\n\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur(),\n\t\t\t\t// break the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t}\n\n\t\t\t// Update tween properties\n\t\t\tif ( parts ) {\n\t\t\t\tstart = tween.start = +start || +target || 0;\n\t\t\t\ttween.unit = unit;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[ 1 ] ?\n\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n\t\t\t\t\t+parts[ 2 ];\n\t\t\t}\n\n\t\t\treturn tween;\n\t\t} ]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(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\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise 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 = ( tweeners[ prop ] || [] ).concat( 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 = data_priv.get( 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\t\t\t// Ensure the complete handler is called 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\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE9-10 do 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\tdata_priv.get( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\t\t\tstyle.display = \"inline-block\";\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always(function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\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 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 = data_priv.access( 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\n\t\t\tdata_priv.remove( 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 won't overwrite existing keys.\n\t\t\t// Reusing 'index' 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 = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\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\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, { specialEasing: {} }, 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\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; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\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 = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\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\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.split(\" \");\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\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.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 ? jQuery.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\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 || data_priv.get( 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 = data_priv.get( 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 && (type == null || timers[ index ].queue === type) ) {\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\n\t\t\t// will dequeue 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 = data_priv.get( 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\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\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 = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// 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 = setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\tclearTimeout( timeout );\n\t\t};\n\t});\n};\n\n\n(function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: iOS<=5.1, Android<=4.2+\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE<=11+\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: Android<=2.3\n\t// Options inside disabled selects are incorrectly marked as disabled\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<=11+\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n})();\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\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 hooks, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || 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 === strundefined ) {\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\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\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\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\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\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\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle;\n\t\tif ( !isXML ) {\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ name ];\n\t\t\tattrHandle[ name ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tname.toLowerCase() :\n\t\t\t\tnull;\n\t\t\tattrHandle[ name ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n});\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/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\treturn this.each(function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\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\treturn hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n\t\t\t\tret :\n\t\t\t\t( elem[ name ] = value );\n\n\t\t} else {\n\t\t\treturn hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ?\n\t\t\t\tret :\n\t\t\t\telem[ name ];\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.hasAttribute( \"tabindex\" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n\t\t\t\t\telem.tabIndex :\n\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\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\n\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\njQuery.fn.extend({\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\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, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\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 ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = 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, clazz, j, finalValue,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\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, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\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\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\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 = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = 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( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// Toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\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 ( type === strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tdata_priv.set( this, \"__className__\", this.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\tthis.className = this.className || value === false ? \"\" : data_priv.get( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\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\nvar rreturn = /\\r/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 ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\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\t\t\t\t\t// Handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\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\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\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\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\tjQuery.trim( jQuery.text( elem ) );\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// IE6-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\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 ? !option.disabled : option.getAttribute( \"disabled\" ) === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !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\t\t\t\t\tif ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {\n\t\t\t\t\t\toptionSet = true;\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\t\t\t\treturn values;\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 ) >= 0 );\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\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(\" \"), function( 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\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\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n\n\nvar nonce = jQuery.now();\n\nvar rquery = (/\\?/);\n\n\n\n// Support: Android 2.3\n// Workaround failure to string-cast null input\njQuery.parseJSON = function( data ) {\n\treturn JSON.parse( 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\n\t// Support: IE9\n\ttry {\n\t\ttmp = new DOMParser();\n\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || 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\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\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 = window.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\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[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\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\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 key, deep,\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\n\tvar ct, type, finalDataType, firstDataType,\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\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\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\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// 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\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\" ] ) {\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 { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\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: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\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 transport,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\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 && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\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\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\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 (prefilters might expect it)\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 ) + \"\" ).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\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] ] + ( 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 && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\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\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = 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\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\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\tclearTimeout( 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\t\t\t\t// Extract error from statusText and normalize 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\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\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\treturn jQuery.ajax({\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});\n\t};\n});\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\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\tvar wrap;\n\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\twrap = 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.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\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\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0;\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\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\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\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\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\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\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\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\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\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\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new XMLHttpRequest();\n\t} catch( e ) {}\n};\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSuccessStatus = {\n\t\t// file protocol always yields status code 0, assume 200\n\t\t0: 200,\n\t\t// Support: IE9\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE9\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 ]();\n\t\t}\n\t});\n}\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport(function( options ) {\n\tvar callback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t// file: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText\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\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\t\t\t\t\t\t\t\t\t// Support: IE9\n\t\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === \"string\" ? {\n\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n\t\t\t\t\t\t\t\t\t} : undefined,\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\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};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\txhr.onerror = callback(\"error\");\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = xhrCallbacks[ id ] = callback(\"abort\");\n\n\t\t\t\ttry {\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\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 crossDomain\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}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery(\"<script>\").prop({\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t}).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\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\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.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\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\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, 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 = jQuery.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 >= 0 ) {\n\t\tselector = jQuery.trim( url.slice( off ) );\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\ttype: type,\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}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\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( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], 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\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\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\t( curCSSTop + curCSSLeft ).indexOf(\"auto\") > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left 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\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\t\t\toptions = options.call( elem, i, 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\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\telem = this[ 0 ],\n\t\t\tbox = { top: 0, left: 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// Support: BlackBerry 5, iOS 3 (original iPhone)\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\tif ( typeof elem.getBoundingClientRect !== strundefined ) {\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.clientTop,\n\t\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\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\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\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\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 || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || docElem;\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 = \"pageYOffset\" === 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 ? win[ prop ] : elem[ 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 : window.pageXOffset,\n\t\t\t\t\ttop ? val : window.pageYOffset\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+, Chrome<37+\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, 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\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 }, function( defaultExtra, funcName ) {\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\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\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\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\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\n\nvar\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 AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === strundefined ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n\n}));\n\n/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under the MIT license\n */\n\nif (typeof jQuery === 'undefined') {\n  throw new Error('Bootstrap\\'s JavaScript requires jQuery')\n}\n\n+function ($) {\n  'use strict';\n  var version = $.fn.jquery.split(' ')[0].split('.')\n  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {\n    throw new Error('Bootstrap\\'s JavaScript requires jQuery version 1.9.1 or higher')\n  }\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: transition.js v3.3.5\n * http://getbootstrap.com/javascript/#transitions\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      WebkitTransition : 'webkitTransitionEnd',\n      MozTransition    : 'transitionend',\n      OTransition      : 'oTransitionEnd otransitionend',\n      transition       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n\n    return false // explicit for ie8 (  ._.)\n  }\n\n  // http://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false\n    var $el = this\n    $(this).one('bsTransitionEnd', function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n\n    if (!$.support.transition) return\n\n    $.event.special.bsTransitionEnd = {\n      bindType: $.support.transition.end,\n      delegateType: $.support.transition.end,\n      handle: function (e) {\n        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)\n      }\n    }\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: alert.js v3.3.5\n * http://getbootstrap.com/javascript/#alerts\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.VERSION = '3.3.5'\n\n  Alert.TRANSITION_DURATION = 150\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = $(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.closest('.alert')\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      // detach from parent, fire event then clean up data\n      $parent.detach().trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one('bsTransitionEnd', removeElement)\n        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  var old = $.fn.alert\n\n  $.fn.alert             = Plugin\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: button.js v3.3.5\n * http://getbootstrap.com/javascript/#buttons\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element  = $(element)\n    this.options   = $.extend({}, Button.DEFAULTS, options)\n    this.isLoading = false\n  }\n\n  Button.VERSION  = '3.3.5'\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state += 'Text'\n\n    if (data.resetText == null) $el.data('resetText', $el[val]())\n\n    // push to event loop to allow forms to submit\n    setTimeout($.proxy(function () {\n      $el[val](data[state] == null ? this.options[state] : data[state])\n\n      if (state == 'loadingText') {\n        this.isLoading = true\n        $el.addClass(d).attr(d, d)\n      } else if (this.isLoading) {\n        this.isLoading = false\n        $el.removeClass(d).removeAttr(d)\n      }\n    }, this), 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var changed = true\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input')\n      if ($input.prop('type') == 'radio') {\n        if ($input.prop('checked')) changed = false\n        $parent.find('.active').removeClass('active')\n        this.$element.addClass('active')\n      } else if ($input.prop('type') == 'checkbox') {\n        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false\n        this.$element.toggleClass('active')\n      }\n      $input.prop('checked', this.$element.hasClass('active'))\n      if (changed) $input.trigger('change')\n    } else {\n      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))\n      this.$element.toggleClass('active')\n    }\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  var old = $.fn.button\n\n  $.fn.button             = Plugin\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document)\n    .on('click.bs.button.data-api', '[data-toggle^=\"button\"]', function (e) {\n      var $btn = $(e.target)\n      if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n      Plugin.call($btn, 'toggle')\n      if (!($(e.target).is('input[type=\"radio\"]') || $(e.target).is('input[type=\"checkbox\"]'))) e.preventDefault()\n    })\n    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^=\"button\"]', function (e) {\n      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))\n    })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: carousel.js v3.3.5\n * http://getbootstrap.com/javascript/#carousel\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      = null\n    this.sliding     = null\n    this.interval    = null\n    this.$active     = null\n    this.$items      = null\n\n    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))\n\n    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element\n      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))\n      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))\n  }\n\n  Carousel.VERSION  = '3.3.5'\n\n  Carousel.TRANSITION_DURATION = 600\n\n  Carousel.DEFAULTS = {\n    interval: 5000,\n    pause: 'hover',\n    wrap: true,\n    keyboard: true\n  }\n\n  Carousel.prototype.keydown = function (e) {\n    if (/input|textarea/i.test(e.target.tagName)) return\n    switch (e.which) {\n      case 37: this.prev(); break\n      case 39: this.next(); break\n      default: return\n    }\n\n    e.preventDefault()\n  }\n\n  Carousel.prototype.cycle = function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getItemIndex = function (item) {\n    this.$items = item.parent().children('.item')\n    return this.$items.index(item || this.$active)\n  }\n\n  Carousel.prototype.getItemForDirection = function (direction, active) {\n    var activeIndex = this.getItemIndex(active)\n    var willWrap = (direction == 'prev' && activeIndex === 0)\n                || (direction == 'next' && activeIndex == (this.$items.length - 1))\n    if (willWrap && !this.options.wrap) return active\n    var delta = direction == 'prev' ? -1 : 1\n    var itemIndex = (activeIndex + delta) % this.$items.length\n    return this.$items.eq(itemIndex)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, \"slid\"\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || this.getItemForDirection(type, $active)\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var that      = this\n\n    if ($next.hasClass('active')) return (this.sliding = false)\n\n    var relatedTarget = $next[0]\n    var slideEvent = $.Event('slide.bs.carousel', {\n      relatedTarget: relatedTarget,\n      direction: direction\n    })\n    this.$element.trigger(slideEvent)\n    if (slideEvent.isDefaultPrevented()) return\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])\n      $nextIndicator && $nextIndicator.addClass('active')\n    }\n\n    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, \"slid\"\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      $next.addClass(type)\n      $next[0].offsetWidth // force reflow\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one('bsTransitionEnd', function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () {\n            that.$element.trigger(slidEvent)\n          }, 0)\n        })\n        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)\n    } else {\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger(slidEvent)\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  var old = $.fn.carousel\n\n  $.fn.carousel             = Plugin\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  var clickHandler = function (e) {\n    var href\n    var $this   = $(this)\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) // strip for ie7\n    if (!$target.hasClass('carousel')) return\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    Plugin.call($target, options)\n\n    if (slideIndex) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  }\n\n  $(document)\n    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)\n    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      Plugin.call($carousel, $carousel.data())\n    })\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: collapse.js v3.3.5\n * http://getbootstrap.com/javascript/#collapse\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.$trigger      = $('[data-toggle=\"collapse\"][href=\"#' + element.id + '\"],' +\n                           '[data-toggle=\"collapse\"][data-target=\"#' + element.id + '\"]')\n    this.transitioning = null\n\n    if (this.options.parent) {\n      this.$parent = this.getParent()\n    } else {\n      this.addAriaAndCollapsedClass(this.$element, this.$trigger)\n    }\n\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.VERSION  = '3.3.5'\n\n  Collapse.TRANSITION_DURATION = 350\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var activesData\n    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')\n\n    if (actives && actives.length) {\n      activesData = actives.data('bs.collapse')\n      if (activesData && activesData.transitioning) return\n    }\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    if (actives && actives.length) {\n      Plugin.call(actives, 'hide')\n      activesData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')[dimension](0)\n      .attr('aria-expanded', true)\n\n    this.$trigger\n      .removeClass('collapsed')\n      .attr('aria-expanded', true)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('collapse in')[dimension]('')\n      this.transitioning = 0\n      this.$element\n        .trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one('bsTransitionEnd', $.proxy(complete, this))\n      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element[dimension](this.$element[dimension]())[0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse in')\n      .attr('aria-expanded', false)\n\n    this.$trigger\n      .addClass('collapsed')\n      .attr('aria-expanded', false)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .removeClass('collapsing')\n        .addClass('collapse')\n        .trigger('hidden.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one('bsTransitionEnd', $.proxy(complete, this))\n      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n  Collapse.prototype.getParent = function () {\n    return $(this.options.parent)\n      .find('[data-toggle=\"collapse\"][data-parent=\"' + this.options.parent + '\"]')\n      .each($.proxy(function (i, element) {\n        var $element = $(element)\n        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)\n      }, this))\n      .end()\n  }\n\n  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {\n    var isOpen = $element.hasClass('in')\n\n    $element.attr('aria-expanded', isOpen)\n    $trigger\n      .toggleClass('collapsed', !isOpen)\n      .attr('aria-expanded', isOpen)\n  }\n\n  function getTargetFromTrigger($trigger) {\n    var href\n    var target = $trigger.attr('data-target')\n      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') // strip for ie7\n\n    return $(target)\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.collapse\n\n  $.fn.collapse             = Plugin\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=\"collapse\"]', function (e) {\n    var $this   = $(this)\n\n    if (!$this.attr('data-target')) e.preventDefault()\n\n    var $target = getTargetFromTrigger($this)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n\n    Plugin.call($target, option)\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: dropdown.js v3.3.5\n * http://getbootstrap.com/javascript/#dropdowns\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=\"dropdown\"]'\n  var Dropdown = function (element) {\n    $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.VERSION = '3.3.5'\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = selector && $(selector)\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n  function clearMenus(e) {\n    if (e && e.which === 3) return\n    $(backdrop).remove()\n    $(toggle).each(function () {\n      var $this         = $(this)\n      var $parent       = getParent($this)\n      var relatedTarget = { relatedTarget: this }\n\n      if (!$parent.hasClass('open')) return\n\n      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return\n\n      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))\n\n      if (e.isDefaultPrevented()) return\n\n      $this.attr('aria-expanded', 'false')\n      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)\n    })\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {\n        // if mobile we use a backdrop because click events don't delegate\n        $(document.createElement('div'))\n          .addClass('dropdown-backdrop')\n          .insertAfter($(this))\n          .on('click', clearMenus)\n      }\n\n      var relatedTarget = { relatedTarget: this }\n      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))\n\n      if (e.isDefaultPrevented()) return\n\n      $this\n        .trigger('focus')\n        .attr('aria-expanded', 'true')\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown', relatedTarget)\n    }\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive && e.which != 27 || isActive && e.which == 27) {\n      if (e.which == 27) $parent.find(toggle).trigger('focus')\n      return $this.trigger('click')\n    }\n\n    var desc = ' li:not(.disabled):visible a'\n    var $items = $parent.find('.dropdown-menu' + desc)\n\n    if (!$items.length) return\n\n    var index = $items.index(e.target)\n\n    if (e.which == 38 && index > 0)                 index--         // up\n    if (e.which == 40 && index < $items.length - 1) index++         // down\n    if (!~index)                                    index = 0\n\n    $items.eq(index).trigger('focus')\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.dropdown')\n\n      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown             = Plugin\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)\n    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.3.5\n * http://getbootstrap.com/javascript/#modals\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options             = options\n    this.$body               = $(document.body)\n    this.$element            = $(element)\n    this.$dialog             = this.$element.find('.modal-dialog')\n    this.$backdrop           = null\n    this.isShown             = null\n    this.originalBodyPad     = null\n    this.scrollbarWidth      = 0\n    this.ignoreBackdropClick = false\n\n    if (this.options.remote) {\n      this.$element\n        .find('.modal-content')\n        .load(this.options.remote, $.proxy(function () {\n          this.$element.trigger('loaded.bs.modal')\n        }, this))\n    }\n  }\n\n  Modal.VERSION  = '3.3.5'\n\n  Modal.TRANSITION_DURATION = 300\n  Modal.BACKDROP_TRANSITION_DURATION = 150\n\n  Modal.DEFAULTS = {\n    backdrop: true,\n    keyboard: true,\n    show: true\n  }\n\n  Modal.prototype.toggle = function (_relatedTarget) {\n    return this.isShown ? this.hide() : this.show(_relatedTarget)\n  }\n\n  Modal.prototype.show = function (_relatedTarget) {\n    var that = this\n    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.checkScrollbar()\n    this.setScrollbar()\n    this.$body.addClass('modal-open')\n\n    this.escape()\n    this.resize()\n\n    this.$element.on('click.dismiss.bs.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n\n    this.$dialog.on('mousedown.dismiss.bs.modal', function () {\n      that.$element.one('mouseup.dismiss.bs.modal', function (e) {\n        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true\n      })\n    })\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(that.$body) // don't move modals dom position\n      }\n\n      that.$element\n        .show()\n        .scrollTop(0)\n\n      that.adjustDialog()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element.addClass('in')\n\n      that.enforceFocus()\n\n      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })\n\n      transition ?\n        that.$dialog // wait for modal to slide in\n          .one('bsTransitionEnd', function () {\n            that.$element.trigger('focus').trigger(e)\n          })\n          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :\n        that.$element.trigger('focus').trigger(e)\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n    this.resize()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .off('click.dismiss.bs.modal')\n      .off('mouseup.dismiss.bs.modal')\n\n    this.$dialog.off('mousedown.dismiss.bs.modal')\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one('bsTransitionEnd', $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n          this.$element.trigger('focus')\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keydown.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.resize = function () {\n    if (this.isShown) {\n      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))\n    } else {\n      $(window).off('resize.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.$body.removeClass('modal-open')\n      that.resetAdjustments()\n      that.resetScrollbar()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $(document.createElement('div'))\n        .addClass('modal-backdrop ' + animate)\n        .appendTo(this.$body)\n\n      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {\n        if (this.ignoreBackdropClick) {\n          this.ignoreBackdropClick = false\n          return\n        }\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus()\n          : this.hide()\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one('bsTransitionEnd', callback)\n          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      var callbackRemove = function () {\n        that.removeBackdrop()\n        callback && callback()\n      }\n      $.support.transition && this.$element.hasClass('fade') ?\n        this.$backdrop\n          .one('bsTransitionEnd', callbackRemove)\n          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :\n        callbackRemove()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n  // these following methods are used to handle overflowing modals\n\n  Modal.prototype.handleUpdate = function () {\n    this.adjustDialog()\n  }\n\n  Modal.prototype.adjustDialog = function () {\n    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight\n\n    this.$element.css({\n      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',\n      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''\n    })\n  }\n\n  Modal.prototype.resetAdjustments = function () {\n    this.$element.css({\n      paddingLeft: '',\n      paddingRight: ''\n    })\n  }\n\n  Modal.prototype.checkScrollbar = function () {\n    var fullWindowWidth = window.innerWidth\n    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8\n      var documentElementRect = document.documentElement.getBoundingClientRect()\n      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)\n    }\n    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth\n    this.scrollbarWidth = this.measureScrollbar()\n  }\n\n  Modal.prototype.setScrollbar = function () {\n    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)\n    this.originalBodyPad = document.body.style.paddingRight || ''\n    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)\n  }\n\n  Modal.prototype.resetScrollbar = function () {\n    this.$body.css('padding-right', this.originalBodyPad)\n  }\n\n  Modal.prototype.measureScrollbar = function () { // thx walsh\n    var scrollDiv = document.createElement('div')\n    scrollDiv.className = 'modal-scrollbar-measure'\n    this.$body.append(scrollDiv)\n    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth\n    this.$body[0].removeChild(scrollDiv)\n    return scrollbarWidth\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  function Plugin(option, _relatedTarget) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option](_relatedTarget)\n      else if (options.show) data.show(_relatedTarget)\n    })\n  }\n\n  var old = $.fn.modal\n\n  $.fn.modal             = Plugin\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) // strip for ie7\n    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())\n\n    if ($this.is('a')) e.preventDefault()\n\n    $target.one('show.bs.modal', function (showEvent) {\n      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown\n      $target.one('hidden.bs.modal', function () {\n        $this.is(':visible') && $this.trigger('focus')\n      })\n    })\n    Plugin.call($target, option, this)\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: tooltip.js v3.3.5\n * http://getbootstrap.com/javascript/#tooltip\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       = null\n    this.options    = null\n    this.enabled    = null\n    this.timeout    = null\n    this.hoverState = null\n    this.$element   = null\n    this.inState    = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.VERSION  = '3.3.5'\n\n  Tooltip.TRANSITION_DURATION = 150\n\n  Tooltip.DEFAULTS = {\n    animation: true,\n    placement: 'top',\n    selector: false,\n    template: '<div class=\"tooltip\" role=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    container: false,\n    viewport: {\n      selector: 'body',\n      padding: 0\n    }\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled   = true\n    this.type      = type\n    this.$element  = $(element)\n    this.options   = this.getOptions(options)\n    this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))\n    this.inState   = { click: false, hover: false, focus: false }\n\n    if (this.$element[0] instanceof document.constructor && !this.options.selector) {\n      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')\n    }\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'\n\n        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay,\n        hide: options.delay\n      }\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.getDelegateOptions = function () {\n    var options  = {}\n    var defaults = this.getDefaults()\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget).data('bs.' + this.type)\n\n    if (!self) {\n      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())\n      $(obj.currentTarget).data('bs.' + this.type, self)\n    }\n\n    if (obj instanceof $.Event) {\n      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true\n    }\n\n    if (self.tip().hasClass('in') || self.hoverState == 'in') {\n      self.hoverState = 'in'\n      return\n    }\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'in'\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.isInStateTrue = function () {\n    for (var key in this.inState) {\n      if (this.inState[key]) return true\n    }\n\n    return false\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget).data('bs.' + this.type)\n\n    if (!self) {\n      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())\n      $(obj.currentTarget).data('bs.' + this.type, self)\n    }\n\n    if (obj instanceof $.Event) {\n      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false\n    }\n\n    if (self.isInStateTrue()) return\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'out'\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.' + this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])\n      if (e.isDefaultPrevented() || !inDom) return\n      var that = this\n\n      var $tip = this.tip()\n\n      var tipId = this.getUID(this.type)\n\n      this.setContent()\n      $tip.attr('id', tipId)\n      this.$element.attr('aria-describedby', tipId)\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n        .data('bs.' + this.type, this)\n\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n      this.$element.trigger('inserted.bs.' + this.type)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var orgPlacement = placement\n        var viewportDim = this.getPosition(this.$viewport)\n\n        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :\n                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :\n                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :\n                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)\n\n      this.applyPlacement(calculatedOffset, placement)\n\n      var complete = function () {\n        var prevHoverState = that.hoverState\n        that.$element.trigger('shown.bs.' + that.type)\n        that.hoverState = null\n\n        if (prevHoverState == 'out') that.leave(that)\n      }\n\n      $.support.transition && this.$tip.hasClass('fade') ?\n        $tip\n          .one('bsTransitionEnd', complete)\n          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :\n        complete()\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function (offset, placement) {\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    var marginTop = parseInt($tip.css('margin-top'), 10)\n    var marginLeft = parseInt($tip.css('margin-left'), 10)\n\n    // we must check for NaN for ie 8/9\n    if (isNaN(marginTop))  marginTop  = 0\n    if (isNaN(marginLeft)) marginLeft = 0\n\n    offset.top  += marginTop\n    offset.left += marginLeft\n\n    // $.fn.offset doesn't round pixel values\n    // so we use setOffset directly with our own function B-0\n    $.offset.setOffset($tip[0], $.extend({\n      using: function (props) {\n        $tip.css({\n          top: Math.round(props.top),\n          left: Math.round(props.left)\n        })\n      }\n    }, offset), 0)\n\n    $tip.addClass('in')\n\n    // check to see if placing tip in new offset caused the tip to resize itself\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      offset.top = offset.top + height - actualHeight\n    }\n\n    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)\n\n    if (delta.left) offset.left += delta.left\n    else offset.top += delta.top\n\n    var isVertical          = /top|bottom/.test(placement)\n    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight\n    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'\n\n    $tip.offset(offset)\n    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)\n  }\n\n  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {\n    this.arrow()\n      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n      .css(isVertical ? 'top' : 'left', '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function (callback) {\n    var that = this\n    var $tip = $(this.$tip)\n    var e    = $.Event('hide.bs.' + this.type)\n\n    function complete() {\n      if (that.hoverState != 'in') $tip.detach()\n      that.$element\n        .removeAttr('aria-describedby')\n        .trigger('hidden.bs.' + that.type)\n      callback && callback()\n    }\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && $tip.hasClass('fade') ?\n      $tip\n        .one('bsTransitionEnd', complete)\n        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :\n      complete()\n\n    this.hoverState = null\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function ($element) {\n    $element   = $element || this.$element\n\n    var el     = $element[0]\n    var isBody = el.tagName == 'BODY'\n\n    var elRect    = el.getBoundingClientRect()\n    if (elRect.width == null) {\n      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })\n    }\n    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()\n    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }\n    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null\n\n    return $.extend({}, elRect, scroll, outerDims, elOffset)\n  }\n\n  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {\n    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :\n           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :\n           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }\n\n  }\n\n  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {\n    var delta = { top: 0, left: 0 }\n    if (!this.$viewport) return delta\n\n    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0\n    var viewportDimensions = this.getPosition(this.$viewport)\n\n    if (/right|left/.test(placement)) {\n      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll\n      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight\n      if (topEdgeOffset < viewportDimensions.top) { // top overflow\n        delta.top = viewportDimensions.top - topEdgeOffset\n      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset\n      }\n    } else {\n      var leftEdgeOffset  = pos.left - viewportPadding\n      var rightEdgeOffset = pos.left + viewportPadding + actualWidth\n      if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n        delta.left = viewportDimensions.left - leftEdgeOffset\n      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow\n        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset\n      }\n    }\n\n    return delta\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.getUID = function (prefix) {\n    do prefix += ~~(Math.random() * 1000000)\n    while (document.getElementById(prefix))\n    return prefix\n  }\n\n  Tooltip.prototype.tip = function () {\n    if (!this.$tip) {\n      this.$tip = $(this.options.template)\n      if (this.$tip.length != 1) {\n        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')\n      }\n    }\n    return this.$tip\n  }\n\n  Tooltip.prototype.arrow = function () {\n    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = this\n    if (e) {\n      self = $(e.currentTarget).data('bs.' + this.type)\n      if (!self) {\n        self = new this.constructor(e.currentTarget, this.getDelegateOptions())\n        $(e.currentTarget).data('bs.' + this.type, self)\n      }\n    }\n\n    if (e) {\n      self.inState.click = !self.inState.click\n      if (self.isInStateTrue()) self.enter(self)\n      else self.leave(self)\n    } else {\n      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n    }\n  }\n\n  Tooltip.prototype.destroy = function () {\n    var that = this\n    clearTimeout(this.timeout)\n    this.hide(function () {\n      that.$element.off('.' + that.type).removeData('bs.' + that.type)\n      if (that.$tip) {\n        that.$tip.detach()\n      }\n      that.$tip = null\n      that.$arrow = null\n      that.$viewport = null\n    })\n  }\n\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data && /destroy|hide/.test(option)) return\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip             = Plugin\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: popover.js v3.3.5\n * http://getbootstrap.com/javascript/#popovers\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.VERSION  = '3.3.5'\n\n  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right',\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events\n      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'\n    ](content)\n\n    $tip.removeClass('fade top bottom left right in')\n\n    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do\n    // this manually by checking the contents.\n    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n            o.content.call($e[0]) :\n            o.content)\n  }\n\n  Popover.prototype.arrow = function () {\n    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data && /destroy|hide/.test(option)) return\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.popover\n\n  $.fn.popover             = Plugin\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: scrollspy.js v3.3.5\n * http://getbootstrap.com/javascript/#scrollspy\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    this.$body          = $(document.body)\n    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target || '') + ' .nav li > a'\n    this.offsets        = []\n    this.targets        = []\n    this.activeTarget   = null\n    this.scrollHeight   = 0\n\n    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.VERSION  = '3.3.5'\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.getScrollHeight = function () {\n    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var that          = this\n    var offsetMethod  = 'offset'\n    var offsetBase    = 0\n\n    this.offsets      = []\n    this.targets      = []\n    this.scrollHeight = this.getScrollHeight()\n\n    if (!$.isWindow(this.$scrollElement[0])) {\n      offsetMethod = 'position'\n      offsetBase   = this.$scrollElement.scrollTop()\n    }\n\n    this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#./.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && $href.is(':visible')\n          && [[$href[offsetMethod]().top + offsetBase, href]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        that.offsets.push(this[0])\n        that.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.getScrollHeight()\n    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (this.scrollHeight != scrollHeight) {\n      this.refresh()\n    }\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)\n    }\n\n    if (activeTarget && scrollTop < offsets[0]) {\n      this.activeTarget = null\n      return this.clear()\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])\n        && this.activate(targets[i])\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    this.clear()\n\n    var selector = this.selector +\n      '[data-target=\"' + target + '\"],' +\n      this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length) {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate.bs.scrollspy')\n  }\n\n  ScrollSpy.prototype.clear = function () {\n    $(this.selector)\n      .parentsUntil(this.options.target, '.active')\n      .removeClass('active')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy             = Plugin\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load.bs.scrollspy.data-api', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      Plugin.call($spy, $spy.data())\n    })\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: tab.js v3.3.5\n * http://getbootstrap.com/javascript/#tabs\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // TAB CLASS DEFINITION\n  // ====================\n\n  var Tab = function (element) {\n    // jscs:disable requireDollarBeforejQueryAssignment\n    this.element = $(element)\n    // jscs:enable requireDollarBeforejQueryAssignment\n  }\n\n  Tab.VERSION = '3.3.5'\n\n  Tab.TRANSITION_DURATION = 150\n\n  Tab.prototype.show = function () {\n    var $this    = this.element\n    var $ul      = $this.closest('ul:not(.dropdown-menu)')\n    var selector = $this.data('target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    if ($this.parent('li').hasClass('active')) return\n\n    var $previous = $ul.find('.active:last a')\n    var hideEvent = $.Event('hide.bs.tab', {\n      relatedTarget: $this[0]\n    })\n    var showEvent = $.Event('show.bs.tab', {\n      relatedTarget: $previous[0]\n    })\n\n    $previous.trigger(hideEvent)\n    $this.trigger(showEvent)\n\n    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return\n\n    var $target = $(selector)\n\n    this.activate($this.closest('li'), $ul)\n    this.activate($target, $target.parent(), function () {\n      $previous.trigger({\n        type: 'hidden.bs.tab',\n        relatedTarget: $this[0]\n      })\n      $this.trigger({\n        type: 'shown.bs.tab',\n        relatedTarget: $previous[0]\n      })\n    })\n  }\n\n  Tab.prototype.activate = function (element, container, callback) {\n    var $active    = container.find('> .active')\n    var transition = callback\n      && $.support.transition\n      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)\n\n    function next() {\n      $active\n        .removeClass('active')\n        .find('> .dropdown-menu > .active')\n          .removeClass('active')\n        .end()\n        .find('[data-toggle=\"tab\"]')\n          .attr('aria-expanded', false)\n\n      element\n        .addClass('active')\n        .find('[data-toggle=\"tab\"]')\n          .attr('aria-expanded', true)\n\n      if (transition) {\n        element[0].offsetWidth // reflow for transition\n        element.addClass('in')\n      } else {\n        element.removeClass('fade')\n      }\n\n      if (element.parent('.dropdown-menu').length) {\n        element\n          .closest('li.dropdown')\n            .addClass('active')\n          .end()\n          .find('[data-toggle=\"tab\"]')\n            .attr('aria-expanded', true)\n      }\n\n      callback && callback()\n    }\n\n    $active.length && transition ?\n      $active\n        .one('bsTransitionEnd', next)\n        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :\n      next()\n\n    $active.removeClass('in')\n  }\n\n\n  // TAB PLUGIN DEFINITION\n  // =====================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.tab')\n\n      if (!data) $this.data('bs.tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.tab\n\n  $.fn.tab             = Plugin\n  $.fn.tab.Constructor = Tab\n\n\n  // TAB NO CONFLICT\n  // ===============\n\n  $.fn.tab.noConflict = function () {\n    $.fn.tab = old\n    return this\n  }\n\n\n  // TAB DATA-API\n  // ============\n\n  var clickHandler = function (e) {\n    e.preventDefault()\n    Plugin.call($(this), 'show')\n  }\n\n  $(document)\n    .on('click.bs.tab.data-api', '[data-toggle=\"tab\"]', clickHandler)\n    .on('click.bs.tab.data-api', '[data-toggle=\"pill\"]', clickHandler)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: affix.js v3.3.5\n * http://getbootstrap.com/javascript/#affix\n * ========================================================================\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n\n    this.$target = $(this.options.target)\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element     = $(element)\n    this.affixed      = null\n    this.unpin        = null\n    this.pinnedOffset = null\n\n    this.checkPosition()\n  }\n\n  Affix.VERSION  = '3.3.5'\n\n  Affix.RESET    = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0,\n    target: window\n  }\n\n  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {\n    var scrollTop    = this.$target.scrollTop()\n    var position     = this.$element.offset()\n    var targetHeight = this.$target.height()\n\n    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false\n\n    if (this.affixed == 'bottom') {\n      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'\n      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'\n    }\n\n    var initializing   = this.affixed == null\n    var colliderTop    = initializing ? scrollTop : position.top\n    var colliderHeight = initializing ? targetHeight : height\n\n    if (offsetTop != null && scrollTop <= offsetTop) return 'top'\n    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'\n\n    return false\n  }\n\n  Affix.prototype.getPinnedOffset = function () {\n    if (this.pinnedOffset) return this.pinnedOffset\n    this.$element.removeClass(Affix.RESET).addClass('affix')\n    var scrollTop = this.$target.scrollTop()\n    var position  = this.$element.offset()\n    return (this.pinnedOffset = position.top - scrollTop)\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var height       = this.$element.height()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n    var scrollHeight = Math.max($(document).height(), $(document.body).height())\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)\n\n    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)\n\n    if (this.affixed != affix) {\n      if (this.unpin != null) this.$element.css('top', '')\n\n      var affixType = 'affix' + (affix ? '-' + affix : '')\n      var e         = $.Event(affixType + '.bs.affix')\n\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      this.affixed = affix\n      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null\n\n      this.$element\n        .removeClass(Affix.RESET)\n        .addClass(affixType)\n        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')\n    }\n\n    if (affix == 'bottom') {\n      this.$element.offset({\n        top: scrollHeight - height - offsetBottom\n      })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.affix\n\n  $.fn.affix             = Plugin\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop    != null) data.offset.top    = data.offsetTop\n\n      Plugin.call($spy, data)\n    })\n  })\n\n}(jQuery);\n\n/*!\n * Select2 4.0.0\n * https://select2.github.io\n *\n * Released under the MIT license\n * https://github.com/select2/select2/blob/master/LICENSE.md\n */\n(function (factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as an anonymous module.\n    define(['jquery'], factory);\n  } else if (typeof exports === 'object') {\n    // Node/CommonJS\n    factory(require('jquery'));\n  } else {\n    // Browser globals\n    factory(jQuery);\n  }\n}(function (jQuery) {\n  // This is needed so we can catch the AMD loader configuration and use it\n  // The inner file should be wrapped (by `banner.start.js`) in a function that\n  // returns the AMD loader references.\n  var S2 =\n(function () {\n  // Restore the Select2 AMD loader so it can be used\n  // Needed mostly in the language files, where the loader is not inserted\n  if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {\n    var S2 = jQuery.fn.select2.amd;\n  }\nvar S2;(function () { if (!S2 || !S2.requirejs) {\nif (!S2) { S2 = {}; } else { require = S2; }\n/**\n * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/almond for details\n */\n//Going sloppy to avoid 'use strict' string cost, but strict practices should\n//be followed.\n/*jslint sloppy: true */\n/*global setTimeout: false */\n\nvar requirejs, require, define;\n(function (undef) {\n    var main, req, makeMap, handlers,\n        defined = {},\n        waiting = {},\n        config = {},\n        defining = {},\n        hasOwn = Object.prototype.hasOwnProperty,\n        aps = [].slice,\n        jsSuffixRegExp = /\\.js$/;\n\n    function hasProp(obj, prop) {\n        return hasOwn.call(obj, prop);\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 nameParts, nameSegment, mapValue, foundMap, lastIndex,\n            foundI, foundStarMap, starI, i, j, part,\n            baseParts = baseName && baseName.split(\"/\"),\n            map = config.map,\n            starMap = (map && map['*']) || {};\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                //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                baseParts = baseParts.slice(0, baseParts.length - 1);\n                name = name.split('/');\n                lastIndex = name.length - 1;\n\n                // Node .js allowance:\n                if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {\n                    name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');\n                }\n\n                name = baseParts.concat(name);\n\n                //start trimDots\n                for (i = 0; i < name.length; i += 1) {\n                    part = name[i];\n                    if (part === \".\") {\n                        name.splice(i, 1);\n                        i -= 1;\n                    } else if (part === \"..\") {\n                        if (i === 1 && (name[2] === '..' || name[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                            name.splice(i - 1, 2);\n                            i -= 2;\n                        }\n                    }\n                }\n                //end trimDots\n\n                name = name.join(\"/\");\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\n        //Apply map config if available.\n        if ((baseParts || starMap) && map) {\n            nameParts = name.split('/');\n\n            for (i = nameParts.length; i > 0; i -= 1) {\n                nameSegment = nameParts.slice(0, i).join(\"/\");\n\n                if (baseParts) {\n                    //Find the longest baseName segment match in the config.\n                    //So, do joins on the biggest to smallest lengths of baseParts.\n                    for (j = baseParts.length; j > 0; j -= 1) {\n                        mapValue = map[baseParts.slice(0, j).join('/')];\n\n                        //baseName segment has  config, find if it has one for\n                        //this name.\n                        if (mapValue) {\n                            mapValue = mapValue[nameSegment];\n                            if (mapValue) {\n                                //Match, update name to the new value.\n                                foundMap = mapValue;\n                                foundI = i;\n                                break;\n                            }\n                        }\n                    }\n                }\n\n                if (foundMap) {\n                    break;\n                }\n\n                //Check for a star map match, but just hold on to it,\n                //if there is a shorter segment match later in a matching\n                //config, then favor over this star map.\n                if (!foundStarMap && starMap && starMap[nameSegment]) {\n                    foundStarMap = starMap[nameSegment];\n                    starI = i;\n                }\n            }\n\n            if (!foundMap && foundStarMap) {\n                foundMap = foundStarMap;\n                foundI = starI;\n            }\n\n            if (foundMap) {\n                nameParts.splice(0, foundI, foundMap);\n                name = nameParts.join('/');\n            }\n        }\n\n        return name;\n    }\n\n    function makeRequire(relName, forceSync) {\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            return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));\n        };\n    }\n\n    function makeNormalize(relName) {\n        return function (name) {\n            return normalize(name, relName);\n        };\n    }\n\n    function makeLoad(depName) {\n        return function (value) {\n            defined[depName] = value;\n        };\n    }\n\n    function callDep(name) {\n        if (hasProp(waiting, name)) {\n            var args = waiting[name];\n            delete waiting[name];\n            defining[name] = true;\n            main.apply(undef, args);\n        }\n\n        if (!hasProp(defined, name) && !hasProp(defining, name)) {\n            throw new Error('No ' + name);\n        }\n        return defined[name];\n    }\n\n    //Turns a plugin!resource to [plugin, resource]\n    //with the plugin being undefined if the name\n    //did not have a plugin prefix.\n    function splitPrefix(name) {\n        var prefix,\n            index = name ? name.indexOf('!') : -1;\n        if (index > -1) {\n            prefix = name.substring(0, index);\n            name = name.substring(index + 1, name.length);\n        }\n        return [prefix, name];\n    }\n\n    /**\n     * Makes a name map, normalizing the name, and using a plugin\n     * for normalization if necessary. Grabs a ref to plugin\n     * too, as an optimization.\n     */\n    makeMap = function (name, relName) {\n        var plugin,\n            parts = splitPrefix(name),\n            prefix = parts[0];\n\n        name = parts[1];\n\n        if (prefix) {\n            prefix = normalize(prefix, relName);\n            plugin = callDep(prefix);\n        }\n\n        //Normalize according\n        if (prefix) {\n            if (plugin && plugin.normalize) {\n                name = plugin.normalize(name, makeNormalize(relName));\n            } else {\n                name = normalize(name, relName);\n            }\n        } else {\n            name = normalize(name, relName);\n            parts = splitPrefix(name);\n            prefix = parts[0];\n            name = parts[1];\n            if (prefix) {\n                plugin = callDep(prefix);\n            }\n        }\n\n        //Using ridiculous property names for space reasons\n        return {\n            f: prefix ? prefix + '!' + name : name, //fullName\n            n: name,\n            pr: prefix,\n            p: plugin\n        };\n    };\n\n    function makeConfig(name) {\n        return function () {\n            return (config && config.config && config.config[name]) || {};\n        };\n    }\n\n    handlers = {\n        require: function (name) {\n            return makeRequire(name);\n        },\n        exports: function (name) {\n            var e = defined[name];\n            if (typeof e !== 'undefined') {\n                return e;\n            } else {\n                return (defined[name] = {});\n            }\n        },\n        module: function (name) {\n            return {\n                id: name,\n                uri: '',\n                exports: defined[name],\n                config: makeConfig(name)\n            };\n        }\n    };\n\n    main = function (name, deps, callback, relName) {\n        var cjsModule, depName, ret, map, i,\n            args = [],\n            callbackType = typeof callback,\n            usingExports;\n\n        //Use name if no relName\n        relName = relName || name;\n\n        //Call the callback to define the module, if necessary.\n        if (callbackType === 'undefined' || callbackType === 'function') {\n            //Pull out the defined dependencies and pass the ordered\n            //values to the callback.\n            //Default to [require, exports, module] if no deps\n            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;\n            for (i = 0; i < deps.length; i += 1) {\n                map = makeMap(deps[i], relName);\n                depName = map.f;\n\n                //Fast path CommonJS standard dependencies.\n                if (depName === \"require\") {\n                    args[i] = handlers.require(name);\n                } else if (depName === \"exports\") {\n                    //CommonJS module spec 1.1\n                    args[i] = handlers.exports(name);\n                    usingExports = true;\n                } else if (depName === \"module\") {\n                    //CommonJS module spec 1.1\n                    cjsModule = args[i] = handlers.module(name);\n                } else if (hasProp(defined, depName) ||\n                           hasProp(waiting, depName) ||\n                           hasProp(defining, depName)) {\n                    args[i] = callDep(depName);\n                } else if (map.p) {\n                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});\n                    args[i] = defined[depName];\n                } else {\n                    throw new Error(name + ' missing ' + depName);\n                }\n            }\n\n            ret = callback ? callback.apply(defined[name], args) : undefined;\n\n            if (name) {\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                if (cjsModule && cjsModule.exports !== undef &&\n                        cjsModule.exports !== defined[name]) {\n                    defined[name] = cjsModule.exports;\n                } else if (ret !== undef || !usingExports) {\n                    //Use the return value from the function.\n                    defined[name] = ret;\n                }\n            }\n        } else if (name) {\n            //May just be an object definition for the module. Only\n            //worry about defining if have a module name.\n            defined[name] = callback;\n        }\n    };\n\n    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {\n        if (typeof deps === \"string\") {\n            if (handlers[deps]) {\n                //callback in this case is really relName\n                return handlers[deps](callback);\n            }\n            //Just return the module wanted. In this scenario, the\n            //deps arg is the module name, and second arg (if passed)\n            //is just the relName.\n            //Normalize module name, if it contains . or ..\n            return callDep(makeMap(deps, callback).f);\n        } else if (!deps.splice) {\n            //deps is a config object, not an array.\n            config = deps;\n            if (config.deps) {\n                req(config.deps, config.callback);\n            }\n            if (!callback) {\n                return;\n            }\n\n            if (callback.splice) {\n                //callback is an array, which means it is a dependency list.\n                //Adjust args if there are dependencies\n                deps = callback;\n                callback = relName;\n                relName = null;\n            } else {\n                deps = undef;\n            }\n        }\n\n        //Support require(['a'])\n        callback = callback || function () {};\n\n        //If relName is a function, it is an errback handler,\n        //so remove it.\n        if (typeof relName === 'function') {\n            relName = forceSync;\n            forceSync = alt;\n        }\n\n        //Simulate async callback;\n        if (forceSync) {\n            main(undef, deps, callback, relName);\n        } else {\n            //Using a non-zero value because of concern for what old browsers\n            //do, and latest browsers \"upgrade\" to 4 if lower value is used:\n            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:\n            //If want a value immediately, use require('id') instead -- something\n            //that works in almond on the global level, but not guaranteed and\n            //unlikely to work in other AMD implementations.\n            setTimeout(function () {\n                main(undef, deps, callback, relName);\n            }, 4);\n        }\n\n        return req;\n    };\n\n    /**\n     * Just drops the config on the floor, but returns req in case\n     * the config return value is used.\n     */\n    req.config = function (cfg) {\n        return req(cfg);\n    };\n\n    /**\n     * Expose module registry for debugging and tooling\n     */\n    requirejs._defined = defined;\n\n    define = function (name, deps, callback) {\n\n        //This module may not have dependencies\n        if (!deps.splice) {\n            //deps is not an array, so probably means\n            //an object literal or factory function for\n            //the value. Adjust args.\n            callback = deps;\n            deps = [];\n        }\n\n        if (!hasProp(defined, name) && !hasProp(waiting, name)) {\n            waiting[name] = [name, deps, callback];\n        }\n    };\n\n    define.amd = {\n        jQuery: true\n    };\n}());\n\nS2.requirejs = requirejs;S2.require = require;S2.define = define;\n}\n}());\nS2.define(\"almond\", function(){});\n\n/* global jQuery:false, $:false */\nS2.define('jquery',[],function () {\n  var _$ = jQuery || $;\n\n  if (_$ == null && console && console.error) {\n    console.error(\n      'Select2: An instance of jQuery or a jQuery-compatible library was not ' +\n      'found. Make sure that you are including jQuery before Select2 on your ' +\n      'web page.'\n    );\n  }\n\n  return _$;\n});\n\nS2.define('select2/utils',[\n  'jquery'\n], function ($) {\n  var Utils = {};\n\n  Utils.Extend = function (ChildClass, SuperClass) {\n    var __hasProp = {}.hasOwnProperty;\n\n    function BaseConstructor () {\n      this.constructor = ChildClass;\n    }\n\n    for (var key in SuperClass) {\n      if (__hasProp.call(SuperClass, key)) {\n        ChildClass[key] = SuperClass[key];\n      }\n    }\n\n    BaseConstructor.prototype = SuperClass.prototype;\n    ChildClass.prototype = new BaseConstructor();\n    ChildClass.__super__ = SuperClass.prototype;\n\n    return ChildClass;\n  };\n\n  function getMethods (theClass) {\n    var proto = theClass.prototype;\n\n    var methods = [];\n\n    for (var methodName in proto) {\n      var m = proto[methodName];\n\n      if (typeof m !== 'function') {\n        continue;\n      }\n\n      if (methodName === 'constructor') {\n        continue;\n      }\n\n      methods.push(methodName);\n    }\n\n    return methods;\n  }\n\n  Utils.Decorate = function (SuperClass, DecoratorClass) {\n    var decoratedMethods = getMethods(DecoratorClass);\n    var superMethods = getMethods(SuperClass);\n\n    function DecoratedClass () {\n      var unshift = Array.prototype.unshift;\n\n      var argCount = DecoratorClass.prototype.constructor.length;\n\n      var calledConstructor = SuperClass.prototype.constructor;\n\n      if (argCount > 0) {\n        unshift.call(arguments, SuperClass.prototype.constructor);\n\n        calledConstructor = DecoratorClass.prototype.constructor;\n      }\n\n      calledConstructor.apply(this, arguments);\n    }\n\n    DecoratorClass.displayName = SuperClass.displayName;\n\n    function ctr () {\n      this.constructor = DecoratedClass;\n    }\n\n    DecoratedClass.prototype = new ctr();\n\n    for (var m = 0; m < superMethods.length; m++) {\n        var superMethod = superMethods[m];\n\n        DecoratedClass.prototype[superMethod] =\n          SuperClass.prototype[superMethod];\n    }\n\n    var calledMethod = function (methodName) {\n      // Stub out the original method if it's not decorating an actual method\n      var originalMethod = function () {};\n\n      if (methodName in DecoratedClass.prototype) {\n        originalMethod = DecoratedClass.prototype[methodName];\n      }\n\n      var decoratedMethod = DecoratorClass.prototype[methodName];\n\n      return function () {\n        var unshift = Array.prototype.unshift;\n\n        unshift.call(arguments, originalMethod);\n\n        return decoratedMethod.apply(this, arguments);\n      };\n    };\n\n    for (var d = 0; d < decoratedMethods.length; d++) {\n      var decoratedMethod = decoratedMethods[d];\n\n      DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);\n    }\n\n    return DecoratedClass;\n  };\n\n  var Observable = function () {\n    this.listeners = {};\n  };\n\n  Observable.prototype.on = function (event, callback) {\n    this.listeners = this.listeners || {};\n\n    if (event in this.listeners) {\n      this.listeners[event].push(callback);\n    } else {\n      this.listeners[event] = [callback];\n    }\n  };\n\n  Observable.prototype.trigger = function (event) {\n    var slice = Array.prototype.slice;\n\n    this.listeners = this.listeners || {};\n\n    if (event in this.listeners) {\n      this.invoke(this.listeners[event], slice.call(arguments, 1));\n    }\n\n    if ('*' in this.listeners) {\n      this.invoke(this.listeners['*'], arguments);\n    }\n  };\n\n  Observable.prototype.invoke = function (listeners, params) {\n    for (var i = 0, len = listeners.length; i < len; i++) {\n      listeners[i].apply(this, params);\n    }\n  };\n\n  Utils.Observable = Observable;\n\n  Utils.generateChars = function (length) {\n    var chars = '';\n\n    for (var i = 0; i < length; i++) {\n      var randomChar = Math.floor(Math.random() * 36);\n      chars += randomChar.toString(36);\n    }\n\n    return chars;\n  };\n\n  Utils.bind = function (func, context) {\n    return function () {\n      func.apply(context, arguments);\n    };\n  };\n\n  Utils._convertData = function (data) {\n    for (var originalKey in data) {\n      var keys = originalKey.split('-');\n\n      var dataLevel = data;\n\n      if (keys.length === 1) {\n        continue;\n      }\n\n      for (var k = 0; k < keys.length; k++) {\n        var key = keys[k];\n\n        // Lowercase the first letter\n        // By default, dash-separated becomes camelCase\n        key = key.substring(0, 1).toLowerCase() + key.substring(1);\n\n        if (!(key in dataLevel)) {\n          dataLevel[key] = {};\n        }\n\n        if (k == keys.length - 1) {\n          dataLevel[key] = data[originalKey];\n        }\n\n        dataLevel = dataLevel[key];\n      }\n\n      delete data[originalKey];\n    }\n\n    return data;\n  };\n\n  Utils.hasScroll = function (index, el) {\n    // Adapted from the function created by @ShadowScripter\n    // and adapted by @BillBarry on the Stack Exchange Code Review website.\n    // The original code can be found at\n    // http://codereview.stackexchange.com/q/13338\n    // and was designed to be used with the Sizzle selector engine.\n\n    var $el = $(el);\n    var overflowX = el.style.overflowX;\n    var overflowY = el.style.overflowY;\n\n    //Check both x and y declarations\n    if (overflowX === overflowY &&\n        (overflowY === 'hidden' || overflowY === 'visible')) {\n      return false;\n    }\n\n    if (overflowX === 'scroll' || overflowY === 'scroll') {\n      return true;\n    }\n\n    return ($el.innerHeight() < el.scrollHeight ||\n      $el.innerWidth() < el.scrollWidth);\n  };\n\n  Utils.escapeMarkup = function (markup) {\n    var replaceMap = {\n      '\\\\': '&#92;',\n      '&': '&amp;',\n      '<': '&lt;',\n      '>': '&gt;',\n      '\"': '&quot;',\n      '\\'': '&#39;',\n      '/': '&#47;'\n    };\n\n    // Do not try to escape the markup if it's not a string\n    if (typeof markup !== 'string') {\n      return markup;\n    }\n\n    return String(markup).replace(/[&<>\"'\\/\\\\]/g, function (match) {\n      return replaceMap[match];\n    });\n  };\n\n  // Append an array of jQuery nodes to a given element.\n  Utils.appendMany = function ($element, $nodes) {\n    // jQuery 1.7.x does not support $.fn.append() with an array\n    // Fall back to a jQuery object collection using $.fn.add()\n    if ($.fn.jquery.substr(0, 3) === '1.7') {\n      var $jqNodes = $();\n\n      $.map($nodes, function (node) {\n        $jqNodes = $jqNodes.add(node);\n      });\n\n      $nodes = $jqNodes;\n    }\n\n    $element.append($nodes);\n  };\n\n  return Utils;\n});\n\nS2.define('select2/results',[\n  'jquery',\n  './utils'\n], function ($, Utils) {\n  function Results ($element, options, dataAdapter) {\n    this.$element = $element;\n    this.data = dataAdapter;\n    this.options = options;\n\n    Results.__super__.constructor.call(this);\n  }\n\n  Utils.Extend(Results, Utils.Observable);\n\n  Results.prototype.render = function () {\n    var $results = $(\n      '<ul class=\"select2-results__options\" role=\"tree\"></ul>'\n    );\n\n    if (this.options.get('multiple')) {\n      $results.attr('aria-multiselectable', 'true');\n    }\n\n    this.$results = $results;\n\n    return $results;\n  };\n\n  Results.prototype.clear = function () {\n    this.$results.empty();\n  };\n\n  Results.prototype.displayMessage = function (params) {\n    var escapeMarkup = this.options.get('escapeMarkup');\n\n    this.clear();\n    this.hideLoading();\n\n    var $message = $(\n      '<li role=\"treeitem\" class=\"select2-results__option\"></li>'\n    );\n\n    var message = this.options.get('translations').get(params.message);\n\n    $message.append(\n      escapeMarkup(\n        message(params.args)\n      )\n    );\n\n    this.$results.append($message);\n  };\n\n  Results.prototype.append = function (data) {\n    this.hideLoading();\n\n    var $options = [];\n\n    if (data.results == null || data.results.length === 0) {\n      if (this.$results.children().length === 0) {\n        this.trigger('results:message', {\n          message: 'noResults'\n        });\n      }\n\n      return;\n    }\n\n    data.results = this.sort(data.results);\n\n    for (var d = 0; d < data.results.length; d++) {\n      var item = data.results[d];\n\n      var $option = this.option(item);\n\n      $options.push($option);\n    }\n\n    this.$results.append($options);\n  };\n\n  Results.prototype.position = function ($results, $dropdown) {\n    var $resultsContainer = $dropdown.find('.select2-results');\n    $resultsContainer.append($results);\n  };\n\n  Results.prototype.sort = function (data) {\n    var sorter = this.options.get('sorter');\n\n    return sorter(data);\n  };\n\n  Results.prototype.setClasses = function () {\n    var self = this;\n\n    this.data.current(function (selected) {\n      var selectedIds = $.map(selected, function (s) {\n        return s.id.toString();\n      });\n\n      var $options = self.$results\n        .find('.select2-results__option[aria-selected]');\n\n      $options.each(function () {\n        var $option = $(this);\n\n        var item = $.data(this, 'data');\n\n        // id needs to be converted to a string when comparing\n        var id = '' + item.id;\n\n        if ((item.element != null && item.element.selected) ||\n            (item.element == null && $.inArray(id, selectedIds) > -1)) {\n          $option.attr('aria-selected', 'true');\n        } else {\n          $option.attr('aria-selected', 'false');\n        }\n      });\n\n      var $selected = $options.filter('[aria-selected=true]');\n\n      // Check if there are any selected options\n      if ($selected.length > 0) {\n        // If there are selected options, highlight the first\n        $selected.first().trigger('mouseenter');\n      } else {\n        // If there are no selected options, highlight the first option\n        // in the dropdown\n        $options.first().trigger('mouseenter');\n      }\n    });\n  };\n\n  Results.prototype.showLoading = function (params) {\n    this.hideLoading();\n\n    var loadingMore = this.options.get('translations').get('searching');\n\n    var loading = {\n      disabled: true,\n      loading: true,\n      text: loadingMore(params)\n    };\n    var $loading = this.option(loading);\n    $loading.className += ' loading-results';\n\n    this.$results.prepend($loading);\n  };\n\n  Results.prototype.hideLoading = function () {\n    this.$results.find('.loading-results').remove();\n  };\n\n  Results.prototype.option = function (data) {\n    var option = document.createElement('li');\n    option.className = 'select2-results__option';\n\n    var attrs = {\n      'role': 'treeitem',\n      'aria-selected': 'false'\n    };\n\n    if (data.disabled) {\n      delete attrs['aria-selected'];\n      attrs['aria-disabled'] = 'true';\n    }\n\n    if (data.id == null) {\n      delete attrs['aria-selected'];\n    }\n\n    if (data._resultId != null) {\n      option.id = data._resultId;\n    }\n\n    if (data.title) {\n      option.title = data.title;\n    }\n\n    if (data.children) {\n      attrs.role = 'group';\n      attrs['aria-label'] = data.text;\n      delete attrs['aria-selected'];\n    }\n\n    for (var attr in attrs) {\n      var val = attrs[attr];\n\n      option.setAttribute(attr, val);\n    }\n\n    if (data.children) {\n      var $option = $(option);\n\n      var label = document.createElement('strong');\n      label.className = 'select2-results__group';\n\n      var $label = $(label);\n      this.template(data, label);\n\n      var $children = [];\n\n      for (var c = 0; c < data.children.length; c++) {\n        var child = data.children[c];\n\n        var $child = this.option(child);\n\n        $children.push($child);\n      }\n\n      var $childrenContainer = $('<ul></ul>', {\n        'class': 'select2-results__options select2-results__options--nested'\n      });\n\n      $childrenContainer.append($children);\n\n      $option.append(label);\n      $option.append($childrenContainer);\n    } else {\n      this.template(data, option);\n    }\n\n    $.data(option, 'data', data);\n\n    return option;\n  };\n\n  Results.prototype.bind = function (container, $container) {\n    var self = this;\n\n    var id = container.id + '-results';\n\n    this.$results.attr('id', id);\n\n    container.on('results:all', function (params) {\n      self.clear();\n      self.append(params.data);\n\n      if (container.isOpen()) {\n        self.setClasses();\n      }\n    });\n\n    container.on('results:append', function (params) {\n      self.append(params.data);\n\n      if (container.isOpen()) {\n        self.setClasses();\n      }\n    });\n\n    container.on('query', function (params) {\n      self.showLoading(params);\n    });\n\n    container.on('select', function () {\n      if (!container.isOpen()) {\n        return;\n      }\n\n      self.setClasses();\n    });\n\n    container.on('unselect', function () {\n      if (!container.isOpen()) {\n        return;\n      }\n\n      self.setClasses();\n    });\n\n    container.on('open', function () {\n      // When the dropdown is open, aria-expended=\"true\"\n      self.$results.attr('aria-expanded', 'true');\n      self.$results.attr('aria-hidden', 'false');\n\n      self.setClasses();\n      self.ensureHighlightVisible();\n    });\n\n    container.on('close', function () {\n      // When the dropdown is closed, aria-expended=\"false\"\n      self.$results.attr('aria-expanded', 'false');\n      self.$results.attr('aria-hidden', 'true');\n      self.$results.removeAttr('aria-activedescendant');\n    });\n\n    container.on('results:toggle', function () {\n      var $highlighted = self.getHighlightedResults();\n\n      if ($highlighted.length === 0) {\n        return;\n      }\n\n      $highlighted.trigger('mouseup');\n    });\n\n    container.on('results:select', function () {\n      var $highlighted = self.getHighlightedResults();\n\n      if ($highlighted.length === 0) {\n        return;\n      }\n\n      var data = $highlighted.data('data');\n\n      if ($highlighted.attr('aria-selected') == 'true') {\n        self.trigger('close');\n      } else {\n        self.trigger('select', {\n          data: data\n        });\n      }\n    });\n\n    container.on('results:previous', function () {\n      var $highlighted = self.getHighlightedResults();\n\n      var $options = self.$results.find('[aria-selected]');\n\n      var currentIndex = $options.index($highlighted);\n\n      // If we are already at te top, don't move further\n      if (currentIndex === 0) {\n        return;\n      }\n\n      var nextIndex = currentIndex - 1;\n\n      // If none are highlighted, highlight the first\n      if ($highlighted.length === 0) {\n        nextIndex = 0;\n      }\n\n      var $next = $options.eq(nextIndex);\n\n      $next.trigger('mouseenter');\n\n      var currentOffset = self.$results.offset().top;\n      var nextTop = $next.offset().top;\n      var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);\n\n      if (nextIndex === 0) {\n        self.$results.scrollTop(0);\n      } else if (nextTop - currentOffset < 0) {\n        self.$results.scrollTop(nextOffset);\n      }\n    });\n\n    container.on('results:next', function () {\n      var $highlighted = self.getHighlightedResults();\n\n      var $options = self.$results.find('[aria-selected]');\n\n      var currentIndex = $options.index($highlighted);\n\n      var nextIndex = currentIndex + 1;\n\n      // If we are at the last option, stay there\n      if (nextIndex >= $options.length) {\n        return;\n      }\n\n      var $next = $options.eq(nextIndex);\n\n      $next.trigger('mouseenter');\n\n      var currentOffset = self.$results.offset().top +\n        self.$results.outerHeight(false);\n      var nextBottom = $next.offset().top + $next.outerHeight(false);\n      var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;\n\n      if (nextIndex === 0) {\n        self.$results.scrollTop(0);\n      } else if (nextBottom > currentOffset) {\n        self.$results.scrollTop(nextOffset);\n      }\n    });\n\n    container.on('results:focus', function (params) {\n      params.element.addClass('select2-results__option--highlighted');\n    });\n\n    container.on('results:message', function (params) {\n      self.displayMessage(params);\n    });\n\n    if ($.fn.mousewheel) {\n      this.$results.on('mousewheel', function (e) {\n        var top = self.$results.scrollTop();\n\n        var bottom = (\n          self.$results.get(0).scrollHeight -\n          self.$results.scrollTop() +\n          e.deltaY\n        );\n\n        var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;\n        var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();\n\n        if (isAtTop) {\n          self.$results.scrollTop(0);\n\n          e.preventDefault();\n          e.stopPropagation();\n        } else if (isAtBottom) {\n          self.$results.scrollTop(\n            self.$results.get(0).scrollHeight - self.$results.height()\n          );\n\n          e.preventDefault();\n          e.stopPropagation();\n        }\n      });\n    }\n\n    this.$results.on('mouseup', '.select2-results__option[aria-selected]',\n      function (evt) {\n      var $this = $(this);\n\n      var data = $this.data('data');\n\n      if ($this.attr('aria-selected') === 'true') {\n        if (self.options.get('multiple')) {\n          self.trigger('unselect', {\n            originalEvent: evt,\n            data: data\n          });\n        } else {\n          self.trigger('close');\n        }\n\n        return;\n      }\n\n      self.trigger('select', {\n        originalEvent: evt,\n        data: data\n      });\n    });\n\n    this.$results.on('mouseenter', '.select2-results__option[aria-selected]',\n      function (evt) {\n      var data = $(this).data('data');\n\n      self.getHighlightedResults()\n          .removeClass('select2-results__option--highlighted');\n\n      self.trigger('results:focus', {\n        data: data,\n        element: $(this)\n      });\n    });\n  };\n\n  Results.prototype.getHighlightedResults = function () {\n    var $highlighted = this.$results\n    .find('.select2-results__option--highlighted');\n\n    return $highlighted;\n  };\n\n  Results.prototype.destroy = function () {\n    this.$results.remove();\n  };\n\n  Results.prototype.ensureHighlightVisible = function () {\n    var $highlighted = this.getHighlightedResults();\n\n    if ($highlighted.length === 0) {\n      return;\n    }\n\n    var $options = this.$results.find('[aria-selected]');\n\n    var currentIndex = $options.index($highlighted);\n\n    var currentOffset = this.$results.offset().top;\n    var nextTop = $highlighted.offset().top;\n    var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);\n\n    var offsetDelta = nextTop - currentOffset;\n    nextOffset -= $highlighted.outerHeight(false) * 2;\n\n    if (currentIndex <= 2) {\n      this.$results.scrollTop(0);\n    } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {\n      this.$results.scrollTop(nextOffset);\n    }\n  };\n\n  Results.prototype.template = function (result, container) {\n    var template = this.options.get('templateResult');\n    var escapeMarkup = this.options.get('escapeMarkup');\n\n    var content = template(result);\n\n    if (content == null) {\n      container.style.display = 'none';\n    } else if (typeof content === 'string') {\n      container.innerHTML = escapeMarkup(content);\n    } else {\n      $(container).append(content);\n    }\n  };\n\n  return Results;\n});\n\nS2.define('select2/keys',[\n\n], function () {\n  var KEYS = {\n    BACKSPACE: 8,\n    TAB: 9,\n    ENTER: 13,\n    SHIFT: 16,\n    CTRL: 17,\n    ALT: 18,\n    ESC: 27,\n    SPACE: 32,\n    PAGE_UP: 33,\n    PAGE_DOWN: 34,\n    END: 35,\n    HOME: 36,\n    LEFT: 37,\n    UP: 38,\n    RIGHT: 39,\n    DOWN: 40,\n    DELETE: 46\n  };\n\n  return KEYS;\n});\n\nS2.define('select2/selection/base',[\n  'jquery',\n  '../utils',\n  '../keys'\n], function ($, Utils, KEYS) {\n  function BaseSelection ($element, options) {\n    this.$element = $element;\n    this.options = options;\n\n    BaseSelection.__super__.constructor.call(this);\n  }\n\n  Utils.Extend(BaseSelection, Utils.Observable);\n\n  BaseSelection.prototype.render = function () {\n    var $selection = $(\n      '<span class=\"select2-selection\" role=\"combobox\" ' +\n      'aria-autocomplete=\"list\" aria-haspopup=\"true\" aria-expanded=\"false\">' +\n      '</span>'\n    );\n\n    this._tabindex = 0;\n\n    if (this.$element.data('old-tabindex') != null) {\n      this._tabindex = this.$element.data('old-tabindex');\n    } else if (this.$element.attr('tabindex') != null) {\n      this._tabindex = this.$element.attr('tabindex');\n    }\n\n    $selection.attr('title', this.$element.attr('title'));\n    $selection.attr('tabindex', this._tabindex);\n\n    this.$selection = $selection;\n\n    return $selection;\n  };\n\n  BaseSelection.prototype.bind = function (container, $container) {\n    var self = this;\n\n    var id = container.id + '-container';\n    var resultsId = container.id + '-results';\n\n    this.container = container;\n\n    this.$selection.on('focus', function (evt) {\n      self.trigger('focus', evt);\n    });\n\n    this.$selection.on('blur', function (evt) {\n      self.trigger('blur', evt);\n    });\n\n    this.$selection.on('keydown', function (evt) {\n      self.trigger('keypress', evt);\n\n      if (evt.which === KEYS.SPACE) {\n        evt.preventDefault();\n      }\n    });\n\n    container.on('results:focus', function (params) {\n      self.$selection.attr('aria-activedescendant', params.data._resultId);\n    });\n\n    container.on('selection:update', function (params) {\n      self.update(params.data);\n    });\n\n    container.on('open', function () {\n      // When the dropdown is open, aria-expanded=\"true\"\n      self.$selection.attr('aria-expanded', 'true');\n      self.$selection.attr('aria-owns', resultsId);\n\n      self._attachCloseHandler(container);\n    });\n\n    container.on('close', function () {\n      // When the dropdown is closed, aria-expanded=\"false\"\n      self.$selection.attr('aria-expanded', 'false');\n      self.$selection.removeAttr('aria-activedescendant');\n      self.$selection.removeAttr('aria-owns');\n\n      self.$selection.focus();\n\n      self._detachCloseHandler(container);\n    });\n\n    container.on('enable', function () {\n      self.$selection.attr('tabindex', self._tabindex);\n    });\n\n    container.on('disable', function () {\n      self.$selection.attr('tabindex', '-1');\n    });\n  };\n\n  BaseSelection.prototype._attachCloseHandler = function (container) {\n    var self = this;\n\n    $(document.body).on('mousedown.select2.' + container.id, function (e) {\n      var $target = $(e.target);\n\n      var $select = $target.closest('.select2');\n\n      var $all = $('.select2.select2-container--open');\n\n      $all.each(function () {\n        var $this = $(this);\n\n        if (this == $select[0]) {\n          return;\n        }\n\n        var $element = $this.data('element');\n\n        $element.select2('close');\n      });\n    });\n  };\n\n  BaseSelection.prototype._detachCloseHandler = function (container) {\n    $(document.body).off('mousedown.select2.' + container.id);\n  };\n\n  BaseSelection.prototype.position = function ($selection, $container) {\n    var $selectionContainer = $container.find('.selection');\n    $selectionContainer.append($selection);\n  };\n\n  BaseSelection.prototype.destroy = function () {\n    this._detachCloseHandler(this.container);\n  };\n\n  BaseSelection.prototype.update = function (data) {\n    throw new Error('The `update` method must be defined in child classes.');\n  };\n\n  return BaseSelection;\n});\n\nS2.define('select2/selection/single',[\n  'jquery',\n  './base',\n  '../utils',\n  '../keys'\n], function ($, BaseSelection, Utils, KEYS) {\n  function SingleSelection () {\n    SingleSelection.__super__.constructor.apply(this, arguments);\n  }\n\n  Utils.Extend(SingleSelection, BaseSelection);\n\n  SingleSelection.prototype.render = function () {\n    var $selection = SingleSelection.__super__.render.call(this);\n\n    $selection.addClass('select2-selection--single');\n\n    $selection.html(\n      '<span class=\"select2-selection__rendered\"></span>' +\n      '<span class=\"select2-selection__arrow\" role=\"presentation\">' +\n        '<b role=\"presentation\"></b>' +\n      '</span>'\n    );\n\n    return $selection;\n  };\n\n  SingleSelection.prototype.bind = function (container, $container) {\n    var self = this;\n\n    SingleSelection.__super__.bind.apply(this, arguments);\n\n    var id = container.id + '-container';\n\n    this.$selection.find('.select2-selection__rendered').attr('id', id);\n    this.$selection.attr('aria-labelledby', id);\n\n    this.$selection.on('mousedown', function (evt) {\n      // Only respond to left clicks\n      if (evt.which !== 1) {\n        return;\n      }\n\n      self.trigger('toggle', {\n        originalEvent: evt\n      });\n    });\n\n    this.$selection.on('focus', function (evt) {\n      // User focuses on the container\n    });\n\n    this.$selection.on('blur', function (evt) {\n      // User exits the container\n    });\n\n    container.on('selection:update', function (params) {\n      self.update(params.data);\n    });\n  };\n\n  SingleSelection.prototype.clear = function () {\n    this.$selection.find('.select2-selection__rendered').empty();\n  };\n\n  SingleSelection.prototype.display = function (data) {\n    var template = this.options.get('templateSelection');\n    var escapeMarkup = this.options.get('escapeMarkup');\n\n    return escapeMarkup(template(data));\n  };\n\n  SingleSelection.prototype.selectionContainer = function () {\n    return $('<span></span>');\n  };\n\n  SingleSelection.prototype.update = function (data) {\n    if (data.length === 0) {\n      this.clear();\n      return;\n    }\n\n    var selection = data[0];\n\n    var formatted = this.display(selection);\n\n    var $rendered = this.$selection.find('.select2-selection__rendered');\n    $rendered.empty().append(formatted);\n    $rendered.prop('title', selection.title || selection.text);\n  };\n\n  return SingleSelection;\n});\n\nS2.define('select2/selection/multiple',[\n  'jquery',\n  './base',\n  '../utils'\n], function ($, BaseSelection, Utils) {\n  function MultipleSelection ($element, options) {\n    MultipleSelection.__super__.constructor.apply(this, arguments);\n  }\n\n  Utils.Extend(MultipleSelection, BaseSelection);\n\n  MultipleSelection.prototype.render = function () {\n    var $selection = MultipleSelection.__super__.render.call(this);\n\n    $selection.addClass('select2-selection--multiple');\n\n    $selection.html(\n      '<ul class=\"select2-selection__rendered\"></ul>'\n    );\n\n    return $selection;\n  };\n\n  MultipleSelection.prototype.bind = function (container, $container) {\n    var self = this;\n\n    MultipleSelection.__super__.bind.apply(this, arguments);\n\n    this.$selection.on('click', function (evt) {\n      self.trigger('toggle', {\n        originalEvent: evt\n      });\n    });\n\n    this.$selection.on('click', '.select2-selection__choice__remove',\n      function (evt) {\n      var $remove = $(this);\n      var $selection = $remove.parent();\n\n      var data = $selection.data('data');\n\n      self.trigger('unselect', {\n        originalEvent: evt,\n        data: data\n      });\n    });\n  };\n\n  MultipleSelection.prototype.clear = function () {\n    this.$selection.find('.select2-selection__rendered').empty();\n  };\n\n  MultipleSelection.prototype.display = function (data) {\n    var template = this.options.get('templateSelection');\n    var escapeMarkup = this.options.get('escapeMarkup');\n\n    return escapeMarkup(template(data));\n  };\n\n  MultipleSelection.prototype.selectionContainer = function () {\n    var $container = $(\n      '<li class=\"select2-selection__choice\">' +\n        '<span class=\"select2-selection__choice__remove\" role=\"presentation\">' +\n          '&times;' +\n        '</span>' +\n      '</li>'\n    );\n\n    return $container;\n  };\n\n  MultipleSelection.prototype.update = function (data) {\n    this.clear();\n\n    if (data.length === 0) {\n      return;\n    }\n\n    var $selections = [];\n\n    for (var d = 0; d < data.length; d++) {\n      var selection = data[d];\n\n      var formatted = this.display(selection);\n      var $selection = this.selectionContainer();\n\n      $selection.append(formatted);\n      $selection.prop('title', selection.title || selection.text);\n\n      $selection.data('data', selection);\n\n      $selections.push($selection);\n    }\n\n    var $rendered = this.$selection.find('.select2-selection__rendered');\n\n    Utils.appendMany($rendered, $selections);\n  };\n\n  return MultipleSelection;\n});\n\nS2.define('select2/selection/placeholder',[\n  '../utils'\n], function (Utils) {\n  function Placeholder (decorated, $element, options) {\n    this.placeholder = this.normalizePlaceholder(options.get('placeholder'));\n\n    decorated.call(this, $element, options);\n  }\n\n  Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {\n    if (typeof placeholder === 'string') {\n      placeholder = {\n        id: '',\n        text: placeholder\n      };\n    }\n\n    return placeholder;\n  };\n\n  Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {\n    var $placeholder = this.selectionContainer();\n\n    $placeholder.html(this.display(placeholder));\n    $placeholder.addClass('select2-selection__placeholder')\n                .removeClass('select2-selection__choice');\n\n    return $placeholder;\n  };\n\n  Placeholder.prototype.update = function (decorated, data) {\n    var singlePlaceholder = (\n      data.length == 1 && data[0].id != this.placeholder.id\n    );\n    var multipleSelections = data.length > 1;\n\n    if (multipleSelections || singlePlaceholder) {\n      return decorated.call(this, data);\n    }\n\n    this.clear();\n\n    var $placeholder = this.createPlaceholder(this.placeholder);\n\n    this.$selection.find('.select2-selection__rendered').append($placeholder);\n  };\n\n  return Placeholder;\n});\n\nS2.define('select2/selection/allowClear',[\n  'jquery',\n  '../keys'\n], function ($, KEYS) {\n  function AllowClear () { }\n\n  AllowClear.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n\n    decorated.call(this, container, $container);\n\n    if (this.placeholder == null) {\n      if (this.options.get('debug') && window.console && console.error) {\n        console.error(\n          'Select2: The `allowClear` option should be used in combination ' +\n          'with the `placeholder` option.'\n        );\n      }\n    }\n\n    this.$selection.on('mousedown', '.select2-selection__clear',\n      function (evt) {\n        self._handleClear(evt);\n    });\n\n    container.on('keypress', function (evt) {\n      self._handleKeyboardClear(evt, container);\n    });\n  };\n\n  AllowClear.prototype._handleClear = function (_, evt) {\n    // Ignore the event if it is disabled\n    if (this.options.get('disabled')) {\n      return;\n    }\n\n    var $clear = this.$selection.find('.select2-selection__clear');\n\n    // Ignore the event if nothing has been selected\n    if ($clear.length === 0) {\n      return;\n    }\n\n    evt.stopPropagation();\n\n    var data = $clear.data('data');\n\n    for (var d = 0; d < data.length; d++) {\n      var unselectData = {\n        data: data[d]\n      };\n\n      // Trigger the `unselect` event, so people can prevent it from being\n      // cleared.\n      this.trigger('unselect', unselectData);\n\n      // If the event was prevented, don't clear it out.\n      if (unselectData.prevented) {\n        return;\n      }\n    }\n\n    this.$element.val(this.placeholder.id).trigger('change');\n\n    this.trigger('toggle');\n  };\n\n  AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {\n    if (container.isOpen()) {\n      return;\n    }\n\n    if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {\n      this._handleClear(evt);\n    }\n  };\n\n  AllowClear.prototype.update = function (decorated, data) {\n    decorated.call(this, data);\n\n    if (this.$selection.find('.select2-selection__placeholder').length > 0 ||\n        data.length === 0) {\n      return;\n    }\n\n    var $remove = $(\n      '<span class=\"select2-selection__clear\">' +\n        '&times;' +\n      '</span>'\n    );\n    $remove.data('data', data);\n\n    this.$selection.find('.select2-selection__rendered').prepend($remove);\n  };\n\n  return AllowClear;\n});\n\nS2.define('select2/selection/search',[\n  'jquery',\n  '../utils',\n  '../keys'\n], function ($, Utils, KEYS) {\n  function Search (decorated, $element, options) {\n    decorated.call(this, $element, options);\n  }\n\n  Search.prototype.render = function (decorated) {\n    var $search = $(\n      '<li class=\"select2-search select2-search--inline\">' +\n        '<input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\"' +\n        ' autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\"' +\n        ' spellcheck=\"false\" role=\"textbox\" />' +\n      '</li>'\n    );\n\n    this.$searchContainer = $search;\n    this.$search = $search.find('input');\n\n    var $rendered = decorated.call(this);\n\n    return $rendered;\n  };\n\n  Search.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n\n    decorated.call(this, container, $container);\n\n    container.on('open', function () {\n      self.$search.attr('tabindex', 0);\n\n      self.$search.focus();\n    });\n\n    container.on('close', function () {\n      self.$search.attr('tabindex', -1);\n\n      self.$search.val('');\n      self.$search.focus();\n    });\n\n    container.on('enable', function () {\n      self.$search.prop('disabled', false);\n    });\n\n    container.on('disable', function () {\n      self.$search.prop('disabled', true);\n    });\n\n    this.$selection.on('focusin', '.select2-search--inline', function (evt) {\n      self.trigger('focus', evt);\n    });\n\n    this.$selection.on('focusout', '.select2-search--inline', function (evt) {\n      self.trigger('blur', evt);\n    });\n\n    this.$selection.on('keydown', '.select2-search--inline', function (evt) {\n      evt.stopPropagation();\n\n      self.trigger('keypress', evt);\n\n      self._keyUpPrevented = evt.isDefaultPrevented();\n\n      var key = evt.which;\n\n      if (key === KEYS.BACKSPACE && self.$search.val() === '') {\n        var $previousChoice = self.$searchContainer\n          .prev('.select2-selection__choice');\n\n        if ($previousChoice.length > 0) {\n          var item = $previousChoice.data('data');\n\n          self.searchRemoveChoice(item);\n\n          evt.preventDefault();\n        }\n      }\n    });\n\n    // Workaround for browsers which do not support the `input` event\n    // This will prevent double-triggering of events for browsers which support\n    // both the `keyup` and `input` events.\n    this.$selection.on('input', '.select2-search--inline', function (evt) {\n      // Unbind the duplicated `keyup` event\n      self.$selection.off('keyup.search');\n    });\n\n    this.$selection.on('keyup.search input', '.select2-search--inline',\n        function (evt) {\n      self.handleSearch(evt);\n    });\n  };\n\n  Search.prototype.createPlaceholder = function (decorated, placeholder) {\n    this.$search.attr('placeholder', placeholder.text);\n  };\n\n  Search.prototype.update = function (decorated, data) {\n    this.$search.attr('placeholder', '');\n\n    decorated.call(this, data);\n\n    this.$selection.find('.select2-selection__rendered')\n                   .append(this.$searchContainer);\n\n    this.resizeSearch();\n  };\n\n  Search.prototype.handleSearch = function () {\n    this.resizeSearch();\n\n    if (!this._keyUpPrevented) {\n      var input = this.$search.val();\n\n      this.trigger('query', {\n        term: input\n      });\n    }\n\n    this._keyUpPrevented = false;\n  };\n\n  Search.prototype.searchRemoveChoice = function (decorated, item) {\n    this.trigger('unselect', {\n      data: item\n    });\n\n    this.trigger('open');\n\n    this.$search.val(item.text + ' ');\n  };\n\n  Search.prototype.resizeSearch = function () {\n    this.$search.css('width', '25px');\n\n    var width = '';\n\n    if (this.$search.attr('placeholder') !== '') {\n      width = this.$selection.find('.select2-selection__rendered').innerWidth();\n    } else {\n      var minimumWidth = this.$search.val().length + 1;\n\n      width = (minimumWidth * 0.75) + 'em';\n    }\n\n    this.$search.css('width', width);\n  };\n\n  return Search;\n});\n\nS2.define('select2/selection/eventRelay',[\n  'jquery'\n], function ($) {\n  function EventRelay () { }\n\n  EventRelay.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n    var relayEvents = [\n      'open', 'opening',\n      'close', 'closing',\n      'select', 'selecting',\n      'unselect', 'unselecting'\n    ];\n\n    var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];\n\n    decorated.call(this, container, $container);\n\n    container.on('*', function (name, params) {\n      // Ignore events that should not be relayed\n      if ($.inArray(name, relayEvents) === -1) {\n        return;\n      }\n\n      // The parameters should always be an object\n      params = params || {};\n\n      // Generate the jQuery event for the Select2 event\n      var evt = $.Event('select2:' + name, {\n        params: params\n      });\n\n      self.$element.trigger(evt);\n\n      // Only handle preventable events if it was one\n      if ($.inArray(name, preventableEvents) === -1) {\n        return;\n      }\n\n      params.prevented = evt.isDefaultPrevented();\n    });\n  };\n\n  return EventRelay;\n});\n\nS2.define('select2/translation',[\n  'jquery',\n  'require'\n], function ($, require) {\n  function Translation (dict) {\n    this.dict = dict || {};\n  }\n\n  Translation.prototype.all = function () {\n    return this.dict;\n  };\n\n  Translation.prototype.get = function (key) {\n    return this.dict[key];\n  };\n\n  Translation.prototype.extend = function (translation) {\n    this.dict = $.extend({}, translation.all(), this.dict);\n  };\n\n  // Static functions\n\n  Translation._cache = {};\n\n  Translation.loadPath = function (path) {\n    if (!(path in Translation._cache)) {\n      var translations = require(path);\n\n      Translation._cache[path] = translations;\n    }\n\n    return new Translation(Translation._cache[path]);\n  };\n\n  return Translation;\n});\n\nS2.define('select2/diacritics',[\n\n], function () {\n  var diacritics = {\n    '\\u24B6': 'A',\n    '\\uFF21': 'A',\n    '\\u00C0': 'A',\n    '\\u00C1': 'A',\n    '\\u00C2': 'A',\n    '\\u1EA6': 'A',\n    '\\u1EA4': 'A',\n    '\\u1EAA': 'A',\n    '\\u1EA8': 'A',\n    '\\u00C3': 'A',\n    '\\u0100': 'A',\n    '\\u0102': 'A',\n    '\\u1EB0': 'A',\n    '\\u1EAE': 'A',\n    '\\u1EB4': 'A',\n    '\\u1EB2': 'A',\n    '\\u0226': 'A',\n    '\\u01E0': 'A',\n    '\\u00C4': 'A',\n    '\\u01DE': 'A',\n    '\\u1EA2': 'A',\n    '\\u00C5': 'A',\n    '\\u01FA': 'A',\n    '\\u01CD': 'A',\n    '\\u0200': 'A',\n    '\\u0202': 'A',\n    '\\u1EA0': 'A',\n    '\\u1EAC': 'A',\n    '\\u1EB6': 'A',\n    '\\u1E00': 'A',\n    '\\u0104': 'A',\n    '\\u023A': 'A',\n    '\\u2C6F': 'A',\n    '\\uA732': 'AA',\n    '\\u00C6': 'AE',\n    '\\u01FC': 'AE',\n    '\\u01E2': 'AE',\n    '\\uA734': 'AO',\n    '\\uA736': 'AU',\n    '\\uA738': 'AV',\n    '\\uA73A': 'AV',\n    '\\uA73C': 'AY',\n    '\\u24B7': 'B',\n    '\\uFF22': 'B',\n    '\\u1E02': 'B',\n    '\\u1E04': 'B',\n    '\\u1E06': 'B',\n    '\\u0243': 'B',\n    '\\u0182': 'B',\n    '\\u0181': 'B',\n    '\\u24B8': 'C',\n    '\\uFF23': 'C',\n    '\\u0106': 'C',\n    '\\u0108': 'C',\n    '\\u010A': 'C',\n    '\\u010C': 'C',\n    '\\u00C7': 'C',\n    '\\u1E08': 'C',\n    '\\u0187': 'C',\n    '\\u023B': 'C',\n    '\\uA73E': 'C',\n    '\\u24B9': 'D',\n    '\\uFF24': 'D',\n    '\\u1E0A': 'D',\n    '\\u010E': 'D',\n    '\\u1E0C': 'D',\n    '\\u1E10': 'D',\n    '\\u1E12': 'D',\n    '\\u1E0E': 'D',\n    '\\u0110': 'D',\n    '\\u018B': 'D',\n    '\\u018A': 'D',\n    '\\u0189': 'D',\n    '\\uA779': 'D',\n    '\\u01F1': 'DZ',\n    '\\u01C4': 'DZ',\n    '\\u01F2': 'Dz',\n    '\\u01C5': 'Dz',\n    '\\u24BA': 'E',\n    '\\uFF25': 'E',\n    '\\u00C8': 'E',\n    '\\u00C9': 'E',\n    '\\u00CA': 'E',\n    '\\u1EC0': 'E',\n    '\\u1EBE': 'E',\n    '\\u1EC4': 'E',\n    '\\u1EC2': 'E',\n    '\\u1EBC': 'E',\n    '\\u0112': 'E',\n    '\\u1E14': 'E',\n    '\\u1E16': 'E',\n    '\\u0114': 'E',\n    '\\u0116': 'E',\n    '\\u00CB': 'E',\n    '\\u1EBA': 'E',\n    '\\u011A': 'E',\n    '\\u0204': 'E',\n    '\\u0206': 'E',\n    '\\u1EB8': 'E',\n    '\\u1EC6': 'E',\n    '\\u0228': 'E',\n    '\\u1E1C': 'E',\n    '\\u0118': 'E',\n    '\\u1E18': 'E',\n    '\\u1E1A': 'E',\n    '\\u0190': 'E',\n    '\\u018E': 'E',\n    '\\u24BB': 'F',\n    '\\uFF26': 'F',\n    '\\u1E1E': 'F',\n    '\\u0191': 'F',\n    '\\uA77B': 'F',\n    '\\u24BC': 'G',\n    '\\uFF27': 'G',\n    '\\u01F4': 'G',\n    '\\u011C': 'G',\n    '\\u1E20': 'G',\n    '\\u011E': 'G',\n    '\\u0120': 'G',\n    '\\u01E6': 'G',\n    '\\u0122': 'G',\n    '\\u01E4': 'G',\n    '\\u0193': 'G',\n    '\\uA7A0': 'G',\n    '\\uA77D': 'G',\n    '\\uA77E': 'G',\n    '\\u24BD': 'H',\n    '\\uFF28': 'H',\n    '\\u0124': 'H',\n    '\\u1E22': 'H',\n    '\\u1E26': 'H',\n    '\\u021E': 'H',\n    '\\u1E24': 'H',\n    '\\u1E28': 'H',\n    '\\u1E2A': 'H',\n    '\\u0126': 'H',\n    '\\u2C67': 'H',\n    '\\u2C75': 'H',\n    '\\uA78D': 'H',\n    '\\u24BE': 'I',\n    '\\uFF29': 'I',\n    '\\u00CC': 'I',\n    '\\u00CD': 'I',\n    '\\u00CE': 'I',\n    '\\u0128': 'I',\n    '\\u012A': 'I',\n    '\\u012C': 'I',\n    '\\u0130': 'I',\n    '\\u00CF': 'I',\n    '\\u1E2E': 'I',\n    '\\u1EC8': 'I',\n    '\\u01CF': 'I',\n    '\\u0208': 'I',\n    '\\u020A': 'I',\n    '\\u1ECA': 'I',\n    '\\u012E': 'I',\n    '\\u1E2C': 'I',\n    '\\u0197': 'I',\n    '\\u24BF': 'J',\n    '\\uFF2A': 'J',\n    '\\u0134': 'J',\n    '\\u0248': 'J',\n    '\\u24C0': 'K',\n    '\\uFF2B': 'K',\n    '\\u1E30': 'K',\n    '\\u01E8': 'K',\n    '\\u1E32': 'K',\n    '\\u0136': 'K',\n    '\\u1E34': 'K',\n    '\\u0198': 'K',\n    '\\u2C69': 'K',\n    '\\uA740': 'K',\n    '\\uA742': 'K',\n    '\\uA744': 'K',\n    '\\uA7A2': 'K',\n    '\\u24C1': 'L',\n    '\\uFF2C': 'L',\n    '\\u013F': 'L',\n    '\\u0139': 'L',\n    '\\u013D': 'L',\n    '\\u1E36': 'L',\n    '\\u1E38': 'L',\n    '\\u013B': 'L',\n    '\\u1E3C': 'L',\n    '\\u1E3A': 'L',\n    '\\u0141': 'L',\n    '\\u023D': 'L',\n    '\\u2C62': 'L',\n    '\\u2C60': 'L',\n    '\\uA748': 'L',\n    '\\uA746': 'L',\n    '\\uA780': 'L',\n    '\\u01C7': 'LJ',\n    '\\u01C8': 'Lj',\n    '\\u24C2': 'M',\n    '\\uFF2D': 'M',\n    '\\u1E3E': 'M',\n    '\\u1E40': 'M',\n    '\\u1E42': 'M',\n    '\\u2C6E': 'M',\n    '\\u019C': 'M',\n    '\\u24C3': 'N',\n    '\\uFF2E': 'N',\n    '\\u01F8': 'N',\n    '\\u0143': 'N',\n    '\\u00D1': 'N',\n    '\\u1E44': 'N',\n    '\\u0147': 'N',\n    '\\u1E46': 'N',\n    '\\u0145': 'N',\n    '\\u1E4A': 'N',\n    '\\u1E48': 'N',\n    '\\u0220': 'N',\n    '\\u019D': 'N',\n    '\\uA790': 'N',\n    '\\uA7A4': 'N',\n    '\\u01CA': 'NJ',\n    '\\u01CB': 'Nj',\n    '\\u24C4': 'O',\n    '\\uFF2F': 'O',\n    '\\u00D2': 'O',\n    '\\u00D3': 'O',\n    '\\u00D4': 'O',\n    '\\u1ED2': 'O',\n    '\\u1ED0': 'O',\n    '\\u1ED6': 'O',\n    '\\u1ED4': 'O',\n    '\\u00D5': 'O',\n    '\\u1E4C': 'O',\n    '\\u022C': 'O',\n    '\\u1E4E': 'O',\n    '\\u014C': 'O',\n    '\\u1E50': 'O',\n    '\\u1E52': 'O',\n    '\\u014E': 'O',\n    '\\u022E': 'O',\n    '\\u0230': 'O',\n    '\\u00D6': 'O',\n    '\\u022A': 'O',\n    '\\u1ECE': 'O',\n    '\\u0150': 'O',\n    '\\u01D1': 'O',\n    '\\u020C': 'O',\n    '\\u020E': 'O',\n    '\\u01A0': 'O',\n    '\\u1EDC': 'O',\n    '\\u1EDA': 'O',\n    '\\u1EE0': 'O',\n    '\\u1EDE': 'O',\n    '\\u1EE2': 'O',\n    '\\u1ECC': 'O',\n    '\\u1ED8': 'O',\n    '\\u01EA': 'O',\n    '\\u01EC': 'O',\n    '\\u00D8': 'O',\n    '\\u01FE': 'O',\n    '\\u0186': 'O',\n    '\\u019F': 'O',\n    '\\uA74A': 'O',\n    '\\uA74C': 'O',\n    '\\u01A2': 'OI',\n    '\\uA74E': 'OO',\n    '\\u0222': 'OU',\n    '\\u24C5': 'P',\n    '\\uFF30': 'P',\n    '\\u1E54': 'P',\n    '\\u1E56': 'P',\n    '\\u01A4': 'P',\n    '\\u2C63': 'P',\n    '\\uA750': 'P',\n    '\\uA752': 'P',\n    '\\uA754': 'P',\n    '\\u24C6': 'Q',\n    '\\uFF31': 'Q',\n    '\\uA756': 'Q',\n    '\\uA758': 'Q',\n    '\\u024A': 'Q',\n    '\\u24C7': 'R',\n    '\\uFF32': 'R',\n    '\\u0154': 'R',\n    '\\u1E58': 'R',\n    '\\u0158': 'R',\n    '\\u0210': 'R',\n    '\\u0212': 'R',\n    '\\u1E5A': 'R',\n    '\\u1E5C': 'R',\n    '\\u0156': 'R',\n    '\\u1E5E': 'R',\n    '\\u024C': 'R',\n    '\\u2C64': 'R',\n    '\\uA75A': 'R',\n    '\\uA7A6': 'R',\n    '\\uA782': 'R',\n    '\\u24C8': 'S',\n    '\\uFF33': 'S',\n    '\\u1E9E': 'S',\n    '\\u015A': 'S',\n    '\\u1E64': 'S',\n    '\\u015C': 'S',\n    '\\u1E60': 'S',\n    '\\u0160': 'S',\n    '\\u1E66': 'S',\n    '\\u1E62': 'S',\n    '\\u1E68': 'S',\n    '\\u0218': 'S',\n    '\\u015E': 'S',\n    '\\u2C7E': 'S',\n    '\\uA7A8': 'S',\n    '\\uA784': 'S',\n    '\\u24C9': 'T',\n    '\\uFF34': 'T',\n    '\\u1E6A': 'T',\n    '\\u0164': 'T',\n    '\\u1E6C': 'T',\n    '\\u021A': 'T',\n    '\\u0162': 'T',\n    '\\u1E70': 'T',\n    '\\u1E6E': 'T',\n    '\\u0166': 'T',\n    '\\u01AC': 'T',\n    '\\u01AE': 'T',\n    '\\u023E': 'T',\n    '\\uA786': 'T',\n    '\\uA728': 'TZ',\n    '\\u24CA': 'U',\n    '\\uFF35': 'U',\n    '\\u00D9': 'U',\n    '\\u00DA': 'U',\n    '\\u00DB': 'U',\n    '\\u0168': 'U',\n    '\\u1E78': 'U',\n    '\\u016A': 'U',\n    '\\u1E7A': 'U',\n    '\\u016C': 'U',\n    '\\u00DC': 'U',\n    '\\u01DB': 'U',\n    '\\u01D7': 'U',\n    '\\u01D5': 'U',\n    '\\u01D9': 'U',\n    '\\u1EE6': 'U',\n    '\\u016E': 'U',\n    '\\u0170': 'U',\n    '\\u01D3': 'U',\n    '\\u0214': 'U',\n    '\\u0216': 'U',\n    '\\u01AF': 'U',\n    '\\u1EEA': 'U',\n    '\\u1EE8': 'U',\n    '\\u1EEE': 'U',\n    '\\u1EEC': 'U',\n    '\\u1EF0': 'U',\n    '\\u1EE4': 'U',\n    '\\u1E72': 'U',\n    '\\u0172': 'U',\n    '\\u1E76': 'U',\n    '\\u1E74': 'U',\n    '\\u0244': 'U',\n    '\\u24CB': 'V',\n    '\\uFF36': 'V',\n    '\\u1E7C': 'V',\n    '\\u1E7E': 'V',\n    '\\u01B2': 'V',\n    '\\uA75E': 'V',\n    '\\u0245': 'V',\n    '\\uA760': 'VY',\n    '\\u24CC': 'W',\n    '\\uFF37': 'W',\n    '\\u1E80': 'W',\n    '\\u1E82': 'W',\n    '\\u0174': 'W',\n    '\\u1E86': 'W',\n    '\\u1E84': 'W',\n    '\\u1E88': 'W',\n    '\\u2C72': 'W',\n    '\\u24CD': 'X',\n    '\\uFF38': 'X',\n    '\\u1E8A': 'X',\n    '\\u1E8C': 'X',\n    '\\u24CE': 'Y',\n    '\\uFF39': 'Y',\n    '\\u1EF2': 'Y',\n    '\\u00DD': 'Y',\n    '\\u0176': 'Y',\n    '\\u1EF8': 'Y',\n    '\\u0232': 'Y',\n    '\\u1E8E': 'Y',\n    '\\u0178': 'Y',\n    '\\u1EF6': 'Y',\n    '\\u1EF4': 'Y',\n    '\\u01B3': 'Y',\n    '\\u024E': 'Y',\n    '\\u1EFE': 'Y',\n    '\\u24CF': 'Z',\n    '\\uFF3A': 'Z',\n    '\\u0179': 'Z',\n    '\\u1E90': 'Z',\n    '\\u017B': 'Z',\n    '\\u017D': 'Z',\n    '\\u1E92': 'Z',\n    '\\u1E94': 'Z',\n    '\\u01B5': 'Z',\n    '\\u0224': 'Z',\n    '\\u2C7F': 'Z',\n    '\\u2C6B': 'Z',\n    '\\uA762': 'Z',\n    '\\u24D0': 'a',\n    '\\uFF41': 'a',\n    '\\u1E9A': 'a',\n    '\\u00E0': 'a',\n    '\\u00E1': 'a',\n    '\\u00E2': 'a',\n    '\\u1EA7': 'a',\n    '\\u1EA5': 'a',\n    '\\u1EAB': 'a',\n    '\\u1EA9': 'a',\n    '\\u00E3': 'a',\n    '\\u0101': 'a',\n    '\\u0103': 'a',\n    '\\u1EB1': 'a',\n    '\\u1EAF': 'a',\n    '\\u1EB5': 'a',\n    '\\u1EB3': 'a',\n    '\\u0227': 'a',\n    '\\u01E1': 'a',\n    '\\u00E4': 'a',\n    '\\u01DF': 'a',\n    '\\u1EA3': 'a',\n    '\\u00E5': 'a',\n    '\\u01FB': 'a',\n    '\\u01CE': 'a',\n    '\\u0201': 'a',\n    '\\u0203': 'a',\n    '\\u1EA1': 'a',\n    '\\u1EAD': 'a',\n    '\\u1EB7': 'a',\n    '\\u1E01': 'a',\n    '\\u0105': 'a',\n    '\\u2C65': 'a',\n    '\\u0250': 'a',\n    '\\uA733': 'aa',\n    '\\u00E6': 'ae',\n    '\\u01FD': 'ae',\n    '\\u01E3': 'ae',\n    '\\uA735': 'ao',\n    '\\uA737': 'au',\n    '\\uA739': 'av',\n    '\\uA73B': 'av',\n    '\\uA73D': 'ay',\n    '\\u24D1': 'b',\n    '\\uFF42': 'b',\n    '\\u1E03': 'b',\n    '\\u1E05': 'b',\n    '\\u1E07': 'b',\n    '\\u0180': 'b',\n    '\\u0183': 'b',\n    '\\u0253': 'b',\n    '\\u24D2': 'c',\n    '\\uFF43': 'c',\n    '\\u0107': 'c',\n    '\\u0109': 'c',\n    '\\u010B': 'c',\n    '\\u010D': 'c',\n    '\\u00E7': 'c',\n    '\\u1E09': 'c',\n    '\\u0188': 'c',\n    '\\u023C': 'c',\n    '\\uA73F': 'c',\n    '\\u2184': 'c',\n    '\\u24D3': 'd',\n    '\\uFF44': 'd',\n    '\\u1E0B': 'd',\n    '\\u010F': 'd',\n    '\\u1E0D': 'd',\n    '\\u1E11': 'd',\n    '\\u1E13': 'd',\n    '\\u1E0F': 'd',\n    '\\u0111': 'd',\n    '\\u018C': 'd',\n    '\\u0256': 'd',\n    '\\u0257': 'd',\n    '\\uA77A': 'd',\n    '\\u01F3': 'dz',\n    '\\u01C6': 'dz',\n    '\\u24D4': 'e',\n    '\\uFF45': 'e',\n    '\\u00E8': 'e',\n    '\\u00E9': 'e',\n    '\\u00EA': 'e',\n    '\\u1EC1': 'e',\n    '\\u1EBF': 'e',\n    '\\u1EC5': 'e',\n    '\\u1EC3': 'e',\n    '\\u1EBD': 'e',\n    '\\u0113': 'e',\n    '\\u1E15': 'e',\n    '\\u1E17': 'e',\n    '\\u0115': 'e',\n    '\\u0117': 'e',\n    '\\u00EB': 'e',\n    '\\u1EBB': 'e',\n    '\\u011B': 'e',\n    '\\u0205': 'e',\n    '\\u0207': 'e',\n    '\\u1EB9': 'e',\n    '\\u1EC7': 'e',\n    '\\u0229': 'e',\n    '\\u1E1D': 'e',\n    '\\u0119': 'e',\n    '\\u1E19': 'e',\n    '\\u1E1B': 'e',\n    '\\u0247': 'e',\n    '\\u025B': 'e',\n    '\\u01DD': 'e',\n    '\\u24D5': 'f',\n    '\\uFF46': 'f',\n    '\\u1E1F': 'f',\n    '\\u0192': 'f',\n    '\\uA77C': 'f',\n    '\\u24D6': 'g',\n    '\\uFF47': 'g',\n    '\\u01F5': 'g',\n    '\\u011D': 'g',\n    '\\u1E21': 'g',\n    '\\u011F': 'g',\n    '\\u0121': 'g',\n    '\\u01E7': 'g',\n    '\\u0123': 'g',\n    '\\u01E5': 'g',\n    '\\u0260': 'g',\n    '\\uA7A1': 'g',\n    '\\u1D79': 'g',\n    '\\uA77F': 'g',\n    '\\u24D7': 'h',\n    '\\uFF48': 'h',\n    '\\u0125': 'h',\n    '\\u1E23': 'h',\n    '\\u1E27': 'h',\n    '\\u021F': 'h',\n    '\\u1E25': 'h',\n    '\\u1E29': 'h',\n    '\\u1E2B': 'h',\n    '\\u1E96': 'h',\n    '\\u0127': 'h',\n    '\\u2C68': 'h',\n    '\\u2C76': 'h',\n    '\\u0265': 'h',\n    '\\u0195': 'hv',\n    '\\u24D8': 'i',\n    '\\uFF49': 'i',\n    '\\u00EC': 'i',\n    '\\u00ED': 'i',\n    '\\u00EE': 'i',\n    '\\u0129': 'i',\n    '\\u012B': 'i',\n    '\\u012D': 'i',\n    '\\u00EF': 'i',\n    '\\u1E2F': 'i',\n    '\\u1EC9': 'i',\n    '\\u01D0': 'i',\n    '\\u0209': 'i',\n    '\\u020B': 'i',\n    '\\u1ECB': 'i',\n    '\\u012F': 'i',\n    '\\u1E2D': 'i',\n    '\\u0268': 'i',\n    '\\u0131': 'i',\n    '\\u24D9': 'j',\n    '\\uFF4A': 'j',\n    '\\u0135': 'j',\n    '\\u01F0': 'j',\n    '\\u0249': 'j',\n    '\\u24DA': 'k',\n    '\\uFF4B': 'k',\n    '\\u1E31': 'k',\n    '\\u01E9': 'k',\n    '\\u1E33': 'k',\n    '\\u0137': 'k',\n    '\\u1E35': 'k',\n    '\\u0199': 'k',\n    '\\u2C6A': 'k',\n    '\\uA741': 'k',\n    '\\uA743': 'k',\n    '\\uA745': 'k',\n    '\\uA7A3': 'k',\n    '\\u24DB': 'l',\n    '\\uFF4C': 'l',\n    '\\u0140': 'l',\n    '\\u013A': 'l',\n    '\\u013E': 'l',\n    '\\u1E37': 'l',\n    '\\u1E39': 'l',\n    '\\u013C': 'l',\n    '\\u1E3D': 'l',\n    '\\u1E3B': 'l',\n    '\\u017F': 'l',\n    '\\u0142': 'l',\n    '\\u019A': 'l',\n    '\\u026B': 'l',\n    '\\u2C61': 'l',\n    '\\uA749': 'l',\n    '\\uA781': 'l',\n    '\\uA747': 'l',\n    '\\u01C9': 'lj',\n    '\\u24DC': 'm',\n    '\\uFF4D': 'm',\n    '\\u1E3F': 'm',\n    '\\u1E41': 'm',\n    '\\u1E43': 'm',\n    '\\u0271': 'm',\n    '\\u026F': 'm',\n    '\\u24DD': 'n',\n    '\\uFF4E': 'n',\n    '\\u01F9': 'n',\n    '\\u0144': 'n',\n    '\\u00F1': 'n',\n    '\\u1E45': 'n',\n    '\\u0148': 'n',\n    '\\u1E47': 'n',\n    '\\u0146': 'n',\n    '\\u1E4B': 'n',\n    '\\u1E49': 'n',\n    '\\u019E': 'n',\n    '\\u0272': 'n',\n    '\\u0149': 'n',\n    '\\uA791': 'n',\n    '\\uA7A5': 'n',\n    '\\u01CC': 'nj',\n    '\\u24DE': 'o',\n    '\\uFF4F': 'o',\n    '\\u00F2': 'o',\n    '\\u00F3': 'o',\n    '\\u00F4': 'o',\n    '\\u1ED3': 'o',\n    '\\u1ED1': 'o',\n    '\\u1ED7': 'o',\n    '\\u1ED5': 'o',\n    '\\u00F5': 'o',\n    '\\u1E4D': 'o',\n    '\\u022D': 'o',\n    '\\u1E4F': 'o',\n    '\\u014D': 'o',\n    '\\u1E51': 'o',\n    '\\u1E53': 'o',\n    '\\u014F': 'o',\n    '\\u022F': 'o',\n    '\\u0231': 'o',\n    '\\u00F6': 'o',\n    '\\u022B': 'o',\n    '\\u1ECF': 'o',\n    '\\u0151': 'o',\n    '\\u01D2': 'o',\n    '\\u020D': 'o',\n    '\\u020F': 'o',\n    '\\u01A1': 'o',\n    '\\u1EDD': 'o',\n    '\\u1EDB': 'o',\n    '\\u1EE1': 'o',\n    '\\u1EDF': 'o',\n    '\\u1EE3': 'o',\n    '\\u1ECD': 'o',\n    '\\u1ED9': 'o',\n    '\\u01EB': 'o',\n    '\\u01ED': 'o',\n    '\\u00F8': 'o',\n    '\\u01FF': 'o',\n    '\\u0254': 'o',\n    '\\uA74B': 'o',\n    '\\uA74D': 'o',\n    '\\u0275': 'o',\n    '\\u01A3': 'oi',\n    '\\u0223': 'ou',\n    '\\uA74F': 'oo',\n    '\\u24DF': 'p',\n    '\\uFF50': 'p',\n    '\\u1E55': 'p',\n    '\\u1E57': 'p',\n    '\\u01A5': 'p',\n    '\\u1D7D': 'p',\n    '\\uA751': 'p',\n    '\\uA753': 'p',\n    '\\uA755': 'p',\n    '\\u24E0': 'q',\n    '\\uFF51': 'q',\n    '\\u024B': 'q',\n    '\\uA757': 'q',\n    '\\uA759': 'q',\n    '\\u24E1': 'r',\n    '\\uFF52': 'r',\n    '\\u0155': 'r',\n    '\\u1E59': 'r',\n    '\\u0159': 'r',\n    '\\u0211': 'r',\n    '\\u0213': 'r',\n    '\\u1E5B': 'r',\n    '\\u1E5D': 'r',\n    '\\u0157': 'r',\n    '\\u1E5F': 'r',\n    '\\u024D': 'r',\n    '\\u027D': 'r',\n    '\\uA75B': 'r',\n    '\\uA7A7': 'r',\n    '\\uA783': 'r',\n    '\\u24E2': 's',\n    '\\uFF53': 's',\n    '\\u00DF': 's',\n    '\\u015B': 's',\n    '\\u1E65': 's',\n    '\\u015D': 's',\n    '\\u1E61': 's',\n    '\\u0161': 's',\n    '\\u1E67': 's',\n    '\\u1E63': 's',\n    '\\u1E69': 's',\n    '\\u0219': 's',\n    '\\u015F': 's',\n    '\\u023F': 's',\n    '\\uA7A9': 's',\n    '\\uA785': 's',\n    '\\u1E9B': 's',\n    '\\u24E3': 't',\n    '\\uFF54': 't',\n    '\\u1E6B': 't',\n    '\\u1E97': 't',\n    '\\u0165': 't',\n    '\\u1E6D': 't',\n    '\\u021B': 't',\n    '\\u0163': 't',\n    '\\u1E71': 't',\n    '\\u1E6F': 't',\n    '\\u0167': 't',\n    '\\u01AD': 't',\n    '\\u0288': 't',\n    '\\u2C66': 't',\n    '\\uA787': 't',\n    '\\uA729': 'tz',\n    '\\u24E4': 'u',\n    '\\uFF55': 'u',\n    '\\u00F9': 'u',\n    '\\u00FA': 'u',\n    '\\u00FB': 'u',\n    '\\u0169': 'u',\n    '\\u1E79': 'u',\n    '\\u016B': 'u',\n    '\\u1E7B': 'u',\n    '\\u016D': 'u',\n    '\\u00FC': 'u',\n    '\\u01DC': 'u',\n    '\\u01D8': 'u',\n    '\\u01D6': 'u',\n    '\\u01DA': 'u',\n    '\\u1EE7': 'u',\n    '\\u016F': 'u',\n    '\\u0171': 'u',\n    '\\u01D4': 'u',\n    '\\u0215': 'u',\n    '\\u0217': 'u',\n    '\\u01B0': 'u',\n    '\\u1EEB': 'u',\n    '\\u1EE9': 'u',\n    '\\u1EEF': 'u',\n    '\\u1EED': 'u',\n    '\\u1EF1': 'u',\n    '\\u1EE5': 'u',\n    '\\u1E73': 'u',\n    '\\u0173': 'u',\n    '\\u1E77': 'u',\n    '\\u1E75': 'u',\n    '\\u0289': 'u',\n    '\\u24E5': 'v',\n    '\\uFF56': 'v',\n    '\\u1E7D': 'v',\n    '\\u1E7F': 'v',\n    '\\u028B': 'v',\n    '\\uA75F': 'v',\n    '\\u028C': 'v',\n    '\\uA761': 'vy',\n    '\\u24E6': 'w',\n    '\\uFF57': 'w',\n    '\\u1E81': 'w',\n    '\\u1E83': 'w',\n    '\\u0175': 'w',\n    '\\u1E87': 'w',\n    '\\u1E85': 'w',\n    '\\u1E98': 'w',\n    '\\u1E89': 'w',\n    '\\u2C73': 'w',\n    '\\u24E7': 'x',\n    '\\uFF58': 'x',\n    '\\u1E8B': 'x',\n    '\\u1E8D': 'x',\n    '\\u24E8': 'y',\n    '\\uFF59': 'y',\n    '\\u1EF3': 'y',\n    '\\u00FD': 'y',\n    '\\u0177': 'y',\n    '\\u1EF9': 'y',\n    '\\u0233': 'y',\n    '\\u1E8F': 'y',\n    '\\u00FF': 'y',\n    '\\u1EF7': 'y',\n    '\\u1E99': 'y',\n    '\\u1EF5': 'y',\n    '\\u01B4': 'y',\n    '\\u024F': 'y',\n    '\\u1EFF': 'y',\n    '\\u24E9': 'z',\n    '\\uFF5A': 'z',\n    '\\u017A': 'z',\n    '\\u1E91': 'z',\n    '\\u017C': 'z',\n    '\\u017E': 'z',\n    '\\u1E93': 'z',\n    '\\u1E95': 'z',\n    '\\u01B6': 'z',\n    '\\u0225': 'z',\n    '\\u0240': 'z',\n    '\\u2C6C': 'z',\n    '\\uA763': 'z',\n    '\\u0386': '\\u0391',\n    '\\u0388': '\\u0395',\n    '\\u0389': '\\u0397',\n    '\\u038A': '\\u0399',\n    '\\u03AA': '\\u0399',\n    '\\u038C': '\\u039F',\n    '\\u038E': '\\u03A5',\n    '\\u03AB': '\\u03A5',\n    '\\u038F': '\\u03A9',\n    '\\u03AC': '\\u03B1',\n    '\\u03AD': '\\u03B5',\n    '\\u03AE': '\\u03B7',\n    '\\u03AF': '\\u03B9',\n    '\\u03CA': '\\u03B9',\n    '\\u0390': '\\u03B9',\n    '\\u03CC': '\\u03BF',\n    '\\u03CD': '\\u03C5',\n    '\\u03CB': '\\u03C5',\n    '\\u03B0': '\\u03C5',\n    '\\u03C9': '\\u03C9',\n    '\\u03C2': '\\u03C3'\n  };\n\n  return diacritics;\n});\n\nS2.define('select2/data/base',[\n  '../utils'\n], function (Utils) {\n  function BaseAdapter ($element, options) {\n    BaseAdapter.__super__.constructor.call(this);\n  }\n\n  Utils.Extend(BaseAdapter, Utils.Observable);\n\n  BaseAdapter.prototype.current = function (callback) {\n    throw new Error('The `current` method must be defined in child classes.');\n  };\n\n  BaseAdapter.prototype.query = function (params, callback) {\n    throw new Error('The `query` method must be defined in child classes.');\n  };\n\n  BaseAdapter.prototype.bind = function (container, $container) {\n    // Can be implemented in subclasses\n  };\n\n  BaseAdapter.prototype.destroy = function () {\n    // Can be implemented in subclasses\n  };\n\n  BaseAdapter.prototype.generateResultId = function (container, data) {\n    var id = container.id + '-result-';\n\n    id += Utils.generateChars(4);\n\n    if (data.id != null) {\n      id += '-' + data.id.toString();\n    } else {\n      id += '-' + Utils.generateChars(4);\n    }\n    return id;\n  };\n\n  return BaseAdapter;\n});\n\nS2.define('select2/data/select',[\n  './base',\n  '../utils',\n  'jquery'\n], function (BaseAdapter, Utils, $) {\n  function SelectAdapter ($element, options) {\n    this.$element = $element;\n    this.options = options;\n\n    SelectAdapter.__super__.constructor.call(this);\n  }\n\n  Utils.Extend(SelectAdapter, BaseAdapter);\n\n  SelectAdapter.prototype.current = function (callback) {\n    var data = [];\n    var self = this;\n\n    this.$element.find(':selected').each(function () {\n      var $option = $(this);\n\n      var option = self.item($option);\n\n      data.push(option);\n    });\n\n    callback(data);\n  };\n\n  SelectAdapter.prototype.select = function (data) {\n    var self = this;\n\n    data.selected = true;\n\n    // If data.element is a DOM node, use it instead\n    if ($(data.element).is('option')) {\n      data.element.selected = true;\n\n      this.$element.trigger('change');\n\n      return;\n    }\n\n    if (this.$element.prop('multiple')) {\n      this.current(function (currentData) {\n        var val = [];\n\n        data = [data];\n        data.push.apply(data, currentData);\n\n        for (var d = 0; d < data.length; d++) {\n          var id = data[d].id;\n\n          if ($.inArray(id, val) === -1) {\n            val.push(id);\n          }\n        }\n\n        self.$element.val(val);\n        self.$element.trigger('change');\n      });\n    } else {\n      var val = data.id;\n\n      this.$element.val(val);\n      this.$element.trigger('change');\n    }\n  };\n\n  SelectAdapter.prototype.unselect = function (data) {\n    var self = this;\n\n    if (!this.$element.prop('multiple')) {\n      return;\n    }\n\n    data.selected = false;\n\n    if ($(data.element).is('option')) {\n      data.element.selected = false;\n\n      this.$element.trigger('change');\n\n      return;\n    }\n\n    this.current(function (currentData) {\n      var val = [];\n\n      for (var d = 0; d < currentData.length; d++) {\n        var id = currentData[d].id;\n\n        if (id !== data.id && $.inArray(id, val) === -1) {\n          val.push(id);\n        }\n      }\n\n      self.$element.val(val);\n\n      self.$element.trigger('change');\n    });\n  };\n\n  SelectAdapter.prototype.bind = function (container, $container) {\n    var self = this;\n\n    this.container = container;\n\n    container.on('select', function (params) {\n      self.select(params.data);\n    });\n\n    container.on('unselect', function (params) {\n      self.unselect(params.data);\n    });\n  };\n\n  SelectAdapter.prototype.destroy = function () {\n    // Remove anything added to child elements\n    this.$element.find('*').each(function () {\n      // Remove any custom data set by Select2\n      $.removeData(this, 'data');\n    });\n  };\n\n  SelectAdapter.prototype.query = function (params, callback) {\n    var data = [];\n    var self = this;\n\n    var $options = this.$element.children();\n\n    $options.each(function () {\n      var $option = $(this);\n\n      if (!$option.is('option') && !$option.is('optgroup')) {\n        return;\n      }\n\n      var option = self.item($option);\n\n      var matches = self.matches(params, option);\n\n      if (matches !== null) {\n        data.push(matches);\n      }\n    });\n\n    callback({\n      results: data\n    });\n  };\n\n  SelectAdapter.prototype.addOptions = function ($options) {\n    Utils.appendMany(this.$element, $options);\n  };\n\n  SelectAdapter.prototype.option = function (data) {\n    var option;\n\n    if (data.children) {\n      option = document.createElement('optgroup');\n      option.label = data.text;\n    } else {\n      option = document.createElement('option');\n\n      if (option.textContent !== undefined) {\n        option.textContent = data.text;\n      } else {\n        option.innerText = data.text;\n      }\n    }\n\n    if (data.id) {\n      option.value = data.id;\n    }\n\n    if (data.disabled) {\n      option.disabled = true;\n    }\n\n    if (data.selected) {\n      option.selected = true;\n    }\n\n    if (data.title) {\n      option.title = data.title;\n    }\n\n    var $option = $(option);\n\n    var normalizedData = this._normalizeItem(data);\n    normalizedData.element = option;\n\n    // Override the option's data with the combined data\n    $.data(option, 'data', normalizedData);\n\n    return $option;\n  };\n\n  SelectAdapter.prototype.item = function ($option) {\n    var data = {};\n\n    data = $.data($option[0], 'data');\n\n    if (data != null) {\n      return data;\n    }\n\n    if ($option.is('option')) {\n      data = {\n        id: $option.val(),\n        text: $option.text(),\n        disabled: $option.prop('disabled'),\n        selected: $option.prop('selected'),\n        title: $option.prop('title')\n      };\n    } else if ($option.is('optgroup')) {\n      data = {\n        text: $option.prop('label'),\n        children: [],\n        title: $option.prop('title')\n      };\n\n      var $children = $option.children('option');\n      var children = [];\n\n      for (var c = 0; c < $children.length; c++) {\n        var $child = $($children[c]);\n\n        var child = this.item($child);\n\n        children.push(child);\n      }\n\n      data.children = children;\n    }\n\n    data = this._normalizeItem(data);\n    data.element = $option[0];\n\n    $.data($option[0], 'data', data);\n\n    return data;\n  };\n\n  SelectAdapter.prototype._normalizeItem = function (item) {\n    if (!$.isPlainObject(item)) {\n      item = {\n        id: item,\n        text: item\n      };\n    }\n\n    item = $.extend({}, {\n      text: ''\n    }, item);\n\n    var defaults = {\n      selected: false,\n      disabled: false\n    };\n\n    if (item.id != null) {\n      item.id = item.id.toString();\n    }\n\n    if (item.text != null) {\n      item.text = item.text.toString();\n    }\n\n    if (item._resultId == null && item.id && this.container != null) {\n      item._resultId = this.generateResultId(this.container, item);\n    }\n\n    return $.extend({}, defaults, item);\n  };\n\n  SelectAdapter.prototype.matches = function (params, data) {\n    var matcher = this.options.get('matcher');\n\n    return matcher(params, data);\n  };\n\n  return SelectAdapter;\n});\n\nS2.define('select2/data/array',[\n  './select',\n  '../utils',\n  'jquery'\n], function (SelectAdapter, Utils, $) {\n  function ArrayAdapter ($element, options) {\n    var data = options.get('data') || [];\n\n    ArrayAdapter.__super__.constructor.call(this, $element, options);\n\n    this.addOptions(this.convertToOptions(data));\n  }\n\n  Utils.Extend(ArrayAdapter, SelectAdapter);\n\n  ArrayAdapter.prototype.select = function (data) {\n    var $option = this.$element.find('option').filter(function (i, elm) {\n      return elm.value == data.id.toString();\n    });\n\n    if ($option.length === 0) {\n      $option = this.option(data);\n\n      this.addOptions($option);\n    }\n\n    ArrayAdapter.__super__.select.call(this, data);\n  };\n\n  ArrayAdapter.prototype.convertToOptions = function (data) {\n    var self = this;\n\n    var $existing = this.$element.find('option');\n    var existingIds = $existing.map(function () {\n      return self.item($(this)).id;\n    }).get();\n\n    var $options = [];\n\n    // Filter out all items except for the one passed in the argument\n    function onlyItem (item) {\n      return function () {\n        return $(this).val() == item.id;\n      };\n    }\n\n    for (var d = 0; d < data.length; d++) {\n      var item = this._normalizeItem(data[d]);\n\n      // Skip items which were pre-loaded, only merge the data\n      if ($.inArray(item.id, existingIds) >= 0) {\n        var $existingOption = $existing.filter(onlyItem(item));\n\n        var existingData = this.item($existingOption);\n        var newData = $.extend(true, {}, existingData, item);\n\n        var $newOption = this.option(existingData);\n\n        $existingOption.replaceWith($newOption);\n\n        continue;\n      }\n\n      var $option = this.option(item);\n\n      if (item.children) {\n        var $children = this.convertToOptions(item.children);\n\n        Utils.appendMany($option, $children);\n      }\n\n      $options.push($option);\n    }\n\n    return $options;\n  };\n\n  return ArrayAdapter;\n});\n\nS2.define('select2/data/ajax',[\n  './array',\n  '../utils',\n  'jquery'\n], function (ArrayAdapter, Utils, $) {\n  function AjaxAdapter ($element, options) {\n    this.ajaxOptions = this._applyDefaults(options.get('ajax'));\n\n    if (this.ajaxOptions.processResults != null) {\n      this.processResults = this.ajaxOptions.processResults;\n    }\n\n    ArrayAdapter.__super__.constructor.call(this, $element, options);\n  }\n\n  Utils.Extend(AjaxAdapter, ArrayAdapter);\n\n  AjaxAdapter.prototype._applyDefaults = function (options) {\n    var defaults = {\n      data: function (params) {\n        return {\n          q: params.term\n        };\n      },\n      transport: function (params, success, failure) {\n        var $request = $.ajax(params);\n\n        $request.then(success);\n        $request.fail(failure);\n\n        return $request;\n      }\n    };\n\n    return $.extend({}, defaults, options, true);\n  };\n\n  AjaxAdapter.prototype.processResults = function (results) {\n    return results;\n  };\n\n  AjaxAdapter.prototype.query = function (params, callback) {\n    var matches = [];\n    var self = this;\n\n    if (this._request != null) {\n      // JSONP requests cannot always be aborted\n      if ($.isFunction(this._request.abort)) {\n        this._request.abort();\n      }\n\n      this._request = null;\n    }\n\n    var options = $.extend({\n      type: 'GET'\n    }, this.ajaxOptions);\n\n    if (typeof options.url === 'function') {\n      options.url = options.url(params);\n    }\n\n    if (typeof options.data === 'function') {\n      options.data = options.data(params);\n    }\n\n    function request () {\n      var $request = options.transport(options, function (data) {\n        var results = self.processResults(data, params);\n\n        if (self.options.get('debug') && window.console && console.error) {\n          // Check to make sure that the response included a `results` key.\n          if (!results || !results.results || !$.isArray(results.results)) {\n            console.error(\n              'Select2: The AJAX results did not return an array in the ' +\n              '`results` key of the response.'\n            );\n          }\n        }\n\n        callback(results);\n      }, function () {\n        // TODO: Handle AJAX errors\n      });\n\n      self._request = $request;\n    }\n\n    if (this.ajaxOptions.delay && params.term !== '') {\n      if (this._queryTimeout) {\n        window.clearTimeout(this._queryTimeout);\n      }\n\n      this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);\n    } else {\n      request();\n    }\n  };\n\n  return AjaxAdapter;\n});\n\nS2.define('select2/data/tags',[\n  'jquery'\n], function ($) {\n  function Tags (decorated, $element, options) {\n    var tags = options.get('tags');\n\n    var createTag = options.get('createTag');\n\n    if (createTag !== undefined) {\n      this.createTag = createTag;\n    }\n\n    decorated.call(this, $element, options);\n\n    if ($.isArray(tags)) {\n      for (var t = 0; t < tags.length; t++) {\n        var tag = tags[t];\n        var item = this._normalizeItem(tag);\n\n        var $option = this.option(item);\n\n        this.$element.append($option);\n      }\n    }\n  }\n\n  Tags.prototype.query = function (decorated, params, callback) {\n    var self = this;\n\n    this._removeOldTags();\n\n    if (params.term == null || params.page != null) {\n      decorated.call(this, params, callback);\n      return;\n    }\n\n    function wrapper (obj, child) {\n      var data = obj.results;\n\n      for (var i = 0; i < data.length; i++) {\n        var option = data[i];\n\n        var checkChildren = (\n          option.children != null &&\n          !wrapper({\n            results: option.children\n          }, true)\n        );\n\n        var checkText = option.text === params.term;\n\n        if (checkText || checkChildren) {\n          if (child) {\n            return false;\n          }\n\n          obj.data = data;\n          callback(obj);\n\n          return;\n        }\n      }\n\n      if (child) {\n        return true;\n      }\n\n      var tag = self.createTag(params);\n\n      if (tag != null) {\n        var $option = self.option(tag);\n        $option.attr('data-select2-tag', true);\n\n        self.addOptions([$option]);\n\n        self.insertTag(data, tag);\n      }\n\n      obj.results = data;\n\n      callback(obj);\n    }\n\n    decorated.call(this, params, wrapper);\n  };\n\n  Tags.prototype.createTag = function (decorated, params) {\n    var term = $.trim(params.term);\n\n    if (term === '') {\n      return null;\n    }\n\n    return {\n      id: term,\n      text: term\n    };\n  };\n\n  Tags.prototype.insertTag = function (_, data, tag) {\n    data.unshift(tag);\n  };\n\n  Tags.prototype._removeOldTags = function (_) {\n    var tag = this._lastTag;\n\n    var $options = this.$element.find('option[data-select2-tag]');\n\n    $options.each(function () {\n      if (this.selected) {\n        return;\n      }\n\n      $(this).remove();\n    });\n  };\n\n  return Tags;\n});\n\nS2.define('select2/data/tokenizer',[\n  'jquery'\n], function ($) {\n  function Tokenizer (decorated, $element, options) {\n    var tokenizer = options.get('tokenizer');\n\n    if (tokenizer !== undefined) {\n      this.tokenizer = tokenizer;\n    }\n\n    decorated.call(this, $element, options);\n  }\n\n  Tokenizer.prototype.bind = function (decorated, container, $container) {\n    decorated.call(this, container, $container);\n\n    this.$search =  container.dropdown.$search || container.selection.$search ||\n      $container.find('.select2-search__field');\n  };\n\n  Tokenizer.prototype.query = function (decorated, params, callback) {\n    var self = this;\n\n    function select (data) {\n      self.select(data);\n    }\n\n    params.term = params.term || '';\n\n    var tokenData = this.tokenizer(params, this.options, select);\n\n    if (tokenData.term !== params.term) {\n      // Replace the search term if we have the search box\n      if (this.$search.length) {\n        this.$search.val(tokenData.term);\n        this.$search.focus();\n      }\n\n      params.term = tokenData.term;\n    }\n\n    decorated.call(this, params, callback);\n  };\n\n  Tokenizer.prototype.tokenizer = function (_, params, options, callback) {\n    var separators = options.get('tokenSeparators') || [];\n    var term = params.term;\n    var i = 0;\n\n    var createTag = this.createTag || function (params) {\n      return {\n        id: params.term,\n        text: params.term\n      };\n    };\n\n    while (i < term.length) {\n      var termChar = term[i];\n\n      if ($.inArray(termChar, separators) === -1) {\n        i++;\n\n        continue;\n      }\n\n      var part = term.substr(0, i);\n      var partParams = $.extend({}, params, {\n        term: part\n      });\n\n      var data = createTag(partParams);\n\n      callback(data);\n\n      // Reset the term to not include the tokenized portion\n      term = term.substr(i + 1) || '';\n      i = 0;\n    }\n\n    return {\n      term: term\n    };\n  };\n\n  return Tokenizer;\n});\n\nS2.define('select2/data/minimumInputLength',[\n\n], function () {\n  function MinimumInputLength (decorated, $e, options) {\n    this.minimumInputLength = options.get('minimumInputLength');\n\n    decorated.call(this, $e, options);\n  }\n\n  MinimumInputLength.prototype.query = function (decorated, params, callback) {\n    params.term = params.term || '';\n\n    if (params.term.length < this.minimumInputLength) {\n      this.trigger('results:message', {\n        message: 'inputTooShort',\n        args: {\n          minimum: this.minimumInputLength,\n          input: params.term,\n          params: params\n        }\n      });\n\n      return;\n    }\n\n    decorated.call(this, params, callback);\n  };\n\n  return MinimumInputLength;\n});\n\nS2.define('select2/data/maximumInputLength',[\n\n], function () {\n  function MaximumInputLength (decorated, $e, options) {\n    this.maximumInputLength = options.get('maximumInputLength');\n\n    decorated.call(this, $e, options);\n  }\n\n  MaximumInputLength.prototype.query = function (decorated, params, callback) {\n    params.term = params.term || '';\n\n    if (this.maximumInputLength > 0 &&\n        params.term.length > this.maximumInputLength) {\n      this.trigger('results:message', {\n        message: 'inputTooLong',\n        args: {\n          maximum: this.maximumInputLength,\n          input: params.term,\n          params: params\n        }\n      });\n\n      return;\n    }\n\n    decorated.call(this, params, callback);\n  };\n\n  return MaximumInputLength;\n});\n\nS2.define('select2/data/maximumSelectionLength',[\n\n], function (){\n  function MaximumSelectionLength (decorated, $e, options) {\n    this.maximumSelectionLength = options.get('maximumSelectionLength');\n\n    decorated.call(this, $e, options);\n  }\n\n  MaximumSelectionLength.prototype.query =\n    function (decorated, params, callback) {\n      var self = this;\n\n      this.current(function (currentData) {\n        var count = currentData != null ? currentData.length : 0;\n        if (self.maximumSelectionLength > 0 &&\n          count >= self.maximumSelectionLength) {\n          self.trigger('results:message', {\n            message: 'maximumSelected',\n            args: {\n              maximum: self.maximumSelectionLength\n            }\n          });\n          return;\n        }\n        decorated.call(self, params, callback);\n      });\n  };\n\n  return MaximumSelectionLength;\n});\n\nS2.define('select2/dropdown',[\n  'jquery',\n  './utils'\n], function ($, Utils) {\n  function Dropdown ($element, options) {\n    this.$element = $element;\n    this.options = options;\n\n    Dropdown.__super__.constructor.call(this);\n  }\n\n  Utils.Extend(Dropdown, Utils.Observable);\n\n  Dropdown.prototype.render = function () {\n    var $dropdown = $(\n      '<span class=\"select2-dropdown\">' +\n        '<span class=\"select2-results\"></span>' +\n      '</span>'\n    );\n\n    $dropdown.attr('dir', this.options.get('dir'));\n\n    this.$dropdown = $dropdown;\n\n    return $dropdown;\n  };\n\n  Dropdown.prototype.position = function ($dropdown, $container) {\n    // Should be implmented in subclasses\n  };\n\n  Dropdown.prototype.destroy = function () {\n    // Remove the dropdown from the DOM\n    this.$dropdown.remove();\n  };\n\n  return Dropdown;\n});\n\nS2.define('select2/dropdown/search',[\n  'jquery',\n  '../utils'\n], function ($, Utils) {\n  function Search () { }\n\n  Search.prototype.render = function (decorated) {\n    var $rendered = decorated.call(this);\n\n    var $search = $(\n      '<span class=\"select2-search select2-search--dropdown\">' +\n        '<input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\"' +\n        ' autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\"' +\n        ' spellcheck=\"false\" role=\"textbox\" />' +\n      '</span>'\n    );\n\n    this.$searchContainer = $search;\n    this.$search = $search.find('input');\n\n    $rendered.prepend($search);\n\n    return $rendered;\n  };\n\n  Search.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n\n    decorated.call(this, container, $container);\n\n    this.$search.on('keydown', function (evt) {\n      self.trigger('keypress', evt);\n\n      self._keyUpPrevented = evt.isDefaultPrevented();\n    });\n\n    // Workaround for browsers which do not support the `input` event\n    // This will prevent double-triggering of events for browsers which support\n    // both the `keyup` and `input` events.\n    this.$search.on('input', function (evt) {\n      // Unbind the duplicated `keyup` event\n      $(this).off('keyup');\n    });\n\n    this.$search.on('keyup input', function (evt) {\n      self.handleSearch(evt);\n    });\n\n    container.on('open', function () {\n      self.$search.attr('tabindex', 0);\n\n      self.$search.focus();\n\n      window.setTimeout(function () {\n        self.$search.focus();\n      }, 0);\n    });\n\n    container.on('close', function () {\n      self.$search.attr('tabindex', -1);\n\n      self.$search.val('');\n    });\n\n    container.on('results:all', function (params) {\n      if (params.query.term == null || params.query.term === '') {\n        var showSearch = self.showSearch(params);\n\n        if (showSearch) {\n          self.$searchContainer.removeClass('select2-search--hide');\n        } else {\n          self.$searchContainer.addClass('select2-search--hide');\n        }\n      }\n    });\n  };\n\n  Search.prototype.handleSearch = function (evt) {\n    if (!this._keyUpPrevented) {\n      var input = this.$search.val();\n\n      this.trigger('query', {\n        term: input\n      });\n    }\n\n    this._keyUpPrevented = false;\n  };\n\n  Search.prototype.showSearch = function (_, params) {\n    return true;\n  };\n\n  return Search;\n});\n\nS2.define('select2/dropdown/hidePlaceholder',[\n\n], function () {\n  function HidePlaceholder (decorated, $element, options, dataAdapter) {\n    this.placeholder = this.normalizePlaceholder(options.get('placeholder'));\n\n    decorated.call(this, $element, options, dataAdapter);\n  }\n\n  HidePlaceholder.prototype.append = function (decorated, data) {\n    data.results = this.removePlaceholder(data.results);\n\n    decorated.call(this, data);\n  };\n\n  HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {\n    if (typeof placeholder === 'string') {\n      placeholder = {\n        id: '',\n        text: placeholder\n      };\n    }\n\n    return placeholder;\n  };\n\n  HidePlaceholder.prototype.removePlaceholder = function (_, data) {\n    var modifiedData = data.slice(0);\n\n    for (var d = data.length - 1; d >= 0; d--) {\n      var item = data[d];\n\n      if (this.placeholder.id === item.id) {\n        modifiedData.splice(d, 1);\n      }\n    }\n\n    return modifiedData;\n  };\n\n  return HidePlaceholder;\n});\n\nS2.define('select2/dropdown/infiniteScroll',[\n  'jquery'\n], function ($) {\n  function InfiniteScroll (decorated, $element, options, dataAdapter) {\n    this.lastParams = {};\n\n    decorated.call(this, $element, options, dataAdapter);\n\n    this.$loadingMore = this.createLoadingMore();\n    this.loading = false;\n  }\n\n  InfiniteScroll.prototype.append = function (decorated, data) {\n    this.$loadingMore.remove();\n    this.loading = false;\n\n    decorated.call(this, data);\n\n    if (this.showLoadingMore(data)) {\n      this.$results.append(this.$loadingMore);\n    }\n  };\n\n  InfiniteScroll.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n\n    decorated.call(this, container, $container);\n\n    container.on('query', function (params) {\n      self.lastParams = params;\n      self.loading = true;\n    });\n\n    container.on('query:append', function (params) {\n      self.lastParams = params;\n      self.loading = true;\n    });\n\n    this.$results.on('scroll', function () {\n      var isLoadMoreVisible = $.contains(\n        document.documentElement,\n        self.$loadingMore[0]\n      );\n\n      if (self.loading || !isLoadMoreVisible) {\n        return;\n      }\n\n      var currentOffset = self.$results.offset().top +\n        self.$results.outerHeight(false);\n      var loadingMoreOffset = self.$loadingMore.offset().top +\n        self.$loadingMore.outerHeight(false);\n\n      if (currentOffset + 50 >= loadingMoreOffset) {\n        self.loadMore();\n      }\n    });\n  };\n\n  InfiniteScroll.prototype.loadMore = function () {\n    this.loading = true;\n\n    var params = $.extend({}, {page: 1}, this.lastParams);\n\n    params.page++;\n\n    this.trigger('query:append', params);\n  };\n\n  InfiniteScroll.prototype.showLoadingMore = function (_, data) {\n    return data.pagination && data.pagination.more;\n  };\n\n  InfiniteScroll.prototype.createLoadingMore = function () {\n    var $option = $(\n      '<li class=\"option load-more\" role=\"treeitem\"></li>'\n    );\n\n    var message = this.options.get('translations').get('loadingMore');\n\n    $option.html(message(this.lastParams));\n\n    return $option;\n  };\n\n  return InfiniteScroll;\n});\n\nS2.define('select2/dropdown/attachBody',[\n  'jquery',\n  '../utils'\n], function ($, Utils) {\n  function AttachBody (decorated, $element, options) {\n    this.$dropdownParent = options.get('dropdownParent') || document.body;\n\n    decorated.call(this, $element, options);\n  }\n\n  AttachBody.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n\n    var setupResultsEvents = false;\n\n    decorated.call(this, container, $container);\n\n    container.on('open', function () {\n      self._showDropdown();\n      self._attachPositioningHandler(container);\n\n      if (!setupResultsEvents) {\n        setupResultsEvents = true;\n\n        container.on('results:all', function () {\n          self._positionDropdown();\n          self._resizeDropdown();\n        });\n\n        container.on('results:append', function () {\n          self._positionDropdown();\n          self._resizeDropdown();\n        });\n      }\n    });\n\n    container.on('close', function () {\n      self._hideDropdown();\n      self._detachPositioningHandler(container);\n    });\n\n    this.$dropdownContainer.on('mousedown', function (evt) {\n      evt.stopPropagation();\n    });\n  };\n\n  AttachBody.prototype.position = function (decorated, $dropdown, $container) {\n    // Clone all of the container classes\n    $dropdown.attr('class', $container.attr('class'));\n\n    $dropdown.removeClass('select2');\n    $dropdown.addClass('select2-container--open');\n\n    $dropdown.css({\n      position: 'absolute',\n      top: -999999\n    });\n\n    this.$container = $container;\n  };\n\n  AttachBody.prototype.render = function (decorated) {\n    var $container = $('<span></span>');\n\n    var $dropdown = decorated.call(this);\n    $container.append($dropdown);\n\n    this.$dropdownContainer = $container;\n\n    return $container;\n  };\n\n  AttachBody.prototype._hideDropdown = function (decorated) {\n    this.$dropdownContainer.detach();\n  };\n\n  AttachBody.prototype._attachPositioningHandler = function (container) {\n    var self = this;\n\n    var scrollEvent = 'scroll.select2.' + container.id;\n    var resizeEvent = 'resize.select2.' + container.id;\n    var orientationEvent = 'orientationchange.select2.' + container.id;\n\n    var $watchers = this.$container.parents().filter(Utils.hasScroll);\n    $watchers.each(function () {\n      $(this).data('select2-scroll-position', {\n        x: $(this).scrollLeft(),\n        y: $(this).scrollTop()\n      });\n    });\n\n    $watchers.on(scrollEvent, function (ev) {\n      var position = $(this).data('select2-scroll-position');\n      $(this).scrollTop(position.y);\n    });\n\n    $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,\n      function (e) {\n      self._positionDropdown();\n      self._resizeDropdown();\n    });\n  };\n\n  AttachBody.prototype._detachPositioningHandler = function (container) {\n    var scrollEvent = 'scroll.select2.' + container.id;\n    var resizeEvent = 'resize.select2.' + container.id;\n    var orientationEvent = 'orientationchange.select2.' + container.id;\n\n    var $watchers = this.$container.parents().filter(Utils.hasScroll);\n    $watchers.off(scrollEvent);\n\n    $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);\n  };\n\n  AttachBody.prototype._positionDropdown = function () {\n    var $window = $(window);\n\n    var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');\n    var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');\n\n    var newDirection = null;\n\n    var position = this.$container.position();\n    var offset = this.$container.offset();\n\n    offset.bottom = offset.top + this.$container.outerHeight(false);\n\n    var container = {\n      height: this.$container.outerHeight(false)\n    };\n\n    container.top = offset.top;\n    container.bottom = offset.top + container.height;\n\n    var dropdown = {\n      height: this.$dropdown.outerHeight(false)\n    };\n\n    var viewport = {\n      top: $window.scrollTop(),\n      bottom: $window.scrollTop() + $window.height()\n    };\n\n    var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);\n    var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);\n\n    var css = {\n      left: offset.left,\n      top: container.bottom\n    };\n\n    if (!isCurrentlyAbove && !isCurrentlyBelow) {\n      newDirection = 'below';\n    }\n\n    if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {\n      newDirection = 'above';\n    } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {\n      newDirection = 'below';\n    }\n\n    if (newDirection == 'above' ||\n      (isCurrentlyAbove && newDirection !== 'below')) {\n      css.top = container.top - dropdown.height;\n    }\n\n    if (newDirection != null) {\n      this.$dropdown\n        .removeClass('select2-dropdown--below select2-dropdown--above')\n        .addClass('select2-dropdown--' + newDirection);\n      this.$container\n        .removeClass('select2-container--below select2-container--above')\n        .addClass('select2-container--' + newDirection);\n    }\n\n    this.$dropdownContainer.css(css);\n  };\n\n  AttachBody.prototype._resizeDropdown = function () {\n    this.$dropdownContainer.width();\n\n    var css = {\n      width: this.$container.outerWidth(false) + 'px'\n    };\n\n    if (this.options.get('dropdownAutoWidth')) {\n      css.minWidth = css.width;\n      css.width = 'auto';\n    }\n\n    this.$dropdown.css(css);\n  };\n\n  AttachBody.prototype._showDropdown = function (decorated) {\n    this.$dropdownContainer.appendTo(this.$dropdownParent);\n\n    this._positionDropdown();\n    this._resizeDropdown();\n  };\n\n  return AttachBody;\n});\n\nS2.define('select2/dropdown/minimumResultsForSearch',[\n\n], function () {\n  function countResults (data) {\n    var count = 0;\n\n    for (var d = 0; d < data.length; d++) {\n      var item = data[d];\n\n      if (item.children) {\n        count += countResults(item.children);\n      } else {\n        count++;\n      }\n    }\n\n    return count;\n  }\n\n  function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {\n    this.minimumResultsForSearch = options.get('minimumResultsForSearch');\n\n    if (this.minimumResultsForSearch < 0) {\n      this.minimumResultsForSearch = Infinity;\n    }\n\n    decorated.call(this, $element, options, dataAdapter);\n  }\n\n  MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {\n    if (countResults(params.data.results) < this.minimumResultsForSearch) {\n      return false;\n    }\n\n    return decorated.call(this, params);\n  };\n\n  return MinimumResultsForSearch;\n});\n\nS2.define('select2/dropdown/selectOnClose',[\n\n], function () {\n  function SelectOnClose () { }\n\n  SelectOnClose.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n\n    decorated.call(this, container, $container);\n\n    container.on('close', function () {\n      self._handleSelectOnClose();\n    });\n  };\n\n  SelectOnClose.prototype._handleSelectOnClose = function () {\n    var $highlightedResults = this.getHighlightedResults();\n\n    if ($highlightedResults.length < 1) {\n      return;\n    }\n\n    this.trigger('select', {\n        data: $highlightedResults.data('data')\n    });\n  };\n\n  return SelectOnClose;\n});\n\nS2.define('select2/dropdown/closeOnSelect',[\n\n], function () {\n  function CloseOnSelect () { }\n\n  CloseOnSelect.prototype.bind = function (decorated, container, $container) {\n    var self = this;\n\n    decorated.call(this, container, $container);\n\n    container.on('select', function (evt) {\n      self._selectTriggered(evt);\n    });\n\n    container.on('unselect', function (evt) {\n      self._selectTriggered(evt);\n    });\n  };\n\n  CloseOnSelect.prototype._selectTriggered = function (_, evt) {\n    var originalEvent = evt.originalEvent;\n\n    // Don't close if the control key is being held\n    if (originalEvent && originalEvent.ctrlKey) {\n      return;\n    }\n\n    this.trigger('close');\n  };\n\n  return CloseOnSelect;\n});\n\nS2.define('select2/i18n/en',[],function () {\n  // English\n  return {\n    errorLoading: function () {\n      return 'The results could not be loaded.';\n    },\n    inputTooLong: function (args) {\n      var overChars = args.input.length - args.maximum;\n\n      var message = 'Please delete ' + overChars + ' character';\n\n      if (overChars != 1) {\n        message += 's';\n      }\n\n      return message;\n    },\n    inputTooShort: function (args) {\n      var remainingChars = args.minimum - args.input.length;\n\n      var message = 'Please enter ' + remainingChars + ' or more characters';\n\n      return message;\n    },\n    loadingMore: function () {\n      return 'Loading more results…';\n    },\n    maximumSelected: function (args) {\n      var message = 'You can only select ' + args.maximum + ' item';\n\n      if (args.maximum != 1) {\n        message += 's';\n      }\n\n      return message;\n    },\n    noResults: function () {\n      return 'No results found';\n    },\n    searching: function () {\n      return 'Searching…';\n    }\n  };\n});\n\nS2.define('select2/defaults',[\n  'jquery',\n  'require',\n\n  './results',\n\n  './selection/single',\n  './selection/multiple',\n  './selection/placeholder',\n  './selection/allowClear',\n  './selection/search',\n  './selection/eventRelay',\n\n  './utils',\n  './translation',\n  './diacritics',\n\n  './data/select',\n  './data/array',\n  './data/ajax',\n  './data/tags',\n  './data/tokenizer',\n  './data/minimumInputLength',\n  './data/maximumInputLength',\n  './data/maximumSelectionLength',\n\n  './dropdown',\n  './dropdown/search',\n  './dropdown/hidePlaceholder',\n  './dropdown/infiniteScroll',\n  './dropdown/attachBody',\n  './dropdown/minimumResultsForSearch',\n  './dropdown/selectOnClose',\n  './dropdown/closeOnSelect',\n\n  './i18n/en'\n], function ($, require,\n\n             ResultsList,\n\n             SingleSelection, MultipleSelection, Placeholder, AllowClear,\n             SelectionSearch, EventRelay,\n\n             Utils, Translation, DIACRITICS,\n\n             SelectData, ArrayData, AjaxData, Tags, Tokenizer,\n             MinimumInputLength, MaximumInputLength, MaximumSelectionLength,\n\n             Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,\n             AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,\n\n             EnglishTranslation) {\n  function Defaults () {\n    this.reset();\n  }\n\n  Defaults.prototype.apply = function (options) {\n    options = $.extend({}, this.defaults, options);\n\n    if (options.dataAdapter == null) {\n      if (options.ajax != null) {\n        options.dataAdapter = AjaxData;\n      } else if (options.data != null) {\n        options.dataAdapter = ArrayData;\n      } else {\n        options.dataAdapter = SelectData;\n      }\n\n      if (options.minimumInputLength > 0) {\n        options.dataAdapter = Utils.Decorate(\n          options.dataAdapter,\n          MinimumInputLength\n        );\n      }\n\n      if (options.maximumInputLength > 0) {\n        options.dataAdapter = Utils.Decorate(\n          options.dataAdapter,\n          MaximumInputLength\n        );\n      }\n\n      if (options.maximumSelectionLength > 0) {\n        options.dataAdapter = Utils.Decorate(\n          options.dataAdapter,\n          MaximumSelectionLength\n        );\n      }\n\n      if (options.tags) {\n        options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);\n      }\n\n      if (options.tokenSeparators != null || options.tokenizer != null) {\n        options.dataAdapter = Utils.Decorate(\n          options.dataAdapter,\n          Tokenizer\n        );\n      }\n\n      if (options.query != null) {\n        var Query = require(options.amdBase + 'compat/query');\n\n        options.dataAdapter = Utils.Decorate(\n          options.dataAdapter,\n          Query\n        );\n      }\n\n      if (options.initSelection != null) {\n        var InitSelection = require(options.amdBase + 'compat/initSelection');\n\n        options.dataAdapter = Utils.Decorate(\n          options.dataAdapter,\n          InitSelection\n        );\n      }\n    }\n\n    if (options.resultsAdapter == null) {\n      options.resultsAdapter = ResultsList;\n\n      if (options.ajax != null) {\n        options.resultsAdapter = Utils.Decorate(\n          options.resultsAdapter,\n          InfiniteScroll\n        );\n      }\n\n      if (options.placeholder != null) {\n        options.resultsAdapter = Utils.Decorate(\n          options.resultsAdapter,\n          HidePlaceholder\n        );\n      }\n\n      if (options.selectOnClose) {\n        options.resultsAdapter = Utils.Decorate(\n          options.resultsAdapter,\n          SelectOnClose\n        );\n      }\n    }\n\n    if (options.dropdownAdapter == null) {\n      if (options.multiple) {\n        options.dropdownAdapter = Dropdown;\n      } else {\n        var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);\n\n        options.dropdownAdapter = SearchableDropdown;\n      }\n\n      if (options.minimumResultsForSearch !== 0) {\n        options.dropdownAdapter = Utils.Decorate(\n          options.dropdownAdapter,\n          MinimumResultsForSearch\n        );\n      }\n\n      if (options.closeOnSelect) {\n        options.dropdownAdapter = Utils.Decorate(\n          options.dropdownAdapter,\n          CloseOnSelect\n        );\n      }\n\n      if (\n        options.dropdownCssClass != null ||\n        options.dropdownCss != null ||\n        options.adaptDropdownCssClass != null\n      ) {\n        var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');\n\n        options.dropdownAdapter = Utils.Decorate(\n          options.dropdownAdapter,\n          DropdownCSS\n        );\n      }\n\n      options.dropdownAdapter = Utils.Decorate(\n        options.dropdownAdapter,\n        AttachBody\n      );\n    }\n\n    if (options.selectionAdapter == null) {\n      if (options.multiple) {\n        options.selectionAdapter = MultipleSelection;\n      } else {\n        options.selectionAdapter = SingleSelection;\n      }\n\n      // Add the placeholder mixin if a placeholder was specified\n      if (options.placeholder != null) {\n        options.selectionAdapter = Utils.Decorate(\n          options.selectionAdapter,\n          Placeholder\n        );\n      }\n\n      if (options.allowClear) {\n        options.selectionAdapter = Utils.Decorate(\n          options.selectionAdapter,\n          AllowClear\n        );\n      }\n\n      if (options.multiple) {\n        options.selectionAdapter = Utils.Decorate(\n          options.selectionAdapter,\n          SelectionSearch\n        );\n      }\n\n      if (\n        options.containerCssClass != null ||\n        options.containerCss != null ||\n        options.adaptContainerCssClass != null\n      ) {\n        var ContainerCSS = require(options.amdBase + 'compat/containerCss');\n\n        options.selectionAdapter = Utils.Decorate(\n          options.selectionAdapter,\n          ContainerCSS\n        );\n      }\n\n      options.selectionAdapter = Utils.Decorate(\n        options.selectionAdapter,\n        EventRelay\n      );\n    }\n\n    if (typeof options.language === 'string') {\n      // Check if the language is specified with a region\n      if (options.language.indexOf('-') > 0) {\n        // Extract the region information if it is included\n        var languageParts = options.language.split('-');\n        var baseLanguage = languageParts[0];\n\n        options.language = [options.language, baseLanguage];\n      } else {\n        options.language = [options.language];\n      }\n    }\n\n    if ($.isArray(options.language)) {\n      var languages = new Translation();\n      options.language.push('en');\n\n      var languageNames = options.language;\n\n      for (var l = 0; l < languageNames.length; l++) {\n        var name = languageNames[l];\n        var language = {};\n\n        try {\n          // Try to load it with the original name\n          language = Translation.loadPath(name);\n        } catch (e) {\n          try {\n            // If we couldn't load it, check if it wasn't the full path\n            name = this.defaults.amdLanguageBase + name;\n            language = Translation.loadPath(name);\n          } catch (ex) {\n            // The translation could not be loaded at all. Sometimes this is\n            // because of a configuration problem, other times this can be\n            // because of how Select2 helps load all possible translation files.\n            if (options.debug && window.console && console.warn) {\n              console.warn(\n                'Select2: The language file for \"' + name + '\" could not be ' +\n                'automatically loaded. A fallback will be used instead.'\n              );\n            }\n\n            continue;\n          }\n        }\n\n        languages.extend(language);\n      }\n\n      options.translations = languages;\n    } else {\n      var baseTranslation = Translation.loadPath(\n        this.defaults.amdLanguageBase + 'en'\n      );\n      var customTranslation = new Translation(options.language);\n\n      customTranslation.extend(baseTranslation);\n\n      options.translations = customTranslation;\n    }\n\n    return options;\n  };\n\n  Defaults.prototype.reset = function () {\n    function stripDiacritics (text) {\n      // Used 'uni range + named function' from http://jsperf.com/diacritics/18\n      function match(a) {\n        return DIACRITICS[a] || a;\n      }\n\n      return text.replace(/[^\\u0000-\\u007E]/g, match);\n    }\n\n    function matcher (params, data) {\n      // Always return the object if there is nothing to compare\n      if ($.trim(params.term) === '') {\n        return data;\n      }\n\n      // Do a recursive check for options with children\n      if (data.children && data.children.length > 0) {\n        // Clone the data object if there are children\n        // This is required as we modify the object to remove any non-matches\n        var match = $.extend(true, {}, data);\n\n        // Check each child of the option\n        for (var c = data.children.length - 1; c >= 0; c--) {\n          var child = data.children[c];\n\n          var matches = matcher(params, child);\n\n          // If there wasn't a match, remove the object in the array\n          if (matches == null) {\n            match.children.splice(c, 1);\n          }\n        }\n\n        // If any children matched, return the new object\n        if (match.children.length > 0) {\n          return match;\n        }\n\n        // If there were no matching children, check just the plain object\n        return matcher(params, match);\n      }\n\n      var original = stripDiacritics(data.text).toUpperCase();\n      var term = stripDiacritics(params.term).toUpperCase();\n\n      // Check if the text contains the term\n      if (original.indexOf(term) > -1) {\n        return data;\n      }\n\n      // If it doesn't contain the term, don't return anything\n      return null;\n    }\n\n    this.defaults = {\n      amdBase: './',\n      amdLanguageBase: './i18n/',\n      closeOnSelect: true,\n      debug: false,\n      dropdownAutoWidth: false,\n      escapeMarkup: Utils.escapeMarkup,\n      language: EnglishTranslation,\n      matcher: matcher,\n      minimumInputLength: 0,\n      maximumInputLength: 0,\n      maximumSelectionLength: 0,\n      minimumResultsForSearch: 0,\n      selectOnClose: false,\n      sorter: function (data) {\n        return data;\n      },\n      templateResult: function (result) {\n        return result.text;\n      },\n      templateSelection: function (selection) {\n        return selection.text;\n      },\n      theme: 'default',\n      width: 'resolve'\n    };\n  };\n\n  Defaults.prototype.set = function (key, value) {\n    var camelKey = $.camelCase(key);\n\n    var data = {};\n    data[camelKey] = value;\n\n    var convertedData = Utils._convertData(data);\n\n    $.extend(this.defaults, convertedData);\n  };\n\n  var defaults = new Defaults();\n\n  return defaults;\n});\n\nS2.define('select2/options',[\n  'require',\n  'jquery',\n  './defaults',\n  './utils'\n], function (require, $, Defaults, Utils) {\n  function Options (options, $element) {\n    this.options = options;\n\n    if ($element != null) {\n      this.fromElement($element);\n    }\n\n    this.options = Defaults.apply(this.options);\n\n    if ($element && $element.is('input')) {\n      var InputCompat = require(this.get('amdBase') + 'compat/inputData');\n\n      this.options.dataAdapter = Utils.Decorate(\n        this.options.dataAdapter,\n        InputCompat\n      );\n    }\n  }\n\n  Options.prototype.fromElement = function ($e) {\n    var excludedData = ['select2'];\n\n    if (this.options.multiple == null) {\n      this.options.multiple = $e.prop('multiple');\n    }\n\n    if (this.options.disabled == null) {\n      this.options.disabled = $e.prop('disabled');\n    }\n\n    if (this.options.language == null) {\n      if ($e.prop('lang')) {\n        this.options.language = $e.prop('lang').toLowerCase();\n      } else if ($e.closest('[lang]').prop('lang')) {\n        this.options.language = $e.closest('[lang]').prop('lang');\n      }\n    }\n\n    if (this.options.dir == null) {\n      if ($e.prop('dir')) {\n        this.options.dir = $e.prop('dir');\n      } else if ($e.closest('[dir]').prop('dir')) {\n        this.options.dir = $e.closest('[dir]').prop('dir');\n      } else {\n        this.options.dir = 'ltr';\n      }\n    }\n\n    $e.prop('disabled', this.options.disabled);\n    $e.prop('multiple', this.options.multiple);\n\n    if ($e.data('select2Tags')) {\n      if (this.options.debug && window.console && console.warn) {\n        console.warn(\n          'Select2: The `data-select2-tags` attribute has been changed to ' +\n          'use the `data-data` and `data-tags=\"true\"` attributes and will be ' +\n          'removed in future versions of Select2.'\n        );\n      }\n\n      $e.data('data', $e.data('select2Tags'));\n      $e.data('tags', true);\n    }\n\n    if ($e.data('ajaxUrl')) {\n      if (this.options.debug && window.console && console.warn) {\n        console.warn(\n          'Select2: The `data-ajax-url` attribute has been changed to ' +\n          '`data-ajax--url` and support for the old attribute will be removed' +\n          ' in future versions of Select2.'\n        );\n      }\n\n      $e.attr('ajax--url', $e.data('ajaxUrl'));\n      $e.data('ajax--url', $e.data('ajaxUrl'));\n    }\n\n    var dataset = {};\n\n    // Prefer the element's `dataset` attribute if it exists\n    // jQuery 1.x does not correctly handle data attributes with multiple dashes\n    if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {\n      dataset = $.extend(true, {}, $e[0].dataset, $e.data());\n    } else {\n      dataset = $e.data();\n    }\n\n    var data = $.extend(true, {}, dataset);\n\n    data = Utils._convertData(data);\n\n    for (var key in data) {\n      if ($.inArray(key, excludedData) > -1) {\n        continue;\n      }\n\n      if ($.isPlainObject(this.options[key])) {\n        $.extend(this.options[key], data[key]);\n      } else {\n        this.options[key] = data[key];\n      }\n    }\n\n    return this;\n  };\n\n  Options.prototype.get = function (key) {\n    return this.options[key];\n  };\n\n  Options.prototype.set = function (key, val) {\n    this.options[key] = val;\n  };\n\n  return Options;\n});\n\nS2.define('select2/core',[\n  'jquery',\n  './options',\n  './utils',\n  './keys'\n], function ($, Options, Utils, KEYS) {\n  var Select2 = function ($element, options) {\n    if ($element.data('select2') != null) {\n      $element.data('select2').destroy();\n    }\n\n    this.$element = $element;\n\n    this.id = this._generateId($element);\n\n    options = options || {};\n\n    this.options = new Options(options, $element);\n\n    Select2.__super__.constructor.call(this);\n\n    // Set up the tabindex\n\n    var tabindex = $element.attr('tabindex') || 0;\n    $element.data('old-tabindex', tabindex);\n    $element.attr('tabindex', '-1');\n\n    // Set up containers and adapters\n\n    var DataAdapter = this.options.get('dataAdapter');\n    this.dataAdapter = new DataAdapter($element, this.options);\n\n    var $container = this.render();\n\n    this._placeContainer($container);\n\n    var SelectionAdapter = this.options.get('selectionAdapter');\n    this.selection = new SelectionAdapter($element, this.options);\n    this.$selection = this.selection.render();\n\n    this.selection.position(this.$selection, $container);\n\n    var DropdownAdapter = this.options.get('dropdownAdapter');\n    this.dropdown = new DropdownAdapter($element, this.options);\n    this.$dropdown = this.dropdown.render();\n\n    this.dropdown.position(this.$dropdown, $container);\n\n    var ResultsAdapter = this.options.get('resultsAdapter');\n    this.results = new ResultsAdapter($element, this.options, this.dataAdapter);\n    this.$results = this.results.render();\n\n    this.results.position(this.$results, this.$dropdown);\n\n    // Bind events\n\n    var self = this;\n\n    // Bind the container to all of the adapters\n    this._bindAdapters();\n\n    // Register any DOM event handlers\n    this._registerDomEvents();\n\n    // Register any internal event handlers\n    this._registerDataEvents();\n    this._registerSelectionEvents();\n    this._registerDropdownEvents();\n    this._registerResultsEvents();\n    this._registerEvents();\n\n    // Set the initial state\n    this.dataAdapter.current(function (initialData) {\n      self.trigger('selection:update', {\n        data: initialData\n      });\n    });\n\n    // Hide the original select\n    $element.addClass('select2-hidden-accessible');\n\t$element.attr('aria-hidden', 'true');\n\t\n    // Synchronize any monitored attributes\n    this._syncAttributes();\n\n    $element.data('select2', this);\n  };\n\n  Utils.Extend(Select2, Utils.Observable);\n\n  Select2.prototype._generateId = function ($element) {\n    var id = '';\n\n    if ($element.attr('id') != null) {\n      id = $element.attr('id');\n    } else if ($element.attr('name') != null) {\n      id = $element.attr('name') + '-' + Utils.generateChars(2);\n    } else {\n      id = Utils.generateChars(4);\n    }\n\n    id = 'select2-' + id;\n\n    return id;\n  };\n\n  Select2.prototype._placeContainer = function ($container) {\n    $container.insertAfter(this.$element);\n\n    var width = this._resolveWidth(this.$element, this.options.get('width'));\n\n    if (width != null) {\n      $container.css('width', width);\n    }\n  };\n\n  Select2.prototype._resolveWidth = function ($element, method) {\n    var WIDTH = /^width:(([-+]?([0-9]*\\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;\n\n    if (method == 'resolve') {\n      var styleWidth = this._resolveWidth($element, 'style');\n\n      if (styleWidth != null) {\n        return styleWidth;\n      }\n\n      return this._resolveWidth($element, 'element');\n    }\n\n    if (method == 'element') {\n      var elementWidth = $element.outerWidth(false);\n\n      if (elementWidth <= 0) {\n        return 'auto';\n      }\n\n      return elementWidth + 'px';\n    }\n\n    if (method == 'style') {\n      var style = $element.attr('style');\n\n      if (typeof(style) !== 'string') {\n        return null;\n      }\n\n      var attrs = style.split(';');\n\n      for (var i = 0, l = attrs.length; i < l; i = i + 1) {\n        var attr = attrs[i].replace(/\\s/g, '');\n        var matches = attr.match(WIDTH);\n\n        if (matches !== null && matches.length >= 1) {\n          return matches[1];\n        }\n      }\n\n      return null;\n    }\n\n    return method;\n  };\n\n  Select2.prototype._bindAdapters = function () {\n    this.dataAdapter.bind(this, this.$container);\n    this.selection.bind(this, this.$container);\n\n    this.dropdown.bind(this, this.$container);\n    this.results.bind(this, this.$container);\n  };\n\n  Select2.prototype._registerDomEvents = function () {\n    var self = this;\n\n    this.$element.on('change.select2', function () {\n      self.dataAdapter.current(function (data) {\n        self.trigger('selection:update', {\n          data: data\n        });\n      });\n    });\n\n    this._sync = Utils.bind(this._syncAttributes, this);\n\n    if (this.$element[0].attachEvent) {\n      this.$element[0].attachEvent('onpropertychange', this._sync);\n    }\n\n    var observer = window.MutationObserver ||\n      window.WebKitMutationObserver ||\n      window.MozMutationObserver\n    ;\n\n    if (observer != null) {\n      this._observer = new observer(function (mutations) {\n        $.each(mutations, self._sync);\n      });\n      this._observer.observe(this.$element[0], {\n        attributes: true,\n        subtree: false\n      });\n    } else if (this.$element[0].addEventListener) {\n      this.$element[0].addEventListener('DOMAttrModified', self._sync, false);\n    }\n  };\n\n  Select2.prototype._registerDataEvents = function () {\n    var self = this;\n\n    this.dataAdapter.on('*', function (name, params) {\n      self.trigger(name, params);\n    });\n  };\n\n  Select2.prototype._registerSelectionEvents = function () {\n    var self = this;\n    var nonRelayEvents = ['toggle'];\n\n    this.selection.on('toggle', function () {\n      self.toggleDropdown();\n    });\n\n    this.selection.on('*', function (name, params) {\n      if ($.inArray(name, nonRelayEvents) !== -1) {\n        return;\n      }\n\n      self.trigger(name, params);\n    });\n  };\n\n  Select2.prototype._registerDropdownEvents = function () {\n    var self = this;\n\n    this.dropdown.on('*', function (name, params) {\n      self.trigger(name, params);\n    });\n  };\n\n  Select2.prototype._registerResultsEvents = function () {\n    var self = this;\n\n    this.results.on('*', function (name, params) {\n      self.trigger(name, params);\n    });\n  };\n\n  Select2.prototype._registerEvents = function () {\n    var self = this;\n\n    this.on('open', function () {\n      self.$container.addClass('select2-container--open');\n    });\n\n    this.on('close', function () {\n      self.$container.removeClass('select2-container--open');\n    });\n\n    this.on('enable', function () {\n      self.$container.removeClass('select2-container--disabled');\n    });\n\n    this.on('disable', function () {\n      self.$container.addClass('select2-container--disabled');\n    });\n\n    this.on('focus', function () {\n      self.$container.addClass('select2-container--focus');\n    });\n\n    this.on('blur', function () {\n      self.$container.removeClass('select2-container--focus');\n    });\n\n    this.on('query', function (params) {\n      if (!self.isOpen()) {\n        self.trigger('open');\n      }\n\n      this.dataAdapter.query(params, function (data) {\n        self.trigger('results:all', {\n          data: data,\n          query: params\n        });\n      });\n    });\n\n    this.on('query:append', function (params) {\n      this.dataAdapter.query(params, function (data) {\n        self.trigger('results:append', {\n          data: data,\n          query: params\n        });\n      });\n    });\n\n    this.on('keypress', function (evt) {\n      var key = evt.which;\n\n      if (self.isOpen()) {\n        if (key === KEYS.ENTER) {\n          self.trigger('results:select');\n\n          evt.preventDefault();\n        } else if ((key === KEYS.SPACE && evt.ctrlKey)) {\n          self.trigger('results:toggle');\n\n          evt.preventDefault();\n        } else if (key === KEYS.UP) {\n          self.trigger('results:previous');\n\n          evt.preventDefault();\n        } else if (key === KEYS.DOWN) {\n          self.trigger('results:next');\n\n          evt.preventDefault();\n        } else if (key === KEYS.ESC || key === KEYS.TAB) {\n          self.close();\n\n          evt.preventDefault();\n        }\n      } else {\n        if (key === KEYS.ENTER || key === KEYS.SPACE ||\n            ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {\n          self.open();\n\n          evt.preventDefault();\n        }\n      }\n    });\n  };\n\n  Select2.prototype._syncAttributes = function () {\n    this.options.set('disabled', this.$element.prop('disabled'));\n\n    if (this.options.get('disabled')) {\n      if (this.isOpen()) {\n        this.close();\n      }\n\n      this.trigger('disable');\n    } else {\n      this.trigger('enable');\n    }\n  };\n\n  /**\n   * Override the trigger method to automatically trigger pre-events when\n   * there are events that can be prevented.\n   */\n  Select2.prototype.trigger = function (name, args) {\n    var actualTrigger = Select2.__super__.trigger;\n    var preTriggerMap = {\n      'open': 'opening',\n      'close': 'closing',\n      'select': 'selecting',\n      'unselect': 'unselecting'\n    };\n\n    if (name in preTriggerMap) {\n      var preTriggerName = preTriggerMap[name];\n      var preTriggerArgs = {\n        prevented: false,\n        name: name,\n        args: args\n      };\n\n      actualTrigger.call(this, preTriggerName, preTriggerArgs);\n\n      if (preTriggerArgs.prevented) {\n        args.prevented = true;\n\n        return;\n      }\n    }\n\n    actualTrigger.call(this, name, args);\n  };\n\n  Select2.prototype.toggleDropdown = function () {\n    if (this.options.get('disabled')) {\n      return;\n    }\n\n    if (this.isOpen()) {\n      this.close();\n    } else {\n      this.open();\n    }\n  };\n\n  Select2.prototype.open = function () {\n    if (this.isOpen()) {\n      return;\n    }\n\n    this.trigger('query', {});\n\n    this.trigger('open');\n  };\n\n  Select2.prototype.close = function () {\n    if (!this.isOpen()) {\n      return;\n    }\n\n    this.trigger('close');\n  };\n\n  Select2.prototype.isOpen = function () {\n    return this.$container.hasClass('select2-container--open');\n  };\n\n  Select2.prototype.enable = function (args) {\n    if (this.options.get('debug') && window.console && console.warn) {\n      console.warn(\n        'Select2: The `select2(\"enable\")` method has been deprecated and will' +\n        ' be removed in later Select2 versions. Use $element.prop(\"disabled\")' +\n        ' instead.'\n      );\n    }\n\n    if (args == null || args.length === 0) {\n      args = [true];\n    }\n\n    var disabled = !args[0];\n\n    this.$element.prop('disabled', disabled);\n  };\n\n  Select2.prototype.data = function () {\n    if (this.options.get('debug') &&\n        arguments.length > 0 && window.console && console.warn) {\n      console.warn(\n        'Select2: Data can no longer be set using `select2(\"data\")`. You ' +\n        'should consider setting the value instead using `$element.val()`.'\n      );\n    }\n\n    var data = [];\n\n    this.dataAdapter.current(function (currentData) {\n      data = currentData;\n    });\n\n    return data;\n  };\n\n  Select2.prototype.val = function (args) {\n    if (this.options.get('debug') && window.console && console.warn) {\n      console.warn(\n        'Select2: The `select2(\"val\")` method has been deprecated and will be' +\n        ' removed in later Select2 versions. Use $element.val() instead.'\n      );\n    }\n\n    if (args == null || args.length === 0) {\n      return this.$element.val();\n    }\n\n    var newVal = args[0];\n\n    if ($.isArray(newVal)) {\n      newVal = $.map(newVal, function (obj) {\n        return obj.toString();\n      });\n    }\n\n    this.$element.val(newVal).trigger('change');\n  };\n\n  Select2.prototype.destroy = function () {\n    this.$container.remove();\n\n    if (this.$element[0].detachEvent) {\n      this.$element[0].detachEvent('onpropertychange', this._sync);\n    }\n\n    if (this._observer != null) {\n      this._observer.disconnect();\n      this._observer = null;\n    } else if (this.$element[0].removeEventListener) {\n      this.$element[0]\n        .removeEventListener('DOMAttrModified', this._sync, false);\n    }\n\n    this._sync = null;\n\n    this.$element.off('.select2');\n    this.$element.attr('tabindex', this.$element.data('old-tabindex'));\n\n    this.$element.removeClass('select2-hidden-accessible');\n\tthis.$element.attr('aria-hidden', 'false');\n    this.$element.removeData('select2');\n\n    this.dataAdapter.destroy();\n    this.selection.destroy();\n    this.dropdown.destroy();\n    this.results.destroy();\n\n    this.dataAdapter = null;\n    this.selection = null;\n    this.dropdown = null;\n    this.results = null;\n  };\n\n  Select2.prototype.render = function () {\n    var $container = $(\n      '<span class=\"select2 select2-container\">' +\n        '<span class=\"selection\"></span>' +\n        '<span class=\"dropdown-wrapper\" aria-hidden=\"true\"></span>' +\n      '</span>'\n    );\n\n    $container.attr('dir', this.options.get('dir'));\n\n    this.$container = $container;\n\n    this.$container.addClass('select2-container--' + this.options.get('theme'));\n\n    $container.data('element', this.$element);\n\n    return $container;\n  };\n\n  return Select2;\n});\n\nS2.define('jquery.select2',[\n  'jquery',\n  'require',\n\n  './select2/core',\n  './select2/defaults'\n], function ($, require, Select2, Defaults) {\n  // Force jQuery.mousewheel to be loaded if it hasn't already\n  require('jquery.mousewheel');\n\n  if ($.fn.select2 == null) {\n    // All methods that should return the element\n    var thisMethods = ['open', 'close', 'destroy'];\n\n    $.fn.select2 = function (options) {\n      options = options || {};\n\n      if (typeof options === 'object') {\n        this.each(function () {\n          var instanceOptions = $.extend({}, options, true);\n\n          var instance = new Select2($(this), instanceOptions);\n        });\n\n        return this;\n      } else if (typeof options === 'string') {\n        var instance = this.data('select2');\n\n        if (instance == null && window.console && console.error) {\n          console.error(\n            'The select2(\\'' + options + '\\') method was called on an ' +\n            'element that is not using Select2.'\n          );\n        }\n\n        var args = Array.prototype.slice.call(arguments, 1);\n\n        var ret = instance[options](args);\n\n        // Check if we should be returning `this`\n        if ($.inArray(options, thisMethods) > -1) {\n          return this;\n        }\n\n        return ret;\n      } else {\n        throw new Error('Invalid arguments for Select2: ' + options);\n      }\n    };\n  }\n\n  if ($.fn.select2.defaults == null) {\n    $.fn.select2.defaults = Defaults;\n  }\n\n  return Select2;\n});\n\nS2.define('jquery.mousewheel',[\n  'jquery'\n], function ($) {\n  // Used to shim jQuery.mousewheel for non-full builds.\n  return $;\n});\n\n  // Return the AMD loader configuration so it can be used outside of this file\n  return {\n    define: S2.define,\n    require: S2.require\n  };\n}());\n\n  // Autoload the jQuery bindings\n  // We know that all of the modules exist above this, so we're safe\n  var select2 = S2.require('jquery.select2');\n\n  // Hold the AMD module references on the jQuery function that was just loaded\n  // This allows Select2 to use the internal loader outside of this file, such\n  // as in the language files.\n  jQuery.fn.select2.amd = S2;\n\n  // Return the Select2 instance for anyone who is importing it.\n  return select2;\n}));\n\n\n/*\n *\n * More info at [www.dropzonejs.com](http://www.dropzonejs.com)\n *\n * Copyright (c) 2012, Matias Meno\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 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\n * THE SOFTWARE.\n *\n */\n\n(function() {\n  var Dropzone, Emitter, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without,\n    __slice = [].slice,\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\n  noop = function() {};\n\n  Emitter = (function() {\n    function Emitter() {}\n\n    Emitter.prototype.addEventListener = Emitter.prototype.on;\n\n    Emitter.prototype.on = function(event, fn) {\n      this._callbacks = this._callbacks || {};\n      if (!this._callbacks[event]) {\n        this._callbacks[event] = [];\n      }\n      this._callbacks[event].push(fn);\n      return this;\n    };\n\n    Emitter.prototype.emit = function() {\n      var args, callback, callbacks, event, _i, _len;\n      event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n      this._callbacks = this._callbacks || {};\n      callbacks = this._callbacks[event];\n      if (callbacks) {\n        for (_i = 0, _len = callbacks.length; _i < _len; _i++) {\n          callback = callbacks[_i];\n          callback.apply(this, args);\n        }\n      }\n      return this;\n    };\n\n    Emitter.prototype.removeListener = Emitter.prototype.off;\n\n    Emitter.prototype.removeAllListeners = Emitter.prototype.off;\n\n    Emitter.prototype.removeEventListener = Emitter.prototype.off;\n\n    Emitter.prototype.off = function(event, fn) {\n      var callback, callbacks, i, _i, _len;\n      if (!this._callbacks || arguments.length === 0) {\n        this._callbacks = {};\n        return this;\n      }\n      callbacks = this._callbacks[event];\n      if (!callbacks) {\n        return this;\n      }\n      if (arguments.length === 1) {\n        delete this._callbacks[event];\n        return this;\n      }\n      for (i = _i = 0, _len = callbacks.length; _i < _len; i = ++_i) {\n        callback = callbacks[i];\n        if (callback === fn) {\n          callbacks.splice(i, 1);\n          break;\n        }\n      }\n      return this;\n    };\n\n    return Emitter;\n\n  })();\n\n  Dropzone = (function(_super) {\n    var extend, resolveOption;\n\n    __extends(Dropzone, _super);\n\n    Dropzone.prototype.Emitter = Emitter;\n\n\n    /*\n    This is a list of all available events you can register on a dropzone object.\n    \n    You can register an event handler like this:\n    \n        dropzone.on(\"dragEnter\", function() { });\n     */\n\n    Dropzone.prototype.events = [\"drop\", \"dragstart\", \"dragend\", \"dragenter\", \"dragover\", \"dragleave\", \"addedfile\", \"addedfiles\", \"removedfile\", \"thumbnail\", \"error\", \"errormultiple\", \"processing\", \"processingmultiple\", \"uploadprogress\", \"totaluploadprogress\", \"sending\", \"sendingmultiple\", \"success\", \"successmultiple\", \"canceled\", \"canceledmultiple\", \"complete\", \"completemultiple\", \"reset\", \"maxfilesexceeded\", \"maxfilesreached\", \"queuecomplete\"];\n\n    Dropzone.prototype.defaultOptions = {\n      url: null,\n      method: \"post\",\n      withCredentials: false,\n      parallelUploads: 2,\n      uploadMultiple: false,\n      maxFilesize: 256,\n      paramName: \"file\",\n      createImageThumbnails: true,\n      maxThumbnailFilesize: 10,\n      thumbnailWidth: 120,\n      thumbnailHeight: 120,\n      filesizeBase: 1000,\n      maxFiles: null,\n      params: {},\n      clickable: true,\n      ignoreHiddenFiles: true,\n      acceptedFiles: null,\n      acceptedMimeTypes: null,\n      autoProcessQueue: true,\n      autoQueue: true,\n      addRemoveLinks: false,\n      previewsContainer: null,\n      hiddenInputContainer: \"body\",\n      capture: null,\n      dictDefaultMessage: \"Drop files here to upload\",\n      dictFallbackMessage: \"Your browser does not support drag'n'drop file uploads.\",\n      dictFallbackText: \"Please use the fallback form below to upload your files like in the olden days.\",\n      dictFileTooBig: \"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.\",\n      dictInvalidFileType: \"You can't upload files of this type.\",\n      dictResponseError: \"Server responded with {{statusCode}} code.\",\n      dictCancelUpload: \"Cancel upload\",\n      dictCancelUploadConfirmation: \"Are you sure you want to cancel this upload?\",\n      dictRemoveFile: \"Remove file\",\n      dictRemoveFileConfirmation: null,\n      dictMaxFilesExceeded: \"You can not upload any more files.\",\n      accept: function(file, done) {\n        return done();\n      },\n      init: function() {\n        return noop;\n      },\n      forceFallback: false,\n      fallback: function() {\n        var child, messageElement, span, _i, _len, _ref;\n        this.element.className = \"\" + this.element.className + \" dz-browser-not-supported\";\n        _ref = this.element.getElementsByTagName(\"div\");\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n          child = _ref[_i];\n          if (/(^| )dz-message($| )/.test(child.className)) {\n            messageElement = child;\n            child.className = \"dz-message\";\n            continue;\n          }\n        }\n        if (!messageElement) {\n          messageElement = Dropzone.createElement(\"<div class=\\\"dz-message\\\"><span></span></div>\");\n          this.element.appendChild(messageElement);\n        }\n        span = messageElement.getElementsByTagName(\"span\")[0];\n        if (span) {\n          if (span.textContent != null) {\n            span.textContent = this.options.dictFallbackMessage;\n          } else if (span.innerText != null) {\n            span.innerText = this.options.dictFallbackMessage;\n          }\n        }\n        return this.element.appendChild(this.getFallbackForm());\n      },\n      resize: function(file) {\n        var info, srcRatio, trgRatio;\n        info = {\n          srcX: 0,\n          srcY: 0,\n          srcWidth: file.width,\n          srcHeight: file.height\n        };\n        srcRatio = file.width / file.height;\n        info.optWidth = this.options.thumbnailWidth;\n        info.optHeight = this.options.thumbnailHeight;\n        if ((info.optWidth == null) && (info.optHeight == null)) {\n          info.optWidth = info.srcWidth;\n          info.optHeight = info.srcHeight;\n        } else if (info.optWidth == null) {\n          info.optWidth = srcRatio * info.optHeight;\n        } else if (info.optHeight == null) {\n          info.optHeight = (1 / srcRatio) * info.optWidth;\n        }\n        trgRatio = info.optWidth / info.optHeight;\n        if (file.height < info.optHeight || file.width < info.optWidth) {\n          info.trgHeight = info.srcHeight;\n          info.trgWidth = info.srcWidth;\n        } else {\n          if (srcRatio > trgRatio) {\n            info.srcHeight = file.height;\n            info.srcWidth = info.srcHeight * trgRatio;\n          } else {\n            info.srcWidth = file.width;\n            info.srcHeight = info.srcWidth / trgRatio;\n          }\n        }\n        info.srcX = (file.width - info.srcWidth) / 2;\n        info.srcY = (file.height - info.srcHeight) / 2;\n        return info;\n      },\n\n      /*\n      Those functions register themselves to the events on init and handle all\n      the user interface specific stuff. Overwriting them won't break the upload\n      but can break the way it's displayed.\n      You can overwrite them if you don't like the default behavior. If you just\n      want to add an additional event handler, register it on the dropzone object\n      and don't overwrite those options.\n       */\n      drop: function(e) {\n        return this.element.classList.remove(\"dz-drag-hover\");\n      },\n      dragstart: noop,\n      dragend: function(e) {\n        return this.element.classList.remove(\"dz-drag-hover\");\n      },\n      dragenter: function(e) {\n        return this.element.classList.add(\"dz-drag-hover\");\n      },\n      dragover: function(e) {\n        return this.element.classList.add(\"dz-drag-hover\");\n      },\n      dragleave: function(e) {\n        return this.element.classList.remove(\"dz-drag-hover\");\n      },\n      paste: noop,\n      reset: function() {\n        return this.element.classList.remove(\"dz-started\");\n      },\n      addedfile: function(file) {\n        var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;\n        if (this.element === this.previewsContainer) {\n          this.element.classList.add(\"dz-started\");\n        }\n        if (this.previewsContainer) {\n          file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());\n          file.previewTemplate = file.previewElement;\n          this.previewsContainer.appendChild(file.previewElement);\n          _ref = file.previewElement.querySelectorAll(\"[data-dz-name]\");\n          for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n            node = _ref[_i];\n            node.textContent = file.name;\n          }\n          _ref1 = file.previewElement.querySelectorAll(\"[data-dz-size]\");\n          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n            node = _ref1[_j];\n            node.innerHTML = this.filesize(file.size);\n          }\n          if (this.options.addRemoveLinks) {\n            file._removeLink = Dropzone.createElement(\"<a class=\\\"dz-remove\\\" href=\\\"javascript:undefined;\\\" data-dz-remove>\" + this.options.dictRemoveFile + \"</a>\");\n            file.previewElement.appendChild(file._removeLink);\n          }\n          removeFileEvent = (function(_this) {\n            return function(e) {\n              e.preventDefault();\n              e.stopPropagation();\n              if (file.status === Dropzone.UPLOADING) {\n                return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() {\n                  return _this.removeFile(file);\n                });\n              } else {\n                if (_this.options.dictRemoveFileConfirmation) {\n                  return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() {\n                    return _this.removeFile(file);\n                  });\n                } else {\n                  return _this.removeFile(file);\n                }\n              }\n            };\n          })(this);\n          _ref2 = file.previewElement.querySelectorAll(\"[data-dz-remove]\");\n          _results = [];\n          for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {\n            removeLink = _ref2[_k];\n            _results.push(removeLink.addEventListener(\"click\", removeFileEvent));\n          }\n          return _results;\n        }\n      },\n      removedfile: function(file) {\n        var _ref;\n        if (file.previewElement) {\n          if ((_ref = file.previewElement) != null) {\n            _ref.parentNode.removeChild(file.previewElement);\n          }\n        }\n        return this._updateMaxFilesReachedClass();\n      },\n      thumbnail: function(file, dataUrl) {\n        var thumbnailElement, _i, _len, _ref;\n        if (file.previewElement) {\n          file.previewElement.classList.remove(\"dz-file-preview\");\n          _ref = file.previewElement.querySelectorAll(\"[data-dz-thumbnail]\");\n          for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n            thumbnailElement = _ref[_i];\n            thumbnailElement.alt = file.name;\n            thumbnailElement.src = dataUrl;\n          }\n          return setTimeout(((function(_this) {\n            return function() {\n              return file.previewElement.classList.add(\"dz-image-preview\");\n            };\n          })(this)), 1);\n        }\n      },\n      error: function(file, message) {\n        var node, _i, _len, _ref, _results;\n        if (file.previewElement) {\n          file.previewElement.classList.add(\"dz-error\");\n          if (typeof message !== \"String\" && message.error) {\n            message = message.error;\n          }\n          _ref = file.previewElement.querySelectorAll(\"[data-dz-errormessage]\");\n          _results = [];\n          for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n            node = _ref[_i];\n            _results.push(node.textContent = message);\n          }\n          return _results;\n        }\n      },\n      errormultiple: noop,\n      processing: function(file) {\n        if (file.previewElement) {\n          file.previewElement.classList.add(\"dz-processing\");\n          if (file._removeLink) {\n            return file._removeLink.textContent = this.options.dictCancelUpload;\n          }\n        }\n      },\n      processingmultiple: noop,\n      uploadprogress: function(file, progress, bytesSent) {\n        var node, _i, _len, _ref, _results;\n        if (file.previewElement) {\n          _ref = file.previewElement.querySelectorAll(\"[data-dz-uploadprogress]\");\n          _results = [];\n          for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n            node = _ref[_i];\n            if (node.nodeName === 'PROGRESS') {\n              _results.push(node.value = progress);\n            } else {\n              _results.push(node.style.width = \"\" + progress + \"%\");\n            }\n          }\n          return _results;\n        }\n      },\n      totaluploadprogress: noop,\n      sending: noop,\n      sendingmultiple: noop,\n      success: function(file) {\n        if (file.previewElement) {\n          return file.previewElement.classList.add(\"dz-success\");\n        }\n      },\n      successmultiple: noop,\n      canceled: function(file) {\n        return this.emit(\"error\", file, \"Upload canceled.\");\n      },\n      canceledmultiple: noop,\n      complete: function(file) {\n        if (file._removeLink) {\n          file._removeLink.textContent = this.options.dictRemoveFile;\n        }\n        if (file.previewElement) {\n          return file.previewElement.classList.add(\"dz-complete\");\n        }\n      },\n      completemultiple: noop,\n      maxfilesexceeded: noop,\n      maxfilesreached: noop,\n      queuecomplete: noop,\n      addedfiles: noop,\n      previewTemplate: \"<div class=\\\"dz-preview dz-file-preview\\\">\\n  <div class=\\\"dz-image\\\"><img data-dz-thumbnail /></div>\\n  <div class=\\\"dz-details\\\">\\n    <div class=\\\"dz-size\\\"><span data-dz-size></span></div>\\n    <div class=\\\"dz-filename\\\"><span data-dz-name></span></div>\\n  </div>\\n  <div class=\\\"dz-progress\\\"><span class=\\\"dz-upload\\\" data-dz-uploadprogress></span></div>\\n  <div class=\\\"dz-error-message\\\"><span data-dz-errormessage></span></div>\\n  <div class=\\\"dz-success-mark\\\">\\n    <svg width=\\\"54px\\\" height=\\\"54px\\\" viewBox=\\\"0 0 54 54\\\" version=\\\"1.1\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xmlns:sketch=\\\"http://www.bohemiancoding.com/sketch/ns\\\">\\n      <title>Check</title>\\n      <defs></defs>\\n      <g id=\\\"Page-1\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" sketch:type=\\\"MSPage\\\">\\n        <path d=\\\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\\" id=\\\"Oval-2\\\" stroke-opacity=\\\"0.198794158\\\" stroke=\\\"#747474\\\" fill-opacity=\\\"0.816519475\\\" fill=\\\"#FFFFFF\\\" sketch:type=\\\"MSShapeGroup\\\"></path>\\n      </g>\\n    </svg>\\n  </div>\\n  <div class=\\\"dz-error-mark\\\">\\n    <svg width=\\\"54px\\\" height=\\\"54px\\\" viewBox=\\\"0 0 54 54\\\" version=\\\"1.1\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xmlns:sketch=\\\"http://www.bohemiancoding.com/sketch/ns\\\">\\n      <title>Error</title>\\n      <defs></defs>\\n      <g id=\\\"Page-1\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" sketch:type=\\\"MSPage\\\">\\n        <g id=\\\"Check-+-Oval-2\\\" sketch:type=\\\"MSLayerGroup\\\" stroke=\\\"#747474\\\" stroke-opacity=\\\"0.198794158\\\" fill=\\\"#FFFFFF\\\" fill-opacity=\\\"0.816519475\\\">\\n          <path d=\\\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\\" id=\\\"Oval-2\\\" sketch:type=\\\"MSShapeGroup\\\"></path>\\n        </g>\\n      </g>\\n    </svg>\\n  </div>\\n</div>\"\n    };\n\n    extend = function() {\n      var key, object, objects, target, val, _i, _len;\n      target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n      for (_i = 0, _len = objects.length; _i < _len; _i++) {\n        object = objects[_i];\n        for (key in object) {\n          val = object[key];\n          target[key] = val;\n        }\n      }\n      return target;\n    };\n\n    function Dropzone(element, options) {\n      var elementOptions, fallback, _ref;\n      this.element = element;\n      this.version = Dropzone.version;\n      this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\\n*/g, \"\");\n      this.clickableElements = [];\n      this.listeners = [];\n      this.files = [];\n      if (typeof this.element === \"string\") {\n        this.element = document.querySelector(this.element);\n      }\n      if (!(this.element && (this.element.nodeType != null))) {\n        throw new Error(\"Invalid dropzone element.\");\n      }\n      if (this.element.dropzone) {\n        throw new Error(\"Dropzone already attached.\");\n      }\n      Dropzone.instances.push(this);\n      this.element.dropzone = this;\n      elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {};\n      this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {});\n      if (this.options.forceFallback || !Dropzone.isBrowserSupported()) {\n        return this.options.fallback.call(this);\n      }\n      if (this.options.url == null) {\n        this.options.url = this.element.getAttribute(\"action\");\n      }\n      if (!this.options.url) {\n        throw new Error(\"No URL provided.\");\n      }\n      if (this.options.acceptedFiles && this.options.acceptedMimeTypes) {\n        throw new Error(\"You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.\");\n      }\n      if (this.options.acceptedMimeTypes) {\n        this.options.acceptedFiles = this.options.acceptedMimeTypes;\n        delete this.options.acceptedMimeTypes;\n      }\n      this.options.method = this.options.method.toUpperCase();\n      if ((fallback = this.getExistingFallback()) && fallback.parentNode) {\n        fallback.parentNode.removeChild(fallback);\n      }\n      if (this.options.previewsContainer !== false) {\n        if (this.options.previewsContainer) {\n          this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, \"previewsContainer\");\n        } else {\n          this.previewsContainer = this.element;\n        }\n      }\n      if (this.options.clickable) {\n        if (this.options.clickable === true) {\n          this.clickableElements = [this.element];\n        } else {\n          this.clickableElements = Dropzone.getElements(this.options.clickable, \"clickable\");\n        }\n      }\n      this.init();\n    }\n\n    Dropzone.prototype.getAcceptedFiles = function() {\n      var file, _i, _len, _ref, _results;\n      _ref = this.files;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        file = _ref[_i];\n        if (file.accepted) {\n          _results.push(file);\n        }\n      }\n      return _results;\n    };\n\n    Dropzone.prototype.getRejectedFiles = function() {\n      var file, _i, _len, _ref, _results;\n      _ref = this.files;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        file = _ref[_i];\n        if (!file.accepted) {\n          _results.push(file);\n        }\n      }\n      return _results;\n    };\n\n    Dropzone.prototype.getFilesWithStatus = function(status) {\n      var file, _i, _len, _ref, _results;\n      _ref = this.files;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        file = _ref[_i];\n        if (file.status === status) {\n          _results.push(file);\n        }\n      }\n      return _results;\n    };\n\n    Dropzone.prototype.getQueuedFiles = function() {\n      return this.getFilesWithStatus(Dropzone.QUEUED);\n    };\n\n    Dropzone.prototype.getUploadingFiles = function() {\n      return this.getFilesWithStatus(Dropzone.UPLOADING);\n    };\n\n    Dropzone.prototype.getAddedFiles = function() {\n      return this.getFilesWithStatus(Dropzone.ADDED);\n    };\n\n    Dropzone.prototype.getActiveFiles = function() {\n      var file, _i, _len, _ref, _results;\n      _ref = this.files;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        file = _ref[_i];\n        if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) {\n          _results.push(file);\n        }\n      }\n      return _results;\n    };\n\n    Dropzone.prototype.init = function() {\n      var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1;\n      if (this.element.tagName === \"form\") {\n        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n      }\n      if (this.element.classList.contains(\"dropzone\") && !this.element.querySelector(\".dz-message\")) {\n        this.element.appendChild(Dropzone.createElement(\"<div class=\\\"dz-default dz-message\\\"><span>\" + this.options.dictDefaultMessage + \"</span></div>\"));\n      }\n      if (this.clickableElements.length) {\n        setupHiddenFileInput = (function(_this) {\n          return function() {\n            if (_this.hiddenFileInput) {\n              _this.hiddenFileInput.parentNode.removeChild(_this.hiddenFileInput);\n            }\n            _this.hiddenFileInput = document.createElement(\"input\");\n            _this.hiddenFileInput.setAttribute(\"type\", \"file\");\n            if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) {\n              _this.hiddenFileInput.setAttribute(\"multiple\", \"multiple\");\n            }\n            _this.hiddenFileInput.className = \"dz-hidden-input\";\n            if (_this.options.acceptedFiles != null) {\n              _this.hiddenFileInput.setAttribute(\"accept\", _this.options.acceptedFiles);\n            }\n            if (_this.options.capture != null) {\n              _this.hiddenFileInput.setAttribute(\"capture\", _this.options.capture);\n            }\n            _this.hiddenFileInput.style.visibility = \"hidden\";\n            _this.hiddenFileInput.style.position = \"absolute\";\n            _this.hiddenFileInput.style.top = \"0\";\n            _this.hiddenFileInput.style.left = \"0\";\n            _this.hiddenFileInput.style.height = \"0\";\n            _this.hiddenFileInput.style.width = \"0\";\n            document.querySelector(_this.options.hiddenInputContainer).appendChild(_this.hiddenFileInput);\n            return _this.hiddenFileInput.addEventListener(\"change\", function() {\n              var file, files, _i, _len;\n              files = _this.hiddenFileInput.files;\n              if (files.length) {\n                for (_i = 0, _len = files.length; _i < _len; _i++) {\n                  file = files[_i];\n                  _this.addFile(file);\n                }\n              }\n              _this.emit(\"addedfiles\", files);\n              return setupHiddenFileInput();\n            });\n          };\n        })(this);\n        setupHiddenFileInput();\n      }\n      this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL;\n      _ref1 = this.events;\n      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n        eventName = _ref1[_i];\n        this.on(eventName, this.options[eventName]);\n      }\n      this.on(\"uploadprogress\", (function(_this) {\n        return function() {\n          return _this.updateTotalUploadProgress();\n        };\n      })(this));\n      this.on(\"removedfile\", (function(_this) {\n        return function() {\n          return _this.updateTotalUploadProgress();\n        };\n      })(this));\n      this.on(\"canceled\", (function(_this) {\n        return function(file) {\n          return _this.emit(\"complete\", file);\n        };\n      })(this));\n      this.on(\"complete\", (function(_this) {\n        return function(file) {\n          if (_this.getAddedFiles().length === 0 && _this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) {\n            return setTimeout((function() {\n              return _this.emit(\"queuecomplete\");\n            }), 0);\n          }\n        };\n      })(this));\n      noPropagation = function(e) {\n        e.stopPropagation();\n        if (e.preventDefault) {\n          return e.preventDefault();\n        } else {\n          return e.returnValue = false;\n        }\n      };\n      this.listeners = [\n        {\n          element: this.element,\n          events: {\n            \"dragstart\": (function(_this) {\n              return function(e) {\n                return _this.emit(\"dragstart\", e);\n              };\n            })(this),\n            \"dragenter\": (function(_this) {\n              return function(e) {\n                noPropagation(e);\n                return _this.emit(\"dragenter\", e);\n              };\n            })(this),\n            \"dragover\": (function(_this) {\n              return function(e) {\n                var efct;\n                try {\n                  efct = e.dataTransfer.effectAllowed;\n                } catch (_error) {}\n                e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';\n                noPropagation(e);\n                return _this.emit(\"dragover\", e);\n              };\n            })(this),\n            \"dragleave\": (function(_this) {\n              return function(e) {\n                return _this.emit(\"dragleave\", e);\n              };\n            })(this),\n            \"drop\": (function(_this) {\n              return function(e) {\n                noPropagation(e);\n                return _this.drop(e);\n              };\n            })(this),\n            \"dragend\": (function(_this) {\n              return function(e) {\n                return _this.emit(\"dragend\", e);\n              };\n            })(this)\n          }\n        }\n      ];\n      this.clickableElements.forEach((function(_this) {\n        return function(clickableElement) {\n          return _this.listeners.push({\n            element: clickableElement,\n            events: {\n              \"click\": function(evt) {\n                if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(\".dz-message\")))) {\n                  _this.hiddenFileInput.click();\n                }\n                return true;\n              }\n            }\n          });\n        };\n      })(this));\n      this.enable();\n      return this.options.init.call(this);\n    };\n\n    Dropzone.prototype.destroy = function() {\n      var _ref;\n      this.disable();\n      this.removeAllFiles(true);\n      if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) {\n        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);\n        this.hiddenFileInput = null;\n      }\n      delete this.element.dropzone;\n      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);\n    };\n\n    Dropzone.prototype.updateTotalUploadProgress = function() {\n      var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref;\n      totalBytesSent = 0;\n      totalBytes = 0;\n      activeFiles = this.getActiveFiles();\n      if (activeFiles.length) {\n        _ref = this.getActiveFiles();\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n          file = _ref[_i];\n          totalBytesSent += file.upload.bytesSent;\n          totalBytes += file.upload.total;\n        }\n        totalUploadProgress = 100 * totalBytesSent / totalBytes;\n      } else {\n        totalUploadProgress = 100;\n      }\n      return this.emit(\"totaluploadprogress\", totalUploadProgress, totalBytes, totalBytesSent);\n    };\n\n    Dropzone.prototype._getParamName = function(n) {\n      if (typeof this.options.paramName === \"function\") {\n        return this.options.paramName(n);\n      } else {\n        return \"\" + this.options.paramName + (this.options.uploadMultiple ? \"[\" + n + \"]\" : \"\");\n      }\n    };\n\n    Dropzone.prototype.getFallbackForm = function() {\n      var existingFallback, fields, fieldsString, form;\n      if (existingFallback = this.getExistingFallback()) {\n        return existingFallback;\n      }\n      fieldsString = \"<div class=\\\"dz-fallback\\\">\";\n      if (this.options.dictFallbackText) {\n        fieldsString += \"<p>\" + this.options.dictFallbackText + \"</p>\";\n      }\n      fieldsString += \"<input type=\\\"file\\\" name=\\\"\" + (this._getParamName(0)) + \"\\\" \" + (this.options.uploadMultiple ? 'multiple=\"multiple\"' : void 0) + \" /><input type=\\\"submit\\\" value=\\\"Upload!\\\"></div>\";\n      fields = Dropzone.createElement(fieldsString);\n      if (this.element.tagName !== \"FORM\") {\n        form = Dropzone.createElement(\"<form action=\\\"\" + this.options.url + \"\\\" enctype=\\\"multipart/form-data\\\" method=\\\"\" + this.options.method + \"\\\"></form>\");\n        form.appendChild(fields);\n      } else {\n        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n        this.element.setAttribute(\"method\", this.options.method);\n      }\n      return form != null ? form : fields;\n    };\n\n    Dropzone.prototype.getExistingFallback = function() {\n      var fallback, getFallback, tagName, _i, _len, _ref;\n      getFallback = function(elements) {\n        var el, _i, _len;\n        for (_i = 0, _len = elements.length; _i < _len; _i++) {\n          el = elements[_i];\n          if (/(^| )fallback($| )/.test(el.className)) {\n            return el;\n          }\n        }\n      };\n      _ref = [\"div\", \"form\"];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        tagName = _ref[_i];\n        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {\n          return fallback;\n        }\n      }\n    };\n\n    Dropzone.prototype.setupEventListeners = function() {\n      var elementListeners, event, listener, _i, _len, _ref, _results;\n      _ref = this.listeners;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        elementListeners = _ref[_i];\n        _results.push((function() {\n          var _ref1, _results1;\n          _ref1 = elementListeners.events;\n          _results1 = [];\n          for (event in _ref1) {\n            listener = _ref1[event];\n            _results1.push(elementListeners.element.addEventListener(event, listener, false));\n          }\n          return _results1;\n        })());\n      }\n      return _results;\n    };\n\n    Dropzone.prototype.removeEventListeners = function() {\n      var elementListeners, event, listener, _i, _len, _ref, _results;\n      _ref = this.listeners;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        elementListeners = _ref[_i];\n        _results.push((function() {\n          var _ref1, _results1;\n          _ref1 = elementListeners.events;\n          _results1 = [];\n          for (event in _ref1) {\n            listener = _ref1[event];\n            _results1.push(elementListeners.element.removeEventListener(event, listener, false));\n          }\n          return _results1;\n        })());\n      }\n      return _results;\n    };\n\n    Dropzone.prototype.disable = function() {\n      var file, _i, _len, _ref, _results;\n      this.clickableElements.forEach(function(element) {\n        return element.classList.remove(\"dz-clickable\");\n      });\n      this.removeEventListeners();\n      _ref = this.files;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        file = _ref[_i];\n        _results.push(this.cancelUpload(file));\n      }\n      return _results;\n    };\n\n    Dropzone.prototype.enable = function() {\n      this.clickableElements.forEach(function(element) {\n        return element.classList.add(\"dz-clickable\");\n      });\n      return this.setupEventListeners();\n    };\n\n    Dropzone.prototype.filesize = function(size) {\n      var cutoff, i, selectedSize, selectedUnit, unit, units, _i, _len;\n      selectedSize = 0;\n      selectedUnit = \"b\";\n      if (size > 0) {\n        units = ['TB', 'GB', 'MB', 'KB', 'b'];\n        for (i = _i = 0, _len = units.length; _i < _len; i = ++_i) {\n          unit = units[i];\n          cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;\n          if (size >= cutoff) {\n            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);\n            selectedUnit = unit;\n            break;\n          }\n        }\n        selectedSize = Math.round(10 * selectedSize) / 10;\n      }\n      return \"<strong>\" + selectedSize + \"</strong> \" + selectedUnit;\n    };\n\n    Dropzone.prototype._updateMaxFilesReachedClass = function() {\n      if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {\n        if (this.getAcceptedFiles().length === this.options.maxFiles) {\n          this.emit('maxfilesreached', this.files);\n        }\n        return this.element.classList.add(\"dz-max-files-reached\");\n      } else {\n        return this.element.classList.remove(\"dz-max-files-reached\");\n      }\n    };\n\n    Dropzone.prototype.drop = function(e) {\n      var files, items;\n      if (!e.dataTransfer) {\n        return;\n      }\n      this.emit(\"drop\", e);\n      files = e.dataTransfer.files;\n      this.emit(\"addedfiles\", files);\n      if (files.length) {\n        items = e.dataTransfer.items;\n        if (items && items.length && (items[0].webkitGetAsEntry != null)) {\n          this._addFilesFromItems(items);\n        } else {\n          this.handleFiles(files);\n        }\n      }\n    };\n\n    Dropzone.prototype.paste = function(e) {\n      var items, _ref;\n      if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) {\n        return;\n      }\n      this.emit(\"paste\", e);\n      items = e.clipboardData.items;\n      if (items.length) {\n        return this._addFilesFromItems(items);\n      }\n    };\n\n    Dropzone.prototype.handleFiles = function(files) {\n      var file, _i, _len, _results;\n      _results = [];\n      for (_i = 0, _len = files.length; _i < _len; _i++) {\n        file = files[_i];\n        _results.push(this.addFile(file));\n      }\n      return _results;\n    };\n\n    Dropzone.prototype._addFilesFromItems = function(items) {\n      var entry, item, _i, _len, _results;\n      _results = [];\n      for (_i = 0, _len = items.length; _i < _len; _i++) {\n        item = items[_i];\n        if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) {\n          if (entry.isFile) {\n            _results.push(this.addFile(item.getAsFile()));\n          } else if (entry.isDirectory) {\n            _results.push(this._addFilesFromDirectory(entry, entry.name));\n          } else {\n            _results.push(void 0);\n          }\n        } else if (item.getAsFile != null) {\n          if ((item.kind == null) || item.kind === \"file\") {\n            _results.push(this.addFile(item.getAsFile()));\n          } else {\n            _results.push(void 0);\n          }\n        } else {\n          _results.push(void 0);\n        }\n      }\n      return _results;\n    };\n\n    Dropzone.prototype._addFilesFromDirectory = function(directory, path) {\n      var dirReader, entriesReader;\n      dirReader = directory.createReader();\n      entriesReader = (function(_this) {\n        return function(entries) {\n          var entry, _i, _len;\n          for (_i = 0, _len = entries.length; _i < _len; _i++) {\n            entry = entries[_i];\n            if (entry.isFile) {\n              entry.file(function(file) {\n                if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {\n                  return;\n                }\n                file.fullPath = \"\" + path + \"/\" + file.name;\n                return _this.addFile(file);\n              });\n            } else if (entry.isDirectory) {\n              _this._addFilesFromDirectory(entry, \"\" + path + \"/\" + entry.name);\n            }\n          }\n        };\n      })(this);\n      return dirReader.readEntries(entriesReader, function(error) {\n        return typeof console !== \"undefined\" && console !== null ? typeof console.log === \"function\" ? console.log(error) : void 0 : void 0;\n      });\n    };\n\n    Dropzone.prototype.accept = function(file, done) {\n      if (file.size > this.options.maxFilesize * 1024 * 1024) {\n        return done(this.options.dictFileTooBig.replace(\"{{filesize}}\", Math.round(file.size / 1024 / 10.24) / 100).replace(\"{{maxFilesize}}\", this.options.maxFilesize));\n      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {\n        return done(this.options.dictInvalidFileType);\n      } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {\n        done(this.options.dictMaxFilesExceeded.replace(\"{{maxFiles}}\", this.options.maxFiles));\n        return this.emit(\"maxfilesexceeded\", file);\n      } else {\n        return this.options.accept.call(this, file, done);\n      }\n    };\n\n    Dropzone.prototype.addFile = function(file) {\n      file.upload = {\n        progress: 0,\n        total: file.size,\n        bytesSent: 0\n      };\n      this.files.push(file);\n      file.status = Dropzone.ADDED;\n      this.emit(\"addedfile\", file);\n      this._enqueueThumbnail(file);\n      return this.accept(file, (function(_this) {\n        return function(error) {\n          if (error) {\n            file.accepted = false;\n            _this._errorProcessing([file], error);\n          } else {\n            file.accepted = true;\n            if (_this.options.autoQueue) {\n              _this.enqueueFile(file);\n            }\n          }\n          return _this._updateMaxFilesReachedClass();\n        };\n      })(this));\n    };\n\n    Dropzone.prototype.enqueueFiles = function(files) {\n      var file, _i, _len;\n      for (_i = 0, _len = files.length; _i < _len; _i++) {\n        file = files[_i];\n        this.enqueueFile(file);\n      }\n      return null;\n    };\n\n    Dropzone.prototype.enqueueFile = function(file) {\n      if (file.status === Dropzone.ADDED && file.accepted === true) {\n        file.status = Dropzone.QUEUED;\n        if (this.options.autoProcessQueue) {\n          return setTimeout(((function(_this) {\n            return function() {\n              return _this.processQueue();\n            };\n          })(this)), 0);\n        }\n      } else {\n        throw new Error(\"This file can't be queued because it has already been processed or was rejected.\");\n      }\n    };\n\n    Dropzone.prototype._thumbnailQueue = [];\n\n    Dropzone.prototype._processingThumbnail = false;\n\n    Dropzone.prototype._enqueueThumbnail = function(file) {\n      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {\n        this._thumbnailQueue.push(file);\n        return setTimeout(((function(_this) {\n          return function() {\n            return _this._processThumbnailQueue();\n          };\n        })(this)), 0);\n      }\n    };\n\n    Dropzone.prototype._processThumbnailQueue = function() {\n      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {\n        return;\n      }\n      this._processingThumbnail = true;\n      return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) {\n        return function() {\n          _this._processingThumbnail = false;\n          return _this._processThumbnailQueue();\n        };\n      })(this));\n    };\n\n    Dropzone.prototype.removeFile = function(file) {\n      if (file.status === Dropzone.UPLOADING) {\n        this.cancelUpload(file);\n      }\n      this.files = without(this.files, file);\n      this.emit(\"removedfile\", file);\n      if (this.files.length === 0) {\n        return this.emit(\"reset\");\n      }\n    };\n\n    Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) {\n      var file, _i, _len, _ref;\n      if (cancelIfNecessary == null) {\n        cancelIfNecessary = false;\n      }\n      _ref = this.files.slice();\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        file = _ref[_i];\n        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {\n          this.removeFile(file);\n        }\n      }\n      return null;\n    };\n\n    Dropzone.prototype.createThumbnail = function(file, callback) {\n      var fileReader;\n      fileReader = new FileReader;\n      fileReader.onload = (function(_this) {\n        return function() {\n          if (file.type === \"image/svg+xml\") {\n            _this.emit(\"thumbnail\", file, fileReader.result);\n            if (callback != null) {\n              callback();\n            }\n            return;\n          }\n          return _this.createThumbnailFromUrl(file, fileReader.result, callback);\n        };\n      })(this);\n      return fileReader.readAsDataURL(file);\n    };\n\n    Dropzone.prototype.createThumbnailFromUrl = function(file, imageUrl, callback, crossOrigin) {\n      var img;\n      img = document.createElement(\"img\");\n      if (crossOrigin) {\n        img.crossOrigin = crossOrigin;\n      }\n      img.onload = (function(_this) {\n        return function() {\n          var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3;\n          file.width = img.width;\n          file.height = img.height;\n          resizeInfo = _this.options.resize.call(_this, file);\n          if (resizeInfo.trgWidth == null) {\n            resizeInfo.trgWidth = resizeInfo.optWidth;\n          }\n          if (resizeInfo.trgHeight == null) {\n            resizeInfo.trgHeight = resizeInfo.optHeight;\n          }\n          canvas = document.createElement(\"canvas\");\n          ctx = canvas.getContext(\"2d\");\n          canvas.width = resizeInfo.trgWidth;\n          canvas.height = resizeInfo.trgHeight;\n          drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);\n          thumbnail = canvas.toDataURL(\"image/png\");\n          _this.emit(\"thumbnail\", file, thumbnail);\n          if (callback != null) {\n            return callback();\n          }\n        };\n      })(this);\n      if (callback != null) {\n        img.onerror = callback;\n      }\n      return img.src = imageUrl;\n    };\n\n    Dropzone.prototype.processQueue = function() {\n      var i, parallelUploads, processingLength, queuedFiles;\n      parallelUploads = this.options.parallelUploads;\n      processingLength = this.getUploadingFiles().length;\n      i = processingLength;\n      if (processingLength >= parallelUploads) {\n        return;\n      }\n      queuedFiles = this.getQueuedFiles();\n      if (!(queuedFiles.length > 0)) {\n        return;\n      }\n      if (this.options.uploadMultiple) {\n        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));\n      } else {\n        while (i < parallelUploads) {\n          if (!queuedFiles.length) {\n            return;\n          }\n          this.processFile(queuedFiles.shift());\n          i++;\n        }\n      }\n    };\n\n    Dropzone.prototype.processFile = function(file) {\n      return this.processFiles([file]);\n    };\n\n    Dropzone.prototype.processFiles = function(files) {\n      var file, _i, _len;\n      for (_i = 0, _len = files.length; _i < _len; _i++) {\n        file = files[_i];\n        file.processing = true;\n        file.status = Dropzone.UPLOADING;\n        this.emit(\"processing\", file);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"processingmultiple\", files);\n      }\n      return this.uploadFiles(files);\n    };\n\n    Dropzone.prototype._getFilesWithXhr = function(xhr) {\n      var file, files;\n      return files = (function() {\n        var _i, _len, _ref, _results;\n        _ref = this.files;\n        _results = [];\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n          file = _ref[_i];\n          if (file.xhr === xhr) {\n            _results.push(file);\n          }\n        }\n        return _results;\n      }).call(this);\n    };\n\n    Dropzone.prototype.cancelUpload = function(file) {\n      var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref;\n      if (file.status === Dropzone.UPLOADING) {\n        groupedFiles = this._getFilesWithXhr(file.xhr);\n        for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) {\n          groupedFile = groupedFiles[_i];\n          groupedFile.status = Dropzone.CANCELED;\n        }\n        file.xhr.abort();\n        for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) {\n          groupedFile = groupedFiles[_j];\n          this.emit(\"canceled\", groupedFile);\n        }\n        if (this.options.uploadMultiple) {\n          this.emit(\"canceledmultiple\", groupedFiles);\n        }\n      } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) {\n        file.status = Dropzone.CANCELED;\n        this.emit(\"canceled\", file);\n        if (this.options.uploadMultiple) {\n          this.emit(\"canceledmultiple\", [file]);\n        }\n      }\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    };\n\n    resolveOption = function() {\n      var args, option;\n      option = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n      if (typeof option === 'function') {\n        return option.apply(this, args);\n      }\n      return option;\n    };\n\n    Dropzone.prototype.uploadFile = function(file) {\n      return this.uploadFiles([file]);\n    };\n\n    Dropzone.prototype.uploadFiles = function(files) {\n      var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, method, option, progressObj, response, updateProgress, url, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;\n      xhr = new XMLHttpRequest();\n      for (_i = 0, _len = files.length; _i < _len; _i++) {\n        file = files[_i];\n        file.xhr = xhr;\n      }\n      method = resolveOption(this.options.method, files);\n      url = resolveOption(this.options.url, files);\n      xhr.open(method, url, true);\n      xhr.withCredentials = !!this.options.withCredentials;\n      response = null;\n      handleError = (function(_this) {\n        return function() {\n          var _j, _len1, _results;\n          _results = [];\n          for (_j = 0, _len1 = files.length; _j < _len1; _j++) {\n            file = files[_j];\n            _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace(\"{{statusCode}}\", xhr.status), xhr));\n          }\n          return _results;\n        };\n      })(this);\n      updateProgress = (function(_this) {\n        return function(e) {\n          var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results;\n          if (e != null) {\n            progress = 100 * e.loaded / e.total;\n            for (_j = 0, _len1 = files.length; _j < _len1; _j++) {\n              file = files[_j];\n              file.upload = {\n                progress: progress,\n                total: e.total,\n                bytesSent: e.loaded\n              };\n            }\n          } else {\n            allFilesFinished = true;\n            progress = 100;\n            for (_k = 0, _len2 = files.length; _k < _len2; _k++) {\n              file = files[_k];\n              if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) {\n                allFilesFinished = false;\n              }\n              file.upload.progress = progress;\n              file.upload.bytesSent = file.upload.total;\n            }\n            if (allFilesFinished) {\n              return;\n            }\n          }\n          _results = [];\n          for (_l = 0, _len3 = files.length; _l < _len3; _l++) {\n            file = files[_l];\n            _results.push(_this.emit(\"uploadprogress\", file, progress, file.upload.bytesSent));\n          }\n          return _results;\n        };\n      })(this);\n      xhr.onload = (function(_this) {\n        return function(e) {\n          var _ref;\n          if (files[0].status === Dropzone.CANCELED) {\n            return;\n          }\n          if (xhr.readyState !== 4) {\n            return;\n          }\n          response = xhr.responseText;\n          if (xhr.getResponseHeader(\"content-type\") && ~xhr.getResponseHeader(\"content-type\").indexOf(\"application/json\")) {\n            try {\n              response = JSON.parse(response);\n            } catch (_error) {\n              e = _error;\n              response = \"Invalid JSON response from server.\";\n            }\n          }\n          updateProgress();\n          if (!((200 <= (_ref = xhr.status) && _ref < 300))) {\n            return handleError();\n          } else {\n            return _this._finished(files, response, e);\n          }\n        };\n      })(this);\n      xhr.onerror = (function(_this) {\n        return function() {\n          if (files[0].status === Dropzone.CANCELED) {\n            return;\n          }\n          return handleError();\n        };\n      })(this);\n      progressObj = (_ref = xhr.upload) != null ? _ref : xhr;\n      progressObj.onprogress = updateProgress;\n      headers = {\n        \"Accept\": \"application/json\",\n        \"Cache-Control\": \"no-cache\",\n        \"X-Requested-With\": \"XMLHttpRequest\"\n      };\n      if (this.options.headers) {\n        extend(headers, this.options.headers);\n      }\n      for (headerName in headers) {\n        headerValue = headers[headerName];\n        if (headerValue) {\n          xhr.setRequestHeader(headerName, headerValue);\n        }\n      }\n      formData = new FormData();\n      if (this.options.params) {\n        _ref1 = this.options.params;\n        for (key in _ref1) {\n          value = _ref1[key];\n          formData.append(key, value);\n        }\n      }\n      for (_j = 0, _len1 = files.length; _j < _len1; _j++) {\n        file = files[_j];\n        this.emit(\"sending\", file, xhr, formData);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"sendingmultiple\", files, xhr, formData);\n      }\n      if (this.element.tagName === \"FORM\") {\n        _ref2 = this.element.querySelectorAll(\"input, textarea, select, button\");\n        for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {\n          input = _ref2[_k];\n          inputName = input.getAttribute(\"name\");\n          inputType = input.getAttribute(\"type\");\n          if (input.tagName === \"SELECT\" && input.hasAttribute(\"multiple\")) {\n            _ref3 = input.options;\n            for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {\n              option = _ref3[_l];\n              if (option.selected) {\n                formData.append(inputName, option.value);\n              }\n            }\n          } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== \"checkbox\" && _ref4 !== \"radio\") || input.checked) {\n            formData.append(inputName, input.value);\n          }\n        }\n      }\n      for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) {\n        formData.append(this._getParamName(i), files[i], files[i].name);\n      }\n      return this.submitRequest(xhr, formData, files);\n    };\n\n    Dropzone.prototype.submitRequest = function(xhr, formData, files) {\n      return xhr.send(formData);\n    };\n\n    Dropzone.prototype._finished = function(files, responseText, e) {\n      var file, _i, _len;\n      for (_i = 0, _len = files.length; _i < _len; _i++) {\n        file = files[_i];\n        file.status = Dropzone.SUCCESS;\n        this.emit(\"success\", file, responseText, e);\n        this.emit(\"complete\", file);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"successmultiple\", files, responseText, e);\n        this.emit(\"completemultiple\", files);\n      }\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    };\n\n    Dropzone.prototype._errorProcessing = function(files, message, xhr) {\n      var file, _i, _len;\n      for (_i = 0, _len = files.length; _i < _len; _i++) {\n        file = files[_i];\n        file.status = Dropzone.ERROR;\n        this.emit(\"error\", file, message, xhr);\n        this.emit(\"complete\", file);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"errormultiple\", files, message, xhr);\n        this.emit(\"completemultiple\", files);\n      }\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    };\n\n    return Dropzone;\n\n  })(Emitter);\n\n  Dropzone.version = \"4.2.0\";\n\n  Dropzone.options = {};\n\n  Dropzone.optionsForElement = function(element) {\n    if (element.getAttribute(\"id\")) {\n      return Dropzone.options[camelize(element.getAttribute(\"id\"))];\n    } else {\n      return void 0;\n    }\n  };\n\n  Dropzone.instances = [];\n\n  Dropzone.forElement = function(element) {\n    if (typeof element === \"string\") {\n      element = document.querySelector(element);\n    }\n    if ((element != null ? element.dropzone : void 0) == null) {\n      throw new Error(\"No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.\");\n    }\n    return element.dropzone;\n  };\n\n  Dropzone.autoDiscover = true;\n\n  Dropzone.discover = function() {\n    var checkElements, dropzone, dropzones, _i, _len, _results;\n    if (document.querySelectorAll) {\n      dropzones = document.querySelectorAll(\".dropzone\");\n    } else {\n      dropzones = [];\n      checkElements = function(elements) {\n        var el, _i, _len, _results;\n        _results = [];\n        for (_i = 0, _len = elements.length; _i < _len; _i++) {\n          el = elements[_i];\n          if (/(^| )dropzone($| )/.test(el.className)) {\n            _results.push(dropzones.push(el));\n          } else {\n            _results.push(void 0);\n          }\n        }\n        return _results;\n      };\n      checkElements(document.getElementsByTagName(\"div\"));\n      checkElements(document.getElementsByTagName(\"form\"));\n    }\n    _results = [];\n    for (_i = 0, _len = dropzones.length; _i < _len; _i++) {\n      dropzone = dropzones[_i];\n      if (Dropzone.optionsForElement(dropzone) !== false) {\n        _results.push(new Dropzone(dropzone));\n      } else {\n        _results.push(void 0);\n      }\n    }\n    return _results;\n  };\n\n  Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\\/12/i];\n\n  Dropzone.isBrowserSupported = function() {\n    var capableBrowser, regex, _i, _len, _ref;\n    capableBrowser = true;\n    if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {\n      if (!(\"classList\" in document.createElement(\"a\"))) {\n        capableBrowser = false;\n      } else {\n        _ref = Dropzone.blacklistedBrowsers;\n        for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n          regex = _ref[_i];\n          if (regex.test(navigator.userAgent)) {\n            capableBrowser = false;\n            continue;\n          }\n        }\n      }\n    } else {\n      capableBrowser = false;\n    }\n    return capableBrowser;\n  };\n\n  without = function(list, rejectedItem) {\n    var item, _i, _len, _results;\n    _results = [];\n    for (_i = 0, _len = list.length; _i < _len; _i++) {\n      item = list[_i];\n      if (item !== rejectedItem) {\n        _results.push(item);\n      }\n    }\n    return _results;\n  };\n\n  camelize = function(str) {\n    return str.replace(/[\\-_](\\w)/g, function(match) {\n      return match.charAt(1).toUpperCase();\n    });\n  };\n\n  Dropzone.createElement = function(string) {\n    var div;\n    div = document.createElement(\"div\");\n    div.innerHTML = string;\n    return div.childNodes[0];\n  };\n\n  Dropzone.elementInside = function(element, container) {\n    if (element === container) {\n      return true;\n    }\n    while (element = element.parentNode) {\n      if (element === container) {\n        return true;\n      }\n    }\n    return false;\n  };\n\n  Dropzone.getElement = function(el, name) {\n    var element;\n    if (typeof el === \"string\") {\n      element = document.querySelector(el);\n    } else if (el.nodeType != null) {\n      element = el;\n    }\n    if (element == null) {\n      throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector or a plain HTML element.\");\n    }\n    return element;\n  };\n\n  Dropzone.getElements = function(els, name) {\n    var e, el, elements, _i, _j, _len, _len1, _ref;\n    if (els instanceof Array) {\n      elements = [];\n      try {\n        for (_i = 0, _len = els.length; _i < _len; _i++) {\n          el = els[_i];\n          elements.push(this.getElement(el, name));\n        }\n      } catch (_error) {\n        e = _error;\n        elements = null;\n      }\n    } else if (typeof els === \"string\") {\n      elements = [];\n      _ref = document.querySelectorAll(els);\n      for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {\n        el = _ref[_j];\n        elements.push(el);\n      }\n    } else if (els.nodeType != null) {\n      elements = [els];\n    }\n    if (!((elements != null) && elements.length)) {\n      throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.\");\n    }\n    return elements;\n  };\n\n  Dropzone.confirm = function(question, accepted, rejected) {\n    if (window.confirm(question)) {\n      return accepted();\n    } else if (rejected != null) {\n      return rejected();\n    }\n  };\n\n  Dropzone.isValidFile = function(file, acceptedFiles) {\n    var baseMimeType, mimeType, validType, _i, _len;\n    if (!acceptedFiles) {\n      return true;\n    }\n    acceptedFiles = acceptedFiles.split(\",\");\n    mimeType = file.type;\n    baseMimeType = mimeType.replace(/\\/.*$/, \"\");\n    for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) {\n      validType = acceptedFiles[_i];\n      validType = validType.trim();\n      if (validType.charAt(0) === \".\") {\n        if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {\n          return true;\n        }\n      } else if (/\\/\\*$/.test(validType)) {\n        if (baseMimeType === validType.replace(/\\/.*$/, \"\")) {\n          return true;\n        }\n      } else {\n        if (mimeType === validType) {\n          return true;\n        }\n      }\n    }\n    return false;\n  };\n\n  if (typeof jQuery !== \"undefined\" && jQuery !== null) {\n    jQuery.fn.dropzone = function(options) {\n      return this.each(function() {\n        return new Dropzone(this, options);\n      });\n    };\n  }\n\n  if (typeof module !== \"undefined\" && module !== null) {\n    module.exports = Dropzone;\n  } else {\n    window.Dropzone = Dropzone;\n  }\n\n  Dropzone.ADDED = \"added\";\n\n  Dropzone.QUEUED = \"queued\";\n\n  Dropzone.ACCEPTED = Dropzone.QUEUED;\n\n  Dropzone.UPLOADING = \"uploading\";\n\n  Dropzone.PROCESSING = Dropzone.UPLOADING;\n\n  Dropzone.CANCELED = \"canceled\";\n\n  Dropzone.ERROR = \"error\";\n\n  Dropzone.SUCCESS = \"success\";\n\n\n  /*\n  \n  Bugfix for iOS 6 and 7\n  Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios\n  based on the work of https://github.com/stomita/ios-imagefile-megapixel\n   */\n\n  detectVerticalSquash = function(img) {\n    var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy;\n    iw = img.naturalWidth;\n    ih = img.naturalHeight;\n    canvas = document.createElement(\"canvas\");\n    canvas.width = 1;\n    canvas.height = ih;\n    ctx = canvas.getContext(\"2d\");\n    ctx.drawImage(img, 0, 0);\n    data = ctx.getImageData(0, 0, 1, ih).data;\n    sy = 0;\n    ey = ih;\n    py = ih;\n    while (py > sy) {\n      alpha = data[(py - 1) * 4 + 3];\n      if (alpha === 0) {\n        ey = py;\n      } else {\n        sy = py;\n      }\n      py = (ey + sy) >> 1;\n    }\n    ratio = py / ih;\n    if (ratio === 0) {\n      return 1;\n    } else {\n      return ratio;\n    }\n  };\n\n  drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {\n    var vertSquashRatio;\n    vertSquashRatio = detectVerticalSquash(img);\n    return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);\n  };\n\n\n  /*\n   * contentloaded.js\n   *\n   * Author: Diego Perini (diego.perini at gmail.com)\n   * Summary: cross-browser wrapper for DOMContentLoaded\n   * Updated: 20101020\n   * License: MIT\n   * Version: 1.2\n   *\n   * URL:\n   * http://javascript.nwbox.com/ContentLoaded/\n   * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE\n   */\n\n  contentLoaded = function(win, fn) {\n    var add, doc, done, init, poll, pre, rem, root, top;\n    done = false;\n    top = true;\n    doc = win.document;\n    root = doc.documentElement;\n    add = (doc.addEventListener ? \"addEventListener\" : \"attachEvent\");\n    rem = (doc.addEventListener ? \"removeEventListener\" : \"detachEvent\");\n    pre = (doc.addEventListener ? \"\" : \"on\");\n    init = function(e) {\n      if (e.type === \"readystatechange\" && doc.readyState !== \"complete\") {\n        return;\n      }\n      (e.type === \"load\" ? win : doc)[rem](pre + e.type, init, false);\n      if (!done && (done = true)) {\n        return fn.call(win, e.type || e);\n      }\n    };\n    poll = function() {\n      var e;\n      try {\n        root.doScroll(\"left\");\n      } catch (_error) {\n        e = _error;\n        setTimeout(poll, 50);\n        return;\n      }\n      return init(\"poll\");\n    };\n    if (doc.readyState !== \"complete\") {\n      if (doc.createEventObject && root.doScroll) {\n        try {\n          top = !win.frameElement;\n        } catch (_error) {}\n        if (top) {\n          poll();\n        }\n      }\n      doc[add](pre + \"DOMContentLoaded\", init, false);\n      doc[add](pre + \"readystatechange\", init, false);\n      return win[add](pre + \"load\", init, false);\n    }\n  };\n\n  Dropzone._autoDiscoverFunction = function() {\n    if (Dropzone.autoDiscover) {\n      return Dropzone.discover();\n    }\n  };\n\n  contentLoaded(window, Dropzone._autoDiscoverFunction);\n\n}).call(this);\n\n;(function () {\n\t'use strict';\n\n\t/**\n\t * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.\n\t *\n\t * @codingstandard ftlabs-jsv2\n\t * @copyright The Financial Times Limited [All Rights Reserved]\n\t * @license MIT License (see LICENSE.txt)\n\t */\n\n\t/*jslint browser:true, node:true*/\n\t/*global define, Event, Node*/\n\n\n\t/**\n\t * Instantiate fast-clicking listeners on the specified layer.\n\t *\n\t * @constructor\n\t * @param {Element} layer The layer to listen on\n\t * @param {Object} [options={}] The options to override the defaults\n\t */\n\tfunction FastClick(layer, options) {\n\t\tvar oldOnClick;\n\n\t\toptions = options || {};\n\n\t\t/**\n\t\t * Whether a click is currently being tracked.\n\t\t *\n\t\t * @type boolean\n\t\t */\n\t\tthis.trackingClick = false;\n\n\n\t\t/**\n\t\t * Timestamp for when click tracking started.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.trackingClickStart = 0;\n\n\n\t\t/**\n\t\t * The element being tracked for a click.\n\t\t *\n\t\t * @type EventTarget\n\t\t */\n\t\tthis.targetElement = null;\n\n\n\t\t/**\n\t\t * X-coordinate of touch start event.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.touchStartX = 0;\n\n\n\t\t/**\n\t\t * Y-coordinate of touch start event.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.touchStartY = 0;\n\n\n\t\t/**\n\t\t * ID of the last touch, retrieved from Touch.identifier.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.lastTouchIdentifier = 0;\n\n\n\t\t/**\n\t\t * Touchmove boundary, beyond which a click will be cancelled.\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.touchBoundary = options.touchBoundary || 10;\n\n\n\t\t/**\n\t\t * The FastClick layer.\n\t\t *\n\t\t * @type Element\n\t\t */\n\t\tthis.layer = layer;\n\n\t\t/**\n\t\t * The minimum time between tap(touchstart and touchend) events\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.tapDelay = options.tapDelay || 200;\n\n\t\t/**\n\t\t * The maximum time for a tap\n\t\t *\n\t\t * @type number\n\t\t */\n\t\tthis.tapTimeout = options.tapTimeout || 700;\n\n\t\tif (FastClick.notNeeded(layer)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Some old versions of Android don't have Function.prototype.bind\n\t\tfunction bind(method, context) {\n\t\t\treturn function() { return method.apply(context, arguments); };\n\t\t}\n\n\n\t\tvar methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];\n\t\tvar context = this;\n\t\tfor (var i = 0, l = methods.length; i < l; i++) {\n\t\t\tcontext[methods[i]] = bind(context[methods[i]], context);\n\t\t}\n\n\t\t// Set up event handlers as required\n\t\tif (deviceIsAndroid) {\n\t\t\tlayer.addEventListener('mouseover', this.onMouse, true);\n\t\t\tlayer.addEventListener('mousedown', this.onMouse, true);\n\t\t\tlayer.addEventListener('mouseup', this.onMouse, true);\n\t\t}\n\n\t\tlayer.addEventListener('click', this.onClick, true);\n\t\tlayer.addEventListener('touchstart', this.onTouchStart, false);\n\t\tlayer.addEventListener('touchmove', this.onTouchMove, false);\n\t\tlayer.addEventListener('touchend', this.onTouchEnd, false);\n\t\tlayer.addEventListener('touchcancel', this.onTouchCancel, false);\n\n\t\t// Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)\n\t\t// which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick\n\t\t// layer when they are cancelled.\n\t\tif (!Event.prototype.stopImmediatePropagation) {\n\t\t\tlayer.removeEventListener = function(type, callback, capture) {\n\t\t\t\tvar rmv = Node.prototype.removeEventListener;\n\t\t\t\tif (type === 'click') {\n\t\t\t\t\trmv.call(layer, type, callback.hijacked || callback, capture);\n\t\t\t\t} else {\n\t\t\t\t\trmv.call(layer, type, callback, capture);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tlayer.addEventListener = function(type, callback, capture) {\n\t\t\t\tvar adv = Node.prototype.addEventListener;\n\t\t\t\tif (type === 'click') {\n\t\t\t\t\tadv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {\n\t\t\t\t\t\tif (!event.propagationStopped) {\n\t\t\t\t\t\t\tcallback(event);\n\t\t\t\t\t\t}\n\t\t\t\t\t}), capture);\n\t\t\t\t} else {\n\t\t\t\t\tadv.call(layer, type, callback, capture);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t// If a handler is already declared in the element's onclick attribute, it will be fired before\n\t\t// FastClick's onClick handler. Fix this by pulling out the user-defined handler function and\n\t\t// adding it as listener.\n\t\tif (typeof layer.onclick === 'function') {\n\n\t\t\t// Android browser on at least 3.2 requires a new reference to the function in layer.onclick\n\t\t\t// - the old one won't work if passed to addEventListener directly.\n\t\t\toldOnClick = layer.onclick;\n\t\t\tlayer.addEventListener('click', function(event) {\n\t\t\t\toldOnClick(event);\n\t\t\t}, false);\n\t\t\tlayer.onclick = null;\n\t\t}\n\t}\n\n\t/**\n\t* Windows Phone 8.1 fakes user agent string to look like Android and iPhone.\n\t*\n\t* @type boolean\n\t*/\n\tvar deviceIsWindowsPhone = navigator.userAgent.indexOf(\"Windows Phone\") >= 0;\n\n\t/**\n\t * Android requires exceptions.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;\n\n\n\t/**\n\t * iOS requires exceptions.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;\n\n\n\t/**\n\t * iOS 4 requires an exception for select elements.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsIOS4 = deviceIsIOS && (/OS 4_\\d(_\\d)?/).test(navigator.userAgent);\n\n\n\t/**\n\t * iOS 6.0-7.* requires the target element to be manually derived\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\\d/).test(navigator.userAgent);\n\n\t/**\n\t * BlackBerry requires exceptions.\n\t *\n\t * @type boolean\n\t */\n\tvar deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;\n\n\t/**\n\t * Determine whether a given element requires a native click.\n\t *\n\t * @param {EventTarget|Element} target Target DOM element\n\t * @returns {boolean} Returns true if the element needs a native click\n\t */\n\tFastClick.prototype.needsClick = function(target) {\n\t\tswitch (target.nodeName.toLowerCase()) {\n\n\t\t// Don't send a synthetic click to disabled inputs (issue #62)\n\t\tcase 'button':\n\t\tcase 'select':\n\t\tcase 'textarea':\n\t\t\tif (target.disabled) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tbreak;\n\t\tcase 'input':\n\n\t\t\t// File inputs need real clicks on iOS 6 due to a browser bug (issue #68)\n\t\t\tif ((deviceIsIOS && target.type === 'file') || target.disabled) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tbreak;\n\t\tcase 'label':\n\t\tcase 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames\n\t\tcase 'video':\n\t\t\treturn true;\n\t\t}\n\n\t\treturn (/\\bneedsclick\\b/).test(target.className);\n\t};\n\n\n\t/**\n\t * Determine whether a given element requires a call to focus to simulate click into element.\n\t *\n\t * @param {EventTarget|Element} target Target DOM element\n\t * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.\n\t */\n\tFastClick.prototype.needsFocus = function(target) {\n\t\tswitch (target.nodeName.toLowerCase()) {\n\t\tcase 'textarea':\n\t\t\treturn true;\n\t\tcase 'select':\n\t\t\treturn !deviceIsAndroid;\n\t\tcase 'input':\n\t\t\tswitch (target.type) {\n\t\t\tcase 'button':\n\t\t\tcase 'checkbox':\n\t\t\tcase 'file':\n\t\t\tcase 'image':\n\t\t\tcase 'radio':\n\t\t\tcase 'submit':\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// No point in attempting to focus disabled inputs\n\t\t\treturn !target.disabled && !target.readOnly;\n\t\tdefault:\n\t\t\treturn (/\\bneedsfocus\\b/).test(target.className);\n\t\t}\n\t};\n\n\n\t/**\n\t * Send a click event to the specified element.\n\t *\n\t * @param {EventTarget|Element} targetElement\n\t * @param {Event} event\n\t */\n\tFastClick.prototype.sendClick = function(targetElement, event) {\n\t\tvar clickEvent, touch;\n\n\t\t// On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)\n\t\tif (document.activeElement && document.activeElement !== targetElement) {\n\t\t\tdocument.activeElement.blur();\n\t\t}\n\n\t\ttouch = event.changedTouches[0];\n\n\t\t// Synthesise a click event, with an extra attribute so it can be tracked\n\t\tclickEvent = document.createEvent('MouseEvents');\n\t\tclickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);\n\t\tclickEvent.forwardedTouchEvent = true;\n\t\ttargetElement.dispatchEvent(clickEvent);\n\t};\n\n\tFastClick.prototype.determineEventType = function(targetElement) {\n\n\t\t//Issue #159: Android Chrome Select Box does not open with a synthetic click event\n\t\tif (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {\n\t\t\treturn 'mousedown';\n\t\t}\n\n\t\treturn 'click';\n\t};\n\n\n\t/**\n\t * @param {EventTarget|Element} targetElement\n\t */\n\tFastClick.prototype.focus = function(targetElement) {\n\t\tvar length;\n\n\t\t// Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.\n\t\tif (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {\n\t\t\tlength = targetElement.value.length;\n\t\t\ttargetElement.setSelectionRange(length, length);\n\t\t} else {\n\t\t\ttargetElement.focus();\n\t\t}\n\t};\n\n\n\t/**\n\t * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.\n\t *\n\t * @param {EventTarget|Element} targetElement\n\t */\n\tFastClick.prototype.updateScrollParent = function(targetElement) {\n\t\tvar scrollParent, parentElement;\n\n\t\tscrollParent = targetElement.fastClickScrollParent;\n\n\t\t// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the\n\t\t// target element was moved to another parent.\n\t\tif (!scrollParent || !scrollParent.contains(targetElement)) {\n\t\t\tparentElement = targetElement;\n\t\t\tdo {\n\t\t\t\tif (parentElement.scrollHeight > parentElement.offsetHeight) {\n\t\t\t\t\tscrollParent = parentElement;\n\t\t\t\t\ttargetElement.fastClickScrollParent = parentElement;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tparentElement = parentElement.parentElement;\n\t\t\t} while (parentElement);\n\t\t}\n\n\t\t// Always update the scroll top tracker if possible.\n\t\tif (scrollParent) {\n\t\t\tscrollParent.fastClickLastScrollTop = scrollParent.scrollTop;\n\t\t}\n\t};\n\n\n\t/**\n\t * @param {EventTarget} targetElement\n\t * @returns {Element|EventTarget}\n\t */\n\tFastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {\n\n\t\t// On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.\n\t\tif (eventTarget.nodeType === Node.TEXT_NODE) {\n\t\t\treturn eventTarget.parentNode;\n\t\t}\n\n\t\treturn eventTarget;\n\t};\n\n\n\t/**\n\t * On touch start, record the position and scroll offset.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onTouchStart = function(event) {\n\t\tvar targetElement, touch, selection;\n\n\t\t// Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).\n\t\tif (event.targetTouches.length > 1) {\n\t\t\treturn true;\n\t\t}\n\n\t\ttargetElement = this.getTargetElementFromEventTarget(event.target);\n\t\ttouch = event.targetTouches[0];\n\n\t\tif (deviceIsIOS) {\n\n\t\t\t// Only trusted events will deselect text on iOS (issue #49)\n\t\t\tselection = window.getSelection();\n\t\t\tif (selection.rangeCount && !selection.isCollapsed) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (!deviceIsIOS4) {\n\n\t\t\t\t// Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):\n\t\t\t\t// when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched\n\t\t\t\t// with the same identifier as the touch event that previously triggered the click that triggered the alert.\n\t\t\t\t// Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an\n\t\t\t\t// immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.\n\t\t\t\t// Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,\n\t\t\t\t// which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,\n\t\t\t\t// random integers, it's safe to to continue if the identifier is 0 here.\n\t\t\t\tif (touch.identifier && touch.identifier === this.lastTouchIdentifier) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tthis.lastTouchIdentifier = touch.identifier;\n\n\t\t\t\t// If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:\n\t\t\t\t// 1) the user does a fling scroll on the scrollable layer\n\t\t\t\t// 2) the user stops the fling scroll with another tap\n\t\t\t\t// then the event.target of the last 'touchend' event will be the element that was under the user's finger\n\t\t\t\t// when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check\n\t\t\t\t// is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).\n\t\t\t\tthis.updateScrollParent(targetElement);\n\t\t\t}\n\t\t}\n\n\t\tthis.trackingClick = true;\n\t\tthis.trackingClickStart = event.timeStamp;\n\t\tthis.targetElement = targetElement;\n\n\t\tthis.touchStartX = touch.pageX;\n\t\tthis.touchStartY = touch.pageY;\n\n\t\t// Prevent phantom clicks on fast double-tap (issue #36)\n\t\tif ((event.timeStamp - this.lastClickTime) < this.tapDelay) {\n\t\t\tevent.preventDefault();\n\t\t}\n\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.touchHasMoved = function(event) {\n\t\tvar touch = event.changedTouches[0], boundary = this.touchBoundary;\n\n\t\tif (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t};\n\n\n\t/**\n\t * Update the last position.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onTouchMove = function(event) {\n\t\tif (!this.trackingClick) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// If the touch has moved, cancel the click tracking\n\t\tif (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {\n\t\t\tthis.trackingClick = false;\n\t\t\tthis.targetElement = null;\n\t\t}\n\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * Attempt to find the labelled control for the given label element.\n\t *\n\t * @param {EventTarget|HTMLLabelElement} labelElement\n\t * @returns {Element|null}\n\t */\n\tFastClick.prototype.findControl = function(labelElement) {\n\n\t\t// Fast path for newer browsers supporting the HTML5 control attribute\n\t\tif (labelElement.control !== undefined) {\n\t\t\treturn labelElement.control;\n\t\t}\n\n\t\t// All browsers under test that support touch events also support the HTML5 htmlFor attribute\n\t\tif (labelElement.htmlFor) {\n\t\t\treturn document.getElementById(labelElement.htmlFor);\n\t\t}\n\n\t\t// If no for attribute exists, attempt to retrieve the first labellable descendant element\n\t\t// the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label\n\t\treturn labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');\n\t};\n\n\n\t/**\n\t * On touch end, determine whether to send a click event at once.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onTouchEnd = function(event) {\n\t\tvar forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;\n\n\t\tif (!this.trackingClick) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Prevent phantom clicks on fast double-tap (issue #36)\n\t\tif ((event.timeStamp - this.lastClickTime) < this.tapDelay) {\n\t\t\tthis.cancelNextClick = true;\n\t\t\treturn true;\n\t\t}\n\n\t\tif ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Reset to prevent wrong click cancel on input (issue #156).\n\t\tthis.cancelNextClick = false;\n\n\t\tthis.lastClickTime = event.timeStamp;\n\n\t\ttrackingClickStart = this.trackingClickStart;\n\t\tthis.trackingClick = false;\n\t\tthis.trackingClickStart = 0;\n\n\t\t// On some iOS devices, the targetElement supplied with the event is invalid if the layer\n\t\t// is performing a transition or scroll, and has to be re-detected manually. Note that\n\t\t// for this to function correctly, it must be called *after* the event target is checked!\n\t\t// See issue #57; also filed as rdar://13048589 .\n\t\tif (deviceIsIOSWithBadTarget) {\n\t\t\ttouch = event.changedTouches[0];\n\n\t\t\t// In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null\n\t\t\ttargetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;\n\t\t\ttargetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;\n\t\t}\n\n\t\ttargetTagName = targetElement.tagName.toLowerCase();\n\t\tif (targetTagName === 'label') {\n\t\t\tforElement = this.findControl(targetElement);\n\t\t\tif (forElement) {\n\t\t\t\tthis.focus(targetElement);\n\t\t\t\tif (deviceIsAndroid) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\ttargetElement = forElement;\n\t\t\t}\n\t\t} else if (this.needsFocus(targetElement)) {\n\n\t\t\t// Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.\n\t\t\t// Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).\n\t\t\tif ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {\n\t\t\t\tthis.targetElement = null;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis.focus(targetElement);\n\t\t\tthis.sendClick(targetElement, event);\n\n\t\t\t// Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.\n\t\t\t// Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)\n\t\t\tif (!deviceIsIOS || targetTagName !== 'select') {\n\t\t\t\tthis.targetElement = null;\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tif (deviceIsIOS && !deviceIsIOS4) {\n\n\t\t\t// Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled\n\t\t\t// and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).\n\t\t\tscrollParent = targetElement.fastClickScrollParent;\n\t\t\tif (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Prevent the actual click from going though - unless the target node is marked as requiring\n\t\t// real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.\n\t\tif (!this.needsClick(targetElement)) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.sendClick(targetElement, event);\n\t\t}\n\n\t\treturn false;\n\t};\n\n\n\t/**\n\t * On touch cancel, stop tracking the click.\n\t *\n\t * @returns {void}\n\t */\n\tFastClick.prototype.onTouchCancel = function() {\n\t\tthis.trackingClick = false;\n\t\tthis.targetElement = null;\n\t};\n\n\n\t/**\n\t * Determine mouse events which should be permitted.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onMouse = function(event) {\n\n\t\t// If a target element was never set (because a touch event was never fired) allow the event\n\t\tif (!this.targetElement) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (event.forwardedTouchEvent) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Programmatically generated events targeting a specific element should be permitted\n\t\tif (!event.cancelable) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Derive and check the target element to see whether the mouse event needs to be permitted;\n\t\t// unless explicitly enabled, prevent non-touch click events from triggering actions,\n\t\t// to prevent ghost/doubleclicks.\n\t\tif (!this.needsClick(this.targetElement) || this.cancelNextClick) {\n\n\t\t\t// Prevent any user-added listeners declared on FastClick element from being fired.\n\t\t\tif (event.stopImmediatePropagation) {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t} else {\n\n\t\t\t\t// Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)\n\t\t\t\tevent.propagationStopped = true;\n\t\t\t}\n\n\t\t\t// Cancel the event\n\t\t\tevent.stopPropagation();\n\t\t\tevent.preventDefault();\n\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the mouse event is permitted, return true for the action to go through.\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * On actual clicks, determine whether this is a touch-generated click, a click action occurring\n\t * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or\n\t * an actual click which should be permitted.\n\t *\n\t * @param {Event} event\n\t * @returns {boolean}\n\t */\n\tFastClick.prototype.onClick = function(event) {\n\t\tvar permitted;\n\n\t\t// It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.\n\t\tif (this.trackingClick) {\n\t\t\tthis.targetElement = null;\n\t\t\tthis.trackingClick = false;\n\t\t\treturn true;\n\t\t}\n\n\t\t// Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.\n\t\tif (event.target.type === 'submit' && event.detail === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tpermitted = this.onMouse(event);\n\n\t\t// Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.\n\t\tif (!permitted) {\n\t\t\tthis.targetElement = null;\n\t\t}\n\n\t\t// If clicks are permitted, return true for the action to go through.\n\t\treturn permitted;\n\t};\n\n\n\t/**\n\t * Remove all FastClick's event listeners.\n\t *\n\t * @returns {void}\n\t */\n\tFastClick.prototype.destroy = function() {\n\t\tvar layer = this.layer;\n\n\t\tif (deviceIsAndroid) {\n\t\t\tlayer.removeEventListener('mouseover', this.onMouse, true);\n\t\t\tlayer.removeEventListener('mousedown', this.onMouse, true);\n\t\t\tlayer.removeEventListener('mouseup', this.onMouse, true);\n\t\t}\n\n\t\tlayer.removeEventListener('click', this.onClick, true);\n\t\tlayer.removeEventListener('touchstart', this.onTouchStart, false);\n\t\tlayer.removeEventListener('touchmove', this.onTouchMove, false);\n\t\tlayer.removeEventListener('touchend', this.onTouchEnd, false);\n\t\tlayer.removeEventListener('touchcancel', this.onTouchCancel, false);\n\t};\n\n\n\t/**\n\t * Check whether FastClick is needed.\n\t *\n\t * @param {Element} layer The layer to listen on\n\t */\n\tFastClick.notNeeded = function(layer) {\n\t\tvar metaViewport;\n\t\tvar chromeVersion;\n\t\tvar blackberryVersion;\n\t\tvar firefoxVersion;\n\n\t\t// Devices that don't support touch don't need FastClick\n\t\tif (typeof window.ontouchstart === 'undefined') {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Chrome version - zero for other browsers\n\t\tchromeVersion = +(/Chrome\\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];\n\n\t\tif (chromeVersion) {\n\n\t\t\tif (deviceIsAndroid) {\n\t\t\t\tmetaViewport = document.querySelector('meta[name=viewport]');\n\n\t\t\t\tif (metaViewport) {\n\t\t\t\t\t// Chrome on Android with user-scalable=\"no\" doesn't need FastClick (issue #89)\n\t\t\t\t\tif (metaViewport.content.indexOf('user-scalable=no') !== -1) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t// Chrome 32 and above with width=device-width or less don't need FastClick\n\t\t\t\t\tif (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Chrome desktop doesn't need FastClick (issue #15)\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tif (deviceIsBlackBerry10) {\n\t\t\tblackberryVersion = navigator.userAgent.match(/Version\\/([0-9]*)\\.([0-9]*)/);\n\n\t\t\t// BlackBerry 10.3+ does not require Fastclick library.\n\t\t\t// https://github.com/ftlabs/fastclick/issues/251\n\t\t\tif (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {\n\t\t\t\tmetaViewport = document.querySelector('meta[name=viewport]');\n\n\t\t\t\tif (metaViewport) {\n\t\t\t\t\t// user-scalable=no eliminates click delay.\n\t\t\t\t\tif (metaViewport.content.indexOf('user-scalable=no') !== -1) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t// width=device-width (or less than device-width) eliminates click delay.\n\t\t\t\t\tif (document.documentElement.scrollWidth <= window.outerWidth) {\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\t// IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)\n\t\tif (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Firefox version - zero for other browsers\n\t\tfirefoxVersion = +(/Firefox\\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];\n\n\t\tif (firefoxVersion >= 27) {\n\t\t\t// Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896\n\n\t\t\tmetaViewport = document.querySelector('meta[name=viewport]');\n\t\t\tif (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version\n\t\t// http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx\n\t\tif (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t};\n\n\n\t/**\n\t * Factory method for creating a FastClick object\n\t *\n\t * @param {Element} layer The layer to listen on\n\t * @param {Object} [options={}] The options to override the defaults\n\t */\n\tFastClick.attach = function(layer, options) {\n\t\treturn new FastClick(layer, options);\n\t};\n\n\n\tif (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine(function() {\n\t\t\treturn FastClick;\n\t\t});\n\t} else if (typeof module !== 'undefined' && module.exports) {\n\t\tmodule.exports = FastClick.attach;\n\t\tmodule.exports.FastClick = FastClick;\n\t} else {\n\t\twindow.FastClick = FastClick;\n\t}\n}());\n\n/*\n *\tTabby jQuery plugin version 0.13.0\n *\n *\tTed Devito - http://web.archive.org/web/20110716201510/http://teddevito.com/demos/textarea.html\n *\n *  Now mirrored at https://github.com/alanhogan/Tabby\n *\n *\tCopyright (c) 2009 Ted Devito. Updated by Alan Hogan.\n *\n *  LICENSE (BSD 3-Clause):\n *\n *\tRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following\n *\tconditions are met:\n *\n *\t\t1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\t\t2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer\n *\t\t\tin the documentation and/or other materials provided with the distribution.\n *\t\t3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written\n *\t\t\tpermission.\n *\n *\tTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n *\tIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE\n *\tLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n *\tPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n *\tTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\n *\tOF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n */\n\n// create closure\n\n(function($) {\n\t// plugin definition\n\n\t$.fn.tabby = function(options) {\n\t\t// build main options before element iteration\n\t\tvar opts = $.extend({}, $.fn.tabby.defaults, options);\n\t\tvar pressed = $.fn.tabby.pressed;\n\n\t\t// iterate and reformat each matched element\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\n\t\t\t// build element specific options\n\t\t\tvar options = $.meta ? $.extend({}, opts, $this.data()) : opts;\n\n\t\t\t$this.bind('keydown',function (e) {\n\t\t\t\tvar kc = $.fn.tabby.catch_kc(e);\n\t\t\t\tif (16 === kc) pressed.shft = true;\n\t\t\t\t/*\n\t\t\t\tbecause both CTRL+TAB and ALT+TAB default to an event (changing tab/window) that\n\t\t\t\twill prevent js from capturing the keyup event, we'll set a timer on releasing them.\n\t\t\t\t*/\n\t\t\t\tif (17 === kc) {pressed.ctrl = true;\tsetTimeout(function(){$.fn.tabby.pressed.ctrl = false;},1000);}\n\t\t\t\tif (18 === kc) {pressed.alt = true; \tsetTimeout(function(){$.fn.tabby.pressed.alt = false;},1000);}\n\n\t\t\t\tif (9 === kc && !pressed.ctrl && !pressed.alt) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tpressed.last = kc;\tsetTimeout(function(){$.fn.tabby.pressed.last = null;},0);\n\t\t\t\t\tprocess_keypress ($(e.target).get(0), pressed.shft, options);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t}).bind('keyup',function (e) {\n\t\t\t\tif (16 === $.fn.tabby.catch_kc(e)) pressed.shft = false;\n\t\t\t}).bind('blur',function (e) { // workaround for Opera -- http://www.webdeveloper.com/forum/showthread.php?p=806588\n\t\t\t\tif (9 === pressed.last) $(e.target).one('focus',function () {pressed.last = null;}).get(0).focus();\n\t\t\t});\n\n\t\t});\n\t};\n\n\t// define and expose any extra methods\n\t$.fn.tabby.catch_kc = function(e) { return e.keyCode ? e.keyCode : e.charCode ? e.charCode : e.which; };\n\t$.fn.tabby.pressed = {shft : false, ctrl : false, alt : false, last: null};\n\n\tfunction process_keypress (o,shft,options) {\n\t\tvar scrollTo = o.scrollTop;\n\t\t//var tabString = String.fromCharCode(9);\n\n\t\t// gecko; o.setSelectionRange is only available when the text box has focus\n\t\tif (o.setSelectionRange) gecko_tab (o, shft, options);\n\n\t\t// ie; document.selection is always available\n\t\telse if (document.selection) ie_tab (o, shft, options);\n\n\t\to.scrollTop = scrollTo;\n\t}\n\n\t// plugin defaults\n\t$.fn.tabby.defaults = {tabString : String.fromCharCode(9)};\n\n\tfunction gecko_tab (o, shft, options) {\n\t\tvar ss = o.selectionStart;\n\t\tvar es = o.selectionEnd;\n\n\t\t// when there's no selection and we're just working with the caret, we'll add/remove the tabs at the caret, providing more control\n\t\tif(ss === es) {\n\t\t\t// SHIFT+TAB\n\t\t\tif (shft) {\n\t\t\t\t// check to the left of the caret first\n\t\t\t\tif (ss-options.tabString === o.value.substring(ss-options.tabString.length, ss)) {\n\t\t\t\t\to.value = o.value.substring(0, ss-options.tabString.length) + o.value.substring(ss); // put it back together omitting one character to the left\n\t\t\t\t\to.focus();\n\t\t\t\t\to.setSelectionRange(ss - options.tabString.length, ss - options.tabString.length);\n\t\t\t\t}\n\t\t\t\t// then check to the right of the caret\n\t\t\t\telse if (ss-options.tabString === o.value.substring(ss, ss + options.tabString.length)) {\n\t\t\t\t\to.value = o.value.substring(0, ss) + o.value.substring(ss + options.tabString.length); // put it back together omitting one character to the right\n\t\t\t\t\to.focus();\n\t\t\t\t\to.setSelectionRange(ss,ss);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// TAB\n\t\t\telse {\n\t\t\t\to.value = o.value.substring(0, ss) + options.tabString + o.value.substring(ss);\n\t\t\t\to.focus();\n\t\t\t\to.setSelectionRange(ss + options.tabString.length, ss + options.tabString.length);\n\t\t\t}\n\t\t}\n\t\t// selections will always add/remove tabs from the start of the line\n\t\telse {\n\t\t\twhile (ss < o.value.length && o.value.charAt(ss).match(/[ \\t]/)) ss++;\n\t\t\t// split the textarea up into lines and figure out which lines are included in the selection\n\t\t\tvar lines = o.value.split(\"\\n\");\n\t\t\tvar indices = [];\n\t\t\tvar sl = 0; // start of the line\n\t\t\tvar el = 0; // end of the line\n\t\t\tvar i = 0;\n\t\t\tfor (i in lines) {\n\t\t\t\tel = sl + lines[i].length;\n\t\t\t\tindices.push({start: sl, end: el, selected: (sl <= ss && el > ss) || (el >= es && sl < es) || (sl > ss && el < es)});\n\t\t\t\tsl = el + 1;// for \"\\n\"\n\t\t\t}\n\n\t\t\t// walk through the array of lines (indices) and add tabs where appropriate\n\t\t\tvar modifier = 0;\n\t\t\tfor (i in indices) {\n\t\t\t\tif (indices[i].selected) {\n\t\t\t\t\tvar pos = indices[i].start + modifier; // adjust for tabs already inserted/removed\n\t\t\t\t\t// SHIFT+TAB\n\t\t\t\t\tif (shft && options.tabString === o.value.substring(pos,pos+options.tabString.length)) { // only SHIFT+TAB if there's a tab at the start of the line\n\t\t\t\t\t\to.value = o.value.substring(0,pos) + o.value.substring(pos + options.tabString.length); // omit the tabstring to the right\n\t\t\t\t\t\tmodifier -= options.tabString.length;\n\t\t\t\t\t}\n\t\t\t\t\t// TAB\n\t\t\t\t\telse if (!shft) {\n\t\t\t\t\t\to.value = o.value.substring(0,pos) + options.tabString + o.value.substring(pos); // insert the tabstring\n\t\t\t\t\t\tmodifier += options.tabString.length;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\to.focus();\n\t\t\tvar ns = ss + ((modifier > 0) ? options.tabString.length : (modifier < 0) ? -options.tabString.length : 0);\n\t\t\tvar ne = es + modifier;\n\t\t\to.setSelectionRange(ns,ne);\n\t\t}\n\t}\n\n\tfunction ie_tab (o, shft, options) {\n\t\tvar range = document.selection.createRange();\n\n\t\tif (o === range.parentElement()) {\n\t\t\t// when there's no selection and we're just working with the caret, we'll add/remove the tabs at the caret, providing more control\n\t\t\tif ('' === range.text) {\n\t\t\t\t// SHIFT+TAB\n\t\t\t\tif (shft) {\n\t\t\t\t\tvar bookmark = range.getBookmark();\n\t\t\t\t\t//first try to the left by moving opening up our empty range to the left\n\t\t\t\t\trange.moveStart('character', -options.tabString.length);\n\t\t\t\t\tif (options.tabString === range.text) {\n\t\t\t\t\t\trange.text = '';\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// if that didn't work then reset the range and try opening it to the right\n\t\t\t\t\t\trange.moveToBookmark(bookmark);\n\t\t\t\t\t\trange.moveEnd('character', options.tabString.length);\n\t\t\t\t\t\tif (options.tabString === range.text)\n\t\t\t\t\t\t\trange.text = '';\n\t\t\t\t\t}\n\t\t\t\t\t// move the pointer to the start of them empty range and select it\n\t\t\t\t\trange.collapse(true);\n\t\t\t\t\trange.select();\n\t\t\t\t}\n\n\t\t\t\telse {\n\t\t\t\t\t// very simple here. just insert the tab into the range and put the pointer at the end\n\t\t\t\t\trange.text = options.tabString;\n\t\t\t\t\trange.collapse(false);\n\t\t\t\t\trange.select();\n\t\t\t\t}\n\t\t\t}\n\t\t\t// selections will always add/remove tabs from the start of the line\n\t\t\telse {\n\n\t\t\t\tvar selection_text = range.text;\n\t\t\t\tvar selection_len = selection_text.length;\n\t\t\t\tvar selection_arr = selection_text.split(\"\\r\\n\");\n\n\t\t\t\tvar before_range = document.body.createTextRange();\n\t\t\t\tbefore_range.moveToElementText(o);\n\t\t\t\tbefore_range.setEndPoint(\"EndToStart\", range);\n\t\t\t\tvar before_text = before_range.text;\n\t\t\t\tvar before_arr = before_text.split(\"\\r\\n\");\n\t\t\t\tvar before_len = before_text.length; // - before_arr.length + 1;\n\n\t\t\t\tvar after_range = document.body.createTextRange();\n\t\t\t\tafter_range.moveToElementText(o);\n\t\t\t\tafter_range.setEndPoint(\"StartToEnd\", range);\n\t\t\t\tvar after_text = after_range.text; // we can accurately calculate distance to the end because we're not worried about MSIE trimming a \\r\\n\n\n\t\t\t\tvar end_range = document.body.createTextRange();\n\t\t\t\tend_range.moveToElementText(o);\n\t\t\t\tend_range.setEndPoint(\"StartToEnd\", before_range);\n\t\t\t\tvar end_text = end_range.text; // we can accurately calculate distance to the end because we're not worried about MSIE trimming a \\r\\n\n\n\t\t\t\tvar check_html = $(o).html();\n\t\t\t\t$(\"#r3\").text(before_len + \" + \" + selection_len + \" + \" + after_text.length + \" = \" + check_html.length);\n\t\t\t\tif((before_len + end_text.length) < check_html.length) {\n\t\t\t\t\tbefore_arr.push(\"\");\n\t\t\t\t\tbefore_len += 2; // for the \\r\\n that was trimmed\n\t\t\t\t\tif (shft && options.tabString === selection_arr[0].substring(0,options.tabString.length))\n\t\t\t\t\t\tselection_arr[0] = selection_arr[0].substring(options.tabString.length);\n\t\t\t\t\telse if (!shft) selection_arr[0] = options.tabString + selection_arr[0];\n\t\t\t\t} else {\n\t\t\t\t\tif (shft && options.tabString === before_arr[before_arr.length-1].substring(0,options.tabString.length))\n\t\t\t\t\t\tbefore_arr[before_arr.length-1] = before_arr[before_arr.length-1].substring(options.tabString.length);\n\t\t\t\t\telse if (!shft) before_arr[before_arr.length-1] = options.tabString + before_arr[before_arr.length-1];\n\t\t\t\t}\n\n\t\t\t\tfor (var i = 1; i < selection_arr.length; i++) {\n\t\t\t\t\tif (shft && options.tabString === selection_arr[i].substring(0,options.tabString.length))\n\t\t\t\t\t\tselection_arr[i] = selection_arr[i].substring(options.tabString.length);\n\t\t\t\t\telse if (!shft) selection_arr[i] = options.tabString + selection_arr[i];\n\t\t\t\t}\n\n\t\t\t\tif (1 === before_arr.length && 0 === before_len) {\n\t\t\t\t\tif (shft && options.tabString === selection_arr[0].substring(0,options.tabString.length))\n\t\t\t\t\t\tselection_arr[0] = selection_arr[0].substring(options.tabString.length);\n\t\t\t\t\telse if (!shft) selection_arr[0] = options.tabString + selection_arr[0];\n\t\t\t\t}\n\n\t\t\t\tif ((before_len + selection_len + after_text.length) < check_html.length) {\n\t\t\t\t\tselection_arr.push(\"\");\n\t\t\t\t\tselection_len += 2; // for the \\r\\n that was trimmed\n\t\t\t\t}\n\n\t\t\t\tbefore_range.text = before_arr.join(\"\\r\\n\");\n\t\t\t\trange.text = selection_arr.join(\"\\r\\n\");\n\n\t\t\t\tvar new_range = document.body.createTextRange();\n\t\t\t\tnew_range.moveToElementText(o);\n\n\t\t\t\tif (0 < before_len)\tnew_range.setEndPoint(\"StartToEnd\", before_range);\n\t\t\t\telse new_range.setEndPoint(\"StartToStart\", before_range);\n\t\t\t\tnew_range.setEndPoint(\"EndToEnd\", range);\n\n\t\t\t\tnew_range.select();\n\n\t\t\t}\n\t\t}\n\t}\n\n// end of closure\n})(jQuery);\n\n/*!\n\tAutosize 3.0.14\n\tlicense: MIT\n\thttp://www.jacklmoore.com/autosize\n*/\n(function (global, factory) {\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine(['exports', 'module'], factory);\n\t} else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {\n\t\tfactory(exports, module);\n\t} else {\n\t\tvar mod = {\n\t\t\texports: {}\n\t\t};\n\t\tfactory(mod.exports, mod);\n\t\tglobal.autosize = mod.exports;\n\t}\n})(this, function (exports, module) {\n\t'use strict';\n\n\tvar set = typeof Set === 'function' ? new Set() : (function () {\n\t\tvar list = [];\n\n\t\treturn {\n\t\t\thas: function has(key) {\n\t\t\t\treturn Boolean(list.indexOf(key) > -1);\n\t\t\t},\n\t\t\tadd: function add(key) {\n\t\t\t\tlist.push(key);\n\t\t\t},\n\t\t\t'delete': function _delete(key) {\n\t\t\t\tlist.splice(list.indexOf(key), 1);\n\t\t\t} };\n\t})();\n\n\tfunction assign(ta) {\n\t\tvar _ref = arguments[1] === undefined ? {} : arguments[1];\n\n\t\tvar _ref$setOverflowX = _ref.setOverflowX;\n\t\tvar setOverflowX = _ref$setOverflowX === undefined ? true : _ref$setOverflowX;\n\t\tvar _ref$setOverflowY = _ref.setOverflowY;\n\t\tvar setOverflowY = _ref$setOverflowY === undefined ? true : _ref$setOverflowY;\n\n\t\tif (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || set.has(ta)) return;\n\n\t\tvar heightOffset = null;\n\t\tvar overflowY = null;\n\t\tvar clientWidth = ta.clientWidth;\n\n\t\tfunction init() {\n\t\t\tvar style = window.getComputedStyle(ta, null);\n\n\t\t\toverflowY = style.overflowY;\n\n\t\t\tif (style.resize === 'vertical') {\n\t\t\t\tta.style.resize = 'none';\n\t\t\t} else if (style.resize === 'both') {\n\t\t\t\tta.style.resize = 'horizontal';\n\t\t\t}\n\n\t\t\tif (style.boxSizing === 'content-box') {\n\t\t\t\theightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));\n\t\t\t} else {\n\t\t\t\theightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);\n\t\t\t}\n\t\t\t// Fix when a textarea is not on document body and heightOffset is Not a Number\n\t\t\tif (isNaN(heightOffset)) {\n\t\t\t\theightOffset = 0;\n\t\t\t}\n\n\t\t\tupdate();\n\t\t}\n\n\t\tfunction changeOverflow(value) {\n\t\t\t{\n\t\t\t\t// Chrome/Safari-specific fix:\n\t\t\t\t// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space\n\t\t\t\t// made available by removing the scrollbar. The following forces the necessary text reflow.\n\t\t\t\tvar width = ta.style.width;\n\t\t\t\tta.style.width = '0px';\n\t\t\t\t// Force reflow:\n\t\t\t\t/* jshint ignore:start */\n\t\t\t\tta.offsetWidth;\n\t\t\t\t/* jshint ignore:end */\n\t\t\t\tta.style.width = width;\n\t\t\t}\n\n\t\t\toverflowY = value;\n\n\t\t\tif (setOverflowY) {\n\t\t\t\tta.style.overflowY = value;\n\t\t\t}\n\n\t\t\tresize();\n\t\t}\n\n\t\tfunction resize() {\n\t\t\tvar htmlTop = window.pageYOffset;\n\t\t\tvar bodyTop = document.body.scrollTop;\n\t\t\tvar originalHeight = ta.style.height;\n\n\t\t\tta.style.height = 'auto';\n\n\t\t\tvar endHeight = ta.scrollHeight + heightOffset;\n\n\t\t\tif (ta.scrollHeight === 0) {\n\t\t\t\t// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.\n\t\t\t\tta.style.height = originalHeight;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tta.style.height = endHeight + 'px';\n\n\t\t\t// used to check if an update is actually necessary on window.resize\n\t\t\tclientWidth = ta.clientWidth;\n\n\t\t\t// prevents scroll-position jumping\n\t\t\tdocument.documentElement.scrollTop = htmlTop;\n\t\t\tdocument.body.scrollTop = bodyTop;\n\t\t}\n\n\t\tfunction update() {\n\t\t\tvar startHeight = ta.style.height;\n\n\t\t\tresize();\n\n\t\t\tvar style = window.getComputedStyle(ta, null);\n\n\t\t\tif (style.height !== ta.style.height) {\n\t\t\t\tif (overflowY !== 'visible') {\n\t\t\t\t\tchangeOverflow('visible');\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (overflowY !== 'hidden') {\n\t\t\t\t\tchangeOverflow('hidden');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (startHeight !== ta.style.height) {\n\t\t\t\tvar evt = document.createEvent('Event');\n\t\t\t\tevt.initEvent('autosize:resized', true, false);\n\t\t\t\tta.dispatchEvent(evt);\n\t\t\t}\n\t\t}\n\n\t\tvar pageResize = function pageResize() {\n\t\t\tif (ta.clientWidth !== clientWidth) {\n\t\t\t\tupdate();\n\t\t\t}\n\t\t};\n\n\t\tvar destroy = (function (style) {\n\t\t\twindow.removeEventListener('resize', pageResize, false);\n\t\t\tta.removeEventListener('input', update, false);\n\t\t\tta.removeEventListener('keyup', update, false);\n\t\t\tta.removeEventListener('autosize:destroy', destroy, false);\n\t\t\tta.removeEventListener('autosize:update', update, false);\n\t\t\tset['delete'](ta);\n\n\t\t\tObject.keys(style).forEach(function (key) {\n\t\t\t\tta.style[key] = style[key];\n\t\t\t});\n\t\t}).bind(ta, {\n\t\t\theight: ta.style.height,\n\t\t\tresize: ta.style.resize,\n\t\t\toverflowY: ta.style.overflowY,\n\t\t\toverflowX: ta.style.overflowX,\n\t\t\twordWrap: ta.style.wordWrap });\n\n\t\tta.addEventListener('autosize:destroy', destroy, false);\n\n\t\t// IE9 does not fire onpropertychange or oninput for deletions,\n\t\t// so binding to onkeyup to catch most of those events.\n\t\t// There is no way that I know of to detect something like 'cut' in IE9.\n\t\tif ('onpropertychange' in ta && 'oninput' in ta) {\n\t\t\tta.addEventListener('keyup', update, false);\n\t\t}\n\n\t\twindow.addEventListener('resize', pageResize, false);\n\t\tta.addEventListener('input', update, false);\n\t\tta.addEventListener('autosize:update', update, false);\n\t\tset.add(ta);\n\n\t\tif (setOverflowX) {\n\t\t\tta.style.overflowX = 'hidden';\n\t\t\tta.style.wordWrap = 'break-word';\n\t\t}\n\n\t\tinit();\n\t}\n\n\tfunction destroy(ta) {\n\t\tif (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;\n\t\tvar evt = document.createEvent('Event');\n\t\tevt.initEvent('autosize:destroy', true, false);\n\t\tta.dispatchEvent(evt);\n\t}\n\n\tfunction update(ta) {\n\t\tif (!(ta && ta.nodeName && ta.nodeName === 'TEXTAREA')) return;\n\t\tvar evt = document.createEvent('Event');\n\t\tevt.initEvent('autosize:update', true, false);\n\t\tta.dispatchEvent(evt);\n\t}\n\n\tvar autosize = null;\n\n\t// Do nothing in Node.js environment and IE8 (or lower)\n\tif (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {\n\t\tautosize = function (el) {\n\t\t\treturn el;\n\t\t};\n\t\tautosize.destroy = function (el) {\n\t\t\treturn el;\n\t\t};\n\t\tautosize.update = function (el) {\n\t\t\treturn el;\n\t\t};\n\t} else {\n\t\tautosize = function (el, options) {\n\t\t\tif (el) {\n\t\t\t\tArray.prototype.forEach.call(el.length ? el : [el], function (x) {\n\t\t\t\t\treturn assign(x, options);\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn el;\n\t\t};\n\t\tautosize.destroy = function (el) {\n\t\t\tif (el) {\n\t\t\t\tArray.prototype.forEach.call(el.length ? el : [el], destroy);\n\t\t\t}\n\t\t\treturn el;\n\t\t};\n\t\tautosize.update = function (el) {\n\t\t\tif (el) {\n\t\t\t\tArray.prototype.forEach.call(el.length ? el : [el], update);\n\t\t\t}\n\t\t\treturn el;\n\t\t};\n\t}\n\n\tmodule.exports = autosize;\n});\n(function(factory) {\n\n  // Setup highlight.js for different environments. First is Node.js or\n  // CommonJS.\n  if(typeof exports !== 'undefined') {\n    factory(exports);\n  } else {\n    // Export hljs globally even when using AMD for cases when this script\n    // is loaded with others that may still expect a global hljs.\n    window.hljs = factory({});\n\n    // Finally register the global hljs with AMD.\n    if(typeof define === 'function' && define.amd) {\n      define('hljs', [], function() {\n        return window.hljs;\n      });\n    }\n  }\n\n}(function(hljs) {\n\n  /* Utility functions */\n\n  function escape(value) {\n    return value.replace(/&/gm, '&amp;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;');\n  }\n\n  function tag(node) {\n    return node.nodeName.toLowerCase();\n  }\n\n  function testRe(re, lexeme) {\n    var match = re && re.exec(lexeme);\n    return match && match.index == 0;\n  }\n\n  function isNotHighlighted(language) {\n    return (/^(no-?highlight|plain|text)$/i).test(language);\n  }\n\n  function blockLanguage(block) {\n    var i, match, length,\n        classes = block.className + ' ';\n\n    classes += block.parentNode ? block.parentNode.className : '';\n\n    // language-* takes precedence over non-prefixed class names\n    match = (/\\blang(?:uage)?-([\\w-]+)\\b/i).exec(classes);\n    if (match) {\n      return getLanguage(match[1]) ? match[1] : 'no-highlight';\n    }\n\n    classes = classes.split(/\\s+/);\n    for (i = 0, length = classes.length; i < length; i++) {\n      if (getLanguage(classes[i]) || isNotHighlighted(classes[i])) {\n        return classes[i];\n      }\n    }\n  }\n\n  function inherit(parent, obj) {\n    var result = {}, key;\n    for (key in parent)\n      result[key] = parent[key];\n    if (obj)\n      for (key in obj)\n        result[key] = obj[key];\n    return result;\n  }\n\n  /* Stream merging */\n\n  function nodeStream(node) {\n    var result = [];\n    (function _nodeStream(node, offset) {\n      for (var child = node.firstChild; child; child = child.nextSibling) {\n        if (child.nodeType == 3)\n          offset += child.nodeValue.length;\n        else if (child.nodeType == 1) {\n          result.push({\n            event: 'start',\n            offset: offset,\n            node: child\n          });\n          offset = _nodeStream(child, offset);\n          // Prevent void elements from having an end tag that would actually\n          // double them in the output. There are more void elements in HTML\n          // but we list only those realistically expected in code display.\n          if (!tag(child).match(/br|hr|img|input/)) {\n            result.push({\n              event: 'stop',\n              offset: offset,\n              node: child\n            });\n          }\n        }\n      }\n      return offset;\n    })(node, 0);\n    return result;\n  }\n\n  function mergeStreams(original, highlighted, value) {\n    var processed = 0;\n    var result = '';\n    var nodeStack = [];\n\n    function selectStream() {\n      if (!original.length || !highlighted.length) {\n        return original.length ? original : highlighted;\n      }\n      if (original[0].offset != highlighted[0].offset) {\n        return (original[0].offset < highlighted[0].offset) ? original : highlighted;\n      }\n\n      /*\n      To avoid starting the stream just before it should stop the order is\n      ensured that original always starts first and closes last:\n\n      if (event1 == 'start' && event2 == 'start')\n        return original;\n      if (event1 == 'start' && event2 == 'stop')\n        return highlighted;\n      if (event1 == 'stop' && event2 == 'start')\n        return original;\n      if (event1 == 'stop' && event2 == 'stop')\n        return highlighted;\n\n      ... which is collapsed to:\n      */\n      return highlighted[0].event == 'start' ? original : highlighted;\n    }\n\n    function open(node) {\n      function attr_str(a) {return ' ' + a.nodeName + '=\"' + escape(a.value) + '\"';}\n      result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attr_str).join('') + '>';\n    }\n\n    function close(node) {\n      result += '</' + tag(node) + '>';\n    }\n\n    function render(event) {\n      (event.event == 'start' ? open : close)(event.node);\n    }\n\n    while (original.length || highlighted.length) {\n      var stream = selectStream();\n      result += escape(value.substr(processed, stream[0].offset - processed));\n      processed = stream[0].offset;\n      if (stream == original) {\n        /*\n        On any opening or closing tag of the original markup we first close\n        the entire highlighted node stack, then render the original tag along\n        with all the following original tags at the same offset and then\n        reopen all the tags on the highlighted stack.\n        */\n        nodeStack.reverse().forEach(close);\n        do {\n          render(stream.splice(0, 1)[0]);\n          stream = selectStream();\n        } while (stream == original && stream.length && stream[0].offset == processed);\n        nodeStack.reverse().forEach(open);\n      } else {\n        if (stream[0].event == 'start') {\n          nodeStack.push(stream[0].node);\n        } else {\n          nodeStack.pop();\n        }\n        render(stream.splice(0, 1)[0]);\n      }\n    }\n    return result + escape(value.substr(processed));\n  }\n\n  /* Initialization */\n\n  function compileLanguage(language) {\n\n    function reStr(re) {\n        return (re && re.source) || re;\n    }\n\n    function langRe(value, global) {\n      return new RegExp(\n        reStr(value),\n        'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '')\n      );\n    }\n\n    function compileMode(mode, parent) {\n      if (mode.compiled)\n        return;\n      mode.compiled = true;\n\n      mode.keywords = mode.keywords || mode.beginKeywords;\n      if (mode.keywords) {\n        var compiled_keywords = {};\n\n        var flatten = function(className, str) {\n          if (language.case_insensitive) {\n            str = str.toLowerCase();\n          }\n          str.split(' ').forEach(function(kw) {\n            var pair = kw.split('|');\n            compiled_keywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1];\n          });\n        };\n\n        if (typeof mode.keywords == 'string') { // string\n          flatten('keyword', mode.keywords);\n        } else {\n          Object.keys(mode.keywords).forEach(function (className) {\n            flatten(className, mode.keywords[className]);\n          });\n        }\n        mode.keywords = compiled_keywords;\n      }\n      mode.lexemesRe = langRe(mode.lexemes || /\\b\\w+\\b/, true);\n\n      if (parent) {\n        if (mode.beginKeywords) {\n          mode.begin = '\\\\b(' + mode.beginKeywords.split(' ').join('|') + ')\\\\b';\n        }\n        if (!mode.begin)\n          mode.begin = /\\B|\\b/;\n        mode.beginRe = langRe(mode.begin);\n        if (!mode.end && !mode.endsWithParent)\n          mode.end = /\\B|\\b/;\n        if (mode.end)\n          mode.endRe = langRe(mode.end);\n        mode.terminator_end = reStr(mode.end) || '';\n        if (mode.endsWithParent && parent.terminator_end)\n          mode.terminator_end += (mode.end ? '|' : '') + parent.terminator_end;\n      }\n      if (mode.illegal)\n        mode.illegalRe = langRe(mode.illegal);\n      if (mode.relevance === undefined)\n        mode.relevance = 1;\n      if (!mode.contains) {\n        mode.contains = [];\n      }\n      var expanded_contains = [];\n      mode.contains.forEach(function(c) {\n        if (c.variants) {\n          c.variants.forEach(function(v) {expanded_contains.push(inherit(c, v));});\n        } else {\n          expanded_contains.push(c == 'self' ? mode : c);\n        }\n      });\n      mode.contains = expanded_contains;\n      mode.contains.forEach(function(c) {compileMode(c, mode);});\n\n      if (mode.starts) {\n        compileMode(mode.starts, parent);\n      }\n\n      var terminators =\n        mode.contains.map(function(c) {\n          return c.beginKeywords ? '\\\\.?(' + c.begin + ')\\\\.?' : c.begin;\n        })\n        .concat([mode.terminator_end, mode.illegal])\n        .map(reStr)\n        .filter(Boolean);\n      mode.terminators = terminators.length ? langRe(terminators.join('|'), true) : {exec: function(/*s*/) {return null;}};\n    }\n\n    compileMode(language);\n  }\n\n  /*\n  Core highlighting function. Accepts a language name, or an alias, and a\n  string with the code to highlight. Returns an object with the following\n  properties:\n\n  - relevance (int)\n  - value (an HTML string with highlighting markup)\n\n  */\n  function highlight(name, value, ignore_illegals, continuation) {\n\n    function subMode(lexeme, mode) {\n      for (var i = 0; i < mode.contains.length; i++) {\n        if (testRe(mode.contains[i].beginRe, lexeme)) {\n          return mode.contains[i];\n        }\n      }\n    }\n\n    function endOfMode(mode, lexeme) {\n      if (testRe(mode.endRe, lexeme)) {\n        while (mode.endsParent && mode.parent) {\n          mode = mode.parent;\n        }\n        return mode;\n      }\n      if (mode.endsWithParent) {\n        return endOfMode(mode.parent, lexeme);\n      }\n    }\n\n    function isIllegal(lexeme, mode) {\n      return !ignore_illegals && testRe(mode.illegalRe, lexeme);\n    }\n\n    function keywordMatch(mode, match) {\n      var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0];\n      return mode.keywords.hasOwnProperty(match_str) && mode.keywords[match_str];\n    }\n\n    function buildSpan(classname, insideSpan, leaveOpen, noPrefix) {\n      var classPrefix = noPrefix ? '' : options.classPrefix,\n          openSpan    = '<span class=\"' + classPrefix,\n          closeSpan   = leaveOpen ? '' : '</span>';\n\n      openSpan += classname + '\">';\n\n      return openSpan + insideSpan + closeSpan;\n    }\n\n    function processKeywords() {\n      if (!top.keywords)\n        return escape(mode_buffer);\n      var result = '';\n      var last_index = 0;\n      top.lexemesRe.lastIndex = 0;\n      var match = top.lexemesRe.exec(mode_buffer);\n      while (match) {\n        result += escape(mode_buffer.substr(last_index, match.index - last_index));\n        var keyword_match = keywordMatch(top, match);\n        if (keyword_match) {\n          relevance += keyword_match[1];\n          result += buildSpan(keyword_match[0], escape(match[0]));\n        } else {\n          result += escape(match[0]);\n        }\n        last_index = top.lexemesRe.lastIndex;\n        match = top.lexemesRe.exec(mode_buffer);\n      }\n      return result + escape(mode_buffer.substr(last_index));\n    }\n\n    function processSubLanguage() {\n      var explicit = typeof top.subLanguage == 'string';\n      if (explicit && !languages[top.subLanguage]) {\n        return escape(mode_buffer);\n      }\n\n      var result = explicit ?\n                   highlight(top.subLanguage, mode_buffer, true, continuations[top.subLanguage]) :\n                   highlightAuto(mode_buffer, top.subLanguage.length ? top.subLanguage : undefined);\n\n      // Counting embedded language score towards the host language may be disabled\n      // with zeroing the containing mode relevance. Usecase in point is Markdown that\n      // allows XML everywhere and makes every XML snippet to have a much larger Markdown\n      // score.\n      if (top.relevance > 0) {\n        relevance += result.relevance;\n      }\n      if (explicit) {\n        continuations[top.subLanguage] = result.top;\n      }\n      return buildSpan(result.language, result.value, false, true);\n    }\n\n    function processBuffer() {\n      return top.subLanguage !== undefined ? processSubLanguage() : processKeywords();\n    }\n\n    function startNewMode(mode, lexeme) {\n      var markup = mode.className? buildSpan(mode.className, '', true): '';\n      if (mode.returnBegin) {\n        result += markup;\n        mode_buffer = '';\n      } else if (mode.excludeBegin) {\n        result += escape(lexeme) + markup;\n        mode_buffer = '';\n      } else {\n        result += markup;\n        mode_buffer = lexeme;\n      }\n      top = Object.create(mode, {parent: {value: top}});\n    }\n\n    function processLexeme(buffer, lexeme) {\n\n      mode_buffer += buffer;\n      if (lexeme === undefined) {\n        result += processBuffer();\n        return 0;\n      }\n\n      var new_mode = subMode(lexeme, top);\n      if (new_mode) {\n        result += processBuffer();\n        startNewMode(new_mode, lexeme);\n        return new_mode.returnBegin ? 0 : lexeme.length;\n      }\n\n      var end_mode = endOfMode(top, lexeme);\n      if (end_mode) {\n        var origin = top;\n        if (!(origin.returnEnd || origin.excludeEnd)) {\n          mode_buffer += lexeme;\n        }\n        result += processBuffer();\n        do {\n          if (top.className) {\n            result += '</span>';\n          }\n          relevance += top.relevance;\n          top = top.parent;\n        } while (top != end_mode.parent);\n        if (origin.excludeEnd) {\n          result += escape(lexeme);\n        }\n        mode_buffer = '';\n        if (end_mode.starts) {\n          startNewMode(end_mode.starts, '');\n        }\n        return origin.returnEnd ? 0 : lexeme.length;\n      }\n\n      if (isIllegal(lexeme, top))\n        throw new Error('Illegal lexeme \"' + lexeme + '\" for mode \"' + (top.className || '<unnamed>') + '\"');\n\n      /*\n      Parser should not reach this point as all types of lexemes should be caught\n      earlier, but if it does due to some bug make sure it advances at least one\n      character forward to prevent infinite looping.\n      */\n      mode_buffer += lexeme;\n      return lexeme.length || 1;\n    }\n\n    var language = getLanguage(name);\n    if (!language) {\n      throw new Error('Unknown language: \"' + name + '\"');\n    }\n\n    compileLanguage(language);\n    var top = continuation || language;\n    var continuations = {}; // keep continuations for sub-languages\n    var result = '', current;\n    for(current = top; current != language; current = current.parent) {\n      if (current.className) {\n        result = buildSpan(current.className, '', true) + result;\n      }\n    }\n    var mode_buffer = '';\n    var relevance = 0;\n    try {\n      var match, count, index = 0;\n      while (true) {\n        top.terminators.lastIndex = index;\n        match = top.terminators.exec(value);\n        if (!match)\n          break;\n        count = processLexeme(value.substr(index, match.index - index), match[0]);\n        index = match.index + count;\n      }\n      processLexeme(value.substr(index));\n      for(current = top; current.parent; current = current.parent) { // close dangling modes\n        if (current.className) {\n          result += '</span>';\n        }\n      }\n      return {\n        relevance: relevance,\n        value: result,\n        language: name,\n        top: top\n      };\n    } catch (e) {\n      if (e.message.indexOf('Illegal') != -1) {\n        return {\n          relevance: 0,\n          value: escape(value)\n        };\n      } else {\n        throw e;\n      }\n    }\n  }\n\n  /*\n  Highlighting with language detection. Accepts a string with the code to\n  highlight. Returns an object with the following properties:\n\n  - language (detected language)\n  - relevance (int)\n  - value (an HTML string with highlighting markup)\n  - second_best (object with the same structure for second-best heuristically\n    detected language, may be absent)\n\n  */\n  function highlightAuto(text, languageSubset) {\n    languageSubset = languageSubset || options.languages || Object.keys(languages);\n    var result = {\n      relevance: 0,\n      value: escape(text)\n    };\n    var second_best = result;\n    languageSubset.forEach(function(name) {\n      if (!getLanguage(name)) {\n        return;\n      }\n      var current = highlight(name, text, false);\n      current.language = name;\n      if (current.relevance > second_best.relevance) {\n        second_best = current;\n      }\n      if (current.relevance > result.relevance) {\n        second_best = result;\n        result = current;\n      }\n    });\n    if (second_best.language) {\n      result.second_best = second_best;\n    }\n    return result;\n  }\n\n  /*\n  Post-processing of the highlighted markup:\n\n  - replace TABs with something more useful\n  - replace real line-breaks with '<br>' for non-pre containers\n\n  */\n  function fixMarkup(value) {\n    if (options.tabReplace) {\n      value = value.replace(/^((<[^>]+>|\\t)+)/gm, function(match, p1 /*..., offset, s*/) {\n        return p1.replace(/\\t/g, options.tabReplace);\n      });\n    }\n    if (options.useBR) {\n      value = value.replace(/\\n/g, '<br>');\n    }\n    return value;\n  }\n\n  function buildClassName(prevClassName, currentLang, resultLang) {\n    var language = currentLang ? aliases[currentLang] : resultLang,\n        result   = [prevClassName.trim()];\n\n    if (!prevClassName.match(/\\bhljs\\b/)) {\n      result.push('hljs');\n    }\n\n    if (prevClassName.indexOf(language) === -1) {\n      result.push(language);\n    }\n\n    return result.join(' ').trim();\n  }\n\n  /*\n  Applies highlighting to a DOM node containing code. Accepts a DOM node and\n  two optional parameters for fixMarkup.\n  */\n  function highlightBlock(block) {\n    var language = blockLanguage(block);\n    if (isNotHighlighted(language))\n        return;\n\n    var node;\n    if (options.useBR) {\n      node = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');\n      node.innerHTML = block.innerHTML.replace(/\\n/g, '').replace(/<br[ \\/]*>/g, '\\n');\n    } else {\n      node = block;\n    }\n    var text = node.textContent;\n    var result = language ? highlight(language, text, true) : highlightAuto(text);\n\n    var originalStream = nodeStream(node);\n    if (originalStream.length) {\n      var resultNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');\n      resultNode.innerHTML = result.value;\n      result.value = mergeStreams(originalStream, nodeStream(resultNode), text);\n    }\n    result.value = fixMarkup(result.value);\n\n    block.innerHTML = result.value;\n    block.className = buildClassName(block.className, language, result.language);\n    block.result = {\n      language: result.language,\n      re: result.relevance\n    };\n    if (result.second_best) {\n      block.second_best = {\n        language: result.second_best.language,\n        re: result.second_best.relevance\n      };\n    }\n  }\n\n  var options = {\n    classPrefix: 'hljs-',\n    tabReplace: null,\n    useBR: false,\n    languages: undefined\n  };\n\n  /*\n  Updates highlight.js global options with values passed in the form of an object\n  */\n  function configure(user_options) {\n    options = inherit(options, user_options);\n  }\n\n  /*\n  Applies highlighting to all <pre><code>..</code></pre> blocks on a page.\n  */\n  function initHighlighting() {\n    if (initHighlighting.called)\n      return;\n    initHighlighting.called = true;\n\n    var blocks = document.querySelectorAll('pre code');\n    Array.prototype.forEach.call(blocks, highlightBlock);\n  }\n\n  /*\n  Attaches highlighting to the page load event.\n  */\n  function initHighlightingOnLoad() {\n    addEventListener('DOMContentLoaded', initHighlighting, false);\n    addEventListener('load', initHighlighting, false);\n  }\n\n  var languages = {};\n  var aliases = {};\n\n  function registerLanguage(name, language) {\n    var lang = languages[name] = language(hljs);\n    if (lang.aliases) {\n      lang.aliases.forEach(function(alias) {aliases[alias] = name;});\n    }\n  }\n\n  function listLanguages() {\n    return Object.keys(languages);\n  }\n\n  function getLanguage(name) {\n    name = (name || '').toLowerCase();\n    return languages[name] || languages[aliases[name]];\n  }\n\n  /* Interface definition */\n\n  hljs.highlight = highlight;\n  hljs.highlightAuto = highlightAuto;\n  hljs.fixMarkup = fixMarkup;\n  hljs.highlightBlock = highlightBlock;\n  hljs.configure = configure;\n  hljs.initHighlighting = initHighlighting;\n  hljs.initHighlightingOnLoad = initHighlightingOnLoad;\n  hljs.registerLanguage = registerLanguage;\n  hljs.listLanguages = listLanguages;\n  hljs.getLanguage = getLanguage;\n  hljs.inherit = inherit;\n\n  // Common regexps\n  hljs.IDENT_RE = '[a-zA-Z]\\\\w*';\n  hljs.UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\\\w*';\n  hljs.NUMBER_RE = '\\\\b\\\\d+(\\\\.\\\\d+)?';\n  hljs.C_NUMBER_RE = '(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)'; // 0x..., 0..., decimal, float\n  hljs.BINARY_NUMBER_RE = '\\\\b(0b[01]+)'; // 0b...\n  hljs.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~';\n\n  // Common modes\n  hljs.BACKSLASH_ESCAPE = {\n    begin: '\\\\\\\\[\\\\s\\\\S]', relevance: 0\n  };\n  hljs.APOS_STRING_MODE = {\n    className: 'string',\n    begin: '\\'', end: '\\'',\n    illegal: '\\\\n',\n    contains: [hljs.BACKSLASH_ESCAPE]\n  };\n  hljs.QUOTE_STRING_MODE = {\n    className: 'string',\n    begin: '\"', end: '\"',\n    illegal: '\\\\n',\n    contains: [hljs.BACKSLASH_ESCAPE]\n  };\n  hljs.PHRASAL_WORDS_MODE = {\n    begin: /\\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\\b/\n  };\n  hljs.COMMENT = function (begin, end, inherits) {\n    var mode = hljs.inherit(\n      {\n        className: 'comment',\n        begin: begin, end: end,\n        contains: []\n      },\n      inherits || {}\n    );\n    mode.contains.push(hljs.PHRASAL_WORDS_MODE);\n    mode.contains.push({\n      className: 'doctag',\n      begin: \"(?:TODO|FIXME|NOTE|BUG|XXX):\",\n      relevance: 0\n    });\n    return mode;\n  };\n  hljs.C_LINE_COMMENT_MODE = hljs.COMMENT('//', '$');\n  hljs.C_BLOCK_COMMENT_MODE = hljs.COMMENT('/\\\\*', '\\\\*/');\n  hljs.HASH_COMMENT_MODE = hljs.COMMENT('#', '$');\n  hljs.NUMBER_MODE = {\n    className: 'number',\n    begin: hljs.NUMBER_RE,\n    relevance: 0\n  };\n  hljs.C_NUMBER_MODE = {\n    className: 'number',\n    begin: hljs.C_NUMBER_RE,\n    relevance: 0\n  };\n  hljs.BINARY_NUMBER_MODE = {\n    className: 'number',\n    begin: hljs.BINARY_NUMBER_RE,\n    relevance: 0\n  };\n  hljs.CSS_NUMBER_MODE = {\n    className: 'number',\n    begin: hljs.NUMBER_RE + '(' +\n      '%|em|ex|ch|rem'  +\n      '|vw|vh|vmin|vmax' +\n      '|cm|mm|in|pt|pc|px' +\n      '|deg|grad|rad|turn' +\n      '|s|ms' +\n      '|Hz|kHz' +\n      '|dpi|dpcm|dppx' +\n      ')?',\n    relevance: 0\n  };\n  hljs.REGEXP_MODE = {\n    className: 'regexp',\n    begin: /\\//, end: /\\/[gimuy]*/,\n    illegal: /\\n/,\n    contains: [\n      hljs.BACKSLASH_ESCAPE,\n      {\n        begin: /\\[/, end: /\\]/,\n        relevance: 0,\n        contains: [hljs.BACKSLASH_ESCAPE]\n      }\n    ]\n  };\n  hljs.TITLE_MODE = {\n    className: 'title',\n    begin: hljs.IDENT_RE,\n    relevance: 0\n  };\n  hljs.UNDERSCORE_TITLE_MODE = {\n    className: 'title',\n    begin: hljs.UNDERSCORE_IDENT_RE,\n    relevance: 0\n  };\n\nhljs.registerLanguage('1c', function(hljs){\n  var IDENT_RE_RU = '[a-zA-Zа-яА-Я][a-zA-Z0-9_а-яА-Я]*';\n  var OneS_KEYWORDS = 'возврат дата для если и или иначе иначеесли исключение конецесли ' +\n    'конецпопытки конецпроцедуры конецфункции конеццикла константа не перейти перем ' +\n    'перечисление по пока попытка прервать продолжить процедура строка тогда фс функция цикл ' +\n    'число экспорт';\n  var OneS_BUILT_IN = 'ansitooem oemtoansi ввестивидсубконто ввестидату ввестизначение ' +\n    'ввестиперечисление ввестипериод ввестиплансчетов ввестистроку ввестичисло вопрос ' +\n    'восстановитьзначение врег выбранныйплансчетов вызватьисключение датагод датамесяц ' +\n    'датачисло добавитьмесяц завершитьработусистемы заголовоксистемы записьжурналарегистрации ' +\n    'запуститьприложение зафиксироватьтранзакцию значениевстроку значениевстрокувнутр ' +\n    'значениевфайл значениеизстроки значениеизстрокивнутр значениеизфайла имякомпьютера ' +\n    'имяпользователя каталогвременныхфайлов каталогиб каталогпользователя каталогпрограммы ' +\n    'кодсимв командасистемы конгода конецпериодаби конецрассчитанногопериодаби ' +\n    'конецстандартногоинтервала конквартала конмесяца коннедели лев лог лог10 макс ' +\n    'максимальноеколичествосубконто мин монопольныйрежим названиеинтерфейса названиенабораправ ' +\n    'назначитьвид назначитьсчет найти найтипомеченныенаудаление найтиссылки началопериодаби ' +\n    'началостандартногоинтервала начатьтранзакцию начгода начквартала начмесяца начнедели ' +\n    'номерднягода номерднянедели номернеделигода нрег обработкаожидания окр описаниеошибки ' +\n    'основнойжурналрасчетов основнойплансчетов основнойязык открытьформу открытьформумодально ' +\n    'отменитьтранзакцию очиститьокносообщений периодстр полноеимяпользователя получитьвремята ' +\n    'получитьдатута получитьдокументта получитьзначенияотбора получитьпозициюта ' +\n    'получитьпустоезначение получитьта прав праводоступа предупреждение префиксавтонумерации ' +\n    'пустаястрока пустоезначение рабочаядаттьпустоезначение рабочаядата разделительстраниц ' +\n    'разделительстрок разм разобратьпозициюдокумента рассчитатьрегистрына ' +\n    'рассчитатьрегистрыпо сигнал симв символтабуляции создатьобъект сокрл сокрлп сокрп ' +\n    'сообщить состояние сохранитьзначение сред статусвозврата стрдлина стрзаменить ' +\n    'стрколичествострок стрполучитьстроку  стрчисловхождений сформироватьпозициюдокумента ' +\n    'счетпокоду текущаядата текущеевремя типзначения типзначениястр удалитьобъекты ' +\n    'установитьтана установитьтапо фиксшаблон формат цел шаблон';\n  var DQUOTE =  {className: 'dquote',  begin: '\"\"'};\n  var STR_START = {\n      className: 'string',\n      begin: '\"', end: '\"|$',\n      contains: [DQUOTE]\n    };\n  var STR_CONT = {\n    className: 'string',\n    begin: '\\\\|', end: '\"|$',\n    contains: [DQUOTE]\n  };\n\n  return {\n    case_insensitive: true,\n    lexemes: IDENT_RE_RU,\n    keywords: {keyword: OneS_KEYWORDS, built_in: OneS_BUILT_IN},\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.NUMBER_MODE,\n      STR_START, STR_CONT,\n      {\n        className: 'function',\n        begin: '(процедура|функция)', end: '$',\n        lexemes: IDENT_RE_RU,\n        keywords: 'процедура функция',\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {begin: IDENT_RE_RU}),\n          {\n            className: 'tail',\n            endsWithParent: true,\n            contains: [\n              {\n                className: 'params',\n                begin: '\\\\(', end: '\\\\)',\n                lexemes: IDENT_RE_RU,\n                keywords: 'знач',\n                contains: [STR_START, STR_CONT]\n              },\n              {\n                className: 'export',\n                begin: 'экспорт', endsWithParent: true,\n                lexemes: IDENT_RE_RU,\n                keywords: 'экспорт',\n                contains: [hljs.C_LINE_COMMENT_MODE]\n              }\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE\n        ]\n      },\n      {className: 'preprocessor', begin: '#', end: '$'},\n      {className: 'date', begin: '\\'\\\\d{2}\\\\.\\\\d{2}\\\\.(\\\\d{2}|\\\\d{4})\\''}\n    ]\n  };\n});\n\nhljs.registerLanguage('accesslog', function(hljs) {\n  return {\n    contains: [\n      // IP\n      {\n        className: 'number',\n        begin: '\\\\b\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}(:\\\\d{1,5})?\\\\b'\n      },\n      // Other numbers\n      {\n        className: 'number',\n        begin: '\\\\b\\\\d+\\\\b',\n        relevance: 0\n      },\n      // Requests\n      {\n        className: 'string',\n        begin: '\"(GET|POST|HEAD|PUT|DELETE|CONNECT|OPTIONS|PATCH|TRACE)', end: '\"',\n        keywords: 'GET POST HEAD PUT DELETE CONNECT OPTIONS PATCH TRACE',\n        illegal: '\\\\n',\n        relevance: 10\n      },\n      // Dates\n      {\n        className: 'string',\n        begin: /\\[/, end: /\\]/,\n        illegal: '\\\\n'\n      },\n      // Strings\n      {\n        className: 'string',\n        begin: '\"', end: '\"',\n        illegal: '\\\\n'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('actionscript', function(hljs) {\n  var IDENT_RE = '[a-zA-Z_$][a-zA-Z0-9_$]*';\n  var IDENT_FUNC_RETURN_TYPE_RE = '([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)';\n\n  var AS3_REST_ARG_MODE = {\n    className: 'rest_arg',\n    begin: '[.]{3}', end: IDENT_RE,\n    relevance: 10\n  };\n\n  return {\n    aliases: ['as'],\n    keywords: {\n      keyword: 'as break case catch class const continue default delete do dynamic each ' +\n        'else extends final finally for function get if implements import in include ' +\n        'instanceof interface internal is namespace native new override package private ' +\n        'protected public return set static super switch this throw try typeof use var void ' +\n        'while with',\n      literal: 'true false null undefined'\n    },\n    contains: [\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'package',\n        beginKeywords: 'package', end: '{',\n        contains: [hljs.TITLE_MODE]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: '{', excludeEnd: true,\n        contains: [\n          {\n            beginKeywords: 'extends implements'\n          },\n          hljs.TITLE_MODE\n        ]\n      },\n      {\n        className: 'preprocessor',\n        beginKeywords: 'import include', end: ';'\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function', end: '[{;]', excludeEnd: true,\n        illegal: '\\\\S',\n        contains: [\n          hljs.TITLE_MODE,\n          {\n            className: 'params',\n            begin: '\\\\(', end: '\\\\)',\n            contains: [\n              hljs.APOS_STRING_MODE,\n              hljs.QUOTE_STRING_MODE,\n              hljs.C_LINE_COMMENT_MODE,\n              hljs.C_BLOCK_COMMENT_MODE,\n              AS3_REST_ARG_MODE\n            ]\n          },\n          {\n            className: 'type',\n            begin: ':',\n            end: IDENT_FUNC_RETURN_TYPE_RE,\n            relevance: 10\n          }\n        ]\n      }\n    ],\n    illegal: /#/\n  };\n});\n\nhljs.registerLanguage('apache', function(hljs) {\n  var NUMBER = {className: 'number', begin: '[\\\\$%]\\\\d+'};\n  return {\n    aliases: ['apacheconf'],\n    case_insensitive: true,\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      {className: 'tag', begin: '</?', end: '>'},\n      {\n        className: 'keyword',\n        begin: /\\w+/,\n        relevance: 0,\n        // keywords aren’t needed for highlighting per se, they only boost relevance\n        // for a very generally defined mode (starts with a word, ends with line-end\n        keywords: {\n          common:\n            'order deny allow setenv rewriterule rewriteengine rewritecond documentroot ' +\n            'sethandler errordocument loadmodule options header listen serverroot ' +\n            'servername'\n        },\n        starts: {\n          end: /$/,\n          relevance: 0,\n          keywords: {\n            literal: 'on off all'\n          },\n          contains: [\n            {\n              className: 'sqbracket',\n              begin: '\\\\s\\\\[', end: '\\\\]$'\n            },\n            {\n              className: 'cbracket',\n              begin: '[\\\\$%]\\\\{', end: '\\\\}',\n              contains: ['self', NUMBER]\n            },\n            NUMBER,\n            hljs.QUOTE_STRING_MODE\n          ]\n        }\n      }\n    ],\n    illegal: /\\S/\n  };\n});\n\nhljs.registerLanguage('applescript', function(hljs) {\n  var STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: ''});\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\(', end: '\\\\)',\n    contains: ['self', hljs.C_NUMBER_MODE, STRING]\n  };\n  var COMMENT_MODE_1 = hljs.COMMENT('--', '$');\n  var COMMENT_MODE_2 = hljs.COMMENT(\n    '\\\\(\\\\*',\n    '\\\\*\\\\)',\n    {\n      contains: ['self', COMMENT_MODE_1] //allow nesting\n    }\n  );\n  var COMMENTS = [\n    COMMENT_MODE_1,\n    COMMENT_MODE_2,\n    hljs.HASH_COMMENT_MODE\n  ];\n\n  return {\n    aliases: ['osascript'],\n    keywords: {\n      keyword:\n        'about above after against and around as at back before beginning ' +\n        'behind below beneath beside between but by considering ' +\n        'contain contains continue copy div does eighth else end equal ' +\n        'equals error every exit fifth first for fourth from front ' +\n        'get given global if ignoring in into is it its last local me ' +\n        'middle mod my ninth not of on onto or over prop property put ref ' +\n        'reference repeat returning script second set seventh since ' +\n        'sixth some tell tenth that the|0 then third through thru ' +\n        'timeout times to transaction try until where while whose with ' +\n        'without',\n      constant:\n        'AppleScript false linefeed return pi quote result space tab true',\n      type:\n        'alias application boolean class constant date file integer list ' +\n        'number real record string text',\n      command:\n        'activate beep count delay launch log offset read round ' +\n        'run say summarize write',\n      property:\n        'character characters contents day frontmost id item length ' +\n        'month name paragraph paragraphs rest reverse running time version ' +\n        'weekday word words year'\n    },\n    contains: [\n      STRING,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'type',\n        begin: '\\\\bPOSIX file\\\\b'\n      },\n      {\n        className: 'command',\n        begin:\n          '\\\\b(clipboard info|the clipboard|info for|list (disks|folder)|' +\n          'mount volume|path to|(close|open for) access|(get|set) eof|' +\n          'current date|do shell script|get volume settings|random number|' +\n          'set volume|system attribute|system info|time to GMT|' +\n          '(load|run|store) script|scripting components|' +\n          'ASCII (character|number)|localized string|' +\n          'choose (application|color|file|file name|' +\n          'folder|from list|remote application|URL)|' +\n          'display (alert|dialog))\\\\b|^\\\\s*return\\\\b'\n      },\n      {\n        className: 'constant',\n        begin:\n          '\\\\b(text item delimiters|current application|missing value)\\\\b'\n      },\n      {\n        className: 'keyword',\n        begin:\n          '\\\\b(apart from|aside from|instead of|out of|greater than|' +\n          \"isn't|(doesn't|does not) (equal|come before|come after|contain)|\" +\n          '(greater|less) than( or equal)?|(starts?|ends|begins?) with|' +\n          'contained by|comes (before|after)|a (ref|reference))\\\\b'\n      },\n      {\n        className: 'property',\n        begin:\n          '\\\\b(POSIX path|(date|time) string|quoted form)\\\\b'\n      },\n      {\n        className: 'function_start',\n        beginKeywords: 'on',\n        illegal: '[${=;\\\\n]',\n        contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS]\n      }\n    ].concat(COMMENTS),\n    illegal: '//|->|=>|\\\\[\\\\['\n  };\n});\n\nhljs.registerLanguage('armasm', function(hljs) {\n    //local labels: %?[FB]?[AT]?\\d{1,2}\\w+\n  return {\n    case_insensitive: true,\n    aliases: ['arm'],\n    lexemes: '\\\\.?' + hljs.IDENT_RE,\n    keywords: {\n      literal:\n        'r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 '+ //standard registers\n        'pc lr sp ip sl sb fp '+ //typical regs plus backward compatibility\n        'a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 '+ //more regs and fp\n        'p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 '+ //coprocessor regs\n        'c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 '+ //more coproc\n        'q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 '+ //advanced SIMD NEON regs\n\n        //program status registers\n        'cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf '+\n        'spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf '+\n\n        //NEON and VFP registers\n        's0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 '+\n        's16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 '+\n        'd0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 '+\n        'd16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 ',\n    preprocessor:\n        //GNU preprocs\n        '.2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .arm .thumb .code16 .code32 .force_thumb .thumb_func .ltorg '+\n        //ARM directives\n        'ALIAS ALIGN ARM AREA ASSERT ATTR CN CODE CODE16 CODE32 COMMON CP DATA DCB DCD DCDU DCDO DCFD DCFDU DCI DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT EXPORTAS EXTERN FIELD FILL FUNCTION GBLA GBLL GBLS GET GLOBAL IF IMPORT INCBIN INCLUDE INFO KEEP LCLA LCLL LCLS LTORG MACRO MAP MEND MEXIT NOFP OPT PRESERVE8 PROC QN READONLY RELOC REQUIRE REQUIRE8 RLIST FN ROUT SETA SETL SETS SN SPACE SUBT THUMB THUMBX TTL WHILE WEND ',\n    built_in:\n        '{PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @ '\n    },\n    contains: [\n      {\n        className: 'keyword',\n        begin: '\\\\b('+     //mnemonics\n            'adc|'+\n            '(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|'+\n            'and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|'+\n            'bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|'+\n            'setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|'+\n            'ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|'+\n            'mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|'+\n            'mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|'+\n            'mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|'+\n            'rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|'+\n            'stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|'+\n            '[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|'+\n            'wfe|wfi|yield'+\n        ')'+\n        '(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?'+ //condition codes\n        '[sptrx]?' ,                                             //legal postfixes\n        end: '\\\\s'\n      },\n      hljs.COMMENT('[;@]', '$', {relevance: 0}),\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        begin: '\\'',\n        end: '[^\\\\\\\\]\\'',\n        relevance: 0\n      },\n      {\n        className: 'title',\n        begin: '\\\\|', end: '\\\\|',\n        illegal: '\\\\n',\n        relevance: 0\n      },\n      {\n        className: 'number',\n        variants: [\n            {begin: '[#$=]?0x[0-9a-f]+'}, //hex\n            {begin: '[#$=]?0b[01]+'},     //bin\n            {begin: '[#$=]\\\\d+'},        //literal\n            {begin: '\\\\b\\\\d+'}           //bare number\n        ],\n        relevance: 0\n      },\n      {\n        className: 'label',\n        variants: [\n            {begin: '^[a-z_\\\\.\\\\$][a-z0-9_\\\\.\\\\$]+'}, //ARM syntax\n            {begin: '^\\\\s*[a-z_\\\\.\\\\$][a-z0-9_\\\\.\\\\$]+:'}, //GNU ARM syntax\n            {begin: '[=#]\\\\w+' }  //label reference\n        ],\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('xml', function(hljs) {\n  var XML_IDENT_RE = '[A-Za-z0-9\\\\._:-]+';\n  var PHP = {\n    begin: /<\\?(php)?(?!\\w)/, end: /\\?>/,\n    subLanguage: 'php'\n  };\n  var TAG_INTERNALS = {\n    endsWithParent: true,\n    illegal: /</,\n    relevance: 0,\n    contains: [\n      PHP,\n      {\n        className: 'attribute',\n        begin: XML_IDENT_RE,\n        relevance: 0\n      },\n      {\n        begin: '=',\n        relevance: 0,\n        contains: [\n          {\n            className: 'value',\n            contains: [PHP],\n            variants: [\n              {begin: /\"/, end: /\"/},\n              {begin: /'/, end: /'/},\n              {begin: /[^\\s\\/>]+/}\n            ]\n          }\n        ]\n      }\n    ]\n  };\n  return {\n    aliases: ['html', 'xhtml', 'rss', 'atom', 'xsl', 'plist'],\n    case_insensitive: true,\n    contains: [\n      {\n        className: 'doctype',\n        begin: '<!DOCTYPE', end: '>',\n        relevance: 10,\n        contains: [{begin: '\\\\[', end: '\\\\]'}]\n      },\n      hljs.COMMENT(\n        '<!--',\n        '-->',\n        {\n          relevance: 10\n        }\n      ),\n      {\n        className: 'cdata',\n        begin: '<\\\\!\\\\[CDATA\\\\[', end: '\\\\]\\\\]>',\n        relevance: 10\n      },\n      {\n        className: 'tag',\n        /*\n        The lookahead pattern (?=...) ensures that 'begin' only matches\n        '<style' as a single word, followed by a whitespace or an\n        ending braket. The '$' is needed for the lexeme to be recognized\n        by hljs.subMode() that tests lexemes outside the stream.\n        */\n        begin: '<style(?=\\\\s|>|$)', end: '>',\n        keywords: {title: 'style'},\n        contains: [TAG_INTERNALS],\n        starts: {\n          end: '</style>', returnEnd: true,\n          subLanguage: 'css'\n        }\n      },\n      {\n        className: 'tag',\n        // See the comment in the <style tag about the lookahead pattern\n        begin: '<script(?=\\\\s|>|$)', end: '>',\n        keywords: {title: 'script'},\n        contains: [TAG_INTERNALS],\n        starts: {\n          end: '\\<\\/script\\>', returnEnd: true,\n          subLanguage: ['actionscript', 'javascript', 'handlebars']\n        }\n      },\n      PHP,\n      {\n        className: 'pi',\n        begin: /<\\?\\w+/, end: /\\?>/,\n        relevance: 10\n      },\n      {\n        className: 'tag',\n        begin: '</?', end: '/?>',\n        contains: [\n          {\n            className: 'title', begin: /[^ \\/><\\n\\t]+/, relevance: 0\n          },\n          TAG_INTERNALS\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('asciidoc', function(hljs) {\n  return {\n    aliases: ['adoc'],\n    contains: [\n      // block comment\n      hljs.COMMENT(\n        '^/{4,}\\\\n',\n        '\\\\n/{4,}$',\n        // can also be done as...\n        //'^/{4,}$',\n        //'^/{4,}$',\n        {\n          relevance: 10\n        }\n      ),\n      // line comment\n      hljs.COMMENT(\n        '^//',\n        '$',\n        {\n          relevance: 0\n        }\n      ),\n      // title\n      {\n        className: 'title',\n        begin: '^\\\\.\\\\w.*$'\n      },\n      // example, admonition & sidebar blocks\n      {\n        begin: '^[=\\\\*]{4,}\\\\n',\n        end: '\\\\n^[=\\\\*]{4,}$',\n        relevance: 10\n      },\n      // headings\n      {\n        className: 'header',\n        begin: '^(={1,5}) .+?( \\\\1)?$',\n        relevance: 10\n      },\n      {\n        className: 'header',\n        begin: '^[^\\\\[\\\\]\\\\n]+?\\\\n[=\\\\-~\\\\^\\\\+]{2,}$',\n        relevance: 10\n      },\n      // document attributes\n      {\n        className: 'attribute',\n        begin: '^:.+?:',\n        end: '\\\\s',\n        excludeEnd: true,\n        relevance: 10\n      },\n      // block attributes\n      {\n        className: 'attribute',\n        begin: '^\\\\[.+?\\\\]$',\n        relevance: 0\n      },\n      // quoteblocks\n      {\n        className: 'blockquote',\n        begin: '^_{4,}\\\\n',\n        end: '\\\\n_{4,}$',\n        relevance: 10\n      },\n      // listing and literal blocks\n      {\n        className: 'code',\n        begin: '^[\\\\-\\\\.]{4,}\\\\n',\n        end: '\\\\n[\\\\-\\\\.]{4,}$',\n        relevance: 10\n      },\n      // passthrough blocks\n      {\n        begin: '^\\\\+{4,}\\\\n',\n        end: '\\\\n\\\\+{4,}$',\n        contains: [\n          {\n            begin: '<', end: '>',\n            subLanguage: 'xml',\n            relevance: 0\n          }\n        ],\n        relevance: 10\n      },\n      // lists (can only capture indicators)\n      {\n        className: 'bullet',\n        begin: '^(\\\\*+|\\\\-+|\\\\.+|[^\\\\n]+?::)\\\\s+'\n      },\n      // admonition\n      {\n        className: 'label',\n        begin: '^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\\\s+',\n        relevance: 10\n      },\n      // inline strong\n      {\n        className: 'strong',\n        // must not follow a word character or be followed by an asterisk or space\n        begin: '\\\\B\\\\*(?![\\\\*\\\\s])',\n        end: '(\\\\n{2}|\\\\*)',\n        // allow escaped asterisk followed by word char\n        contains: [\n          {\n            begin: '\\\\\\\\*\\\\w',\n            relevance: 0\n          }\n        ]\n      },\n      // inline emphasis\n      {\n        className: 'emphasis',\n        // must not follow a word character or be followed by a single quote or space\n        begin: '\\\\B\\'(?![\\'\\\\s])',\n        end: '(\\\\n{2}|\\')',\n        // allow escaped single quote followed by word char\n        contains: [\n          {\n            begin: '\\\\\\\\\\'\\\\w',\n            relevance: 0\n          }\n        ],\n        relevance: 0\n      },\n      // inline emphasis (alt)\n      {\n        className: 'emphasis',\n        // must not follow a word character or be followed by an underline or space\n        begin: '_(?![_\\\\s])',\n        end: '(\\\\n{2}|_)',\n        relevance: 0\n      },\n      // inline smart quotes\n      {\n        className: 'smartquote',\n        variants: [\n          {begin: \"``.+?''\"},\n          {begin: \"`.+?'\"}\n        ]\n      },\n      // inline code snippets (TODO should get same treatment as strong and emphasis)\n      {\n        className: 'code',\n        begin: '(`.+?`|\\\\+.+?\\\\+)',\n        relevance: 0\n      },\n      // indented literal block\n      {\n        className: 'code',\n        begin: '^[ \\\\t]',\n        end: '$',\n        relevance: 0\n      },\n      // horizontal rules\n      {\n        className: 'horizontal_rule',\n        begin: '^\\'{3,}[ \\\\t]*$',\n        relevance: 10\n      },\n      // images and links\n      {\n        begin: '(link:)?(http|https|ftp|file|irc|image:?):\\\\S+\\\\[.*?\\\\]',\n        returnBegin: true,\n        contains: [\n          {\n            //className: 'macro',\n            begin: '(link|image:?):',\n            relevance: 0\n          },\n          {\n            className: 'link_url',\n            begin: '\\\\w',\n            end: '[^\\\\[]+',\n            relevance: 0\n          },\n          {\n            className: 'link_label',\n            begin: '\\\\[',\n            end: '\\\\]',\n            excludeBegin: true,\n            excludeEnd: true,\n            relevance: 0\n          }\n        ],\n        relevance: 10\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('aspectj', function (hljs) {\n  var KEYWORDS =\n    'false synchronized int abstract float private char boolean static null if const ' +\n    'for true while long throw strictfp finally protected import native final return void ' +\n    'enum else extends implements break transient new catch instanceof byte super volatile case ' +\n    'assert short package default double public try this switch continue throws privileged ' +\n    'aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization ' +\n    'staticinitialization withincode target within execution getWithinTypeName handler ' +\n    'thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents '+\n    'warning error soft precedence thisAspectInstance';\n  var SHORTKEYS = 'get set args call';\n  return {\n    keywords : KEYWORDS,\n    illegal : /<\\/|#/,\n    contains : [\n      hljs.COMMENT(\n        '/\\\\*\\\\*',\n        '\\\\*/',\n        {\n          relevance : 0,\n          contains : [{\n            className : 'doctag',\n            begin : '@[A-Za-z]+'\n          }]\n        }\n      ),\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className : 'aspect',\n        beginKeywords : 'aspect',\n        end : /[{;=]/,\n        excludeEnd : true,\n        illegal : /[:;\"\\[\\]]/,\n        contains : [\n          {\n            beginKeywords : 'extends implements pertypewithin perthis pertarget percflowbelow percflow issingleton'\n          },\n          hljs.UNDERSCORE_TITLE_MODE,\n          {\n            begin : /\\([^\\)]*/,\n            end : /[)]+/,\n            keywords : KEYWORDS + ' ' + SHORTKEYS,\n            excludeEnd : false\n          }\n        ]\n      },\n      {\n        className : 'class',\n        beginKeywords : 'class interface',\n        end : /[{;=]/,\n        excludeEnd : true,\n        relevance: 0,\n        keywords : 'class interface',\n        illegal : /[:\"\\[\\]]/,\n        contains : [\n          {beginKeywords : 'extends implements'},\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        // AspectJ Constructs\n        beginKeywords : 'pointcut after before around throwing returning',\n        end : /[)]/,\n        excludeEnd : false,\n        illegal : /[\"\\[\\]]/,\n        contains : [\n          {\n            begin : hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(',\n            returnBegin : true,\n            contains : [hljs.UNDERSCORE_TITLE_MODE]\n          }\n        ]\n      },\n      {\n        begin : /[:]/,\n        returnBegin : true,\n        end : /[{;]/,\n        relevance: 0,\n        excludeEnd : false,\n        keywords : KEYWORDS,\n        illegal : /[\"\\[\\]]/,\n        contains : [\n          {\n            begin : hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(',\n            keywords : KEYWORDS + ' ' + SHORTKEYS\n          },\n          hljs.QUOTE_STRING_MODE\n        ]\n      },\n      {\n        // this prevents 'new Name(...), or throw ...' from being recognized as a function definition\n        beginKeywords : 'new throw',\n        relevance : 0\n      },\n      {\n        // the function class is a bit different for AspectJ compared to the Java language\n        className : 'function',\n        begin : /\\w+ +\\w+(\\.)?\\w+\\s*\\([^\\)]*\\)\\s*((throws)[\\w\\s,]+)?[\\{;]/,\n        returnBegin : true,\n        end : /[{;=]/,\n        keywords : KEYWORDS,\n        excludeEnd : true,\n        contains : [\n          {\n            begin : hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(',\n            returnBegin : true,\n            relevance: 0,\n            contains : [hljs.UNDERSCORE_TITLE_MODE]\n          },\n          {\n            className : 'params',\n            begin : /\\(/, end : /\\)/,\n            relevance: 0,\n            keywords : KEYWORDS,\n            contains : [\n              hljs.APOS_STRING_MODE,\n              hljs.QUOTE_STRING_MODE,\n              hljs.C_NUMBER_MODE,\n              hljs.C_BLOCK_COMMENT_MODE\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      },\n      hljs.C_NUMBER_MODE,\n      {\n        // annotation is also used in this language\n        className : 'annotation',\n        begin : '@[A-Za-z]+'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('autohotkey', function(hljs) {\n  var BACKTICK_ESCAPE = {\n    className: 'escape',\n    begin: '`[\\\\s\\\\S]'\n  };\n  var COMMENTS = hljs.COMMENT(\n    ';',\n    '$',\n    {\n      relevance: 0\n    }\n  );\n  var BUILT_IN = [\n    {\n      className: 'built_in',\n      begin: 'A_[a-zA-Z0-9]+'\n    },\n    {\n      className: 'built_in',\n      beginKeywords: 'ComSpec Clipboard ClipboardAll ErrorLevel'\n    }\n  ];\n\n  return {\n    case_insensitive: true,\n    keywords: {\n      keyword: 'Break Continue Else Gosub If Loop Return While',\n      literal: 'A true false NOT AND OR'\n    },\n    contains: BUILT_IN.concat([\n      BACKTICK_ESCAPE,\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {contains: [BACKTICK_ESCAPE]}),\n      COMMENTS,\n      {\n        className: 'number',\n        begin: hljs.NUMBER_RE,\n        relevance: 0\n      },\n      {\n        className: 'var_expand', // FIXME\n        begin: '%', end: '%',\n        illegal: '\\\\n',\n        contains: [BACKTICK_ESCAPE]\n      },\n      {\n        className: 'label',\n        contains: [BACKTICK_ESCAPE],\n        variants: [\n          {begin: '^[^\\\\n\";]+::(?!=)'},\n          {begin: '^[^\\\\n\";]+:(?!=)', relevance: 0} // zero relevance as it catches a lot of things\n                                                    // followed by a single ':' in many languages\n        ]\n      },\n      {\n        // consecutive commas, not for highlighting but just for relevance\n        begin: ',\\\\s*,',\n        relevance: 10\n      }\n    ])\n  }\n});\n\nhljs.registerLanguage('autoit', function(hljs) {\n    var KEYWORDS = 'ByRef Case Const ContinueCase ContinueLoop ' +\n        'Default Dim Do Else ElseIf EndFunc EndIf EndSelect ' +\n        'EndSwitch EndWith Enum Exit ExitLoop For Func ' +\n        'Global If In Local Next ReDim Return Select Static ' +\n        'Step Switch Then To Until Volatile WEnd While With',\n\n        LITERAL = 'True False And Null Not Or',\n\n        BUILT_IN = 'Abs ACos AdlibRegister AdlibUnRegister Asc AscW ASin ' +\n        'Assign ATan AutoItSetOption AutoItWinGetTitle ' +\n        'AutoItWinSetTitle Beep Binary BinaryLen BinaryMid ' +\n        'BinaryToString BitAND BitNOT BitOR BitRotate BitShift ' +\n        'BitXOR BlockInput Break Call CDTray Ceiling Chr ' +\n        'ChrW ClipGet ClipPut ConsoleRead ConsoleWrite ' +\n        'ConsoleWriteError ControlClick ControlCommand ' +\n        'ControlDisable ControlEnable ControlFocus ControlGetFocus ' +\n        'ControlGetHandle ControlGetPos ControlGetText ControlHide ' +\n        'ControlListView ControlMove ControlSend ControlSetText ' +\n        'ControlShow ControlTreeView Cos Dec DirCopy DirCreate ' +\n        'DirGetSize DirMove DirRemove DllCall DllCallAddress ' +\n        'DllCallbackFree DllCallbackGetPtr DllCallbackRegister ' +\n        'DllClose DllOpen DllStructCreate DllStructGetData ' +\n        'DllStructGetPtr DllStructGetSize DllStructSetData ' +\n        'DriveGetDrive DriveGetFileSystem DriveGetLabel ' +\n        'DriveGetSerial DriveGetType DriveMapAdd DriveMapDel ' +\n        'DriveMapGet DriveSetLabel DriveSpaceFree DriveSpaceTotal ' +\n        'DriveStatus EnvGet EnvSet EnvUpdate Eval Execute Exp ' +\n        'FileChangeDir FileClose FileCopy FileCreateNTFSLink ' +\n        'FileCreateShortcut FileDelete FileExists FileFindFirstFile ' +\n        'FileFindNextFile FileFlush FileGetAttrib FileGetEncoding ' +\n        'FileGetLongName FileGetPos FileGetShortcut FileGetShortName ' +\n        'FileGetSize FileGetTime FileGetVersion FileInstall ' +\n        'FileMove FileOpen FileOpenDialog FileRead FileReadLine ' +\n        'FileReadToArray FileRecycle FileRecycleEmpty FileSaveDialog ' +\n        'FileSelectFolder FileSetAttrib FileSetEnd FileSetPos ' +\n        'FileSetTime FileWrite FileWriteLine Floor FtpSetProxy ' +\n        'FuncName GUICreate GUICtrlCreateAvi GUICtrlCreateButton ' +\n        'GUICtrlCreateCheckbox GUICtrlCreateCombo ' +\n        'GUICtrlCreateContextMenu GUICtrlCreateDate GUICtrlCreateDummy ' +\n        'GUICtrlCreateEdit GUICtrlCreateGraphic GUICtrlCreateGroup ' +\n        'GUICtrlCreateIcon GUICtrlCreateInput GUICtrlCreateLabel ' +\n        'GUICtrlCreateList GUICtrlCreateListView ' +\n        'GUICtrlCreateListViewItem GUICtrlCreateMenu ' +\n        'GUICtrlCreateMenuItem GUICtrlCreateMonthCal GUICtrlCreateObj ' +\n        'GUICtrlCreatePic GUICtrlCreateProgress GUICtrlCreateRadio ' +\n        'GUICtrlCreateSlider GUICtrlCreateTab GUICtrlCreateTabItem ' +\n        'GUICtrlCreateTreeView GUICtrlCreateTreeViewItem ' +\n        'GUICtrlCreateUpdown GUICtrlDelete GUICtrlGetHandle ' +\n        'GUICtrlGetState GUICtrlRead GUICtrlRecvMsg ' +\n        'GUICtrlRegisterListViewSort GUICtrlSendMsg GUICtrlSendToDummy ' +\n        'GUICtrlSetBkColor GUICtrlSetColor GUICtrlSetCursor ' +\n        'GUICtrlSetData GUICtrlSetDefBkColor GUICtrlSetDefColor ' +\n        'GUICtrlSetFont GUICtrlSetGraphic GUICtrlSetImage ' +\n        'GUICtrlSetLimit GUICtrlSetOnEvent GUICtrlSetPos ' +\n        'GUICtrlSetResizing GUICtrlSetState GUICtrlSetStyle ' +\n        'GUICtrlSetTip GUIDelete GUIGetCursorInfo GUIGetMsg ' +\n        'GUIGetStyle GUIRegisterMsg GUISetAccelerators GUISetBkColor ' +\n        'GUISetCoord GUISetCursor GUISetFont GUISetHelp GUISetIcon ' +\n        'GUISetOnEvent GUISetState GUISetStyle GUIStartGroup ' +\n        'GUISwitch Hex HotKeySet HttpSetProxy HttpSetUserAgent ' +\n        'HWnd InetClose InetGet InetGetInfo InetGetSize InetRead ' +\n        'IniDelete IniRead IniReadSection IniReadSectionNames ' +\n        'IniRenameSection IniWrite IniWriteSection InputBox Int ' +\n        'IsAdmin IsArray IsBinary IsBool IsDeclared IsDllStruct ' +\n        'IsFloat IsFunc IsHWnd IsInt IsKeyword IsNumber IsObj ' +\n        'IsPtr IsString Log MemGetStats Mod MouseClick ' +\n        'MouseClickDrag MouseDown MouseGetCursor MouseGetPos ' +\n        'MouseMove MouseUp MouseWheel MsgBox Number ObjCreate ' +\n        'ObjCreateInterface ObjEvent ObjGet ObjName ' +\n        'OnAutoItExitRegister OnAutoItExitUnRegister Opt Ping ' +\n        'PixelChecksum PixelGetColor PixelSearch ProcessClose ' +\n        'ProcessExists ProcessGetStats ProcessList ' +\n        'ProcessSetPriority ProcessWait ProcessWaitClose ProgressOff ' +\n        'ProgressOn ProgressSet Ptr Random RegDelete RegEnumKey ' +\n        'RegEnumVal RegRead RegWrite Round Run RunAs RunAsWait ' +\n        'RunWait Send SendKeepActive SetError SetExtended ' +\n        'ShellExecute ShellExecuteWait Shutdown Sin Sleep ' +\n        'SoundPlay SoundSetWaveVolume SplashImageOn SplashOff ' +\n        'SplashTextOn Sqrt SRandom StatusbarGetText StderrRead ' +\n        'StdinWrite StdioClose StdoutRead String StringAddCR ' +\n        'StringCompare StringFormat StringFromASCIIArray StringInStr ' +\n        'StringIsAlNum StringIsAlpha StringIsASCII StringIsDigit ' +\n        'StringIsFloat StringIsInt StringIsLower StringIsSpace ' +\n        'StringIsUpper StringIsXDigit StringLeft StringLen ' +\n        'StringLower StringMid StringRegExp StringRegExpReplace ' +\n        'StringReplace StringReverse StringRight StringSplit ' +\n        'StringStripCR StringStripWS StringToASCIIArray ' +\n        'StringToBinary StringTrimLeft StringTrimRight StringUpper ' +\n        'Tan TCPAccept TCPCloseSocket TCPConnect TCPListen ' +\n        'TCPNameToIP TCPRecv TCPSend TCPShutdown TCPStartup ' +\n        'TimerDiff TimerInit ToolTip TrayCreateItem TrayCreateMenu ' +\n        'TrayGetMsg TrayItemDelete TrayItemGetHandle ' +\n        'TrayItemGetState TrayItemGetText TrayItemSetOnEvent ' +\n        'TrayItemSetState TrayItemSetText TraySetClick TraySetIcon ' +\n        'TraySetOnEvent TraySetPauseIcon TraySetState TraySetToolTip ' +\n        'TrayTip UBound UDPBind UDPCloseSocket UDPOpen UDPRecv ' +\n        'UDPSend UDPShutdown UDPStartup VarGetType WinActivate ' +\n        'WinActive WinClose WinExists WinFlash WinGetCaretPos ' +\n        'WinGetClassList WinGetClientSize WinGetHandle WinGetPos ' +\n        'WinGetProcess WinGetState WinGetText WinGetTitle WinKill ' +\n        'WinList WinMenuSelectItem WinMinimizeAll WinMinimizeAllUndo ' +\n        'WinMove WinSetOnTop WinSetState WinSetTitle WinSetTrans ' +\n        'WinWait WinWaitActive WinWaitClose WinWaitNotActive ' +\n        'Array1DToHistogram ArrayAdd ArrayBinarySearch ' +\n        'ArrayColDelete ArrayColInsert ArrayCombinations ' +\n        'ArrayConcatenate ArrayDelete ArrayDisplay ArrayExtract ' +\n        'ArrayFindAll ArrayInsert ArrayMax ArrayMaxIndex ArrayMin ' +\n        'ArrayMinIndex ArrayPermute ArrayPop ArrayPush ' +\n        'ArrayReverse ArraySearch ArrayShuffle ArraySort ArraySwap ' +\n        'ArrayToClip ArrayToString ArrayTranspose ArrayTrim ' +\n        'ArrayUnique Assert ChooseColor ChooseFont ' +\n        'ClipBoard_ChangeChain ClipBoard_Close ClipBoard_CountFormats ' +\n        'ClipBoard_Empty ClipBoard_EnumFormats ClipBoard_FormatStr ' +\n        'ClipBoard_GetData ClipBoard_GetDataEx ClipBoard_GetFormatName ' +\n        'ClipBoard_GetOpenWindow ClipBoard_GetOwner ' +\n        'ClipBoard_GetPriorityFormat ClipBoard_GetSequenceNumber ' +\n        'ClipBoard_GetViewer ClipBoard_IsFormatAvailable ' +\n        'ClipBoard_Open ClipBoard_RegisterFormat ClipBoard_SetData ' +\n        'ClipBoard_SetDataEx ClipBoard_SetViewer ClipPutFile ' +\n        'ColorConvertHSLtoRGB ColorConvertRGBtoHSL ColorGetBlue ' +\n        'ColorGetCOLORREF ColorGetGreen ColorGetRed ColorGetRGB ' +\n        'ColorSetCOLORREF ColorSetRGB Crypt_DecryptData ' +\n        'Crypt_DecryptFile Crypt_DeriveKey Crypt_DestroyKey ' +\n        'Crypt_EncryptData Crypt_EncryptFile Crypt_GenRandom ' +\n        'Crypt_HashData Crypt_HashFile Crypt_Shutdown Crypt_Startup ' +\n        'DateAdd DateDayOfWeek DateDaysInMonth DateDiff ' +\n        'DateIsLeapYear DateIsValid DateTimeFormat DateTimeSplit ' +\n        'DateToDayOfWeek DateToDayOfWeekISO DateToDayValue ' +\n        'DateToMonth Date_Time_CompareFileTime ' +\n        'Date_Time_DOSDateTimeToArray Date_Time_DOSDateTimeToFileTime ' +\n        'Date_Time_DOSDateTimeToStr Date_Time_DOSDateToArray ' +\n        'Date_Time_DOSDateToStr Date_Time_DOSTimeToArray ' +\n        'Date_Time_DOSTimeToStr Date_Time_EncodeFileTime ' +\n        'Date_Time_EncodeSystemTime Date_Time_FileTimeToArray ' +\n        'Date_Time_FileTimeToDOSDateTime ' +\n        'Date_Time_FileTimeToLocalFileTime Date_Time_FileTimeToStr ' +\n        'Date_Time_FileTimeToSystemTime Date_Time_GetFileTime ' +\n        'Date_Time_GetLocalTime Date_Time_GetSystemTime ' +\n        'Date_Time_GetSystemTimeAdjustment ' +\n        'Date_Time_GetSystemTimeAsFileTime Date_Time_GetSystemTimes ' +\n        'Date_Time_GetTickCount Date_Time_GetTimeZoneInformation ' +\n        'Date_Time_LocalFileTimeToFileTime Date_Time_SetFileTime ' +\n        'Date_Time_SetLocalTime Date_Time_SetSystemTime ' +\n        'Date_Time_SetSystemTimeAdjustment ' +\n        'Date_Time_SetTimeZoneInformation Date_Time_SystemTimeToArray ' +\n        'Date_Time_SystemTimeToDateStr Date_Time_SystemTimeToDateTimeStr ' +\n        'Date_Time_SystemTimeToFileTime Date_Time_SystemTimeToTimeStr ' +\n        'Date_Time_SystemTimeToTzSpecificLocalTime ' +\n        'Date_Time_TzSpecificLocalTimeToSystemTime DayValueToDate ' +\n        'DebugBugReportEnv DebugCOMError DebugOut DebugReport ' +\n        'DebugReportEx DebugReportVar DebugSetup Degree ' +\n        'EventLog__Backup EventLog__Clear EventLog__Close ' +\n        'EventLog__Count EventLog__DeregisterSource EventLog__Full ' +\n        'EventLog__Notify EventLog__Oldest EventLog__Open ' +\n        'EventLog__OpenBackup EventLog__Read EventLog__RegisterSource ' +\n        'EventLog__Report Excel_BookAttach Excel_BookClose ' +\n        'Excel_BookList Excel_BookNew Excel_BookOpen ' +\n        'Excel_BookOpenText Excel_BookSave Excel_BookSaveAs ' +\n        'Excel_Close Excel_ColumnToLetter Excel_ColumnToNumber ' +\n        'Excel_ConvertFormula Excel_Export Excel_FilterGet ' +\n        'Excel_FilterSet Excel_Open Excel_PictureAdd Excel_Print ' +\n        'Excel_RangeCopyPaste Excel_RangeDelete Excel_RangeFind ' +\n        'Excel_RangeInsert Excel_RangeLinkAddRemove Excel_RangeRead ' +\n        'Excel_RangeReplace Excel_RangeSort Excel_RangeValidate ' +\n        'Excel_RangeWrite Excel_SheetAdd Excel_SheetCopyMove ' +\n        'Excel_SheetDelete Excel_SheetList FileCountLines FileCreate ' +\n        'FileListToArray FileListToArrayRec FilePrint ' +\n        'FileReadToArray FileWriteFromArray FileWriteLog ' +\n        'FileWriteToLine FTP_Close FTP_Command FTP_Connect ' +\n        'FTP_DecodeInternetStatus FTP_DirCreate FTP_DirDelete ' +\n        'FTP_DirGetCurrent FTP_DirPutContents FTP_DirSetCurrent ' +\n        'FTP_FileClose FTP_FileDelete FTP_FileGet FTP_FileGetSize ' +\n        'FTP_FileOpen FTP_FilePut FTP_FileRead FTP_FileRename ' +\n        'FTP_FileTimeLoHiToStr FTP_FindFileClose FTP_FindFileFirst ' +\n        'FTP_FindFileNext FTP_GetLastResponseInfo FTP_ListToArray ' +\n        'FTP_ListToArray2D FTP_ListToArrayEx FTP_Open ' +\n        'FTP_ProgressDownload FTP_ProgressUpload FTP_SetStatusCallback ' +\n        'GDIPlus_ArrowCapCreate GDIPlus_ArrowCapDispose ' +\n        'GDIPlus_ArrowCapGetFillState GDIPlus_ArrowCapGetHeight ' +\n        'GDIPlus_ArrowCapGetMiddleInset GDIPlus_ArrowCapGetWidth ' +\n        'GDIPlus_ArrowCapSetFillState GDIPlus_ArrowCapSetHeight ' +\n        'GDIPlus_ArrowCapSetMiddleInset GDIPlus_ArrowCapSetWidth ' +\n        'GDIPlus_BitmapApplyEffect GDIPlus_BitmapApplyEffectEx ' +\n        'GDIPlus_BitmapCloneArea GDIPlus_BitmapConvertFormat ' +\n        'GDIPlus_BitmapCreateApplyEffect ' +\n        'GDIPlus_BitmapCreateApplyEffectEx ' +\n        'GDIPlus_BitmapCreateDIBFromBitmap GDIPlus_BitmapCreateFromFile ' +\n        'GDIPlus_BitmapCreateFromGraphics ' +\n        'GDIPlus_BitmapCreateFromHBITMAP GDIPlus_BitmapCreateFromHICON ' +\n        'GDIPlus_BitmapCreateFromHICON32 GDIPlus_BitmapCreateFromMemory ' +\n        'GDIPlus_BitmapCreateFromResource GDIPlus_BitmapCreateFromScan0 ' +\n        'GDIPlus_BitmapCreateFromStream ' +\n        'GDIPlus_BitmapCreateHBITMAPFromBitmap GDIPlus_BitmapDispose ' +\n        'GDIPlus_BitmapGetHistogram GDIPlus_BitmapGetHistogramEx ' +\n        'GDIPlus_BitmapGetHistogramSize GDIPlus_BitmapGetPixel ' +\n        'GDIPlus_BitmapLockBits GDIPlus_BitmapSetPixel ' +\n        'GDIPlus_BitmapUnlockBits GDIPlus_BrushClone ' +\n        'GDIPlus_BrushCreateSolid GDIPlus_BrushDispose ' +\n        'GDIPlus_BrushGetSolidColor GDIPlus_BrushGetType ' +\n        'GDIPlus_BrushSetSolidColor GDIPlus_ColorMatrixCreate ' +\n        'GDIPlus_ColorMatrixCreateGrayScale ' +\n        'GDIPlus_ColorMatrixCreateNegative ' +\n        'GDIPlus_ColorMatrixCreateSaturation ' +\n        'GDIPlus_ColorMatrixCreateScale ' +\n        'GDIPlus_ColorMatrixCreateTranslate GDIPlus_CustomLineCapClone ' +\n        'GDIPlus_CustomLineCapCreate GDIPlus_CustomLineCapDispose ' +\n        'GDIPlus_CustomLineCapGetStrokeCaps ' +\n        'GDIPlus_CustomLineCapSetStrokeCaps GDIPlus_Decoders ' +\n        'GDIPlus_DecodersGetCount GDIPlus_DecodersGetSize ' +\n        'GDIPlus_DrawImageFX GDIPlus_DrawImageFXEx ' +\n        'GDIPlus_DrawImagePoints GDIPlus_EffectCreate ' +\n        'GDIPlus_EffectCreateBlur GDIPlus_EffectCreateBrightnessContrast ' +\n        'GDIPlus_EffectCreateColorBalance GDIPlus_EffectCreateColorCurve ' +\n        'GDIPlus_EffectCreateColorLUT GDIPlus_EffectCreateColorMatrix ' +\n        'GDIPlus_EffectCreateHueSaturationLightness ' +\n        'GDIPlus_EffectCreateLevels GDIPlus_EffectCreateRedEyeCorrection ' +\n        'GDIPlus_EffectCreateSharpen GDIPlus_EffectCreateTint ' +\n        'GDIPlus_EffectDispose GDIPlus_EffectGetParameters ' +\n        'GDIPlus_EffectSetParameters GDIPlus_Encoders ' +\n        'GDIPlus_EncodersGetCLSID GDIPlus_EncodersGetCount ' +\n        'GDIPlus_EncodersGetParamList GDIPlus_EncodersGetParamListSize ' +\n        'GDIPlus_EncodersGetSize GDIPlus_FontCreate ' +\n        'GDIPlus_FontDispose GDIPlus_FontFamilyCreate ' +\n        'GDIPlus_FontFamilyCreateFromCollection ' +\n        'GDIPlus_FontFamilyDispose GDIPlus_FontFamilyGetCellAscent ' +\n        'GDIPlus_FontFamilyGetCellDescent GDIPlus_FontFamilyGetEmHeight ' +\n        'GDIPlus_FontFamilyGetLineSpacing GDIPlus_FontGetHeight ' +\n        'GDIPlus_FontPrivateAddFont GDIPlus_FontPrivateAddMemoryFont ' +\n        'GDIPlus_FontPrivateCollectionDispose ' +\n        'GDIPlus_FontPrivateCreateCollection GDIPlus_GraphicsClear ' +\n        'GDIPlus_GraphicsCreateFromHDC GDIPlus_GraphicsCreateFromHWND ' +\n        'GDIPlus_GraphicsDispose GDIPlus_GraphicsDrawArc ' +\n        'GDIPlus_GraphicsDrawBezier GDIPlus_GraphicsDrawClosedCurve ' +\n        'GDIPlus_GraphicsDrawClosedCurve2 GDIPlus_GraphicsDrawCurve ' +\n        'GDIPlus_GraphicsDrawCurve2 GDIPlus_GraphicsDrawEllipse ' +\n        'GDIPlus_GraphicsDrawImage GDIPlus_GraphicsDrawImagePointsRect ' +\n        'GDIPlus_GraphicsDrawImageRect GDIPlus_GraphicsDrawImageRectRect ' +\n        'GDIPlus_GraphicsDrawLine GDIPlus_GraphicsDrawPath ' +\n        'GDIPlus_GraphicsDrawPie GDIPlus_GraphicsDrawPolygon ' +\n        'GDIPlus_GraphicsDrawRect GDIPlus_GraphicsDrawString ' +\n        'GDIPlus_GraphicsDrawStringEx GDIPlus_GraphicsFillClosedCurve ' +\n        'GDIPlus_GraphicsFillClosedCurve2 GDIPlus_GraphicsFillEllipse ' +\n        'GDIPlus_GraphicsFillPath GDIPlus_GraphicsFillPie ' +\n        'GDIPlus_GraphicsFillPolygon GDIPlus_GraphicsFillRect ' +\n        'GDIPlus_GraphicsFillRegion GDIPlus_GraphicsGetCompositingMode ' +\n        'GDIPlus_GraphicsGetCompositingQuality GDIPlus_GraphicsGetDC ' +\n        'GDIPlus_GraphicsGetInterpolationMode ' +\n        'GDIPlus_GraphicsGetSmoothingMode GDIPlus_GraphicsGetTransform ' +\n        'GDIPlus_GraphicsMeasureCharacterRanges ' +\n        'GDIPlus_GraphicsMeasureString GDIPlus_GraphicsReleaseDC ' +\n        'GDIPlus_GraphicsResetClip GDIPlus_GraphicsResetTransform ' +\n        'GDIPlus_GraphicsRestore GDIPlus_GraphicsRotateTransform ' +\n        'GDIPlus_GraphicsSave GDIPlus_GraphicsScaleTransform ' +\n        'GDIPlus_GraphicsSetClipPath GDIPlus_GraphicsSetClipRect ' +\n        'GDIPlus_GraphicsSetClipRegion ' +\n        'GDIPlus_GraphicsSetCompositingMode ' +\n        'GDIPlus_GraphicsSetCompositingQuality ' +\n        'GDIPlus_GraphicsSetInterpolationMode ' +\n        'GDIPlus_GraphicsSetPixelOffsetMode ' +\n        'GDIPlus_GraphicsSetSmoothingMode ' +\n        'GDIPlus_GraphicsSetTextRenderingHint ' +\n        'GDIPlus_GraphicsSetTransform GDIPlus_GraphicsTransformPoints ' +\n        'GDIPlus_GraphicsTranslateTransform GDIPlus_HatchBrushCreate ' +\n        'GDIPlus_HICONCreateFromBitmap GDIPlus_ImageAttributesCreate ' +\n        'GDIPlus_ImageAttributesDispose ' +\n        'GDIPlus_ImageAttributesSetColorKeys ' +\n        'GDIPlus_ImageAttributesSetColorMatrix GDIPlus_ImageDispose ' +\n        'GDIPlus_ImageGetDimension GDIPlus_ImageGetFlags ' +\n        'GDIPlus_ImageGetGraphicsContext GDIPlus_ImageGetHeight ' +\n        'GDIPlus_ImageGetHorizontalResolution ' +\n        'GDIPlus_ImageGetPixelFormat GDIPlus_ImageGetRawFormat ' +\n        'GDIPlus_ImageGetThumbnail GDIPlus_ImageGetType ' +\n        'GDIPlus_ImageGetVerticalResolution GDIPlus_ImageGetWidth ' +\n        'GDIPlus_ImageLoadFromFile GDIPlus_ImageLoadFromStream ' +\n        'GDIPlus_ImageResize GDIPlus_ImageRotateFlip ' +\n        'GDIPlus_ImageSaveToFile GDIPlus_ImageSaveToFileEx ' +\n        'GDIPlus_ImageSaveToStream GDIPlus_ImageScale ' +\n        'GDIPlus_LineBrushCreate GDIPlus_LineBrushCreateFromRect ' +\n        'GDIPlus_LineBrushCreateFromRectWithAngle ' +\n        'GDIPlus_LineBrushGetColors GDIPlus_LineBrushGetRect ' +\n        'GDIPlus_LineBrushMultiplyTransform ' +\n        'GDIPlus_LineBrushResetTransform GDIPlus_LineBrushSetBlend ' +\n        'GDIPlus_LineBrushSetColors GDIPlus_LineBrushSetGammaCorrection ' +\n        'GDIPlus_LineBrushSetLinearBlend GDIPlus_LineBrushSetPresetBlend ' +\n        'GDIPlus_LineBrushSetSigmaBlend GDIPlus_LineBrushSetTransform ' +\n        'GDIPlus_MatrixClone GDIPlus_MatrixCreate ' +\n        'GDIPlus_MatrixDispose GDIPlus_MatrixGetElements ' +\n        'GDIPlus_MatrixInvert GDIPlus_MatrixMultiply ' +\n        'GDIPlus_MatrixRotate GDIPlus_MatrixScale ' +\n        'GDIPlus_MatrixSetElements GDIPlus_MatrixShear ' +\n        'GDIPlus_MatrixTransformPoints GDIPlus_MatrixTranslate ' +\n        'GDIPlus_PaletteInitialize GDIPlus_ParamAdd GDIPlus_ParamInit ' +\n        'GDIPlus_ParamSize GDIPlus_PathAddArc GDIPlus_PathAddBezier ' +\n        'GDIPlus_PathAddClosedCurve GDIPlus_PathAddClosedCurve2 ' +\n        'GDIPlus_PathAddCurve GDIPlus_PathAddCurve2 ' +\n        'GDIPlus_PathAddCurve3 GDIPlus_PathAddEllipse ' +\n        'GDIPlus_PathAddLine GDIPlus_PathAddLine2 GDIPlus_PathAddPath ' +\n        'GDIPlus_PathAddPie GDIPlus_PathAddPolygon ' +\n        'GDIPlus_PathAddRectangle GDIPlus_PathAddString ' +\n        'GDIPlus_PathBrushCreate GDIPlus_PathBrushCreateFromPath ' +\n        'GDIPlus_PathBrushGetCenterPoint GDIPlus_PathBrushGetFocusScales ' +\n        'GDIPlus_PathBrushGetPointCount GDIPlus_PathBrushGetRect ' +\n        'GDIPlus_PathBrushGetWrapMode GDIPlus_PathBrushMultiplyTransform ' +\n        'GDIPlus_PathBrushResetTransform GDIPlus_PathBrushSetBlend ' +\n        'GDIPlus_PathBrushSetCenterColor GDIPlus_PathBrushSetCenterPoint ' +\n        'GDIPlus_PathBrushSetFocusScales ' +\n        'GDIPlus_PathBrushSetGammaCorrection ' +\n        'GDIPlus_PathBrushSetLinearBlend GDIPlus_PathBrushSetPresetBlend ' +\n        'GDIPlus_PathBrushSetSigmaBlend ' +\n        'GDIPlus_PathBrushSetSurroundColor ' +\n        'GDIPlus_PathBrushSetSurroundColorsWithCount ' +\n        'GDIPlus_PathBrushSetTransform GDIPlus_PathBrushSetWrapMode ' +\n        'GDIPlus_PathClone GDIPlus_PathCloseFigure GDIPlus_PathCreate ' +\n        'GDIPlus_PathCreate2 GDIPlus_PathDispose GDIPlus_PathFlatten ' +\n        'GDIPlus_PathGetData GDIPlus_PathGetFillMode ' +\n        'GDIPlus_PathGetLastPoint GDIPlus_PathGetPointCount ' +\n        'GDIPlus_PathGetPoints GDIPlus_PathGetWorldBounds ' +\n        'GDIPlus_PathIsOutlineVisiblePoint GDIPlus_PathIsVisiblePoint ' +\n        'GDIPlus_PathIterCreate GDIPlus_PathIterDispose ' +\n        'GDIPlus_PathIterGetSubpathCount GDIPlus_PathIterNextMarkerPath ' +\n        'GDIPlus_PathIterNextSubpathPath GDIPlus_PathIterRewind ' +\n        'GDIPlus_PathReset GDIPlus_PathReverse GDIPlus_PathSetFillMode ' +\n        'GDIPlus_PathSetMarker GDIPlus_PathStartFigure ' +\n        'GDIPlus_PathTransform GDIPlus_PathWarp GDIPlus_PathWiden ' +\n        'GDIPlus_PathWindingModeOutline GDIPlus_PenCreate ' +\n        'GDIPlus_PenCreate2 GDIPlus_PenDispose GDIPlus_PenGetAlignment ' +\n        'GDIPlus_PenGetColor GDIPlus_PenGetCustomEndCap ' +\n        'GDIPlus_PenGetDashCap GDIPlus_PenGetDashStyle ' +\n        'GDIPlus_PenGetEndCap GDIPlus_PenGetMiterLimit ' +\n        'GDIPlus_PenGetWidth GDIPlus_PenSetAlignment ' +\n        'GDIPlus_PenSetColor GDIPlus_PenSetCustomEndCap ' +\n        'GDIPlus_PenSetDashCap GDIPlus_PenSetDashStyle ' +\n        'GDIPlus_PenSetEndCap GDIPlus_PenSetLineCap ' +\n        'GDIPlus_PenSetLineJoin GDIPlus_PenSetMiterLimit ' +\n        'GDIPlus_PenSetStartCap GDIPlus_PenSetWidth ' +\n        'GDIPlus_RectFCreate GDIPlus_RegionClone ' +\n        'GDIPlus_RegionCombinePath GDIPlus_RegionCombineRect ' +\n        'GDIPlus_RegionCombineRegion GDIPlus_RegionCreate ' +\n        'GDIPlus_RegionCreateFromPath GDIPlus_RegionCreateFromRect ' +\n        'GDIPlus_RegionDispose GDIPlus_RegionGetBounds ' +\n        'GDIPlus_RegionGetHRgn GDIPlus_RegionTransform ' +\n        'GDIPlus_RegionTranslate GDIPlus_Shutdown GDIPlus_Startup ' +\n        'GDIPlus_StringFormatCreate GDIPlus_StringFormatDispose ' +\n        'GDIPlus_StringFormatGetMeasurableCharacterRangeCount ' +\n        'GDIPlus_StringFormatSetAlign GDIPlus_StringFormatSetLineAlign ' +\n        'GDIPlus_StringFormatSetMeasurableCharacterRanges ' +\n        'GDIPlus_TextureCreate GDIPlus_TextureCreate2 ' +\n        'GDIPlus_TextureCreateIA GetIP GUICtrlAVI_Close ' +\n        'GUICtrlAVI_Create GUICtrlAVI_Destroy GUICtrlAVI_IsPlaying ' +\n        'GUICtrlAVI_Open GUICtrlAVI_OpenEx GUICtrlAVI_Play ' +\n        'GUICtrlAVI_Seek GUICtrlAVI_Show GUICtrlAVI_Stop ' +\n        'GUICtrlButton_Click GUICtrlButton_Create ' +\n        'GUICtrlButton_Destroy GUICtrlButton_Enable ' +\n        'GUICtrlButton_GetCheck GUICtrlButton_GetFocus ' +\n        'GUICtrlButton_GetIdealSize GUICtrlButton_GetImage ' +\n        'GUICtrlButton_GetImageList GUICtrlButton_GetNote ' +\n        'GUICtrlButton_GetNoteLength GUICtrlButton_GetSplitInfo ' +\n        'GUICtrlButton_GetState GUICtrlButton_GetText ' +\n        'GUICtrlButton_GetTextMargin GUICtrlButton_SetCheck ' +\n        'GUICtrlButton_SetDontClick GUICtrlButton_SetFocus ' +\n        'GUICtrlButton_SetImage GUICtrlButton_SetImageList ' +\n        'GUICtrlButton_SetNote GUICtrlButton_SetShield ' +\n        'GUICtrlButton_SetSize GUICtrlButton_SetSplitInfo ' +\n        'GUICtrlButton_SetState GUICtrlButton_SetStyle ' +\n        'GUICtrlButton_SetText GUICtrlButton_SetTextMargin ' +\n        'GUICtrlButton_Show GUICtrlComboBoxEx_AddDir ' +\n        'GUICtrlComboBoxEx_AddString GUICtrlComboBoxEx_BeginUpdate ' +\n        'GUICtrlComboBoxEx_Create GUICtrlComboBoxEx_CreateSolidBitMap ' +\n        'GUICtrlComboBoxEx_DeleteString GUICtrlComboBoxEx_Destroy ' +\n        'GUICtrlComboBoxEx_EndUpdate GUICtrlComboBoxEx_FindStringExact ' +\n        'GUICtrlComboBoxEx_GetComboBoxInfo ' +\n        'GUICtrlComboBoxEx_GetComboControl GUICtrlComboBoxEx_GetCount ' +\n        'GUICtrlComboBoxEx_GetCurSel ' +\n        'GUICtrlComboBoxEx_GetDroppedControlRect ' +\n        'GUICtrlComboBoxEx_GetDroppedControlRectEx ' +\n        'GUICtrlComboBoxEx_GetDroppedState ' +\n        'GUICtrlComboBoxEx_GetDroppedWidth ' +\n        'GUICtrlComboBoxEx_GetEditControl GUICtrlComboBoxEx_GetEditSel ' +\n        'GUICtrlComboBoxEx_GetEditText ' +\n        'GUICtrlComboBoxEx_GetExtendedStyle ' +\n        'GUICtrlComboBoxEx_GetExtendedUI GUICtrlComboBoxEx_GetImageList ' +\n        'GUICtrlComboBoxEx_GetItem GUICtrlComboBoxEx_GetItemEx ' +\n        'GUICtrlComboBoxEx_GetItemHeight GUICtrlComboBoxEx_GetItemImage ' +\n        'GUICtrlComboBoxEx_GetItemIndent ' +\n        'GUICtrlComboBoxEx_GetItemOverlayImage ' +\n        'GUICtrlComboBoxEx_GetItemParam ' +\n        'GUICtrlComboBoxEx_GetItemSelectedImage ' +\n        'GUICtrlComboBoxEx_GetItemText GUICtrlComboBoxEx_GetItemTextLen ' +\n        'GUICtrlComboBoxEx_GetList GUICtrlComboBoxEx_GetListArray ' +\n        'GUICtrlComboBoxEx_GetLocale GUICtrlComboBoxEx_GetLocaleCountry ' +\n        'GUICtrlComboBoxEx_GetLocaleLang ' +\n        'GUICtrlComboBoxEx_GetLocalePrimLang ' +\n        'GUICtrlComboBoxEx_GetLocaleSubLang ' +\n        'GUICtrlComboBoxEx_GetMinVisible GUICtrlComboBoxEx_GetTopIndex ' +\n        'GUICtrlComboBoxEx_GetUnicode GUICtrlComboBoxEx_InitStorage ' +\n        'GUICtrlComboBoxEx_InsertString GUICtrlComboBoxEx_LimitText ' +\n        'GUICtrlComboBoxEx_ReplaceEditSel GUICtrlComboBoxEx_ResetContent ' +\n        'GUICtrlComboBoxEx_SetCurSel GUICtrlComboBoxEx_SetDroppedWidth ' +\n        'GUICtrlComboBoxEx_SetEditSel GUICtrlComboBoxEx_SetEditText ' +\n        'GUICtrlComboBoxEx_SetExtendedStyle ' +\n        'GUICtrlComboBoxEx_SetExtendedUI GUICtrlComboBoxEx_SetImageList ' +\n        'GUICtrlComboBoxEx_SetItem GUICtrlComboBoxEx_SetItemEx ' +\n        'GUICtrlComboBoxEx_SetItemHeight GUICtrlComboBoxEx_SetItemImage ' +\n        'GUICtrlComboBoxEx_SetItemIndent ' +\n        'GUICtrlComboBoxEx_SetItemOverlayImage ' +\n        'GUICtrlComboBoxEx_SetItemParam ' +\n        'GUICtrlComboBoxEx_SetItemSelectedImage ' +\n        'GUICtrlComboBoxEx_SetMinVisible GUICtrlComboBoxEx_SetTopIndex ' +\n        'GUICtrlComboBoxEx_SetUnicode GUICtrlComboBoxEx_ShowDropDown ' +\n        'GUICtrlComboBox_AddDir GUICtrlComboBox_AddString ' +\n        'GUICtrlComboBox_AutoComplete GUICtrlComboBox_BeginUpdate ' +\n        'GUICtrlComboBox_Create GUICtrlComboBox_DeleteString ' +\n        'GUICtrlComboBox_Destroy GUICtrlComboBox_EndUpdate ' +\n        'GUICtrlComboBox_FindString GUICtrlComboBox_FindStringExact ' +\n        'GUICtrlComboBox_GetComboBoxInfo GUICtrlComboBox_GetCount ' +\n        'GUICtrlComboBox_GetCueBanner GUICtrlComboBox_GetCurSel ' +\n        'GUICtrlComboBox_GetDroppedControlRect ' +\n        'GUICtrlComboBox_GetDroppedControlRectEx ' +\n        'GUICtrlComboBox_GetDroppedState GUICtrlComboBox_GetDroppedWidth ' +\n        'GUICtrlComboBox_GetEditSel GUICtrlComboBox_GetEditText ' +\n        'GUICtrlComboBox_GetExtendedUI ' +\n        'GUICtrlComboBox_GetHorizontalExtent ' +\n        'GUICtrlComboBox_GetItemHeight GUICtrlComboBox_GetLBText ' +\n        'GUICtrlComboBox_GetLBTextLen GUICtrlComboBox_GetList ' +\n        'GUICtrlComboBox_GetListArray GUICtrlComboBox_GetLocale ' +\n        'GUICtrlComboBox_GetLocaleCountry GUICtrlComboBox_GetLocaleLang ' +\n        'GUICtrlComboBox_GetLocalePrimLang ' +\n        'GUICtrlComboBox_GetLocaleSubLang GUICtrlComboBox_GetMinVisible ' +\n        'GUICtrlComboBox_GetTopIndex GUICtrlComboBox_InitStorage ' +\n        'GUICtrlComboBox_InsertString GUICtrlComboBox_LimitText ' +\n        'GUICtrlComboBox_ReplaceEditSel GUICtrlComboBox_ResetContent ' +\n        'GUICtrlComboBox_SelectString GUICtrlComboBox_SetCueBanner ' +\n        'GUICtrlComboBox_SetCurSel GUICtrlComboBox_SetDroppedWidth ' +\n        'GUICtrlComboBox_SetEditSel GUICtrlComboBox_SetEditText ' +\n        'GUICtrlComboBox_SetExtendedUI ' +\n        'GUICtrlComboBox_SetHorizontalExtent ' +\n        'GUICtrlComboBox_SetItemHeight GUICtrlComboBox_SetMinVisible ' +\n        'GUICtrlComboBox_SetTopIndex GUICtrlComboBox_ShowDropDown ' +\n        'GUICtrlDTP_Create GUICtrlDTP_Destroy GUICtrlDTP_GetMCColor ' +\n        'GUICtrlDTP_GetMCFont GUICtrlDTP_GetMonthCal ' +\n        'GUICtrlDTP_GetRange GUICtrlDTP_GetRangeEx ' +\n        'GUICtrlDTP_GetSystemTime GUICtrlDTP_GetSystemTimeEx ' +\n        'GUICtrlDTP_SetFormat GUICtrlDTP_SetMCColor ' +\n        'GUICtrlDTP_SetMCFont GUICtrlDTP_SetRange ' +\n        'GUICtrlDTP_SetRangeEx GUICtrlDTP_SetSystemTime ' +\n        'GUICtrlDTP_SetSystemTimeEx GUICtrlEdit_AppendText ' +\n        'GUICtrlEdit_BeginUpdate GUICtrlEdit_CanUndo ' +\n        'GUICtrlEdit_CharFromPos GUICtrlEdit_Create ' +\n        'GUICtrlEdit_Destroy GUICtrlEdit_EmptyUndoBuffer ' +\n        'GUICtrlEdit_EndUpdate GUICtrlEdit_Find GUICtrlEdit_FmtLines ' +\n        'GUICtrlEdit_GetCueBanner GUICtrlEdit_GetFirstVisibleLine ' +\n        'GUICtrlEdit_GetLimitText GUICtrlEdit_GetLine ' +\n        'GUICtrlEdit_GetLineCount GUICtrlEdit_GetMargins ' +\n        'GUICtrlEdit_GetModify GUICtrlEdit_GetPasswordChar ' +\n        'GUICtrlEdit_GetRECT GUICtrlEdit_GetRECTEx GUICtrlEdit_GetSel ' +\n        'GUICtrlEdit_GetText GUICtrlEdit_GetTextLen ' +\n        'GUICtrlEdit_HideBalloonTip GUICtrlEdit_InsertText ' +\n        'GUICtrlEdit_LineFromChar GUICtrlEdit_LineIndex ' +\n        'GUICtrlEdit_LineLength GUICtrlEdit_LineScroll ' +\n        'GUICtrlEdit_PosFromChar GUICtrlEdit_ReplaceSel ' +\n        'GUICtrlEdit_Scroll GUICtrlEdit_SetCueBanner ' +\n        'GUICtrlEdit_SetLimitText GUICtrlEdit_SetMargins ' +\n        'GUICtrlEdit_SetModify GUICtrlEdit_SetPasswordChar ' +\n        'GUICtrlEdit_SetReadOnly GUICtrlEdit_SetRECT ' +\n        'GUICtrlEdit_SetRECTEx GUICtrlEdit_SetRECTNP ' +\n        'GUICtrlEdit_SetRectNPEx GUICtrlEdit_SetSel ' +\n        'GUICtrlEdit_SetTabStops GUICtrlEdit_SetText ' +\n        'GUICtrlEdit_ShowBalloonTip GUICtrlEdit_Undo ' +\n        'GUICtrlHeader_AddItem GUICtrlHeader_ClearFilter ' +\n        'GUICtrlHeader_ClearFilterAll GUICtrlHeader_Create ' +\n        'GUICtrlHeader_CreateDragImage GUICtrlHeader_DeleteItem ' +\n        'GUICtrlHeader_Destroy GUICtrlHeader_EditFilter ' +\n        'GUICtrlHeader_GetBitmapMargin GUICtrlHeader_GetImageList ' +\n        'GUICtrlHeader_GetItem GUICtrlHeader_GetItemAlign ' +\n        'GUICtrlHeader_GetItemBitmap GUICtrlHeader_GetItemCount ' +\n        'GUICtrlHeader_GetItemDisplay GUICtrlHeader_GetItemFlags ' +\n        'GUICtrlHeader_GetItemFormat GUICtrlHeader_GetItemImage ' +\n        'GUICtrlHeader_GetItemOrder GUICtrlHeader_GetItemParam ' +\n        'GUICtrlHeader_GetItemRect GUICtrlHeader_GetItemRectEx ' +\n        'GUICtrlHeader_GetItemText GUICtrlHeader_GetItemWidth ' +\n        'GUICtrlHeader_GetOrderArray GUICtrlHeader_GetUnicodeFormat ' +\n        'GUICtrlHeader_HitTest GUICtrlHeader_InsertItem ' +\n        'GUICtrlHeader_Layout GUICtrlHeader_OrderToIndex ' +\n        'GUICtrlHeader_SetBitmapMargin ' +\n        'GUICtrlHeader_SetFilterChangeTimeout ' +\n        'GUICtrlHeader_SetHotDivider GUICtrlHeader_SetImageList ' +\n        'GUICtrlHeader_SetItem GUICtrlHeader_SetItemAlign ' +\n        'GUICtrlHeader_SetItemBitmap GUICtrlHeader_SetItemDisplay ' +\n        'GUICtrlHeader_SetItemFlags GUICtrlHeader_SetItemFormat ' +\n        'GUICtrlHeader_SetItemImage GUICtrlHeader_SetItemOrder ' +\n        'GUICtrlHeader_SetItemParam GUICtrlHeader_SetItemText ' +\n        'GUICtrlHeader_SetItemWidth GUICtrlHeader_SetOrderArray ' +\n        'GUICtrlHeader_SetUnicodeFormat GUICtrlIpAddress_ClearAddress ' +\n        'GUICtrlIpAddress_Create GUICtrlIpAddress_Destroy ' +\n        'GUICtrlIpAddress_Get GUICtrlIpAddress_GetArray ' +\n        'GUICtrlIpAddress_GetEx GUICtrlIpAddress_IsBlank ' +\n        'GUICtrlIpAddress_Set GUICtrlIpAddress_SetArray ' +\n        'GUICtrlIpAddress_SetEx GUICtrlIpAddress_SetFocus ' +\n        'GUICtrlIpAddress_SetFont GUICtrlIpAddress_SetRange ' +\n        'GUICtrlIpAddress_ShowHide GUICtrlListBox_AddFile ' +\n        'GUICtrlListBox_AddString GUICtrlListBox_BeginUpdate ' +\n        'GUICtrlListBox_ClickItem GUICtrlListBox_Create ' +\n        'GUICtrlListBox_DeleteString GUICtrlListBox_Destroy ' +\n        'GUICtrlListBox_Dir GUICtrlListBox_EndUpdate ' +\n        'GUICtrlListBox_FindInText GUICtrlListBox_FindString ' +\n        'GUICtrlListBox_GetAnchorIndex GUICtrlListBox_GetCaretIndex ' +\n        'GUICtrlListBox_GetCount GUICtrlListBox_GetCurSel ' +\n        'GUICtrlListBox_GetHorizontalExtent GUICtrlListBox_GetItemData ' +\n        'GUICtrlListBox_GetItemHeight GUICtrlListBox_GetItemRect ' +\n        'GUICtrlListBox_GetItemRectEx GUICtrlListBox_GetListBoxInfo ' +\n        'GUICtrlListBox_GetLocale GUICtrlListBox_GetLocaleCountry ' +\n        'GUICtrlListBox_GetLocaleLang GUICtrlListBox_GetLocalePrimLang ' +\n        'GUICtrlListBox_GetLocaleSubLang GUICtrlListBox_GetSel ' +\n        'GUICtrlListBox_GetSelCount GUICtrlListBox_GetSelItems ' +\n        'GUICtrlListBox_GetSelItemsText GUICtrlListBox_GetText ' +\n        'GUICtrlListBox_GetTextLen GUICtrlListBox_GetTopIndex ' +\n        'GUICtrlListBox_InitStorage GUICtrlListBox_InsertString ' +\n        'GUICtrlListBox_ItemFromPoint GUICtrlListBox_ReplaceString ' +\n        'GUICtrlListBox_ResetContent GUICtrlListBox_SelectString ' +\n        'GUICtrlListBox_SelItemRange GUICtrlListBox_SelItemRangeEx ' +\n        'GUICtrlListBox_SetAnchorIndex GUICtrlListBox_SetCaretIndex ' +\n        'GUICtrlListBox_SetColumnWidth GUICtrlListBox_SetCurSel ' +\n        'GUICtrlListBox_SetHorizontalExtent GUICtrlListBox_SetItemData ' +\n        'GUICtrlListBox_SetItemHeight GUICtrlListBox_SetLocale ' +\n        'GUICtrlListBox_SetSel GUICtrlListBox_SetTabStops ' +\n        'GUICtrlListBox_SetTopIndex GUICtrlListBox_Sort ' +\n        'GUICtrlListBox_SwapString GUICtrlListBox_UpdateHScroll ' +\n        'GUICtrlListView_AddArray GUICtrlListView_AddColumn ' +\n        'GUICtrlListView_AddItem GUICtrlListView_AddSubItem ' +\n        'GUICtrlListView_ApproximateViewHeight ' +\n        'GUICtrlListView_ApproximateViewRect ' +\n        'GUICtrlListView_ApproximateViewWidth GUICtrlListView_Arrange ' +\n        'GUICtrlListView_BeginUpdate GUICtrlListView_CancelEditLabel ' +\n        'GUICtrlListView_ClickItem GUICtrlListView_CopyItems ' +\n        'GUICtrlListView_Create GUICtrlListView_CreateDragImage ' +\n        'GUICtrlListView_CreateSolidBitMap ' +\n        'GUICtrlListView_DeleteAllItems GUICtrlListView_DeleteColumn ' +\n        'GUICtrlListView_DeleteItem GUICtrlListView_DeleteItemsSelected ' +\n        'GUICtrlListView_Destroy GUICtrlListView_DrawDragImage ' +\n        'GUICtrlListView_EditLabel GUICtrlListView_EnableGroupView ' +\n        'GUICtrlListView_EndUpdate GUICtrlListView_EnsureVisible ' +\n        'GUICtrlListView_FindInText GUICtrlListView_FindItem ' +\n        'GUICtrlListView_FindNearest GUICtrlListView_FindParam ' +\n        'GUICtrlListView_FindText GUICtrlListView_GetBkColor ' +\n        'GUICtrlListView_GetBkImage GUICtrlListView_GetCallbackMask ' +\n        'GUICtrlListView_GetColumn GUICtrlListView_GetColumnCount ' +\n        'GUICtrlListView_GetColumnOrder ' +\n        'GUICtrlListView_GetColumnOrderArray ' +\n        'GUICtrlListView_GetColumnWidth GUICtrlListView_GetCounterPage ' +\n        'GUICtrlListView_GetEditControl ' +\n        'GUICtrlListView_GetExtendedListViewStyle ' +\n        'GUICtrlListView_GetFocusedGroup GUICtrlListView_GetGroupCount ' +\n        'GUICtrlListView_GetGroupInfo ' +\n        'GUICtrlListView_GetGroupInfoByIndex ' +\n        'GUICtrlListView_GetGroupRect ' +\n        'GUICtrlListView_GetGroupViewEnabled GUICtrlListView_GetHeader ' +\n        'GUICtrlListView_GetHotCursor GUICtrlListView_GetHotItem ' +\n        'GUICtrlListView_GetHoverTime GUICtrlListView_GetImageList ' +\n        'GUICtrlListView_GetISearchString GUICtrlListView_GetItem ' +\n        'GUICtrlListView_GetItemChecked GUICtrlListView_GetItemCount ' +\n        'GUICtrlListView_GetItemCut GUICtrlListView_GetItemDropHilited ' +\n        'GUICtrlListView_GetItemEx GUICtrlListView_GetItemFocused ' +\n        'GUICtrlListView_GetItemGroupID GUICtrlListView_GetItemImage ' +\n        'GUICtrlListView_GetItemIndent GUICtrlListView_GetItemParam ' +\n        'GUICtrlListView_GetItemPosition ' +\n        'GUICtrlListView_GetItemPositionX ' +\n        'GUICtrlListView_GetItemPositionY GUICtrlListView_GetItemRect ' +\n        'GUICtrlListView_GetItemRectEx GUICtrlListView_GetItemSelected ' +\n        'GUICtrlListView_GetItemSpacing GUICtrlListView_GetItemSpacingX ' +\n        'GUICtrlListView_GetItemSpacingY GUICtrlListView_GetItemState ' +\n        'GUICtrlListView_GetItemStateImage GUICtrlListView_GetItemText ' +\n        'GUICtrlListView_GetItemTextArray ' +\n        'GUICtrlListView_GetItemTextString GUICtrlListView_GetNextItem ' +\n        'GUICtrlListView_GetNumberOfWorkAreas GUICtrlListView_GetOrigin ' +\n        'GUICtrlListView_GetOriginX GUICtrlListView_GetOriginY ' +\n        'GUICtrlListView_GetOutlineColor ' +\n        'GUICtrlListView_GetSelectedColumn ' +\n        'GUICtrlListView_GetSelectedCount ' +\n        'GUICtrlListView_GetSelectedIndices ' +\n        'GUICtrlListView_GetSelectionMark GUICtrlListView_GetStringWidth ' +\n        'GUICtrlListView_GetSubItemRect GUICtrlListView_GetTextBkColor ' +\n        'GUICtrlListView_GetTextColor GUICtrlListView_GetToolTips ' +\n        'GUICtrlListView_GetTopIndex GUICtrlListView_GetUnicodeFormat ' +\n        'GUICtrlListView_GetView GUICtrlListView_GetViewDetails ' +\n        'GUICtrlListView_GetViewLarge GUICtrlListView_GetViewList ' +\n        'GUICtrlListView_GetViewRect GUICtrlListView_GetViewSmall ' +\n        'GUICtrlListView_GetViewTile GUICtrlListView_HideColumn ' +\n        'GUICtrlListView_HitTest GUICtrlListView_InsertColumn ' +\n        'GUICtrlListView_InsertGroup GUICtrlListView_InsertItem ' +\n        'GUICtrlListView_JustifyColumn GUICtrlListView_MapIDToIndex ' +\n        'GUICtrlListView_MapIndexToID GUICtrlListView_RedrawItems ' +\n        'GUICtrlListView_RegisterSortCallBack ' +\n        'GUICtrlListView_RemoveAllGroups GUICtrlListView_RemoveGroup ' +\n        'GUICtrlListView_Scroll GUICtrlListView_SetBkColor ' +\n        'GUICtrlListView_SetBkImage GUICtrlListView_SetCallBackMask ' +\n        'GUICtrlListView_SetColumn GUICtrlListView_SetColumnOrder ' +\n        'GUICtrlListView_SetColumnOrderArray ' +\n        'GUICtrlListView_SetColumnWidth ' +\n        'GUICtrlListView_SetExtendedListViewStyle ' +\n        'GUICtrlListView_SetGroupInfo GUICtrlListView_SetHotItem ' +\n        'GUICtrlListView_SetHoverTime GUICtrlListView_SetIconSpacing ' +\n        'GUICtrlListView_SetImageList GUICtrlListView_SetItem ' +\n        'GUICtrlListView_SetItemChecked GUICtrlListView_SetItemCount ' +\n        'GUICtrlListView_SetItemCut GUICtrlListView_SetItemDropHilited ' +\n        'GUICtrlListView_SetItemEx GUICtrlListView_SetItemFocused ' +\n        'GUICtrlListView_SetItemGroupID GUICtrlListView_SetItemImage ' +\n        'GUICtrlListView_SetItemIndent GUICtrlListView_SetItemParam ' +\n        'GUICtrlListView_SetItemPosition ' +\n        'GUICtrlListView_SetItemPosition32 ' +\n        'GUICtrlListView_SetItemSelected GUICtrlListView_SetItemState ' +\n        'GUICtrlListView_SetItemStateImage GUICtrlListView_SetItemText ' +\n        'GUICtrlListView_SetOutlineColor ' +\n        'GUICtrlListView_SetSelectedColumn ' +\n        'GUICtrlListView_SetSelectionMark GUICtrlListView_SetTextBkColor ' +\n        'GUICtrlListView_SetTextColor GUICtrlListView_SetToolTips ' +\n        'GUICtrlListView_SetUnicodeFormat GUICtrlListView_SetView ' +\n        'GUICtrlListView_SetWorkAreas GUICtrlListView_SimpleSort ' +\n        'GUICtrlListView_SortItems GUICtrlListView_SubItemHitTest ' +\n        'GUICtrlListView_UnRegisterSortCallBack GUICtrlMenu_AddMenuItem ' +\n        'GUICtrlMenu_AppendMenu GUICtrlMenu_CalculatePopupWindowPosition ' +\n        'GUICtrlMenu_CheckMenuItem GUICtrlMenu_CheckRadioItem ' +\n        'GUICtrlMenu_CreateMenu GUICtrlMenu_CreatePopup ' +\n        'GUICtrlMenu_DeleteMenu GUICtrlMenu_DestroyMenu ' +\n        'GUICtrlMenu_DrawMenuBar GUICtrlMenu_EnableMenuItem ' +\n        'GUICtrlMenu_FindItem GUICtrlMenu_FindParent ' +\n        'GUICtrlMenu_GetItemBmp GUICtrlMenu_GetItemBmpChecked ' +\n        'GUICtrlMenu_GetItemBmpUnchecked GUICtrlMenu_GetItemChecked ' +\n        'GUICtrlMenu_GetItemCount GUICtrlMenu_GetItemData ' +\n        'GUICtrlMenu_GetItemDefault GUICtrlMenu_GetItemDisabled ' +\n        'GUICtrlMenu_GetItemEnabled GUICtrlMenu_GetItemGrayed ' +\n        'GUICtrlMenu_GetItemHighlighted GUICtrlMenu_GetItemID ' +\n        'GUICtrlMenu_GetItemInfo GUICtrlMenu_GetItemRect ' +\n        'GUICtrlMenu_GetItemRectEx GUICtrlMenu_GetItemState ' +\n        'GUICtrlMenu_GetItemStateEx GUICtrlMenu_GetItemSubMenu ' +\n        'GUICtrlMenu_GetItemText GUICtrlMenu_GetItemType ' +\n        'GUICtrlMenu_GetMenu GUICtrlMenu_GetMenuBackground ' +\n        'GUICtrlMenu_GetMenuBarInfo GUICtrlMenu_GetMenuContextHelpID ' +\n        'GUICtrlMenu_GetMenuData GUICtrlMenu_GetMenuDefaultItem ' +\n        'GUICtrlMenu_GetMenuHeight GUICtrlMenu_GetMenuInfo ' +\n        'GUICtrlMenu_GetMenuStyle GUICtrlMenu_GetSystemMenu ' +\n        'GUICtrlMenu_InsertMenuItem GUICtrlMenu_InsertMenuItemEx ' +\n        'GUICtrlMenu_IsMenu GUICtrlMenu_LoadMenu ' +\n        'GUICtrlMenu_MapAccelerator GUICtrlMenu_MenuItemFromPoint ' +\n        'GUICtrlMenu_RemoveMenu GUICtrlMenu_SetItemBitmaps ' +\n        'GUICtrlMenu_SetItemBmp GUICtrlMenu_SetItemBmpChecked ' +\n        'GUICtrlMenu_SetItemBmpUnchecked GUICtrlMenu_SetItemChecked ' +\n        'GUICtrlMenu_SetItemData GUICtrlMenu_SetItemDefault ' +\n        'GUICtrlMenu_SetItemDisabled GUICtrlMenu_SetItemEnabled ' +\n        'GUICtrlMenu_SetItemGrayed GUICtrlMenu_SetItemHighlighted ' +\n        'GUICtrlMenu_SetItemID GUICtrlMenu_SetItemInfo ' +\n        'GUICtrlMenu_SetItemState GUICtrlMenu_SetItemSubMenu ' +\n        'GUICtrlMenu_SetItemText GUICtrlMenu_SetItemType ' +\n        'GUICtrlMenu_SetMenu GUICtrlMenu_SetMenuBackground ' +\n        'GUICtrlMenu_SetMenuContextHelpID GUICtrlMenu_SetMenuData ' +\n        'GUICtrlMenu_SetMenuDefaultItem GUICtrlMenu_SetMenuHeight ' +\n        'GUICtrlMenu_SetMenuInfo GUICtrlMenu_SetMenuStyle ' +\n        'GUICtrlMenu_TrackPopupMenu GUICtrlMonthCal_Create ' +\n        'GUICtrlMonthCal_Destroy GUICtrlMonthCal_GetCalendarBorder ' +\n        'GUICtrlMonthCal_GetCalendarCount GUICtrlMonthCal_GetColor ' +\n        'GUICtrlMonthCal_GetColorArray GUICtrlMonthCal_GetCurSel ' +\n        'GUICtrlMonthCal_GetCurSelStr GUICtrlMonthCal_GetFirstDOW ' +\n        'GUICtrlMonthCal_GetFirstDOWStr GUICtrlMonthCal_GetMaxSelCount ' +\n        'GUICtrlMonthCal_GetMaxTodayWidth ' +\n        'GUICtrlMonthCal_GetMinReqHeight GUICtrlMonthCal_GetMinReqRect ' +\n        'GUICtrlMonthCal_GetMinReqRectArray ' +\n        'GUICtrlMonthCal_GetMinReqWidth GUICtrlMonthCal_GetMonthDelta ' +\n        'GUICtrlMonthCal_GetMonthRange GUICtrlMonthCal_GetMonthRangeMax ' +\n        'GUICtrlMonthCal_GetMonthRangeMaxStr ' +\n        'GUICtrlMonthCal_GetMonthRangeMin ' +\n        'GUICtrlMonthCal_GetMonthRangeMinStr ' +\n        'GUICtrlMonthCal_GetMonthRangeSpan GUICtrlMonthCal_GetRange ' +\n        'GUICtrlMonthCal_GetRangeMax GUICtrlMonthCal_GetRangeMaxStr ' +\n        'GUICtrlMonthCal_GetRangeMin GUICtrlMonthCal_GetRangeMinStr ' +\n        'GUICtrlMonthCal_GetSelRange GUICtrlMonthCal_GetSelRangeMax ' +\n        'GUICtrlMonthCal_GetSelRangeMaxStr ' +\n        'GUICtrlMonthCal_GetSelRangeMin ' +\n        'GUICtrlMonthCal_GetSelRangeMinStr GUICtrlMonthCal_GetToday ' +\n        'GUICtrlMonthCal_GetTodayStr GUICtrlMonthCal_GetUnicodeFormat ' +\n        'GUICtrlMonthCal_HitTest GUICtrlMonthCal_SetCalendarBorder ' +\n        'GUICtrlMonthCal_SetColor GUICtrlMonthCal_SetCurSel ' +\n        'GUICtrlMonthCal_SetDayState GUICtrlMonthCal_SetFirstDOW ' +\n        'GUICtrlMonthCal_SetMaxSelCount GUICtrlMonthCal_SetMonthDelta ' +\n        'GUICtrlMonthCal_SetRange GUICtrlMonthCal_SetSelRange ' +\n        'GUICtrlMonthCal_SetToday GUICtrlMonthCal_SetUnicodeFormat ' +\n        'GUICtrlRebar_AddBand GUICtrlRebar_AddToolBarBand ' +\n        'GUICtrlRebar_BeginDrag GUICtrlRebar_Create ' +\n        'GUICtrlRebar_DeleteBand GUICtrlRebar_Destroy ' +\n        'GUICtrlRebar_DragMove GUICtrlRebar_EndDrag ' +\n        'GUICtrlRebar_GetBandBackColor GUICtrlRebar_GetBandBorders ' +\n        'GUICtrlRebar_GetBandBordersEx GUICtrlRebar_GetBandChildHandle ' +\n        'GUICtrlRebar_GetBandChildSize GUICtrlRebar_GetBandCount ' +\n        'GUICtrlRebar_GetBandForeColor GUICtrlRebar_GetBandHeaderSize ' +\n        'GUICtrlRebar_GetBandID GUICtrlRebar_GetBandIdealSize ' +\n        'GUICtrlRebar_GetBandLength GUICtrlRebar_GetBandLParam ' +\n        'GUICtrlRebar_GetBandMargins GUICtrlRebar_GetBandMarginsEx ' +\n        'GUICtrlRebar_GetBandRect GUICtrlRebar_GetBandRectEx ' +\n        'GUICtrlRebar_GetBandStyle GUICtrlRebar_GetBandStyleBreak ' +\n        'GUICtrlRebar_GetBandStyleChildEdge ' +\n        'GUICtrlRebar_GetBandStyleFixedBMP ' +\n        'GUICtrlRebar_GetBandStyleFixedSize ' +\n        'GUICtrlRebar_GetBandStyleGripperAlways ' +\n        'GUICtrlRebar_GetBandStyleHidden ' +\n        'GUICtrlRebar_GetBandStyleHideTitle ' +\n        'GUICtrlRebar_GetBandStyleNoGripper ' +\n        'GUICtrlRebar_GetBandStyleTopAlign ' +\n        'GUICtrlRebar_GetBandStyleUseChevron ' +\n        'GUICtrlRebar_GetBandStyleVariableHeight ' +\n        'GUICtrlRebar_GetBandText GUICtrlRebar_GetBarHeight ' +\n        'GUICtrlRebar_GetBarInfo GUICtrlRebar_GetBKColor ' +\n        'GUICtrlRebar_GetColorScheme GUICtrlRebar_GetRowCount ' +\n        'GUICtrlRebar_GetRowHeight GUICtrlRebar_GetTextColor ' +\n        'GUICtrlRebar_GetToolTips GUICtrlRebar_GetUnicodeFormat ' +\n        'GUICtrlRebar_HitTest GUICtrlRebar_IDToIndex ' +\n        'GUICtrlRebar_MaximizeBand GUICtrlRebar_MinimizeBand ' +\n        'GUICtrlRebar_MoveBand GUICtrlRebar_SetBandBackColor ' +\n        'GUICtrlRebar_SetBandForeColor GUICtrlRebar_SetBandHeaderSize ' +\n        'GUICtrlRebar_SetBandID GUICtrlRebar_SetBandIdealSize ' +\n        'GUICtrlRebar_SetBandLength GUICtrlRebar_SetBandLParam ' +\n        'GUICtrlRebar_SetBandStyle GUICtrlRebar_SetBandStyleBreak ' +\n        'GUICtrlRebar_SetBandStyleChildEdge ' +\n        'GUICtrlRebar_SetBandStyleFixedBMP ' +\n        'GUICtrlRebar_SetBandStyleFixedSize ' +\n        'GUICtrlRebar_SetBandStyleGripperAlways ' +\n        'GUICtrlRebar_SetBandStyleHidden ' +\n        'GUICtrlRebar_SetBandStyleHideTitle ' +\n        'GUICtrlRebar_SetBandStyleNoGripper ' +\n        'GUICtrlRebar_SetBandStyleTopAlign ' +\n        'GUICtrlRebar_SetBandStyleUseChevron ' +\n        'GUICtrlRebar_SetBandStyleVariableHeight ' +\n        'GUICtrlRebar_SetBandText GUICtrlRebar_SetBarInfo ' +\n        'GUICtrlRebar_SetBKColor GUICtrlRebar_SetColorScheme ' +\n        'GUICtrlRebar_SetTextColor GUICtrlRebar_SetToolTips ' +\n        'GUICtrlRebar_SetUnicodeFormat GUICtrlRebar_ShowBand ' +\n        'GUICtrlRichEdit_AppendText GUICtrlRichEdit_AutoDetectURL ' +\n        'GUICtrlRichEdit_CanPaste GUICtrlRichEdit_CanPasteSpecial ' +\n        'GUICtrlRichEdit_CanRedo GUICtrlRichEdit_CanUndo ' +\n        'GUICtrlRichEdit_ChangeFontSize GUICtrlRichEdit_Copy ' +\n        'GUICtrlRichEdit_Create GUICtrlRichEdit_Cut ' +\n        'GUICtrlRichEdit_Deselect GUICtrlRichEdit_Destroy ' +\n        'GUICtrlRichEdit_EmptyUndoBuffer GUICtrlRichEdit_FindText ' +\n        'GUICtrlRichEdit_FindTextInRange GUICtrlRichEdit_GetBkColor ' +\n        'GUICtrlRichEdit_GetCharAttributes ' +\n        'GUICtrlRichEdit_GetCharBkColor GUICtrlRichEdit_GetCharColor ' +\n        'GUICtrlRichEdit_GetCharPosFromXY ' +\n        'GUICtrlRichEdit_GetCharPosOfNextWord ' +\n        'GUICtrlRichEdit_GetCharPosOfPreviousWord ' +\n        'GUICtrlRichEdit_GetCharWordBreakInfo ' +\n        'GUICtrlRichEdit_GetFirstCharPosOnLine GUICtrlRichEdit_GetFont ' +\n        'GUICtrlRichEdit_GetLineCount GUICtrlRichEdit_GetLineLength ' +\n        'GUICtrlRichEdit_GetLineNumberFromCharPos ' +\n        'GUICtrlRichEdit_GetNextRedo GUICtrlRichEdit_GetNextUndo ' +\n        'GUICtrlRichEdit_GetNumberOfFirstVisibleLine ' +\n        'GUICtrlRichEdit_GetParaAlignment ' +\n        'GUICtrlRichEdit_GetParaAttributes GUICtrlRichEdit_GetParaBorder ' +\n        'GUICtrlRichEdit_GetParaIndents GUICtrlRichEdit_GetParaNumbering ' +\n        'GUICtrlRichEdit_GetParaShading GUICtrlRichEdit_GetParaSpacing ' +\n        'GUICtrlRichEdit_GetParaTabStops GUICtrlRichEdit_GetPasswordChar ' +\n        'GUICtrlRichEdit_GetRECT GUICtrlRichEdit_GetScrollPos ' +\n        'GUICtrlRichEdit_GetSel GUICtrlRichEdit_GetSelAA ' +\n        'GUICtrlRichEdit_GetSelText GUICtrlRichEdit_GetSpaceUnit ' +\n        'GUICtrlRichEdit_GetText GUICtrlRichEdit_GetTextInLine ' +\n        'GUICtrlRichEdit_GetTextInRange GUICtrlRichEdit_GetTextLength ' +\n        'GUICtrlRichEdit_GetVersion GUICtrlRichEdit_GetXYFromCharPos ' +\n        'GUICtrlRichEdit_GetZoom GUICtrlRichEdit_GotoCharPos ' +\n        'GUICtrlRichEdit_HideSelection GUICtrlRichEdit_InsertText ' +\n        'GUICtrlRichEdit_IsModified GUICtrlRichEdit_IsTextSelected ' +\n        'GUICtrlRichEdit_Paste GUICtrlRichEdit_PasteSpecial ' +\n        'GUICtrlRichEdit_PauseRedraw GUICtrlRichEdit_Redo ' +\n        'GUICtrlRichEdit_ReplaceText GUICtrlRichEdit_ResumeRedraw ' +\n        'GUICtrlRichEdit_ScrollLineOrPage GUICtrlRichEdit_ScrollLines ' +\n        'GUICtrlRichEdit_ScrollToCaret GUICtrlRichEdit_SetBkColor ' +\n        'GUICtrlRichEdit_SetCharAttributes ' +\n        'GUICtrlRichEdit_SetCharBkColor GUICtrlRichEdit_SetCharColor ' +\n        'GUICtrlRichEdit_SetEventMask GUICtrlRichEdit_SetFont ' +\n        'GUICtrlRichEdit_SetLimitOnText GUICtrlRichEdit_SetModified ' +\n        'GUICtrlRichEdit_SetParaAlignment ' +\n        'GUICtrlRichEdit_SetParaAttributes GUICtrlRichEdit_SetParaBorder ' +\n        'GUICtrlRichEdit_SetParaIndents GUICtrlRichEdit_SetParaNumbering ' +\n        'GUICtrlRichEdit_SetParaShading GUICtrlRichEdit_SetParaSpacing ' +\n        'GUICtrlRichEdit_SetParaTabStops GUICtrlRichEdit_SetPasswordChar ' +\n        'GUICtrlRichEdit_SetReadOnly GUICtrlRichEdit_SetRECT ' +\n        'GUICtrlRichEdit_SetScrollPos GUICtrlRichEdit_SetSel ' +\n        'GUICtrlRichEdit_SetSpaceUnit GUICtrlRichEdit_SetTabStops ' +\n        'GUICtrlRichEdit_SetText GUICtrlRichEdit_SetUndoLimit ' +\n        'GUICtrlRichEdit_SetZoom GUICtrlRichEdit_StreamFromFile ' +\n        'GUICtrlRichEdit_StreamFromVar GUICtrlRichEdit_StreamToFile ' +\n        'GUICtrlRichEdit_StreamToVar GUICtrlRichEdit_Undo ' +\n        'GUICtrlSlider_ClearSel GUICtrlSlider_ClearTics ' +\n        'GUICtrlSlider_Create GUICtrlSlider_Destroy ' +\n        'GUICtrlSlider_GetBuddy GUICtrlSlider_GetChannelRect ' +\n        'GUICtrlSlider_GetChannelRectEx GUICtrlSlider_GetLineSize ' +\n        'GUICtrlSlider_GetLogicalTics GUICtrlSlider_GetNumTics ' +\n        'GUICtrlSlider_GetPageSize GUICtrlSlider_GetPos ' +\n        'GUICtrlSlider_GetRange GUICtrlSlider_GetRangeMax ' +\n        'GUICtrlSlider_GetRangeMin GUICtrlSlider_GetSel ' +\n        'GUICtrlSlider_GetSelEnd GUICtrlSlider_GetSelStart ' +\n        'GUICtrlSlider_GetThumbLength GUICtrlSlider_GetThumbRect ' +\n        'GUICtrlSlider_GetThumbRectEx GUICtrlSlider_GetTic ' +\n        'GUICtrlSlider_GetTicPos GUICtrlSlider_GetToolTips ' +\n        'GUICtrlSlider_GetUnicodeFormat GUICtrlSlider_SetBuddy ' +\n        'GUICtrlSlider_SetLineSize GUICtrlSlider_SetPageSize ' +\n        'GUICtrlSlider_SetPos GUICtrlSlider_SetRange ' +\n        'GUICtrlSlider_SetRangeMax GUICtrlSlider_SetRangeMin ' +\n        'GUICtrlSlider_SetSel GUICtrlSlider_SetSelEnd ' +\n        'GUICtrlSlider_SetSelStart GUICtrlSlider_SetThumbLength ' +\n        'GUICtrlSlider_SetTic GUICtrlSlider_SetTicFreq ' +\n        'GUICtrlSlider_SetTipSide GUICtrlSlider_SetToolTips ' +\n        'GUICtrlSlider_SetUnicodeFormat GUICtrlStatusBar_Create ' +\n        'GUICtrlStatusBar_Destroy GUICtrlStatusBar_EmbedControl ' +\n        'GUICtrlStatusBar_GetBorders GUICtrlStatusBar_GetBordersHorz ' +\n        'GUICtrlStatusBar_GetBordersRect GUICtrlStatusBar_GetBordersVert ' +\n        'GUICtrlStatusBar_GetCount GUICtrlStatusBar_GetHeight ' +\n        'GUICtrlStatusBar_GetIcon GUICtrlStatusBar_GetParts ' +\n        'GUICtrlStatusBar_GetRect GUICtrlStatusBar_GetRectEx ' +\n        'GUICtrlStatusBar_GetText GUICtrlStatusBar_GetTextFlags ' +\n        'GUICtrlStatusBar_GetTextLength GUICtrlStatusBar_GetTextLengthEx ' +\n        'GUICtrlStatusBar_GetTipText GUICtrlStatusBar_GetUnicodeFormat ' +\n        'GUICtrlStatusBar_GetWidth GUICtrlStatusBar_IsSimple ' +\n        'GUICtrlStatusBar_Resize GUICtrlStatusBar_SetBkColor ' +\n        'GUICtrlStatusBar_SetIcon GUICtrlStatusBar_SetMinHeight ' +\n        'GUICtrlStatusBar_SetParts GUICtrlStatusBar_SetSimple ' +\n        'GUICtrlStatusBar_SetText GUICtrlStatusBar_SetTipText ' +\n        'GUICtrlStatusBar_SetUnicodeFormat GUICtrlStatusBar_ShowHide ' +\n        'GUICtrlTab_ActivateTab GUICtrlTab_ClickTab GUICtrlTab_Create ' +\n        'GUICtrlTab_DeleteAllItems GUICtrlTab_DeleteItem ' +\n        'GUICtrlTab_DeselectAll GUICtrlTab_Destroy GUICtrlTab_FindTab ' +\n        'GUICtrlTab_GetCurFocus GUICtrlTab_GetCurSel ' +\n        'GUICtrlTab_GetDisplayRect GUICtrlTab_GetDisplayRectEx ' +\n        'GUICtrlTab_GetExtendedStyle GUICtrlTab_GetImageList ' +\n        'GUICtrlTab_GetItem GUICtrlTab_GetItemCount ' +\n        'GUICtrlTab_GetItemImage GUICtrlTab_GetItemParam ' +\n        'GUICtrlTab_GetItemRect GUICtrlTab_GetItemRectEx ' +\n        'GUICtrlTab_GetItemState GUICtrlTab_GetItemText ' +\n        'GUICtrlTab_GetRowCount GUICtrlTab_GetToolTips ' +\n        'GUICtrlTab_GetUnicodeFormat GUICtrlTab_HighlightItem ' +\n        'GUICtrlTab_HitTest GUICtrlTab_InsertItem ' +\n        'GUICtrlTab_RemoveImage GUICtrlTab_SetCurFocus ' +\n        'GUICtrlTab_SetCurSel GUICtrlTab_SetExtendedStyle ' +\n        'GUICtrlTab_SetImageList GUICtrlTab_SetItem ' +\n        'GUICtrlTab_SetItemImage GUICtrlTab_SetItemParam ' +\n        'GUICtrlTab_SetItemSize GUICtrlTab_SetItemState ' +\n        'GUICtrlTab_SetItemText GUICtrlTab_SetMinTabWidth ' +\n        'GUICtrlTab_SetPadding GUICtrlTab_SetToolTips ' +\n        'GUICtrlTab_SetUnicodeFormat GUICtrlToolbar_AddBitmap ' +\n        'GUICtrlToolbar_AddButton GUICtrlToolbar_AddButtonSep ' +\n        'GUICtrlToolbar_AddString GUICtrlToolbar_ButtonCount ' +\n        'GUICtrlToolbar_CheckButton GUICtrlToolbar_ClickAccel ' +\n        'GUICtrlToolbar_ClickButton GUICtrlToolbar_ClickIndex ' +\n        'GUICtrlToolbar_CommandToIndex GUICtrlToolbar_Create ' +\n        'GUICtrlToolbar_Customize GUICtrlToolbar_DeleteButton ' +\n        'GUICtrlToolbar_Destroy GUICtrlToolbar_EnableButton ' +\n        'GUICtrlToolbar_FindToolbar GUICtrlToolbar_GetAnchorHighlight ' +\n        'GUICtrlToolbar_GetBitmapFlags GUICtrlToolbar_GetButtonBitmap ' +\n        'GUICtrlToolbar_GetButtonInfo GUICtrlToolbar_GetButtonInfoEx ' +\n        'GUICtrlToolbar_GetButtonParam GUICtrlToolbar_GetButtonRect ' +\n        'GUICtrlToolbar_GetButtonRectEx GUICtrlToolbar_GetButtonSize ' +\n        'GUICtrlToolbar_GetButtonState GUICtrlToolbar_GetButtonStyle ' +\n        'GUICtrlToolbar_GetButtonText GUICtrlToolbar_GetColorScheme ' +\n        'GUICtrlToolbar_GetDisabledImageList ' +\n        'GUICtrlToolbar_GetExtendedStyle GUICtrlToolbar_GetHotImageList ' +\n        'GUICtrlToolbar_GetHotItem GUICtrlToolbar_GetImageList ' +\n        'GUICtrlToolbar_GetInsertMark GUICtrlToolbar_GetInsertMarkColor ' +\n        'GUICtrlToolbar_GetMaxSize GUICtrlToolbar_GetMetrics ' +\n        'GUICtrlToolbar_GetPadding GUICtrlToolbar_GetRows ' +\n        'GUICtrlToolbar_GetString GUICtrlToolbar_GetStyle ' +\n        'GUICtrlToolbar_GetStyleAltDrag ' +\n        'GUICtrlToolbar_GetStyleCustomErase GUICtrlToolbar_GetStyleFlat ' +\n        'GUICtrlToolbar_GetStyleList GUICtrlToolbar_GetStyleRegisterDrop ' +\n        'GUICtrlToolbar_GetStyleToolTips ' +\n        'GUICtrlToolbar_GetStyleTransparent ' +\n        'GUICtrlToolbar_GetStyleWrapable GUICtrlToolbar_GetTextRows ' +\n        'GUICtrlToolbar_GetToolTips GUICtrlToolbar_GetUnicodeFormat ' +\n        'GUICtrlToolbar_HideButton GUICtrlToolbar_HighlightButton ' +\n        'GUICtrlToolbar_HitTest GUICtrlToolbar_IndexToCommand ' +\n        'GUICtrlToolbar_InsertButton GUICtrlToolbar_InsertMarkHitTest ' +\n        'GUICtrlToolbar_IsButtonChecked GUICtrlToolbar_IsButtonEnabled ' +\n        'GUICtrlToolbar_IsButtonHidden ' +\n        'GUICtrlToolbar_IsButtonHighlighted ' +\n        'GUICtrlToolbar_IsButtonIndeterminate ' +\n        'GUICtrlToolbar_IsButtonPressed GUICtrlToolbar_LoadBitmap ' +\n        'GUICtrlToolbar_LoadImages GUICtrlToolbar_MapAccelerator ' +\n        'GUICtrlToolbar_MoveButton GUICtrlToolbar_PressButton ' +\n        'GUICtrlToolbar_SetAnchorHighlight GUICtrlToolbar_SetBitmapSize ' +\n        'GUICtrlToolbar_SetButtonBitMap GUICtrlToolbar_SetButtonInfo ' +\n        'GUICtrlToolbar_SetButtonInfoEx GUICtrlToolbar_SetButtonParam ' +\n        'GUICtrlToolbar_SetButtonSize GUICtrlToolbar_SetButtonState ' +\n        'GUICtrlToolbar_SetButtonStyle GUICtrlToolbar_SetButtonText ' +\n        'GUICtrlToolbar_SetButtonWidth GUICtrlToolbar_SetCmdID ' +\n        'GUICtrlToolbar_SetColorScheme ' +\n        'GUICtrlToolbar_SetDisabledImageList ' +\n        'GUICtrlToolbar_SetDrawTextFlags GUICtrlToolbar_SetExtendedStyle ' +\n        'GUICtrlToolbar_SetHotImageList GUICtrlToolbar_SetHotItem ' +\n        'GUICtrlToolbar_SetImageList GUICtrlToolbar_SetIndent ' +\n        'GUICtrlToolbar_SetIndeterminate GUICtrlToolbar_SetInsertMark ' +\n        'GUICtrlToolbar_SetInsertMarkColor GUICtrlToolbar_SetMaxTextRows ' +\n        'GUICtrlToolbar_SetMetrics GUICtrlToolbar_SetPadding ' +\n        'GUICtrlToolbar_SetParent GUICtrlToolbar_SetRows ' +\n        'GUICtrlToolbar_SetStyle GUICtrlToolbar_SetStyleAltDrag ' +\n        'GUICtrlToolbar_SetStyleCustomErase GUICtrlToolbar_SetStyleFlat ' +\n        'GUICtrlToolbar_SetStyleList GUICtrlToolbar_SetStyleRegisterDrop ' +\n        'GUICtrlToolbar_SetStyleToolTips ' +\n        'GUICtrlToolbar_SetStyleTransparent ' +\n        'GUICtrlToolbar_SetStyleWrapable GUICtrlToolbar_SetToolTips ' +\n        'GUICtrlToolbar_SetUnicodeFormat GUICtrlToolbar_SetWindowTheme ' +\n        'GUICtrlTreeView_Add GUICtrlTreeView_AddChild ' +\n        'GUICtrlTreeView_AddChildFirst GUICtrlTreeView_AddFirst ' +\n        'GUICtrlTreeView_BeginUpdate GUICtrlTreeView_ClickItem ' +\n        'GUICtrlTreeView_Create GUICtrlTreeView_CreateDragImage ' +\n        'GUICtrlTreeView_CreateSolidBitMap GUICtrlTreeView_Delete ' +\n        'GUICtrlTreeView_DeleteAll GUICtrlTreeView_DeleteChildren ' +\n        'GUICtrlTreeView_Destroy GUICtrlTreeView_DisplayRect ' +\n        'GUICtrlTreeView_DisplayRectEx GUICtrlTreeView_EditText ' +\n        'GUICtrlTreeView_EndEdit GUICtrlTreeView_EndUpdate ' +\n        'GUICtrlTreeView_EnsureVisible GUICtrlTreeView_Expand ' +\n        'GUICtrlTreeView_ExpandedOnce GUICtrlTreeView_FindItem ' +\n        'GUICtrlTreeView_FindItemEx GUICtrlTreeView_GetBkColor ' +\n        'GUICtrlTreeView_GetBold GUICtrlTreeView_GetChecked ' +\n        'GUICtrlTreeView_GetChildCount GUICtrlTreeView_GetChildren ' +\n        'GUICtrlTreeView_GetCount GUICtrlTreeView_GetCut ' +\n        'GUICtrlTreeView_GetDropTarget GUICtrlTreeView_GetEditControl ' +\n        'GUICtrlTreeView_GetExpanded GUICtrlTreeView_GetFirstChild ' +\n        'GUICtrlTreeView_GetFirstItem GUICtrlTreeView_GetFirstVisible ' +\n        'GUICtrlTreeView_GetFocused GUICtrlTreeView_GetHeight ' +\n        'GUICtrlTreeView_GetImageIndex ' +\n        'GUICtrlTreeView_GetImageListIconHandle ' +\n        'GUICtrlTreeView_GetIndent GUICtrlTreeView_GetInsertMarkColor ' +\n        'GUICtrlTreeView_GetISearchString GUICtrlTreeView_GetItemByIndex ' +\n        'GUICtrlTreeView_GetItemHandle GUICtrlTreeView_GetItemParam ' +\n        'GUICtrlTreeView_GetLastChild GUICtrlTreeView_GetLineColor ' +\n        'GUICtrlTreeView_GetNext GUICtrlTreeView_GetNextChild ' +\n        'GUICtrlTreeView_GetNextSibling GUICtrlTreeView_GetNextVisible ' +\n        'GUICtrlTreeView_GetNormalImageList ' +\n        'GUICtrlTreeView_GetParentHandle GUICtrlTreeView_GetParentParam ' +\n        'GUICtrlTreeView_GetPrev GUICtrlTreeView_GetPrevChild ' +\n        'GUICtrlTreeView_GetPrevSibling GUICtrlTreeView_GetPrevVisible ' +\n        'GUICtrlTreeView_GetScrollTime GUICtrlTreeView_GetSelected ' +\n        'GUICtrlTreeView_GetSelectedImageIndex ' +\n        'GUICtrlTreeView_GetSelection GUICtrlTreeView_GetSiblingCount ' +\n        'GUICtrlTreeView_GetState GUICtrlTreeView_GetStateImageIndex ' +\n        'GUICtrlTreeView_GetStateImageList GUICtrlTreeView_GetText ' +\n        'GUICtrlTreeView_GetTextColor GUICtrlTreeView_GetToolTips ' +\n        'GUICtrlTreeView_GetTree GUICtrlTreeView_GetUnicodeFormat ' +\n        'GUICtrlTreeView_GetVisible GUICtrlTreeView_GetVisibleCount ' +\n        'GUICtrlTreeView_HitTest GUICtrlTreeView_HitTestEx ' +\n        'GUICtrlTreeView_HitTestItem GUICtrlTreeView_Index ' +\n        'GUICtrlTreeView_InsertItem GUICtrlTreeView_IsFirstItem ' +\n        'GUICtrlTreeView_IsParent GUICtrlTreeView_Level ' +\n        'GUICtrlTreeView_SelectItem GUICtrlTreeView_SelectItemByIndex ' +\n        'GUICtrlTreeView_SetBkColor GUICtrlTreeView_SetBold ' +\n        'GUICtrlTreeView_SetChecked GUICtrlTreeView_SetCheckedByIndex ' +\n        'GUICtrlTreeView_SetChildren GUICtrlTreeView_SetCut ' +\n        'GUICtrlTreeView_SetDropTarget GUICtrlTreeView_SetFocused ' +\n        'GUICtrlTreeView_SetHeight GUICtrlTreeView_SetIcon ' +\n        'GUICtrlTreeView_SetImageIndex GUICtrlTreeView_SetIndent ' +\n        'GUICtrlTreeView_SetInsertMark ' +\n        'GUICtrlTreeView_SetInsertMarkColor ' +\n        'GUICtrlTreeView_SetItemHeight GUICtrlTreeView_SetItemParam ' +\n        'GUICtrlTreeView_SetLineColor GUICtrlTreeView_SetNormalImageList ' +\n        'GUICtrlTreeView_SetScrollTime GUICtrlTreeView_SetSelected ' +\n        'GUICtrlTreeView_SetSelectedImageIndex GUICtrlTreeView_SetState ' +\n        'GUICtrlTreeView_SetStateImageIndex ' +\n        'GUICtrlTreeView_SetStateImageList GUICtrlTreeView_SetText ' +\n        'GUICtrlTreeView_SetTextColor GUICtrlTreeView_SetToolTips ' +\n        'GUICtrlTreeView_SetUnicodeFormat GUICtrlTreeView_Sort ' +\n        'GUIImageList_Add GUIImageList_AddBitmap GUIImageList_AddIcon ' +\n        'GUIImageList_AddMasked GUIImageList_BeginDrag ' +\n        'GUIImageList_Copy GUIImageList_Create GUIImageList_Destroy ' +\n        'GUIImageList_DestroyIcon GUIImageList_DragEnter ' +\n        'GUIImageList_DragLeave GUIImageList_DragMove ' +\n        'GUIImageList_Draw GUIImageList_DrawEx GUIImageList_Duplicate ' +\n        'GUIImageList_EndDrag GUIImageList_GetBkColor ' +\n        'GUIImageList_GetIcon GUIImageList_GetIconHeight ' +\n        'GUIImageList_GetIconSize GUIImageList_GetIconSizeEx ' +\n        'GUIImageList_GetIconWidth GUIImageList_GetImageCount ' +\n        'GUIImageList_GetImageInfoEx GUIImageList_Remove ' +\n        'GUIImageList_ReplaceIcon GUIImageList_SetBkColor ' +\n        'GUIImageList_SetIconSize GUIImageList_SetImageCount ' +\n        'GUIImageList_Swap GUIScrollBars_EnableScrollBar ' +\n        'GUIScrollBars_GetScrollBarInfoEx GUIScrollBars_GetScrollBarRect ' +\n        'GUIScrollBars_GetScrollBarRGState ' +\n        'GUIScrollBars_GetScrollBarXYLineButton ' +\n        'GUIScrollBars_GetScrollBarXYThumbBottom ' +\n        'GUIScrollBars_GetScrollBarXYThumbTop ' +\n        'GUIScrollBars_GetScrollInfo GUIScrollBars_GetScrollInfoEx ' +\n        'GUIScrollBars_GetScrollInfoMax GUIScrollBars_GetScrollInfoMin ' +\n        'GUIScrollBars_GetScrollInfoPage GUIScrollBars_GetScrollInfoPos ' +\n        'GUIScrollBars_GetScrollInfoTrackPos GUIScrollBars_GetScrollPos ' +\n        'GUIScrollBars_GetScrollRange GUIScrollBars_Init ' +\n        'GUIScrollBars_ScrollWindow GUIScrollBars_SetScrollInfo ' +\n        'GUIScrollBars_SetScrollInfoMax GUIScrollBars_SetScrollInfoMin ' +\n        'GUIScrollBars_SetScrollInfoPage GUIScrollBars_SetScrollInfoPos ' +\n        'GUIScrollBars_SetScrollRange GUIScrollBars_ShowScrollBar ' +\n        'GUIToolTip_Activate GUIToolTip_AddTool GUIToolTip_AdjustRect ' +\n        'GUIToolTip_BitsToTTF GUIToolTip_Create GUIToolTip_Deactivate ' +\n        'GUIToolTip_DelTool GUIToolTip_Destroy GUIToolTip_EnumTools ' +\n        'GUIToolTip_GetBubbleHeight GUIToolTip_GetBubbleSize ' +\n        'GUIToolTip_GetBubbleWidth GUIToolTip_GetCurrentTool ' +\n        'GUIToolTip_GetDelayTime GUIToolTip_GetMargin ' +\n        'GUIToolTip_GetMarginEx GUIToolTip_GetMaxTipWidth ' +\n        'GUIToolTip_GetText GUIToolTip_GetTipBkColor ' +\n        'GUIToolTip_GetTipTextColor GUIToolTip_GetTitleBitMap ' +\n        'GUIToolTip_GetTitleText GUIToolTip_GetToolCount ' +\n        'GUIToolTip_GetToolInfo GUIToolTip_HitTest ' +\n        'GUIToolTip_NewToolRect GUIToolTip_Pop GUIToolTip_PopUp ' +\n        'GUIToolTip_SetDelayTime GUIToolTip_SetMargin ' +\n        'GUIToolTip_SetMaxTipWidth GUIToolTip_SetTipBkColor ' +\n        'GUIToolTip_SetTipTextColor GUIToolTip_SetTitle ' +\n        'GUIToolTip_SetToolInfo GUIToolTip_SetWindowTheme ' +\n        'GUIToolTip_ToolExists GUIToolTip_ToolToArray ' +\n        'GUIToolTip_TrackActivate GUIToolTip_TrackPosition ' +\n        'GUIToolTip_Update GUIToolTip_UpdateTipText HexToString ' +\n        'IEAction IEAttach IEBodyReadHTML IEBodyReadText ' +\n        'IEBodyWriteHTML IECreate IECreateEmbedded IEDocGetObj ' +\n        'IEDocInsertHTML IEDocInsertText IEDocReadHTML ' +\n        'IEDocWriteHTML IEErrorNotify IEFormElementCheckBoxSelect ' +\n        'IEFormElementGetCollection IEFormElementGetObjByName ' +\n        'IEFormElementGetValue IEFormElementOptionSelect ' +\n        'IEFormElementRadioSelect IEFormElementSetValue ' +\n        'IEFormGetCollection IEFormGetObjByName IEFormImageClick ' +\n        'IEFormReset IEFormSubmit IEFrameGetCollection ' +\n        'IEFrameGetObjByName IEGetObjById IEGetObjByName ' +\n        'IEHeadInsertEventScript IEImgClick IEImgGetCollection ' +\n        'IEIsFrameSet IELinkClickByIndex IELinkClickByText ' +\n        'IELinkGetCollection IELoadWait IELoadWaitTimeout IENavigate ' +\n        'IEPropertyGet IEPropertySet IEQuit IETableGetCollection ' +\n        'IETableWriteToArray IETagNameAllGetCollection ' +\n        'IETagNameGetCollection IE_Example IE_Introduction ' +\n        'IE_VersionInfo INetExplorerCapable INetGetSource INetMail ' +\n        'INetSmtpMail IsPressed MathCheckDiv Max MemGlobalAlloc ' +\n        'MemGlobalFree MemGlobalLock MemGlobalSize MemGlobalUnlock ' +\n        'MemMoveMemory MemVirtualAlloc MemVirtualAllocEx ' +\n        'MemVirtualFree MemVirtualFreeEx Min MouseTrap ' +\n        'NamedPipes_CallNamedPipe NamedPipes_ConnectNamedPipe ' +\n        'NamedPipes_CreateNamedPipe NamedPipes_CreatePipe ' +\n        'NamedPipes_DisconnectNamedPipe ' +\n        'NamedPipes_GetNamedPipeHandleState NamedPipes_GetNamedPipeInfo ' +\n        'NamedPipes_PeekNamedPipe NamedPipes_SetNamedPipeHandleState ' +\n        'NamedPipes_TransactNamedPipe NamedPipes_WaitNamedPipe ' +\n        'Net_Share_ConnectionEnum Net_Share_FileClose ' +\n        'Net_Share_FileEnum Net_Share_FileGetInfo Net_Share_PermStr ' +\n        'Net_Share_ResourceStr Net_Share_SessionDel ' +\n        'Net_Share_SessionEnum Net_Share_SessionGetInfo ' +\n        'Net_Share_ShareAdd Net_Share_ShareCheck Net_Share_ShareDel ' +\n        'Net_Share_ShareEnum Net_Share_ShareGetInfo ' +\n        'Net_Share_ShareSetInfo Net_Share_StatisticsGetSvr ' +\n        'Net_Share_StatisticsGetWrk Now NowCalc NowCalcDate ' +\n        'NowDate NowTime PathFull PathGetRelative PathMake ' +\n        'PathSplit ProcessGetName ProcessGetPriority Radian ' +\n        'ReplaceStringInFile RunDos ScreenCapture_Capture ' +\n        'ScreenCapture_CaptureWnd ScreenCapture_SaveImage ' +\n        'ScreenCapture_SetBMPFormat ScreenCapture_SetJPGQuality ' +\n        'ScreenCapture_SetTIFColorDepth ScreenCapture_SetTIFCompression ' +\n        'Security__AdjustTokenPrivileges ' +\n        'Security__CreateProcessWithToken Security__DuplicateTokenEx ' +\n        'Security__GetAccountSid Security__GetLengthSid ' +\n        'Security__GetTokenInformation Security__ImpersonateSelf ' +\n        'Security__IsValidSid Security__LookupAccountName ' +\n        'Security__LookupAccountSid Security__LookupPrivilegeValue ' +\n        'Security__OpenProcessToken Security__OpenThreadToken ' +\n        'Security__OpenThreadTokenEx Security__SetPrivilege ' +\n        'Security__SetTokenInformation Security__SidToStringSid ' +\n        'Security__SidTypeStr Security__StringSidToSid SendMessage ' +\n        'SendMessageA SetDate SetTime Singleton SoundClose ' +\n        'SoundLength SoundOpen SoundPause SoundPlay SoundPos ' +\n        'SoundResume SoundSeek SoundStatus SoundStop ' +\n        'SQLite_Changes SQLite_Close SQLite_Display2DResult ' +\n        'SQLite_Encode SQLite_ErrCode SQLite_ErrMsg SQLite_Escape ' +\n        'SQLite_Exec SQLite_FastEncode SQLite_FastEscape ' +\n        'SQLite_FetchData SQLite_FetchNames SQLite_GetTable ' +\n        'SQLite_GetTable2d SQLite_LastInsertRowID SQLite_LibVersion ' +\n        'SQLite_Open SQLite_Query SQLite_QueryFinalize ' +\n        'SQLite_QueryReset SQLite_QuerySingleRow SQLite_SafeMode ' +\n        'SQLite_SetTimeout SQLite_Shutdown SQLite_SQLiteExe ' +\n        'SQLite_Startup SQLite_TotalChanges StringBetween ' +\n        'StringExplode StringInsert StringProper StringRepeat ' +\n        'StringTitleCase StringToHex TCPIpToName TempFile ' +\n        'TicksToTime Timer_Diff Timer_GetIdleTime Timer_GetTimerID ' +\n        'Timer_Init Timer_KillAllTimers Timer_KillTimer ' +\n        'Timer_SetTimer TimeToTicks VersionCompare viClose ' +\n        'viExecCommand viFindGpib viGpibBusReset viGTL ' +\n        'viInteractiveControl viOpen viSetAttribute viSetTimeout ' +\n        'WeekNumberISO WinAPI_AbortPath WinAPI_ActivateKeyboardLayout ' +\n        'WinAPI_AddClipboardFormatListener WinAPI_AddFontMemResourceEx ' +\n        'WinAPI_AddFontResourceEx WinAPI_AddIconOverlay ' +\n        'WinAPI_AddIconTransparency WinAPI_AddMRUString ' +\n        'WinAPI_AdjustBitmap WinAPI_AdjustTokenPrivileges ' +\n        'WinAPI_AdjustWindowRectEx WinAPI_AlphaBlend WinAPI_AngleArc ' +\n        'WinAPI_AnimateWindow WinAPI_Arc WinAPI_ArcTo ' +\n        'WinAPI_ArrayToStruct WinAPI_AssignProcessToJobObject ' +\n        'WinAPI_AssocGetPerceivedType WinAPI_AssocQueryString ' +\n        'WinAPI_AttachConsole WinAPI_AttachThreadInput ' +\n        'WinAPI_BackupRead WinAPI_BackupReadAbort WinAPI_BackupSeek ' +\n        'WinAPI_BackupWrite WinAPI_BackupWriteAbort WinAPI_Beep ' +\n        'WinAPI_BeginBufferedPaint WinAPI_BeginDeferWindowPos ' +\n        'WinAPI_BeginPaint WinAPI_BeginPath WinAPI_BeginUpdateResource ' +\n        'WinAPI_BitBlt WinAPI_BringWindowToTop ' +\n        'WinAPI_BroadcastSystemMessage WinAPI_BrowseForFolderDlg ' +\n        'WinAPI_BufferedPaintClear WinAPI_BufferedPaintInit ' +\n        'WinAPI_BufferedPaintSetAlpha WinAPI_BufferedPaintUnInit ' +\n        'WinAPI_CallNextHookEx WinAPI_CallWindowProc ' +\n        'WinAPI_CallWindowProcW WinAPI_CascadeWindows ' +\n        'WinAPI_ChangeWindowMessageFilterEx WinAPI_CharToOem ' +\n        'WinAPI_ChildWindowFromPointEx WinAPI_ClientToScreen ' +\n        'WinAPI_ClipCursor WinAPI_CloseDesktop WinAPI_CloseEnhMetaFile ' +\n        'WinAPI_CloseFigure WinAPI_CloseHandle WinAPI_CloseThemeData ' +\n        'WinAPI_CloseWindow WinAPI_CloseWindowStation ' +\n        'WinAPI_CLSIDFromProgID WinAPI_CoInitialize ' +\n        'WinAPI_ColorAdjustLuma WinAPI_ColorHLSToRGB ' +\n        'WinAPI_ColorRGBToHLS WinAPI_CombineRgn ' +\n        'WinAPI_CombineTransform WinAPI_CommandLineToArgv ' +\n        'WinAPI_CommDlgExtendedError WinAPI_CommDlgExtendedErrorEx ' +\n        'WinAPI_CompareString WinAPI_CompressBitmapBits ' +\n        'WinAPI_CompressBuffer WinAPI_ComputeCrc32 ' +\n        'WinAPI_ConfirmCredentials WinAPI_CopyBitmap WinAPI_CopyCursor ' +\n        'WinAPI_CopyEnhMetaFile WinAPI_CopyFileEx WinAPI_CopyIcon ' +\n        'WinAPI_CopyImage WinAPI_CopyRect WinAPI_CopyStruct ' +\n        'WinAPI_CoTaskMemAlloc WinAPI_CoTaskMemFree ' +\n        'WinAPI_CoTaskMemRealloc WinAPI_CoUninitialize ' +\n        'WinAPI_Create32BitHBITMAP WinAPI_Create32BitHICON ' +\n        'WinAPI_CreateANDBitmap WinAPI_CreateBitmap ' +\n        'WinAPI_CreateBitmapIndirect WinAPI_CreateBrushIndirect ' +\n        'WinAPI_CreateBuffer WinAPI_CreateBufferFromStruct ' +\n        'WinAPI_CreateCaret WinAPI_CreateColorAdjustment ' +\n        'WinAPI_CreateCompatibleBitmap WinAPI_CreateCompatibleBitmapEx ' +\n        'WinAPI_CreateCompatibleDC WinAPI_CreateDesktop ' +\n        'WinAPI_CreateDIB WinAPI_CreateDIBColorTable ' +\n        'WinAPI_CreateDIBitmap WinAPI_CreateDIBSection ' +\n        'WinAPI_CreateDirectory WinAPI_CreateDirectoryEx ' +\n        'WinAPI_CreateEllipticRgn WinAPI_CreateEmptyIcon ' +\n        'WinAPI_CreateEnhMetaFile WinAPI_CreateEvent WinAPI_CreateFile ' +\n        'WinAPI_CreateFileEx WinAPI_CreateFileMapping ' +\n        'WinAPI_CreateFont WinAPI_CreateFontEx ' +\n        'WinAPI_CreateFontIndirect WinAPI_CreateGUID ' +\n        'WinAPI_CreateHardLink WinAPI_CreateIcon ' +\n        'WinAPI_CreateIconFromResourceEx WinAPI_CreateIconIndirect ' +\n        'WinAPI_CreateJobObject WinAPI_CreateMargins ' +\n        'WinAPI_CreateMRUList WinAPI_CreateMutex WinAPI_CreateNullRgn ' +\n        'WinAPI_CreateNumberFormatInfo WinAPI_CreateObjectID ' +\n        'WinAPI_CreatePen WinAPI_CreatePoint WinAPI_CreatePolygonRgn ' +\n        'WinAPI_CreateProcess WinAPI_CreateProcessWithToken ' +\n        'WinAPI_CreateRect WinAPI_CreateRectEx WinAPI_CreateRectRgn ' +\n        'WinAPI_CreateRectRgnIndirect WinAPI_CreateRoundRectRgn ' +\n        'WinAPI_CreateSemaphore WinAPI_CreateSize ' +\n        'WinAPI_CreateSolidBitmap WinAPI_CreateSolidBrush ' +\n        'WinAPI_CreateStreamOnHGlobal WinAPI_CreateString ' +\n        'WinAPI_CreateSymbolicLink WinAPI_CreateTransform ' +\n        'WinAPI_CreateWindowEx WinAPI_CreateWindowStation ' +\n        'WinAPI_DecompressBuffer WinAPI_DecryptFile ' +\n        'WinAPI_DeferWindowPos WinAPI_DefineDosDevice ' +\n        'WinAPI_DefRawInputProc WinAPI_DefSubclassProc ' +\n        'WinAPI_DefWindowProc WinAPI_DefWindowProcW WinAPI_DeleteDC ' +\n        'WinAPI_DeleteEnhMetaFile WinAPI_DeleteFile ' +\n        'WinAPI_DeleteObject WinAPI_DeleteObjectID ' +\n        'WinAPI_DeleteVolumeMountPoint WinAPI_DeregisterShellHookWindow ' +\n        'WinAPI_DestroyCaret WinAPI_DestroyCursor WinAPI_DestroyIcon ' +\n        'WinAPI_DestroyWindow WinAPI_DeviceIoControl ' +\n        'WinAPI_DisplayStruct WinAPI_DllGetVersion WinAPI_DllInstall ' +\n        'WinAPI_DllUninstall WinAPI_DPtoLP WinAPI_DragAcceptFiles ' +\n        'WinAPI_DragFinish WinAPI_DragQueryFileEx ' +\n        'WinAPI_DragQueryPoint WinAPI_DrawAnimatedRects ' +\n        'WinAPI_DrawBitmap WinAPI_DrawEdge WinAPI_DrawFocusRect ' +\n        'WinAPI_DrawFrameControl WinAPI_DrawIcon WinAPI_DrawIconEx ' +\n        'WinAPI_DrawLine WinAPI_DrawShadowText WinAPI_DrawText ' +\n        'WinAPI_DrawThemeBackground WinAPI_DrawThemeEdge ' +\n        'WinAPI_DrawThemeIcon WinAPI_DrawThemeParentBackground ' +\n        'WinAPI_DrawThemeText WinAPI_DrawThemeTextEx ' +\n        'WinAPI_DuplicateEncryptionInfoFile WinAPI_DuplicateHandle ' +\n        'WinAPI_DuplicateTokenEx WinAPI_DwmDefWindowProc ' +\n        'WinAPI_DwmEnableBlurBehindWindow WinAPI_DwmEnableComposition ' +\n        'WinAPI_DwmExtendFrameIntoClientArea ' +\n        'WinAPI_DwmGetColorizationColor ' +\n        'WinAPI_DwmGetColorizationParameters ' +\n        'WinAPI_DwmGetWindowAttribute WinAPI_DwmInvalidateIconicBitmaps ' +\n        'WinAPI_DwmIsCompositionEnabled ' +\n        'WinAPI_DwmQueryThumbnailSourceSize WinAPI_DwmRegisterThumbnail ' +\n        'WinAPI_DwmSetColorizationParameters ' +\n        'WinAPI_DwmSetIconicLivePreviewBitmap ' +\n        'WinAPI_DwmSetIconicThumbnail WinAPI_DwmSetWindowAttribute ' +\n        'WinAPI_DwmUnregisterThumbnail ' +\n        'WinAPI_DwmUpdateThumbnailProperties WinAPI_DWordToFloat ' +\n        'WinAPI_DWordToInt WinAPI_EjectMedia WinAPI_Ellipse ' +\n        'WinAPI_EmptyWorkingSet WinAPI_EnableWindow WinAPI_EncryptFile ' +\n        'WinAPI_EncryptionDisable WinAPI_EndBufferedPaint ' +\n        'WinAPI_EndDeferWindowPos WinAPI_EndPaint WinAPI_EndPath ' +\n        'WinAPI_EndUpdateResource WinAPI_EnumChildProcess ' +\n        'WinAPI_EnumChildWindows WinAPI_EnumDesktops ' +\n        'WinAPI_EnumDesktopWindows WinAPI_EnumDeviceDrivers ' +\n        'WinAPI_EnumDisplayDevices WinAPI_EnumDisplayMonitors ' +\n        'WinAPI_EnumDisplaySettings WinAPI_EnumDllProc ' +\n        'WinAPI_EnumFiles WinAPI_EnumFileStreams ' +\n        'WinAPI_EnumFontFamilies WinAPI_EnumHardLinks ' +\n        'WinAPI_EnumMRUList WinAPI_EnumPageFiles ' +\n        'WinAPI_EnumProcessHandles WinAPI_EnumProcessModules ' +\n        'WinAPI_EnumProcessThreads WinAPI_EnumProcessWindows ' +\n        'WinAPI_EnumRawInputDevices WinAPI_EnumResourceLanguages ' +\n        'WinAPI_EnumResourceNames WinAPI_EnumResourceTypes ' +\n        'WinAPI_EnumSystemGeoID WinAPI_EnumSystemLocales ' +\n        'WinAPI_EnumUILanguages WinAPI_EnumWindows ' +\n        'WinAPI_EnumWindowsPopup WinAPI_EnumWindowStations ' +\n        'WinAPI_EnumWindowsTop WinAPI_EqualMemory WinAPI_EqualRect ' +\n        'WinAPI_EqualRgn WinAPI_ExcludeClipRect ' +\n        'WinAPI_ExpandEnvironmentStrings WinAPI_ExtCreatePen ' +\n        'WinAPI_ExtCreateRegion WinAPI_ExtFloodFill WinAPI_ExtractIcon ' +\n        'WinAPI_ExtractIconEx WinAPI_ExtSelectClipRgn ' +\n        'WinAPI_FatalAppExit WinAPI_FatalExit ' +\n        'WinAPI_FileEncryptionStatus WinAPI_FileExists ' +\n        'WinAPI_FileIconInit WinAPI_FileInUse WinAPI_FillMemory ' +\n        'WinAPI_FillPath WinAPI_FillRect WinAPI_FillRgn ' +\n        'WinAPI_FindClose WinAPI_FindCloseChangeNotification ' +\n        'WinAPI_FindExecutable WinAPI_FindFirstChangeNotification ' +\n        'WinAPI_FindFirstFile WinAPI_FindFirstFileName ' +\n        'WinAPI_FindFirstStream WinAPI_FindNextChangeNotification ' +\n        'WinAPI_FindNextFile WinAPI_FindNextFileName ' +\n        'WinAPI_FindNextStream WinAPI_FindResource ' +\n        'WinAPI_FindResourceEx WinAPI_FindTextDlg WinAPI_FindWindow ' +\n        'WinAPI_FlashWindow WinAPI_FlashWindowEx WinAPI_FlattenPath ' +\n        'WinAPI_FloatToDWord WinAPI_FloatToInt WinAPI_FlushFileBuffers ' +\n        'WinAPI_FlushFRBuffer WinAPI_FlushViewOfFile ' +\n        'WinAPI_FormatDriveDlg WinAPI_FormatMessage WinAPI_FrameRect ' +\n        'WinAPI_FrameRgn WinAPI_FreeLibrary WinAPI_FreeMemory ' +\n        'WinAPI_FreeMRUList WinAPI_FreeResource WinAPI_GdiComment ' +\n        'WinAPI_GetActiveWindow WinAPI_GetAllUsersProfileDirectory ' +\n        'WinAPI_GetAncestor WinAPI_GetApplicationRestartSettings ' +\n        'WinAPI_GetArcDirection WinAPI_GetAsyncKeyState ' +\n        'WinAPI_GetBinaryType WinAPI_GetBitmapBits ' +\n        'WinAPI_GetBitmapDimension WinAPI_GetBitmapDimensionEx ' +\n        'WinAPI_GetBkColor WinAPI_GetBkMode WinAPI_GetBoundsRect ' +\n        'WinAPI_GetBrushOrg WinAPI_GetBufferedPaintBits ' +\n        'WinAPI_GetBufferedPaintDC WinAPI_GetBufferedPaintTargetDC ' +\n        'WinAPI_GetBufferedPaintTargetRect WinAPI_GetBValue ' +\n        'WinAPI_GetCaretBlinkTime WinAPI_GetCaretPos WinAPI_GetCDType ' +\n        'WinAPI_GetClassInfoEx WinAPI_GetClassLongEx ' +\n        'WinAPI_GetClassName WinAPI_GetClientHeight ' +\n        'WinAPI_GetClientRect WinAPI_GetClientWidth ' +\n        'WinAPI_GetClipboardSequenceNumber WinAPI_GetClipBox ' +\n        'WinAPI_GetClipCursor WinAPI_GetClipRgn ' +\n        'WinAPI_GetColorAdjustment WinAPI_GetCompressedFileSize ' +\n        'WinAPI_GetCompression WinAPI_GetConnectedDlg ' +\n        'WinAPI_GetCurrentDirectory WinAPI_GetCurrentHwProfile ' +\n        'WinAPI_GetCurrentObject WinAPI_GetCurrentPosition ' +\n        'WinAPI_GetCurrentProcess ' +\n        'WinAPI_GetCurrentProcessExplicitAppUserModelID ' +\n        'WinAPI_GetCurrentProcessID WinAPI_GetCurrentThemeName ' +\n        'WinAPI_GetCurrentThread WinAPI_GetCurrentThreadId ' +\n        'WinAPI_GetCursor WinAPI_GetCursorInfo WinAPI_GetDateFormat ' +\n        'WinAPI_GetDC WinAPI_GetDCEx WinAPI_GetDefaultPrinter ' +\n        'WinAPI_GetDefaultUserProfileDirectory WinAPI_GetDesktopWindow ' +\n        'WinAPI_GetDeviceCaps WinAPI_GetDeviceDriverBaseName ' +\n        'WinAPI_GetDeviceDriverFileName WinAPI_GetDeviceGammaRamp ' +\n        'WinAPI_GetDIBColorTable WinAPI_GetDIBits ' +\n        'WinAPI_GetDiskFreeSpaceEx WinAPI_GetDlgCtrlID ' +\n        'WinAPI_GetDlgItem WinAPI_GetDllDirectory ' +\n        'WinAPI_GetDriveBusType WinAPI_GetDriveGeometryEx ' +\n        'WinAPI_GetDriveNumber WinAPI_GetDriveType ' +\n        'WinAPI_GetDurationFormat WinAPI_GetEffectiveClientRect ' +\n        'WinAPI_GetEnhMetaFile WinAPI_GetEnhMetaFileBits ' +\n        'WinAPI_GetEnhMetaFileDescription WinAPI_GetEnhMetaFileDimension ' +\n        'WinAPI_GetEnhMetaFileHeader WinAPI_GetErrorMessage ' +\n        'WinAPI_GetErrorMode WinAPI_GetExitCodeProcess ' +\n        'WinAPI_GetExtended WinAPI_GetFileAttributes WinAPI_GetFileID ' +\n        'WinAPI_GetFileInformationByHandle ' +\n        'WinAPI_GetFileInformationByHandleEx WinAPI_GetFilePointerEx ' +\n        'WinAPI_GetFileSizeEx WinAPI_GetFileSizeOnDisk ' +\n        'WinAPI_GetFileTitle WinAPI_GetFileType ' +\n        'WinAPI_GetFileVersionInfo WinAPI_GetFinalPathNameByHandle ' +\n        'WinAPI_GetFinalPathNameByHandleEx WinAPI_GetFocus ' +\n        'WinAPI_GetFontMemoryResourceInfo WinAPI_GetFontName ' +\n        'WinAPI_GetFontResourceInfo WinAPI_GetForegroundWindow ' +\n        'WinAPI_GetFRBuffer WinAPI_GetFullPathName WinAPI_GetGeoInfo ' +\n        'WinAPI_GetGlyphOutline WinAPI_GetGraphicsMode ' +\n        'WinAPI_GetGuiResources WinAPI_GetGUIThreadInfo ' +\n        'WinAPI_GetGValue WinAPI_GetHandleInformation ' +\n        'WinAPI_GetHGlobalFromStream WinAPI_GetIconDimension ' +\n        'WinAPI_GetIconInfo WinAPI_GetIconInfoEx WinAPI_GetIdleTime ' +\n        'WinAPI_GetKeyboardLayout WinAPI_GetKeyboardLayoutList ' +\n        'WinAPI_GetKeyboardState WinAPI_GetKeyboardType ' +\n        'WinAPI_GetKeyNameText WinAPI_GetKeyState ' +\n        'WinAPI_GetLastActivePopup WinAPI_GetLastError ' +\n        'WinAPI_GetLastErrorMessage WinAPI_GetLayeredWindowAttributes ' +\n        'WinAPI_GetLocaleInfo WinAPI_GetLogicalDrives ' +\n        'WinAPI_GetMapMode WinAPI_GetMemorySize ' +\n        'WinAPI_GetMessageExtraInfo WinAPI_GetModuleFileNameEx ' +\n        'WinAPI_GetModuleHandle WinAPI_GetModuleHandleEx ' +\n        'WinAPI_GetModuleInformation WinAPI_GetMonitorInfo ' +\n        'WinAPI_GetMousePos WinAPI_GetMousePosX WinAPI_GetMousePosY ' +\n        'WinAPI_GetMUILanguage WinAPI_GetNumberFormat WinAPI_GetObject ' +\n        'WinAPI_GetObjectID WinAPI_GetObjectInfoByHandle ' +\n        'WinAPI_GetObjectNameByHandle WinAPI_GetObjectType ' +\n        'WinAPI_GetOpenFileName WinAPI_GetOutlineTextMetrics ' +\n        'WinAPI_GetOverlappedResult WinAPI_GetParent ' +\n        'WinAPI_GetParentProcess WinAPI_GetPerformanceInfo ' +\n        'WinAPI_GetPEType WinAPI_GetPhysicallyInstalledSystemMemory ' +\n        'WinAPI_GetPixel WinAPI_GetPolyFillMode WinAPI_GetPosFromRect ' +\n        'WinAPI_GetPriorityClass WinAPI_GetProcAddress ' +\n        'WinAPI_GetProcessAffinityMask WinAPI_GetProcessCommandLine ' +\n        'WinAPI_GetProcessFileName WinAPI_GetProcessHandleCount ' +\n        'WinAPI_GetProcessID WinAPI_GetProcessIoCounters ' +\n        'WinAPI_GetProcessMemoryInfo WinAPI_GetProcessName ' +\n        'WinAPI_GetProcessShutdownParameters WinAPI_GetProcessTimes ' +\n        'WinAPI_GetProcessUser WinAPI_GetProcessWindowStation ' +\n        'WinAPI_GetProcessWorkingDirectory WinAPI_GetProfilesDirectory ' +\n        'WinAPI_GetPwrCapabilities WinAPI_GetRawInputBuffer ' +\n        'WinAPI_GetRawInputBufferLength WinAPI_GetRawInputData ' +\n        'WinAPI_GetRawInputDeviceInfo WinAPI_GetRegionData ' +\n        'WinAPI_GetRegisteredRawInputDevices ' +\n        'WinAPI_GetRegKeyNameByHandle WinAPI_GetRgnBox WinAPI_GetROP2 ' +\n        'WinAPI_GetRValue WinAPI_GetSaveFileName WinAPI_GetShellWindow ' +\n        'WinAPI_GetStartupInfo WinAPI_GetStdHandle ' +\n        'WinAPI_GetStockObject WinAPI_GetStretchBltMode ' +\n        'WinAPI_GetString WinAPI_GetSysColor WinAPI_GetSysColorBrush ' +\n        'WinAPI_GetSystemDefaultLangID WinAPI_GetSystemDefaultLCID ' +\n        'WinAPI_GetSystemDefaultUILanguage WinAPI_GetSystemDEPPolicy ' +\n        'WinAPI_GetSystemInfo WinAPI_GetSystemMetrics ' +\n        'WinAPI_GetSystemPowerStatus WinAPI_GetSystemTimes ' +\n        'WinAPI_GetSystemWow64Directory WinAPI_GetTabbedTextExtent ' +\n        'WinAPI_GetTempFileName WinAPI_GetTextAlign ' +\n        'WinAPI_GetTextCharacterExtra WinAPI_GetTextColor ' +\n        'WinAPI_GetTextExtentPoint32 WinAPI_GetTextFace ' +\n        'WinAPI_GetTextMetrics WinAPI_GetThemeAppProperties ' +\n        'WinAPI_GetThemeBackgroundContentRect ' +\n        'WinAPI_GetThemeBackgroundExtent WinAPI_GetThemeBackgroundRegion ' +\n        'WinAPI_GetThemeBitmap WinAPI_GetThemeBool ' +\n        'WinAPI_GetThemeColor WinAPI_GetThemeDocumentationProperty ' +\n        'WinAPI_GetThemeEnumValue WinAPI_GetThemeFilename ' +\n        'WinAPI_GetThemeFont WinAPI_GetThemeInt WinAPI_GetThemeMargins ' +\n        'WinAPI_GetThemeMetric WinAPI_GetThemePartSize ' +\n        'WinAPI_GetThemePosition WinAPI_GetThemePropertyOrigin ' +\n        'WinAPI_GetThemeRect WinAPI_GetThemeString ' +\n        'WinAPI_GetThemeSysBool WinAPI_GetThemeSysColor ' +\n        'WinAPI_GetThemeSysColorBrush WinAPI_GetThemeSysFont ' +\n        'WinAPI_GetThemeSysInt WinAPI_GetThemeSysSize ' +\n        'WinAPI_GetThemeSysString WinAPI_GetThemeTextExtent ' +\n        'WinAPI_GetThemeTextMetrics WinAPI_GetThemeTransitionDuration ' +\n        'WinAPI_GetThreadDesktop WinAPI_GetThreadErrorMode ' +\n        'WinAPI_GetThreadLocale WinAPI_GetThreadUILanguage ' +\n        'WinAPI_GetTickCount WinAPI_GetTickCount64 ' +\n        'WinAPI_GetTimeFormat WinAPI_GetTopWindow ' +\n        'WinAPI_GetUDFColorMode WinAPI_GetUpdateRect ' +\n        'WinAPI_GetUpdateRgn WinAPI_GetUserDefaultLangID ' +\n        'WinAPI_GetUserDefaultLCID WinAPI_GetUserDefaultUILanguage ' +\n        'WinAPI_GetUserGeoID WinAPI_GetUserObjectInformation ' +\n        'WinAPI_GetVersion WinAPI_GetVersionEx ' +\n        'WinAPI_GetVolumeInformation WinAPI_GetVolumeInformationByHandle ' +\n        'WinAPI_GetVolumeNameForVolumeMountPoint WinAPI_GetWindow ' +\n        'WinAPI_GetWindowDC WinAPI_GetWindowDisplayAffinity ' +\n        'WinAPI_GetWindowExt WinAPI_GetWindowFileName ' +\n        'WinAPI_GetWindowHeight WinAPI_GetWindowInfo ' +\n        'WinAPI_GetWindowLong WinAPI_GetWindowOrg ' +\n        'WinAPI_GetWindowPlacement WinAPI_GetWindowRect ' +\n        'WinAPI_GetWindowRgn WinAPI_GetWindowRgnBox ' +\n        'WinAPI_GetWindowSubclass WinAPI_GetWindowText ' +\n        'WinAPI_GetWindowTheme WinAPI_GetWindowThreadProcessId ' +\n        'WinAPI_GetWindowWidth WinAPI_GetWorkArea ' +\n        'WinAPI_GetWorldTransform WinAPI_GetXYFromPoint ' +\n        'WinAPI_GlobalMemoryStatus WinAPI_GradientFill ' +\n        'WinAPI_GUIDFromString WinAPI_GUIDFromStringEx WinAPI_HashData ' +\n        'WinAPI_HashString WinAPI_HiByte WinAPI_HideCaret ' +\n        'WinAPI_HiDWord WinAPI_HiWord WinAPI_InflateRect ' +\n        'WinAPI_InitMUILanguage WinAPI_InProcess ' +\n        'WinAPI_IntersectClipRect WinAPI_IntersectRect ' +\n        'WinAPI_IntToDWord WinAPI_IntToFloat WinAPI_InvalidateRect ' +\n        'WinAPI_InvalidateRgn WinAPI_InvertANDBitmap ' +\n        'WinAPI_InvertColor WinAPI_InvertRect WinAPI_InvertRgn ' +\n        'WinAPI_IOCTL WinAPI_IsAlphaBitmap WinAPI_IsBadCodePtr ' +\n        'WinAPI_IsBadReadPtr WinAPI_IsBadStringPtr ' +\n        'WinAPI_IsBadWritePtr WinAPI_IsChild WinAPI_IsClassName ' +\n        'WinAPI_IsDoorOpen WinAPI_IsElevated WinAPI_IsHungAppWindow ' +\n        'WinAPI_IsIconic WinAPI_IsInternetConnected ' +\n        'WinAPI_IsLoadKBLayout WinAPI_IsMemory ' +\n        'WinAPI_IsNameInExpression WinAPI_IsNetworkAlive ' +\n        'WinAPI_IsPathShared WinAPI_IsProcessInJob ' +\n        'WinAPI_IsProcessorFeaturePresent WinAPI_IsRectEmpty ' +\n        'WinAPI_IsThemeActive ' +\n        'WinAPI_IsThemeBackgroundPartiallyTransparent ' +\n        'WinAPI_IsThemePartDefined WinAPI_IsValidLocale ' +\n        'WinAPI_IsWindow WinAPI_IsWindowEnabled WinAPI_IsWindowUnicode ' +\n        'WinAPI_IsWindowVisible WinAPI_IsWow64Process ' +\n        'WinAPI_IsWritable WinAPI_IsZoomed WinAPI_Keybd_Event ' +\n        'WinAPI_KillTimer WinAPI_LineDDA WinAPI_LineTo ' +\n        'WinAPI_LoadBitmap WinAPI_LoadCursor WinAPI_LoadCursorFromFile ' +\n        'WinAPI_LoadIcon WinAPI_LoadIconMetric ' +\n        'WinAPI_LoadIconWithScaleDown WinAPI_LoadImage ' +\n        'WinAPI_LoadIndirectString WinAPI_LoadKeyboardLayout ' +\n        'WinAPI_LoadLibrary WinAPI_LoadLibraryEx WinAPI_LoadMedia ' +\n        'WinAPI_LoadResource WinAPI_LoadShell32Icon WinAPI_LoadString ' +\n        'WinAPI_LoadStringEx WinAPI_LoByte WinAPI_LocalFree ' +\n        'WinAPI_LockDevice WinAPI_LockFile WinAPI_LockResource ' +\n        'WinAPI_LockWindowUpdate WinAPI_LockWorkStation WinAPI_LoDWord ' +\n        'WinAPI_LongMid WinAPI_LookupIconIdFromDirectoryEx ' +\n        'WinAPI_LoWord WinAPI_LPtoDP WinAPI_MAKELANGID ' +\n        'WinAPI_MAKELCID WinAPI_MakeLong WinAPI_MakeQWord ' +\n        'WinAPI_MakeWord WinAPI_MapViewOfFile WinAPI_MapVirtualKey ' +\n        'WinAPI_MaskBlt WinAPI_MessageBeep WinAPI_MessageBoxCheck ' +\n        'WinAPI_MessageBoxIndirect WinAPI_MirrorIcon ' +\n        'WinAPI_ModifyWorldTransform WinAPI_MonitorFromPoint ' +\n        'WinAPI_MonitorFromRect WinAPI_MonitorFromWindow ' +\n        'WinAPI_Mouse_Event WinAPI_MoveFileEx WinAPI_MoveMemory ' +\n        'WinAPI_MoveTo WinAPI_MoveToEx WinAPI_MoveWindow ' +\n        'WinAPI_MsgBox WinAPI_MulDiv WinAPI_MultiByteToWideChar ' +\n        'WinAPI_MultiByteToWideCharEx WinAPI_NtStatusToDosError ' +\n        'WinAPI_OemToChar WinAPI_OffsetClipRgn WinAPI_OffsetPoints ' +\n        'WinAPI_OffsetRect WinAPI_OffsetRgn WinAPI_OffsetWindowOrg ' +\n        'WinAPI_OpenDesktop WinAPI_OpenFileById WinAPI_OpenFileDlg ' +\n        'WinAPI_OpenFileMapping WinAPI_OpenIcon ' +\n        'WinAPI_OpenInputDesktop WinAPI_OpenJobObject WinAPI_OpenMutex ' +\n        'WinAPI_OpenProcess WinAPI_OpenProcessToken ' +\n        'WinAPI_OpenSemaphore WinAPI_OpenThemeData ' +\n        'WinAPI_OpenWindowStation WinAPI_PageSetupDlg ' +\n        'WinAPI_PaintDesktop WinAPI_PaintRgn WinAPI_ParseURL ' +\n        'WinAPI_ParseUserName WinAPI_PatBlt WinAPI_PathAddBackslash ' +\n        'WinAPI_PathAddExtension WinAPI_PathAppend ' +\n        'WinAPI_PathBuildRoot WinAPI_PathCanonicalize ' +\n        'WinAPI_PathCommonPrefix WinAPI_PathCompactPath ' +\n        'WinAPI_PathCompactPathEx WinAPI_PathCreateFromUrl ' +\n        'WinAPI_PathFindExtension WinAPI_PathFindFileName ' +\n        'WinAPI_PathFindNextComponent WinAPI_PathFindOnPath ' +\n        'WinAPI_PathGetArgs WinAPI_PathGetCharType ' +\n        'WinAPI_PathGetDriveNumber WinAPI_PathIsContentType ' +\n        'WinAPI_PathIsDirectory WinAPI_PathIsDirectoryEmpty ' +\n        'WinAPI_PathIsExe WinAPI_PathIsFileSpec ' +\n        'WinAPI_PathIsLFNFileSpec WinAPI_PathIsRelative ' +\n        'WinAPI_PathIsRoot WinAPI_PathIsSameRoot ' +\n        'WinAPI_PathIsSystemFolder WinAPI_PathIsUNC ' +\n        'WinAPI_PathIsUNCServer WinAPI_PathIsUNCServerShare ' +\n        'WinAPI_PathMakeSystemFolder WinAPI_PathMatchSpec ' +\n        'WinAPI_PathParseIconLocation WinAPI_PathRelativePathTo ' +\n        'WinAPI_PathRemoveArgs WinAPI_PathRemoveBackslash ' +\n        'WinAPI_PathRemoveExtension WinAPI_PathRemoveFileSpec ' +\n        'WinAPI_PathRenameExtension WinAPI_PathSearchAndQualify ' +\n        'WinAPI_PathSkipRoot WinAPI_PathStripPath ' +\n        'WinAPI_PathStripToRoot WinAPI_PathToRegion ' +\n        'WinAPI_PathUndecorate WinAPI_PathUnExpandEnvStrings ' +\n        'WinAPI_PathUnmakeSystemFolder WinAPI_PathUnquoteSpaces ' +\n        'WinAPI_PathYetAnotherMakeUniqueName WinAPI_PickIconDlg ' +\n        'WinAPI_PlayEnhMetaFile WinAPI_PlaySound WinAPI_PlgBlt ' +\n        'WinAPI_PointFromRect WinAPI_PolyBezier WinAPI_PolyBezierTo ' +\n        'WinAPI_PolyDraw WinAPI_Polygon WinAPI_PostMessage ' +\n        'WinAPI_PrimaryLangId WinAPI_PrintDlg WinAPI_PrintDlgEx ' +\n        'WinAPI_PrintWindow WinAPI_ProgIDFromCLSID WinAPI_PtInRect ' +\n        'WinAPI_PtInRectEx WinAPI_PtInRegion WinAPI_PtVisible ' +\n        'WinAPI_QueryDosDevice WinAPI_QueryInformationJobObject ' +\n        'WinAPI_QueryPerformanceCounter WinAPI_QueryPerformanceFrequency ' +\n        'WinAPI_RadialGradientFill WinAPI_ReadDirectoryChanges ' +\n        'WinAPI_ReadFile WinAPI_ReadProcessMemory WinAPI_Rectangle ' +\n        'WinAPI_RectInRegion WinAPI_RectIsEmpty WinAPI_RectVisible ' +\n        'WinAPI_RedrawWindow WinAPI_RegCloseKey ' +\n        'WinAPI_RegConnectRegistry WinAPI_RegCopyTree ' +\n        'WinAPI_RegCopyTreeEx WinAPI_RegCreateKey ' +\n        'WinAPI_RegDeleteEmptyKey WinAPI_RegDeleteKey ' +\n        'WinAPI_RegDeleteKeyValue WinAPI_RegDeleteTree ' +\n        'WinAPI_RegDeleteTreeEx WinAPI_RegDeleteValue ' +\n        'WinAPI_RegDisableReflectionKey WinAPI_RegDuplicateHKey ' +\n        'WinAPI_RegEnableReflectionKey WinAPI_RegEnumKey ' +\n        'WinAPI_RegEnumValue WinAPI_RegFlushKey ' +\n        'WinAPI_RegisterApplicationRestart WinAPI_RegisterClass ' +\n        'WinAPI_RegisterClassEx WinAPI_RegisterHotKey ' +\n        'WinAPI_RegisterPowerSettingNotification ' +\n        'WinAPI_RegisterRawInputDevices WinAPI_RegisterShellHookWindow ' +\n        'WinAPI_RegisterWindowMessage WinAPI_RegLoadMUIString ' +\n        'WinAPI_RegNotifyChangeKeyValue WinAPI_RegOpenKey ' +\n        'WinAPI_RegQueryInfoKey WinAPI_RegQueryLastWriteTime ' +\n        'WinAPI_RegQueryMultipleValues WinAPI_RegQueryReflectionKey ' +\n        'WinAPI_RegQueryValue WinAPI_RegRestoreKey WinAPI_RegSaveKey ' +\n        'WinAPI_RegSetValue WinAPI_ReleaseCapture WinAPI_ReleaseDC ' +\n        'WinAPI_ReleaseMutex WinAPI_ReleaseSemaphore ' +\n        'WinAPI_ReleaseStream WinAPI_RemoveClipboardFormatListener ' +\n        'WinAPI_RemoveDirectory WinAPI_RemoveFontMemResourceEx ' +\n        'WinAPI_RemoveFontResourceEx WinAPI_RemoveWindowSubclass ' +\n        'WinAPI_ReOpenFile WinAPI_ReplaceFile WinAPI_ReplaceTextDlg ' +\n        'WinAPI_ResetEvent WinAPI_RestartDlg WinAPI_RestoreDC ' +\n        'WinAPI_RGB WinAPI_RotatePoints WinAPI_RoundRect ' +\n        'WinAPI_SaveDC WinAPI_SaveFileDlg WinAPI_SaveHBITMAPToFile ' +\n        'WinAPI_SaveHICONToFile WinAPI_ScaleWindowExt ' +\n        'WinAPI_ScreenToClient WinAPI_SearchPath WinAPI_SelectClipPath ' +\n        'WinAPI_SelectClipRgn WinAPI_SelectObject ' +\n        'WinAPI_SendMessageTimeout WinAPI_SetActiveWindow ' +\n        'WinAPI_SetArcDirection WinAPI_SetBitmapBits ' +\n        'WinAPI_SetBitmapDimensionEx WinAPI_SetBkColor ' +\n        'WinAPI_SetBkMode WinAPI_SetBoundsRect WinAPI_SetBrushOrg ' +\n        'WinAPI_SetCapture WinAPI_SetCaretBlinkTime WinAPI_SetCaretPos ' +\n        'WinAPI_SetClassLongEx WinAPI_SetColorAdjustment ' +\n        'WinAPI_SetCompression WinAPI_SetCurrentDirectory ' +\n        'WinAPI_SetCurrentProcessExplicitAppUserModelID WinAPI_SetCursor ' +\n        'WinAPI_SetDCBrushColor WinAPI_SetDCPenColor ' +\n        'WinAPI_SetDefaultPrinter WinAPI_SetDeviceGammaRamp ' +\n        'WinAPI_SetDIBColorTable WinAPI_SetDIBits ' +\n        'WinAPI_SetDIBitsToDevice WinAPI_SetDllDirectory ' +\n        'WinAPI_SetEndOfFile WinAPI_SetEnhMetaFileBits ' +\n        'WinAPI_SetErrorMode WinAPI_SetEvent WinAPI_SetFileAttributes ' +\n        'WinAPI_SetFileInformationByHandleEx WinAPI_SetFilePointer ' +\n        'WinAPI_SetFilePointerEx WinAPI_SetFileShortName ' +\n        'WinAPI_SetFileValidData WinAPI_SetFocus WinAPI_SetFont ' +\n        'WinAPI_SetForegroundWindow WinAPI_SetFRBuffer ' +\n        'WinAPI_SetGraphicsMode WinAPI_SetHandleInformation ' +\n        'WinAPI_SetInformationJobObject WinAPI_SetKeyboardLayout ' +\n        'WinAPI_SetKeyboardState WinAPI_SetLastError ' +\n        'WinAPI_SetLayeredWindowAttributes WinAPI_SetLocaleInfo ' +\n        'WinAPI_SetMapMode WinAPI_SetMessageExtraInfo WinAPI_SetParent ' +\n        'WinAPI_SetPixel WinAPI_SetPolyFillMode ' +\n        'WinAPI_SetPriorityClass WinAPI_SetProcessAffinityMask ' +\n        'WinAPI_SetProcessShutdownParameters ' +\n        'WinAPI_SetProcessWindowStation WinAPI_SetRectRgn ' +\n        'WinAPI_SetROP2 WinAPI_SetSearchPathMode ' +\n        'WinAPI_SetStretchBltMode WinAPI_SetSysColors ' +\n        'WinAPI_SetSystemCursor WinAPI_SetTextAlign ' +\n        'WinAPI_SetTextCharacterExtra WinAPI_SetTextColor ' +\n        'WinAPI_SetTextJustification WinAPI_SetThemeAppProperties ' +\n        'WinAPI_SetThreadDesktop WinAPI_SetThreadErrorMode ' +\n        'WinAPI_SetThreadExecutionState WinAPI_SetThreadLocale ' +\n        'WinAPI_SetThreadUILanguage WinAPI_SetTimer ' +\n        'WinAPI_SetUDFColorMode WinAPI_SetUserGeoID ' +\n        'WinAPI_SetUserObjectInformation WinAPI_SetVolumeMountPoint ' +\n        'WinAPI_SetWindowDisplayAffinity WinAPI_SetWindowExt ' +\n        'WinAPI_SetWindowLong WinAPI_SetWindowOrg ' +\n        'WinAPI_SetWindowPlacement WinAPI_SetWindowPos ' +\n        'WinAPI_SetWindowRgn WinAPI_SetWindowsHookEx ' +\n        'WinAPI_SetWindowSubclass WinAPI_SetWindowText ' +\n        'WinAPI_SetWindowTheme WinAPI_SetWinEventHook ' +\n        'WinAPI_SetWorldTransform WinAPI_SfcIsFileProtected ' +\n        'WinAPI_SfcIsKeyProtected WinAPI_ShellAboutDlg ' +\n        'WinAPI_ShellAddToRecentDocs WinAPI_ShellChangeNotify ' +\n        'WinAPI_ShellChangeNotifyDeregister ' +\n        'WinAPI_ShellChangeNotifyRegister WinAPI_ShellCreateDirectory ' +\n        'WinAPI_ShellEmptyRecycleBin WinAPI_ShellExecute ' +\n        'WinAPI_ShellExecuteEx WinAPI_ShellExtractAssociatedIcon ' +\n        'WinAPI_ShellExtractIcon WinAPI_ShellFileOperation ' +\n        'WinAPI_ShellFlushSFCache WinAPI_ShellGetFileInfo ' +\n        'WinAPI_ShellGetIconOverlayIndex WinAPI_ShellGetImageList ' +\n        'WinAPI_ShellGetKnownFolderIDList WinAPI_ShellGetKnownFolderPath ' +\n        'WinAPI_ShellGetLocalizedName WinAPI_ShellGetPathFromIDList ' +\n        'WinAPI_ShellGetSetFolderCustomSettings WinAPI_ShellGetSettings ' +\n        'WinAPI_ShellGetSpecialFolderLocation ' +\n        'WinAPI_ShellGetSpecialFolderPath WinAPI_ShellGetStockIconInfo ' +\n        'WinAPI_ShellILCreateFromPath WinAPI_ShellNotifyIcon ' +\n        'WinAPI_ShellNotifyIconGetRect WinAPI_ShellObjectProperties ' +\n        'WinAPI_ShellOpenFolderAndSelectItems WinAPI_ShellOpenWithDlg ' +\n        'WinAPI_ShellQueryRecycleBin ' +\n        'WinAPI_ShellQueryUserNotificationState ' +\n        'WinAPI_ShellRemoveLocalizedName WinAPI_ShellRestricted ' +\n        'WinAPI_ShellSetKnownFolderPath WinAPI_ShellSetLocalizedName ' +\n        'WinAPI_ShellSetSettings WinAPI_ShellStartNetConnectionDlg ' +\n        'WinAPI_ShellUpdateImage WinAPI_ShellUserAuthenticationDlg ' +\n        'WinAPI_ShellUserAuthenticationDlgEx WinAPI_ShortToWord ' +\n        'WinAPI_ShowCaret WinAPI_ShowCursor WinAPI_ShowError ' +\n        'WinAPI_ShowLastError WinAPI_ShowMsg WinAPI_ShowOwnedPopups ' +\n        'WinAPI_ShowWindow WinAPI_ShutdownBlockReasonCreate ' +\n        'WinAPI_ShutdownBlockReasonDestroy ' +\n        'WinAPI_ShutdownBlockReasonQuery WinAPI_SizeOfResource ' +\n        'WinAPI_StretchBlt WinAPI_StretchDIBits ' +\n        'WinAPI_StrFormatByteSize WinAPI_StrFormatByteSizeEx ' +\n        'WinAPI_StrFormatKBSize WinAPI_StrFromTimeInterval ' +\n        'WinAPI_StringFromGUID WinAPI_StringLenA WinAPI_StringLenW ' +\n        'WinAPI_StrLen WinAPI_StrokeAndFillPath WinAPI_StrokePath ' +\n        'WinAPI_StructToArray WinAPI_SubLangId WinAPI_SubtractRect ' +\n        'WinAPI_SwapDWord WinAPI_SwapQWord WinAPI_SwapWord ' +\n        'WinAPI_SwitchColor WinAPI_SwitchDesktop ' +\n        'WinAPI_SwitchToThisWindow WinAPI_SystemParametersInfo ' +\n        'WinAPI_TabbedTextOut WinAPI_TerminateJobObject ' +\n        'WinAPI_TerminateProcess WinAPI_TextOut WinAPI_TileWindows ' +\n        'WinAPI_TrackMouseEvent WinAPI_TransparentBlt ' +\n        'WinAPI_TwipsPerPixelX WinAPI_TwipsPerPixelY ' +\n        'WinAPI_UnhookWindowsHookEx WinAPI_UnhookWinEvent ' +\n        'WinAPI_UnionRect WinAPI_UnionStruct WinAPI_UniqueHardwareID ' +\n        'WinAPI_UnloadKeyboardLayout WinAPI_UnlockFile ' +\n        'WinAPI_UnmapViewOfFile WinAPI_UnregisterApplicationRestart ' +\n        'WinAPI_UnregisterClass WinAPI_UnregisterHotKey ' +\n        'WinAPI_UnregisterPowerSettingNotification ' +\n        'WinAPI_UpdateLayeredWindow WinAPI_UpdateLayeredWindowEx ' +\n        'WinAPI_UpdateLayeredWindowIndirect WinAPI_UpdateResource ' +\n        'WinAPI_UpdateWindow WinAPI_UrlApplyScheme ' +\n        'WinAPI_UrlCanonicalize WinAPI_UrlCombine WinAPI_UrlCompare ' +\n        'WinAPI_UrlCreateFromPath WinAPI_UrlFixup WinAPI_UrlGetPart ' +\n        'WinAPI_UrlHash WinAPI_UrlIs WinAPI_UserHandleGrantAccess ' +\n        'WinAPI_ValidateRect WinAPI_ValidateRgn WinAPI_VerQueryRoot ' +\n        'WinAPI_VerQueryValue WinAPI_VerQueryValueEx ' +\n        'WinAPI_WaitForInputIdle WinAPI_WaitForMultipleObjects ' +\n        'WinAPI_WaitForSingleObject WinAPI_WideCharToMultiByte ' +\n        'WinAPI_WidenPath WinAPI_WindowFromDC WinAPI_WindowFromPoint ' +\n        'WinAPI_WordToShort WinAPI_Wow64EnableWow64FsRedirection ' +\n        'WinAPI_WriteConsole WinAPI_WriteFile ' +\n        'WinAPI_WriteProcessMemory WinAPI_ZeroMemory ' +\n        'WinNet_AddConnection WinNet_AddConnection2 ' +\n        'WinNet_AddConnection3 WinNet_CancelConnection ' +\n        'WinNet_CancelConnection2 WinNet_CloseEnum ' +\n        'WinNet_ConnectionDialog WinNet_ConnectionDialog1 ' +\n        'WinNet_DisconnectDialog WinNet_DisconnectDialog1 ' +\n        'WinNet_EnumResource WinNet_GetConnection ' +\n        'WinNet_GetConnectionPerformance WinNet_GetLastError ' +\n        'WinNet_GetNetworkInformation WinNet_GetProviderName ' +\n        'WinNet_GetResourceInformation WinNet_GetResourceParent ' +\n        'WinNet_GetUniversalName WinNet_GetUser WinNet_OpenEnum ' +\n        'WinNet_RestoreConnection WinNet_UseConnection Word_Create ' +\n        'Word_DocAdd Word_DocAttach Word_DocClose Word_DocExport ' +\n        'Word_DocFind Word_DocFindReplace Word_DocGet ' +\n        'Word_DocLinkAdd Word_DocLinkGet Word_DocOpen ' +\n        'Word_DocPictureAdd Word_DocPrint Word_DocRangeSet ' +\n        'Word_DocSave Word_DocSaveAs Word_DocTableRead ' +\n        'Word_DocTableWrite Word_Quit',\n\n        COMMENT = {\n            variants: [\n              hljs.COMMENT(';', '$', {relevance: 0}),\n              hljs.COMMENT('#cs', '#ce'),\n              hljs.COMMENT('#comments-start', '#comments-end')\n            ]\n        },\n\n        VARIABLE = {\n            className: 'variable',\n            begin: '\\\\$[A-z0-9_]+'\n        },\n\n        STRING = {\n            className: 'string',\n            variants: [{\n                begin: /\"/,\n                end: /\"/,\n                contains: [{\n                    begin: /\"\"/,\n                    relevance: 0\n                }]\n            }, {\n                begin: /'/,\n                end: /'/,\n                contains: [{\n                    begin: /''/,\n                    relevance: 0\n                }]\n            }]\n        },\n\n        NUMBER = {\n            variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]\n        },\n\n        PREPROCESSOR = {\n            className: 'preprocessor',\n            begin: '#',\n            end: '$',\n            keywords: 'include include-once NoTrayIcon OnAutoItStartRegister RequireAdmin pragma ' +\n                'Au3Stripper_Ignore_Funcs Au3Stripper_Ignore_Variables ' +\n                'Au3Stripper_Off Au3Stripper_On Au3Stripper_Parameters ' +\n                'AutoIt3Wrapper_Add_Constants AutoIt3Wrapper_Au3Check_Parameters ' +\n                'AutoIt3Wrapper_Au3Check_Stop_OnWarning AutoIt3Wrapper_Aut2Exe ' +\n                'AutoIt3Wrapper_AutoIt3 AutoIt3Wrapper_AutoIt3Dir ' +\n                'AutoIt3Wrapper_Change2CUI AutoIt3Wrapper_Compile_Both ' +\n                'AutoIt3Wrapper_Compression AutoIt3Wrapper_EndIf ' +\n                'AutoIt3Wrapper_Icon AutoIt3Wrapper_If_Compile ' +\n                'AutoIt3Wrapper_If_Run AutoIt3Wrapper_Jump_To_First_Error ' +\n                'AutoIt3Wrapper_OutFile AutoIt3Wrapper_OutFile_Type ' +\n                'AutoIt3Wrapper_OutFile_X64 AutoIt3Wrapper_PlugIn_Funcs ' +\n                'AutoIt3Wrapper_Res_Comment Autoit3Wrapper_Res_Compatibility ' +\n                'AutoIt3Wrapper_Res_Description AutoIt3Wrapper_Res_Field ' +\n                'AutoIt3Wrapper_Res_File_Add AutoIt3Wrapper_Res_FileVersion ' +\n                'AutoIt3Wrapper_Res_FileVersion_AutoIncrement ' +\n                'AutoIt3Wrapper_Res_Icon_Add AutoIt3Wrapper_Res_Language ' +\n                'AutoIt3Wrapper_Res_LegalCopyright ' +\n                'AutoIt3Wrapper_Res_ProductVersion ' +\n                'AutoIt3Wrapper_Res_requestedExecutionLevel ' +\n                'AutoIt3Wrapper_Res_SaveSource AutoIt3Wrapper_Run_After ' +\n                'AutoIt3Wrapper_Run_Au3Check AutoIt3Wrapper_Run_Au3Stripper ' +\n                'AutoIt3Wrapper_Run_Before AutoIt3Wrapper_Run_Debug_Mode ' +\n                'AutoIt3Wrapper_Run_SciTE_Minimized ' +\n                'AutoIt3Wrapper_Run_SciTE_OutputPane_Minimized ' +\n                'AutoIt3Wrapper_Run_Tidy AutoIt3Wrapper_ShowProgress ' +\n                'AutoIt3Wrapper_Testing AutoIt3Wrapper_Tidy_Stop_OnError ' +\n                'AutoIt3Wrapper_UPX_Parameters AutoIt3Wrapper_UseUPX ' +\n                'AutoIt3Wrapper_UseX64 AutoIt3Wrapper_Version ' +\n                'AutoIt3Wrapper_Versioning AutoIt3Wrapper_Versioning_Parameters ' +\n                'Tidy_Off Tidy_On Tidy_Parameters EndRegion Region',\n            contains: [{\n                    begin: /\\\\\\n/,\n                    relevance: 0\n                }, {\n                    beginKeywords: 'include',\n                    end: '$',\n                    contains: [\n                        STRING, {\n                            className: 'string',\n                            variants: [{\n                                begin: '<',\n                                end: '>'\n                            }, {\n                                begin: /\"/,\n                                end: /\"/,\n                                contains: [{\n                                    begin: /\"\"/,\n                                    relevance: 0\n                                }]\n                            }, {\n                                begin: /'/,\n                                end: /'/,\n                                contains: [{\n                                    begin: /''/,\n                                    relevance: 0\n                                }]\n                            }]\n                        }\n                    ]\n                },\n                STRING,\n                COMMENT\n            ]\n        },\n\n        CONSTANT = {\n            className: 'constant',\n            // begin: '@',\n            // end: '$',\n            // keywords: 'AppDataCommonDir AppDataDir AutoItExe AutoItPID AutoItVersion AutoItX64 COM_EventObj CommonFilesDir Compiled ComputerName ComSpec CPUArch CR CRLF DesktopCommonDir DesktopDepth DesktopDir DesktopHeight DesktopRefresh DesktopWidth DocumentsCommonDir error exitCode exitMethod extended FavoritesCommonDir FavoritesDir GUI_CtrlHandle GUI_CtrlId GUI_DragFile GUI_DragId GUI_DropId GUI_WinHandle HomeDrive HomePath HomeShare HotKeyPressed HOUR IPAddress1 IPAddress2 IPAddress3 IPAddress4 KBLayout LF LocalAppDataDir LogonDNSDomain LogonDomain LogonServer MDAY MIN MON MSEC MUILang MyDocumentsDir NumParams OSArch OSBuild OSLang OSServicePack OSType OSVersion ProgramFilesDir ProgramsCommonDir ProgramsDir ScriptDir ScriptFullPath ScriptLineNumber ScriptName SEC StartMenuCommonDir StartMenuDir StartupCommonDir StartupDir SW_DISABLE SW_ENABLE SW_HIDE SW_LOCK SW_MAXIMIZE SW_MINIMIZE SW_RESTORE SW_SHOW SW_SHOWDEFAULT SW_SHOWMAXIMIZED SW_SHOWMINIMIZED SW_SHOWMINNOACTIVE SW_SHOWNA SW_SHOWNOACTIVATE SW_SHOWNORMAL SW_UNLOCK SystemDir TAB TempDir TRAY_ID TrayIconFlashing TrayIconVisible UserName UserProfileDir WDAY WindowsDir WorkingDir YDAY YEAR',\n            // relevance: 5\n            begin: '@[A-z0-9_]+'\n        },\n\n        FUNCTION = {\n            className: 'function',\n            beginKeywords: 'Func',\n            end: '$',\n            excludeEnd: true,\n            illegal: '\\\\$|\\\\[|%',\n            contains: [\n                hljs.UNDERSCORE_TITLE_MODE, {\n                    className: 'params',\n                    begin: '\\\\(',\n                    end: '\\\\)',\n                    contains: [\n                        VARIABLE,\n                        STRING,\n                        NUMBER\n                    ]\n                }\n            ]\n        };\n\n    return {\n        case_insensitive: true,\n        illegal: /\\/\\*/,\n        keywords: {\n            keyword: KEYWORDS,\n            built_in: BUILT_IN,\n            literal: LITERAL\n        },\n        contains: [\n            COMMENT,\n            VARIABLE,\n            STRING,\n            NUMBER,\n            PREPROCESSOR,\n            CONSTANT,\n            FUNCTION\n        ]\n    }\n});\n\nhljs.registerLanguage('avrasm', function(hljs) {\n  return {\n    case_insensitive: true,\n    lexemes: '\\\\.?' + hljs.IDENT_RE,\n    keywords: {\n      keyword:\n        /* mnemonic */\n        'adc add adiw and andi asr bclr bld brbc brbs brcc brcs break breq brge brhc brhs ' +\n        'brid brie brlo brlt brmi brne brpl brsh brtc brts brvc brvs bset bst call cbi cbr ' +\n        'clc clh cli cln clr cls clt clv clz com cp cpc cpi cpse dec eicall eijmp elpm eor ' +\n        'fmul fmuls fmulsu icall ijmp in inc jmp ld ldd ldi lds lpm lsl lsr mov movw mul ' +\n        'muls mulsu neg nop or ori out pop push rcall ret reti rjmp rol ror sbc sbr sbrc sbrs ' +\n        'sec seh sbi sbci sbic sbis sbiw sei sen ser ses set sev sez sleep spm st std sts sub ' +\n        'subi swap tst wdr',\n      built_in:\n        /* general purpose registers */\n        'r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 ' +\n        'r23 r24 r25 r26 r27 r28 r29 r30 r31 x|0 xh xl y|0 yh yl z|0 zh zl ' +\n        /* IO Registers (ATMega128) */\n        'ucsr1c udr1 ucsr1a ucsr1b ubrr1l ubrr1h ucsr0c ubrr0h tccr3c tccr3a tccr3b tcnt3h ' +\n        'tcnt3l ocr3ah ocr3al ocr3bh ocr3bl ocr3ch ocr3cl icr3h icr3l etimsk etifr tccr1c ' +\n        'ocr1ch ocr1cl twcr twdr twar twsr twbr osccal xmcra xmcrb eicra spmcsr spmcr portg ' +\n        'ddrg ping portf ddrf sreg sph spl xdiv rampz eicrb eimsk gimsk gicr eifr gifr timsk ' +\n        'tifr mcucr mcucsr tccr0 tcnt0 ocr0 assr tccr1a tccr1b tcnt1h tcnt1l ocr1ah ocr1al ' +\n        'ocr1bh ocr1bl icr1h icr1l tccr2 tcnt2 ocr2 ocdr wdtcr sfior eearh eearl eedr eecr ' +\n        'porta ddra pina portb ddrb pinb portc ddrc pinc portd ddrd pind spdr spsr spcr udr0 ' +\n        'ucsr0a ucsr0b ubrr0l acsr admux adcsr adch adcl porte ddre pine pinf',\n      preprocessor:\n        '.byte .cseg .db .def .device .dseg .dw .endmacro .equ .eseg .exit .include .list ' +\n        '.listmac .macro .nolist .org .set'\n    },\n    contains: [\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.COMMENT(\n        ';',\n        '$',\n        {\n          relevance: 0\n        }\n      ),\n      hljs.C_NUMBER_MODE, // 0x..., decimal, float\n      hljs.BINARY_NUMBER_MODE, // 0b...\n      {\n        className: 'number',\n        begin: '\\\\b(\\\\$[a-zA-Z0-9]+|0o[0-7]+)' // $..., 0o...\n      },\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        begin: '\\'', end: '[^\\\\\\\\]\\'',\n        illegal: '[^\\\\\\\\][^\\']'\n      },\n      {className: 'label',  begin: '^[A-Za-z0-9_.$]+:'},\n      {className: 'preprocessor', begin: '#', end: '$'},\n      {  // подстановка в «.macro»\n        className: 'localvars',\n        begin: '@[0-9]+'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('axapta', function(hljs) {\n  return {\n    keywords: 'false int abstract private char boolean static null if for true ' +\n      'while long throw finally protected final return void enum else ' +\n      'break new catch byte super case short default double public try this switch ' +\n      'continue reverse firstfast firstonly forupdate nofetch sum avg minof maxof count ' +\n      'order group by asc desc index hint like dispaly edit client server ttsbegin ' +\n      'ttscommit str real date container anytype common div mod',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'preprocessor',\n        begin: '#', end: '$'\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: '{', excludeEnd: true,\n        illegal: ':',\n        contains: [\n          {beginKeywords: 'extends implements'},\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('bash', function(hljs) {\n  var VAR = {\n    className: 'variable',\n    variants: [\n      {begin: /\\$[\\w\\d#@][\\w\\d_]*/},\n      {begin: /\\$\\{(.*?)}/}\n    ]\n  };\n  var QUOTE_STRING = {\n    className: 'string',\n    begin: /\"/, end: /\"/,\n    contains: [\n      hljs.BACKSLASH_ESCAPE,\n      VAR,\n      {\n        className: 'variable',\n        begin: /\\$\\(/, end: /\\)/,\n        contains: [hljs.BACKSLASH_ESCAPE]\n      }\n    ]\n  };\n  var APOS_STRING = {\n    className: 'string',\n    begin: /'/, end: /'/\n  };\n\n  return {\n    aliases: ['sh', 'zsh'],\n    lexemes: /-?[a-z\\.]+/,\n    keywords: {\n      keyword:\n        'if then else elif fi for while in do done case esac function',\n      literal:\n        'true false',\n      built_in:\n        // Shell built-ins\n        // http://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html\n        'break cd continue eval exec exit export getopts hash pwd readonly return shift test times ' +\n        'trap umask unset ' +\n        // Bash built-ins\n        'alias bind builtin caller command declare echo enable help let local logout mapfile printf ' +\n        'read readarray source type typeset ulimit unalias ' +\n        // Shell modifiers\n        'set shopt ' +\n        // Zsh built-ins\n        'autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles ' +\n        'compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate ' +\n        'fc fg float functions getcap getln history integer jobs kill limit log noglob popd print ' +\n        'pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit ' +\n        'unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof ' +\n        'zpty zregexparse zsocket zstyle ztcp',\n      operator:\n        '-ne -eq -lt -gt -f -d -e -s -l -a' // relevance booster\n    },\n    contains: [\n      {\n        className: 'shebang',\n        begin: /^#![^\\n]+sh\\s*$/,\n        relevance: 10\n      },\n      {\n        className: 'function',\n        begin: /\\w[\\w\\d_]*\\s*\\(\\s*\\)\\s*\\{/,\n        returnBegin: true,\n        contains: [hljs.inherit(hljs.TITLE_MODE, {begin: /\\w[\\w\\d_]*/})],\n        relevance: 0\n      },\n      hljs.HASH_COMMENT_MODE,\n      hljs.NUMBER_MODE,\n      QUOTE_STRING,\n      APOS_STRING,\n      VAR\n    ]\n  };\n});\n\nhljs.registerLanguage('brainfuck', function(hljs){\n  var LITERAL = {\n    className: 'literal',\n    begin: '[\\\\+\\\\-]',\n    relevance: 0\n  };\n  return {\n    aliases: ['bf'],\n    contains: [\n      hljs.COMMENT(\n        '[^\\\\[\\\\]\\\\.,\\\\+\\\\-<> \\r\\n]',\n        '[\\\\[\\\\]\\\\.,\\\\+\\\\-<> \\r\\n]',\n        {\n          returnEnd: true,\n          relevance: 0\n        }\n      ),\n      {\n        className: 'title',\n        begin: '[\\\\[\\\\]]',\n        relevance: 0\n      },\n      {\n        className: 'string',\n        begin: '[\\\\.,]',\n        relevance: 0\n      },\n      {\n        // this mode works as the only relevance counter\n        begin: /\\+\\+|\\-\\-/, returnBegin: true,\n        contains: [LITERAL]\n      },\n      LITERAL\n    ]\n  };\n});\n\nhljs.registerLanguage('cal', function(hljs) {\n  var KEYWORDS =\n    'div mod in and or not xor asserterror begin case do downto else end exit for if of repeat then to ' +\n    'until while with var';\n  var LITERALS = 'false true';\n  var COMMENT_MODES = [\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.COMMENT(\n      /\\{/,\n      /\\}/,\n      {\n        relevance: 0\n      }\n    ),\n    hljs.COMMENT(\n      /\\(\\*/,\n      /\\*\\)/,\n      {\n        relevance: 10\n      }\n    )\n  ];\n  var STRING = {\n    className: 'string',\n    begin: /'/, end: /'/,\n    contains: [{begin: /''/}]\n  };\n  var CHAR_STRING = {\n    className: 'string', begin: /(#\\d+)+/\n  };\n  var DATE = {\n      className: 'date',\n      begin: '\\\\b\\\\d+(\\\\.\\\\d+)?(DT|D|T)',\n      relevance: 0\n  };\n  var DBL_QUOTED_VARIABLE = {\n      className: 'variable',\n      begin: '\"',\n      end: '\"'\n  };\n\n  var PROCEDURE = {\n    className: 'function',\n    beginKeywords: 'procedure', end: /[:;]/,\n    keywords: 'procedure|10',\n    contains: [\n      hljs.TITLE_MODE,\n      {\n        className: 'params',\n        begin: /\\(/, end: /\\)/,\n        keywords: KEYWORDS,\n        contains: [STRING, CHAR_STRING]\n      }\n    ].concat(COMMENT_MODES)\n  };\n\n  var OBJECT = {\n    className: 'class',\n    begin: 'OBJECT (Table|Form|Report|Dataport|Codeunit|XMLport|MenuSuite|Page|Query) (\\\\d+) ([^\\\\r\\\\n]+)',\n    returnBegin: true,\n    contains: [\n      hljs.TITLE_MODE,\n        PROCEDURE\n    ]\n  };\n\n  return {\n    case_insensitive: true,\n    keywords: { keyword: KEYWORDS, literal: LITERALS },\n    illegal: /\\/\\*/,\n    contains: [\n      STRING, CHAR_STRING,\n      DATE, DBL_QUOTED_VARIABLE,\n      hljs.NUMBER_MODE,\n      OBJECT,\n      PROCEDURE\n    ]\n  };\n});\n\nhljs.registerLanguage('capnproto', function(hljs) {\n  return {\n    aliases: ['capnp'],\n    keywords: {\n      keyword:\n        'struct enum interface union group import using const annotation extends in of on as with from fixed',\n      built_in:\n        'Void Bool Int8 Int16 Int32 Int64 UInt8 UInt16 UInt32 UInt64 Float32 Float64 ' +\n        'Text Data AnyPointer AnyStruct Capability List',\n      literal:\n        'true false'\n    },\n    contains: [\n      hljs.QUOTE_STRING_MODE,\n      hljs.NUMBER_MODE,\n      hljs.HASH_COMMENT_MODE,\n      {\n        className: 'shebang',\n        begin: /@0x[\\w\\d]{16};/,\n        illegal: /\\n/\n      },\n      {\n        className: 'number',\n        begin: /@\\d+\\b/\n      },\n      {\n        className: 'class',\n        beginKeywords: 'struct enum', end: /\\{/,\n        illegal: /\\n/,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {\n            starts: {endsWithParent: true, excludeEnd: true} // hack: eating everything after the first title\n          })\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'interface', end: /\\{/,\n        illegal: /\\n/,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {\n            starts: {endsWithParent: true, excludeEnd: true} // hack: eating everything after the first title\n          })\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('ceylon', function(hljs) {\n  // 2.3. Identifiers and keywords\n  var KEYWORDS =\n    'assembly module package import alias class interface object given value ' +\n    'assign void function new of extends satisfies abstracts in out return ' +\n    'break continue throw assert dynamic if else switch case for while try ' +\n    'catch finally then let this outer super is exists nonempty';\n  // 7.4.1 Declaration Modifiers\n  var DECLARATION_MODIFIERS =\n    'shared abstract formal default actual variable late native deprecated' +\n    'final sealed annotation suppressWarnings small';\n  // 7.4.2 Documentation\n  var DOCUMENTATION =\n    'doc by license see throws tagged';\n  var LANGUAGE_ANNOTATIONS = DECLARATION_MODIFIERS + ' ' + DOCUMENTATION;\n  var SUBST = {\n    className: 'subst', excludeBegin: true, excludeEnd: true,\n    begin: /``/, end: /``/,\n    keywords: KEYWORDS,\n    relevance: 10\n  };\n  var EXPRESSIONS = [\n    {\n      // verbatim string\n      className: 'string',\n      begin: '\"\"\"',\n      end: '\"\"\"',\n      relevance: 10\n    },\n    {\n      // string literal or template\n      className: 'string',\n      begin: '\"', end: '\"',\n      contains: [SUBST]\n    },\n    {\n      // character literal\n      className: 'string',\n      begin: \"'\",\n      end: \"'\"\n    },\n    {\n      // numeric literal\n      className: 'number',\n      begin: '#[0-9a-fA-F_]+|\\\\$[01_]+|[0-9_]+(?:\\\\.[0-9_](?:[eE][+-]?\\\\d+)?)?[kMGTPmunpf]?',\n      relevance: 0\n    }\n  ];\n  SUBST.contains = EXPRESSIONS;\n\n  return {\n    keywords: {\n      keyword: KEYWORDS,\n      annotation: LANGUAGE_ANNOTATIONS\n    },\n    illegal: '\\\\$[^01]|#[^0-9a-fA-F]',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.COMMENT('/\\\\*', '\\\\*/', {contains: ['self']}),\n      {\n        // compiler annotation\n        className: 'annotation',\n        begin: '@[a-z]\\\\w*(?:\\\\:\\\"[^\\\"]*\\\")?'\n      }\n    ].concat(EXPRESSIONS)\n  };\n});\n\nhljs.registerLanguage('clojure', function(hljs) {\n  var keywords = {\n    built_in:\n      // Clojure keywords\n      'def defonce cond apply if-not if-let if not not= = < > <= >= == + / * - rem '+\n      'quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? '+\n      'set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? '+\n      'class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? '+\n      'string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . '+\n      'inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last '+\n      'drop-while while intern condp case reduced cycle split-at split-with repeat replicate '+\n      'iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext '+\n      'nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends '+\n      'add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler '+\n      'set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter '+\n      'monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or '+\n      'when when-not when-let comp juxt partial sequence memoize constantly complement identity assert '+\n      'peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast '+\n      'sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import '+\n      'refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! '+\n      'assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger '+\n      'bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline '+\n      'flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking '+\n      'assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! '+\n      'reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! '+\n      'new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty '+\n      'hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list '+\n      'disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer '+\n      'chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate '+\n      'unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta '+\n      'lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize'\n   };\n\n  var SYMBOLSTART = 'a-zA-Z_\\\\-!.?+*=<>&#\\'';\n  var SYMBOL_RE = '[' + SYMBOLSTART + '][' + SYMBOLSTART + '0-9/;:]*';\n  var SIMPLE_NUMBER_RE = '[-+]?\\\\d+(\\\\.\\\\d+)?';\n\n  var SYMBOL = {\n    begin: SYMBOL_RE,\n    relevance: 0\n  };\n  var NUMBER = {\n    className: 'number', begin: SIMPLE_NUMBER_RE,\n    relevance: 0\n  };\n  var STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null});\n  var COMMENT = hljs.COMMENT(\n    ';',\n    '$',\n    {\n      relevance: 0\n    }\n  );\n  var LITERAL = {\n    className: 'literal',\n    begin: /\\b(true|false|nil)\\b/\n  };\n  var COLLECTION = {\n    className: 'collection',\n    begin: '[\\\\[\\\\{]', end: '[\\\\]\\\\}]'\n  };\n  var HINT = {\n    className: 'comment',\n    begin: '\\\\^' + SYMBOL_RE\n  };\n  var HINT_COL = hljs.COMMENT('\\\\^\\\\{', '\\\\}');\n  var KEY = {\n    className: 'attribute',\n    begin: '[:]' + SYMBOL_RE\n  };\n  var LIST = {\n    className: 'list',\n    begin: '\\\\(', end: '\\\\)'\n  };\n  var BODY = {\n    endsWithParent: true,\n    relevance: 0\n  };\n  var NAME = {\n    keywords: keywords,\n    lexemes: SYMBOL_RE,\n    className: 'keyword', begin: SYMBOL_RE,\n    starts: BODY\n  };\n  var DEFAULT_CONTAINS = [LIST, STRING, HINT, HINT_COL, COMMENT, KEY, COLLECTION, NUMBER, LITERAL, SYMBOL];\n\n  LIST.contains = [hljs.COMMENT('comment', ''), NAME, BODY];\n  BODY.contains = DEFAULT_CONTAINS;\n  COLLECTION.contains = DEFAULT_CONTAINS;\n\n  return {\n    aliases: ['clj'],\n    illegal: /\\S/,\n    contains: [LIST, STRING, HINT, HINT_COL, COMMENT, KEY, COLLECTION, NUMBER, LITERAL]\n  }\n});\n\nhljs.registerLanguage('clojure-repl', function(hljs) {\n  return {\n    contains: [\n      {\n        className: 'prompt',\n        begin: /^([\\w.-]+|\\s*#_)=>/,\n        starts: {\n          end: /$/,\n          subLanguage: 'clojure'\n        }\n      }\n    ]\n  }\n});\n\nhljs.registerLanguage('cmake', function(hljs) {\n  return {\n    aliases: ['cmake.in'],\n    case_insensitive: true,\n    keywords: {\n      keyword:\n        'add_custom_command add_custom_target add_definitions add_dependencies ' +\n        'add_executable add_library add_subdirectory add_test aux_source_directory ' +\n        'break build_command cmake_minimum_required cmake_policy configure_file ' +\n        'create_test_sourcelist define_property else elseif enable_language enable_testing ' +\n        'endforeach endfunction endif endmacro endwhile execute_process export find_file ' +\n        'find_library find_package find_path find_program fltk_wrap_ui foreach function ' +\n        'get_cmake_property get_directory_property get_filename_component get_property ' +\n        'get_source_file_property get_target_property get_test_property if include ' +\n        'include_directories include_external_msproject include_regular_expression install ' +\n        'link_directories load_cache load_command macro mark_as_advanced message option ' +\n        'output_required_files project qt_wrap_cpp qt_wrap_ui remove_definitions return ' +\n        'separate_arguments set set_directory_properties set_property ' +\n        'set_source_files_properties set_target_properties set_tests_properties site_name ' +\n        'source_group string target_link_libraries try_compile try_run unset variable_watch ' +\n        'while build_name exec_program export_library_dependencies install_files ' +\n        'install_programs install_targets link_libraries make_directory remove subdir_depends ' +\n        'subdirs use_mangled_mesa utility_source variable_requires write_file ' +\n        'qt5_use_modules qt5_use_package qt5_wrap_cpp on off true false and or',\n      operator:\n        'equal less greater strless strgreater strequal matches'\n    },\n    contains: [\n      {\n        className: 'envvar',\n        begin: '\\\\${', end: '}'\n      },\n      hljs.HASH_COMMENT_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('coffeescript', function(hljs) {\n  var KEYWORDS = {\n    keyword:\n      // JS keywords\n      'in if for while finally new do return else break catch instanceof throw try this ' +\n      'switch continue typeof delete debugger super ' +\n      // Coffee keywords\n      'then unless until loop of by when and or is isnt not',\n    literal:\n      // JS literals\n      'true false null undefined ' +\n      // Coffee literals\n      'yes no on off',\n    built_in:\n      'npm require console print module global window document'\n  };\n  var JS_IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';\n  var SUBST = {\n    className: 'subst',\n    begin: /#\\{/, end: /}/,\n    keywords: KEYWORDS\n  };\n  var EXPRESSIONS = [\n    hljs.BINARY_NUMBER_MODE,\n    hljs.inherit(hljs.C_NUMBER_MODE, {starts: {end: '(\\\\s*/)?', relevance: 0}}), // a number tries to eat the following slash to prevent treating it as a regexp\n    {\n      className: 'string',\n      variants: [\n        {\n          begin: /'''/, end: /'''/,\n          contains: [hljs.BACKSLASH_ESCAPE]\n        },\n        {\n          begin: /'/, end: /'/,\n          contains: [hljs.BACKSLASH_ESCAPE]\n        },\n        {\n          begin: /\"\"\"/, end: /\"\"\"/,\n          contains: [hljs.BACKSLASH_ESCAPE, SUBST]\n        },\n        {\n          begin: /\"/, end: /\"/,\n          contains: [hljs.BACKSLASH_ESCAPE, SUBST]\n        }\n      ]\n    },\n    {\n      className: 'regexp',\n      variants: [\n        {\n          begin: '///', end: '///',\n          contains: [SUBST, hljs.HASH_COMMENT_MODE]\n        },\n        {\n          begin: '//[gim]*',\n          relevance: 0\n        },\n        {\n          // regex can't start with space to parse x / 2 / 3 as two divisions\n          // regex can't start with *, and it supports an \"illegal\" in the main mode\n          begin: /\\/(?![ *])(\\\\\\/|.)*?\\/[gim]*(?=\\W|$)/\n        }\n      ]\n    },\n    {\n      className: 'property',\n      begin: '@' + JS_IDENT_RE\n    },\n    {\n      begin: '`', end: '`',\n      excludeBegin: true, excludeEnd: true,\n      subLanguage: 'javascript'\n    }\n  ];\n  SUBST.contains = EXPRESSIONS;\n\n  var TITLE = hljs.inherit(hljs.TITLE_MODE, {begin: JS_IDENT_RE});\n  var PARAMS_RE = '(\\\\(.*\\\\))?\\\\s*\\\\B[-=]>';\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\([^\\\\(]', returnBegin: true,\n    /* We need another contained nameless mode to not have every nested\n    pair of parens to be called \"params\" */\n    contains: [{\n      begin: /\\(/, end: /\\)/,\n      keywords: KEYWORDS,\n      contains: ['self'].concat(EXPRESSIONS)\n    }]\n  };\n\n  return {\n    aliases: ['coffee', 'cson', 'iced'],\n    keywords: KEYWORDS,\n    illegal: /\\/\\*/,\n    contains: EXPRESSIONS.concat([\n      hljs.COMMENT('###', '###'),\n      hljs.HASH_COMMENT_MODE,\n      {\n        className: 'function',\n        begin: '^\\\\s*' + JS_IDENT_RE + '\\\\s*=\\\\s*' + PARAMS_RE, end: '[-=]>',\n        returnBegin: true,\n        contains: [TITLE, PARAMS]\n      },\n      {\n        // anonymous function start\n        begin: /[:\\(,=]\\s*/,\n        relevance: 0,\n        contains: [\n          {\n            className: 'function',\n            begin: PARAMS_RE, end: '[-=]>',\n            returnBegin: true,\n            contains: [PARAMS]\n          }\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class',\n        end: '$',\n        illegal: /[:=\"\\[\\]]/,\n        contains: [\n          {\n            beginKeywords: 'extends',\n            endsWithParent: true,\n            illegal: /[:=\"\\[\\]]/,\n            contains: [TITLE]\n          },\n          TITLE\n        ]\n      },\n      {\n        className: 'attribute',\n        begin: JS_IDENT_RE + ':', end: ':',\n        returnBegin: true, returnEnd: true,\n        relevance: 0\n      }\n    ])\n  };\n});\n\nhljs.registerLanguage('cpp', function(hljs) {\n  var CPP_PRIMATIVE_TYPES = {\n    className: 'keyword',\n    begin: '\\\\b[a-z\\\\d_]*_t\\\\b'\n  };\n\n  var STRINGS = {\n    className: 'string',\n    variants: [\n      hljs.inherit(hljs.QUOTE_STRING_MODE, { begin: '((u8?|U)|L)?\"' }),\n      {\n        begin: '(u8?|U)?R\"', end: '\"',\n        contains: [hljs.BACKSLASH_ESCAPE]\n      },\n      {\n        begin: '\\'\\\\\\\\?.', end: '\\'',\n        illegal: '.'\n      }\n    ]\n  };\n\n  var NUMBERS = {\n    className: 'number',\n    variants: [\n      { begin: '\\\\b(\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)(u|U|l|L|ul|UL|f|F)' },\n      { begin: hljs.C_NUMBER_RE }\n    ]\n  };\n\n  var PREPROCESSOR =       {\n    className: 'preprocessor',\n    begin: '#', end: '$',\n    keywords: 'if else elif endif define undef warning error line ' +\n              'pragma ifdef ifndef',\n    contains: [\n      {\n        begin: /\\\\\\n/, relevance: 0\n      },\n      {\n        beginKeywords: 'include', end: '$',\n        contains: [\n          STRINGS,\n          {\n            className: 'string',\n            begin: '<', end: '>',\n            illegal: '\\\\n',\n          }\n        ]\n      },\n      STRINGS,\n      NUMBERS,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE\n    ]\n  };\n\n  var FUNCTION_TITLE = hljs.IDENT_RE + '\\\\s*\\\\(';\n\n  var CPP_KEYWORDS = {\n    keyword: 'int float while private char catch export virtual operator sizeof ' +\n      'dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace ' +\n      'unsigned long volatile static protected bool template mutable if public friend ' +\n      'do goto auto void enum else break extern using class asm case typeid ' +\n      'short reinterpret_cast|10 default double register explicit signed typename try this ' +\n      'switch continue inline delete alignof constexpr decltype ' +\n      'noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary ' +\n      'atomic_bool atomic_char atomic_schar ' +\n      'atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong ' +\n      'atomic_ullong',\n    built_in: 'std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream ' +\n      'auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set ' +\n      'unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos ' +\n      'asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp ' +\n      'fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper ' +\n      'isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow ' +\n      'printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp ' +\n      'strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan ' +\n      'vfprintf vprintf vsprintf',\n    literal: 'true false nullptr NULL'\n  };\n\n  return {\n    aliases: ['c', 'cc', 'h', 'c++', 'h++', 'hpp'],\n    keywords: CPP_KEYWORDS,\n    illegal: '</',\n    contains: [\n      CPP_PRIMATIVE_TYPES,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      NUMBERS,\n      STRINGS,\n      PREPROCESSOR,\n      {\n        begin: '\\\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\\\s*<', end: '>',\n        keywords: CPP_KEYWORDS,\n        contains: ['self', CPP_PRIMATIVE_TYPES]\n      },\n      {\n        begin: hljs.IDENT_RE + '::',\n        keywords: CPP_KEYWORDS\n      },\n      {\n        // Expression keywords prevent 'keyword Name(...) or else if(...)' from\n        // being recognized as a function definition\n        beginKeywords: 'new throw return else',\n        relevance: 0\n      },\n      {\n        className: 'function',\n        begin: '(' + hljs.IDENT_RE + '[\\\\*&\\\\s]+)+' + FUNCTION_TITLE,\n        returnBegin: true, end: /[{;=]/,\n        excludeEnd: true,\n        keywords: CPP_KEYWORDS,\n        illegal: /[^\\w\\s\\*&]/,\n        contains: [\n          {\n            begin: FUNCTION_TITLE, returnBegin: true,\n            contains: [hljs.TITLE_MODE],\n            relevance: 0\n          },\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            keywords: CPP_KEYWORDS,\n            relevance: 0,\n            contains: [\n              hljs.C_LINE_COMMENT_MODE,\n              hljs.C_BLOCK_COMMENT_MODE,\n              STRINGS,\n              NUMBERS\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE,\n          PREPROCESSOR\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('crmsh', function(hljs) {\n  var RESOURCES = 'primitive rsc_template';\n\n  var COMMANDS = 'group clone ms master location colocation order fencing_topology ' +\n      'rsc_ticket acl_target acl_group user role ' +\n      'tag xml';\n\n  var PROPERTY_SETS = 'property rsc_defaults op_defaults';\n\n  var KEYWORDS = 'params meta operations op rule attributes utilization';\n\n  var OPERATORS = 'read write deny defined not_defined in_range date spec in ' +\n      'ref reference attribute type xpath version and or lt gt tag ' +\n      'lte gte eq ne \\\\';\n\n  var TYPES = 'number string';\n\n  var LITERALS = 'Master Started Slave Stopped start promote demote stop monitor true false';\n\n  return {\n    aliases: ['crm', 'pcmk'],\n    case_insensitive: true,\n    keywords: {\n      keyword: KEYWORDS,\n      operator: OPERATORS,\n      type: TYPES,\n      literal: LITERALS\n    },\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      {\n        beginKeywords: 'node',\n        starts: {\n          className: 'identifier',\n          end: '\\\\s*([\\\\w_-]+:)?',\n          starts: {\n            className: 'title',\n            end: '\\\\s*[\\\\$\\\\w_][\\\\w_-]*'\n          }\n        }\n      },\n      {\n        beginKeywords: RESOURCES,\n        starts: {\n          className: 'title',\n          end: '\\\\s*[\\\\$\\\\w_][\\\\w_-]*',\n          starts: {\n            className: 'pragma',\n            end: '\\\\s*@?[\\\\w_][\\\\w_\\\\.:-]*',\n          }\n        }\n      },\n      {\n        begin: '\\\\b(' + COMMANDS.split(' ').join('|') + ')\\\\s+',\n        keywords: COMMANDS,\n        starts: {\n          className: 'title',\n          end: '[\\\\$\\\\w_][\\\\w_-]*',\n        }\n      },\n      {\n        beginKeywords: PROPERTY_SETS,\n        starts: {\n          className: 'title',\n          end: '\\\\s*([\\\\w_-]+:)?'\n        }\n      },\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'pragma',\n        begin: '(ocf|systemd|service|lsb):[\\\\w_:-]+',\n        relevance: 0\n      },\n      {\n        className: 'number',\n        begin: '\\\\b\\\\d+(\\\\.\\\\d+)?(ms|s|h|m)?',\n        relevance: 0\n      },\n      {\n        className: 'number',\n        begin: '[-]?(infinity|inf)',\n        relevance: 0\n      },\n      {\n        className: 'variable',\n        begin: /([A-Za-z\\$_\\#][\\w_-]+)=/,\n        relevance: 0\n      },\n      {\n        className: 'tag',\n        begin: '</?',\n        end: '/?>',\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('crystal', function(hljs) {\n  var NUM_SUFFIX = '(_[uif](8|16|32|64))?';\n  var CRYSTAL_IDENT_RE = '[a-zA-Z_]\\\\w*[!?=]?';\n  var RE_STARTER = '!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|' +\n    '>>|>|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~';\n  var CRYSTAL_METHOD_RE = '[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\][=?]?';\n  var CRYSTAL_KEYWORDS = {\n    keyword:\n      'abstract alias as asm begin break case class def do else elsif end ensure enum extend for fun if ifdef ' +\n      'include instance_sizeof is_a? lib macro module next of out pointerof private protected rescue responds_to? ' +\n      'return require self sizeof struct super then type typeof union unless until when while with yield ' +\n      '__DIR__ __FILE__ __LINE__',\n    literal: 'false nil true'\n  };\n  var SUBST = {\n    className: 'subst',\n    begin: '#{', end: '}',\n    keywords: CRYSTAL_KEYWORDS\n  };\n  var EXPANSION = {\n    className: 'expansion',\n    variants: [\n      {begin: '\\\\{\\\\{', end: '\\\\}\\\\}'},\n      {begin: '\\\\{%', end: '%\\\\}'}\n    ],\n    keywords: CRYSTAL_KEYWORDS,\n    relevance: 10\n  };\n\n  function recursiveParen(begin, end) {\n    var\n    contains = [{begin: begin, end: end}];\n    contains[0].contains = contains;\n    return contains;\n  }\n  var STRING = {\n    className: 'string',\n    contains: [hljs.BACKSLASH_ESCAPE, SUBST],\n    variants: [\n      {begin: /'/, end: /'/},\n      {begin: /\"/, end: /\"/},\n      {begin: /`/, end: /`/},\n      {begin: '%w?\\\\(', end: '\\\\)', contains: recursiveParen('\\\\(', '\\\\)')},\n      {begin: '%w?\\\\[', end: '\\\\]', contains: recursiveParen('\\\\[', '\\\\]')},\n      {begin: '%w?{', end: '}', contains: recursiveParen('{', '}')},\n      {begin: '%w?<', end: '>', contains: recursiveParen('<', '>')},\n      {begin: '%w?/', end: '/'},\n      {begin: '%w?%', end: '%'},\n      {begin: '%w?-', end: '-'},\n      {begin: '%w?\\\\|', end: '\\\\|'},\n    ],\n    relevance: 0,\n  };\n  var REGEXP = {\n    begin: '(' + RE_STARTER + ')\\\\s*',\n    contains: [\n      {\n        className: 'regexp',\n        contains: [hljs.BACKSLASH_ESCAPE, SUBST],\n        variants: [\n          {begin: '/', end: '/[a-z]*'},\n          {begin: '%r\\\\(', end: '\\\\)', contains: recursiveParen('\\\\(', '\\\\)')},\n          {begin: '%r\\\\[', end: '\\\\]', contains: recursiveParen('\\\\[', '\\\\]')},\n          {begin: '%r{', end: '}', contains: recursiveParen('{', '}')},\n          {begin: '%r<', end: '>', contains: recursiveParen('<', '>')},\n          {begin: '%r/', end: '/'},\n          {begin: '%r%', end: '%'},\n          {begin: '%r-', end: '-'},\n          {begin: '%r\\\\|', end: '\\\\|'},\n        ]\n      }\n    ],\n    relevance: 0\n  };\n  var REGEXP2 = {\n    className: 'regexp',\n    contains: [hljs.BACKSLASH_ESCAPE, SUBST],\n    variants: [\n      {begin: '%r\\\\(', end: '\\\\)', contains: recursiveParen('\\\\(', '\\\\)')},\n      {begin: '%r\\\\[', end: '\\\\]', contains: recursiveParen('\\\\[', '\\\\]')},\n      {begin: '%r{', end: '}', contains: recursiveParen('{', '}')},\n      {begin: '%r<', end: '>', contains: recursiveParen('<', '>')},\n      {begin: '%r/', end: '/'},\n      {begin: '%r%', end: '%'},\n      {begin: '%r-', end: '-'},\n      {begin: '%r\\\\|', end: '\\\\|'},\n    ],\n    relevance: 0\n  };\n  var ATTRIBUTE = {\n    className: 'annotation',\n    begin: '@\\\\[', end: '\\\\]',\n    relevance: 5\n  };\n  var CRYSTAL_DEFAULT_CONTAINS = [\n    EXPANSION,\n    STRING,\n    REGEXP,\n    REGEXP2,\n    ATTRIBUTE,\n    hljs.HASH_COMMENT_MODE,\n    {\n      className: 'class',\n      beginKeywords: 'class module struct', end: '$|;',\n      illegal: /=/,\n      contains: [\n        hljs.HASH_COMMENT_MODE,\n        hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?'}),\n        {\n          className: 'inheritance',\n          begin: '<\\\\s*',\n          contains: [{\n            className: 'parent',\n            begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE\n          }]\n        }\n      ]\n    },\n    {\n      className: 'class',\n      beginKeywords: 'lib enum union', end: '$|;',\n      illegal: /=/,\n      contains: [\n        hljs.HASH_COMMENT_MODE,\n        hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?'}),\n      ],\n      relevance: 10\n    },\n    {\n      className: 'function',\n      beginKeywords: 'def', end: /\\B\\b/,\n      contains: [\n        hljs.inherit(hljs.TITLE_MODE, {\n          begin: CRYSTAL_METHOD_RE,\n          endsParent: true\n        })\n      ]\n    },\n    {\n      className: 'function',\n      beginKeywords: 'fun macro', end: /\\B\\b/,\n      contains: [\n        hljs.inherit(hljs.TITLE_MODE, {\n          begin: CRYSTAL_METHOD_RE,\n          endsParent: true\n        })\n      ],\n      relevance: 5\n    },\n    {\n      className: 'constant',\n      begin: '(::)?(\\\\b[A-Z]\\\\w*(::)?)+',\n      relevance: 0\n    },\n    {\n      className: 'symbol',\n      begin: hljs.UNDERSCORE_IDENT_RE + '(\\\\!|\\\\?)?:',\n      relevance: 0\n    },\n    {\n      className: 'symbol',\n      begin: ':',\n      contains: [STRING, {begin: CRYSTAL_METHOD_RE}],\n      relevance: 0\n    },\n    {\n      className: 'number',\n      variants: [\n        { begin: '\\\\b0b([01_]*[01])' + NUM_SUFFIX },\n        { begin: '\\\\b0o([0-7_]*[0-7])' + NUM_SUFFIX },\n        { begin: '\\\\b0x([A-Fa-f0-9_]*[A-Fa-f0-9])' + NUM_SUFFIX },\n        { begin: '\\\\b(([0-9][0-9_]*[0-9]|[0-9])(\\\\.[0-9_]*[0-9])?([eE][+-]?[0-9_]*[0-9])?)' + NUM_SUFFIX}\n      ],\n      relevance: 0\n    },\n    {\n      className: 'variable',\n      begin: '(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?|%)(\\\\w+))'\n    }\n  ];\n  SUBST.contains = CRYSTAL_DEFAULT_CONTAINS;\n  ATTRIBUTE.contains = CRYSTAL_DEFAULT_CONTAINS;\n  EXPANSION.contains = CRYSTAL_DEFAULT_CONTAINS.slice(1); // without EXPANSION\n\n  return {\n    aliases: ['cr'],\n    lexemes: CRYSTAL_IDENT_RE,\n    keywords: CRYSTAL_KEYWORDS,\n    contains: CRYSTAL_DEFAULT_CONTAINS\n  };\n});\n\nhljs.registerLanguage('cs', function(hljs) {\n  var KEYWORDS =\n    // Normal keywords.\n    'abstract as base bool break byte case catch char checked const continue decimal dynamic ' +\n    'default delegate do double else enum event explicit extern false finally fixed float ' +\n    'for foreach goto if implicit in int interface internal is lock long null when ' +\n    'object operator out override params private protected public readonly ref sbyte ' +\n    'sealed short sizeof stackalloc static string struct switch this true try typeof ' +\n    'uint ulong unchecked unsafe ushort using virtual volatile void while async ' +\n    'protected public private internal ' +\n    // Contextual keywords.\n    'ascending descending from get group into join let orderby partial select set value var ' +\n    'where yield';\n  var GENERIC_IDENT_RE = hljs.IDENT_RE + '(<' + hljs.IDENT_RE + '>)?';\n  return {\n    aliases: ['csharp'],\n    keywords: KEYWORDS,\n    illegal: /::/,\n    contains: [\n      hljs.COMMENT(\n        '///',\n        '$',\n        {\n          returnBegin: true,\n          contains: [\n            {\n              className: 'xmlDocTag',\n              variants: [\n                {\n                  begin: '///', relevance: 0\n                },\n                {\n                  begin: '<!--|-->'\n                },\n                {\n                  begin: '</?', end: '>'\n                }\n              ]\n            }\n          ]\n        }\n      ),\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'preprocessor',\n        begin: '#', end: '$',\n        keywords: 'if else elif endif define undef warning error line region endregion pragma checksum'\n      },\n      {\n        className: 'string',\n        begin: '@\"', end: '\"',\n        contains: [{begin: '\"\"'}]\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        beginKeywords: 'class interface', end: /[{;=]/,\n        illegal: /[^\\s:]/,\n        contains: [\n          hljs.TITLE_MODE,\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      },\n      {\n        beginKeywords: 'namespace', end: /[{;=]/,\n        illegal: /[^\\s:]/,\n        contains: [\n          {\n            // Customization of hljs.TITLE_MODE that allows '.'\n            className: 'title',\n            begin: '[a-zA-Z](\\\\.?\\\\w)*',\n            relevance: 0\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      },\n      {\n        // Expression keywords prevent 'keyword Name(...)' from being\n        // recognized as a function definition\n        beginKeywords: 'new return throw await',\n        relevance: 0\n      },\n      {\n        className: 'function',\n        begin: '(' + GENERIC_IDENT_RE + '\\\\s+)+' + hljs.IDENT_RE + '\\\\s*\\\\(', returnBegin: true, end: /[{;=]/,\n        excludeEnd: true,\n        keywords: KEYWORDS,\n        contains: [\n          {\n            begin: hljs.IDENT_RE + '\\\\s*\\\\(', returnBegin: true,\n            contains: [hljs.TITLE_MODE],\n            relevance: 0\n          },\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            excludeBegin: true,\n            excludeEnd: true,\n            keywords: KEYWORDS,\n            relevance: 0,\n            contains: [\n              hljs.APOS_STRING_MODE,\n              hljs.QUOTE_STRING_MODE,\n              hljs.C_NUMBER_MODE,\n              hljs.C_BLOCK_COMMENT_MODE\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('css', function(hljs) {\n  var IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*';\n  var FUNCTION = {\n    className: 'function',\n    begin: IDENT_RE + '\\\\(',\n    returnBegin: true,\n    excludeEnd: true,\n    end: '\\\\('\n  };\n  var RULE = {\n    className: 'rule',\n    begin: /[A-Z\\_\\.\\-]+\\s*:/, returnBegin: true, end: ';', endsWithParent: true,\n    contains: [\n      {\n        className: 'attribute',\n        begin: /\\S/, end: ':', excludeEnd: true,\n        starts: {\n          className: 'value',\n          endsWithParent: true, excludeEnd: true,\n          contains: [\n            FUNCTION,\n            hljs.CSS_NUMBER_MODE,\n            hljs.QUOTE_STRING_MODE,\n            hljs.APOS_STRING_MODE,\n            hljs.C_BLOCK_COMMENT_MODE,\n            {\n              className: 'hexcolor', begin: '#[0-9A-Fa-f]+'\n            },\n            {\n              className: 'important', begin: '!important'\n            }\n          ]\n        }\n      }\n    ]\n  };\n\n  return {\n    case_insensitive: true,\n    illegal: /[=\\/|'\\$]/,\n    contains: [\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'id', begin: /\\#[A-Za-z0-9_-]+/\n      },\n      {\n        className: 'class', begin: /\\.[A-Za-z0-9_-]+/\n      },\n      {\n        className: 'attr_selector',\n        begin: /\\[/, end: /\\]/,\n        illegal: '$'\n      },\n      {\n        className: 'pseudo',\n        begin: /:(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\"']+/\n      },\n      {\n        className: 'at_rule',\n        begin: '@(font-face|page)',\n        lexemes: '[a-z-]+',\n        keywords: 'font-face page'\n      },\n      {\n        className: 'at_rule',\n        begin: '@', end: '[{;]', // at_rule eating first \"{\" is a good thing\n                                 // because it doesn’t let it to be parsed as\n                                 // a rule set but instead drops parser into\n                                 // the default mode which is how it should be.\n        contains: [\n          {\n            className: 'keyword',\n            begin: /\\S+/\n          },\n          {\n            begin: /\\s/, endsWithParent: true, excludeEnd: true,\n            relevance: 0,\n            contains: [\n              FUNCTION,\n              hljs.APOS_STRING_MODE, hljs.QUOTE_STRING_MODE,\n              hljs.CSS_NUMBER_MODE\n            ]\n          }\n        ]\n      },\n      {\n        className: 'tag', begin: IDENT_RE,\n        relevance: 0\n      },\n      {\n        className: 'rules',\n        begin: '{', end: '}',\n        illegal: /\\S/,\n        contains: [\n          hljs.C_BLOCK_COMMENT_MODE,\n          RULE,\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('d', /**\n * Known issues:\n *\n * - invalid hex string literals will be recognized as a double quoted strings\n *   but 'x' at the beginning of string will not be matched\n *\n * - delimited string literals are not checked for matching end delimiter\n *   (not possible to do with js regexp)\n *\n * - content of token string is colored as a string (i.e. no keyword coloring inside a token string)\n *   also, content of token string is not validated to contain only valid D tokens\n *\n * - special token sequence rule is not strictly following D grammar (anything following #line\n *   up to the end of line is matched as special token sequence)\n */\n\nfunction(hljs) {\n  /**\n   * Language keywords\n   *\n   * @type {Object}\n   */\n  var D_KEYWORDS = {\n    keyword:\n      'abstract alias align asm assert auto body break byte case cast catch class ' +\n      'const continue debug default delete deprecated do else enum export extern final ' +\n      'finally for foreach foreach_reverse|10 goto if immutable import in inout int ' +\n      'interface invariant is lazy macro mixin module new nothrow out override package ' +\n      'pragma private protected public pure ref return scope shared static struct ' +\n      'super switch synchronized template this throw try typedef typeid typeof union ' +\n      'unittest version void volatile while with __FILE__ __LINE__ __gshared|10 ' +\n      '__thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__',\n    built_in:\n      'bool cdouble cent cfloat char creal dchar delegate double dstring float function ' +\n      'idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar ' +\n      'wstring',\n    literal:\n      'false null true'\n  };\n\n  /**\n   * Number literal regexps\n   *\n   * @type {String}\n   */\n  var decimal_integer_re = '(0|[1-9][\\\\d_]*)',\n    decimal_integer_nosus_re = '(0|[1-9][\\\\d_]*|\\\\d[\\\\d_]*|[\\\\d_]+?\\\\d)',\n    binary_integer_re = '0[bB][01_]+',\n    hexadecimal_digits_re = '([\\\\da-fA-F][\\\\da-fA-F_]*|_[\\\\da-fA-F][\\\\da-fA-F_]*)',\n    hexadecimal_integer_re = '0[xX]' + hexadecimal_digits_re,\n\n    decimal_exponent_re = '([eE][+-]?' + decimal_integer_nosus_re + ')',\n    decimal_float_re = '(' + decimal_integer_nosus_re + '(\\\\.\\\\d*|' + decimal_exponent_re + ')|' +\n                '\\\\d+\\\\.' + decimal_integer_nosus_re + decimal_integer_nosus_re + '|' +\n                '\\\\.' + decimal_integer_re + decimal_exponent_re + '?' +\n              ')',\n    hexadecimal_float_re = '(0[xX](' +\n                  hexadecimal_digits_re + '\\\\.' + hexadecimal_digits_re + '|'+\n                  '\\\\.?' + hexadecimal_digits_re +\n                 ')[pP][+-]?' + decimal_integer_nosus_re + ')',\n\n    integer_re = '(' +\n      decimal_integer_re + '|' +\n      binary_integer_re  + '|' +\n       hexadecimal_integer_re   +\n    ')',\n\n    float_re = '(' +\n      hexadecimal_float_re + '|' +\n      decimal_float_re  +\n    ')';\n\n  /**\n   * Escape sequence supported in D string and character literals\n   *\n   * @type {String}\n   */\n  var escape_sequence_re = '\\\\\\\\(' +\n              '[\\'\"\\\\?\\\\\\\\abfnrtv]|' +  // common escapes\n              'u[\\\\dA-Fa-f]{4}|' +     // four hex digit unicode codepoint\n              '[0-7]{1,3}|' +       // one to three octal digit ascii char code\n              'x[\\\\dA-Fa-f]{2}|' +    // two hex digit ascii char code\n              'U[\\\\dA-Fa-f]{8}' +      // eight hex digit unicode codepoint\n              ')|' +\n              '&[a-zA-Z\\\\d]{2,};';      // named character entity\n\n  /**\n   * D integer number literals\n   *\n   * @type {Object}\n   */\n  var D_INTEGER_MODE = {\n    className: 'number',\n      begin: '\\\\b' + integer_re + '(L|u|U|Lu|LU|uL|UL)?',\n      relevance: 0\n  };\n\n  /**\n   * [D_FLOAT_MODE description]\n   * @type {Object}\n   */\n  var D_FLOAT_MODE = {\n    className: 'number',\n    begin: '\\\\b(' +\n        float_re + '([fF]|L|i|[fF]i|Li)?|' +\n        integer_re + '(i|[fF]i|Li)' +\n      ')',\n    relevance: 0\n  };\n\n  /**\n   * D character literal\n   *\n   * @type {Object}\n   */\n  var D_CHARACTER_MODE = {\n    className: 'string',\n    begin: '\\'(' + escape_sequence_re + '|.)', end: '\\'',\n    illegal: '.'\n  };\n\n  /**\n   * D string escape sequence\n   *\n   * @type {Object}\n   */\n  var D_ESCAPE_SEQUENCE = {\n    begin: escape_sequence_re,\n    relevance: 0\n  };\n\n  /**\n   * D double quoted string literal\n   *\n   * @type {Object}\n   */\n  var D_STRING_MODE = {\n    className: 'string',\n    begin: '\"',\n    contains: [D_ESCAPE_SEQUENCE],\n    end: '\"[cwd]?'\n  };\n\n  /**\n   * D wysiwyg and delimited string literals\n   *\n   * @type {Object}\n   */\n  var D_WYSIWYG_DELIMITED_STRING_MODE = {\n    className: 'string',\n    begin: '[rq]\"',\n    end: '\"[cwd]?',\n    relevance: 5\n  };\n\n  /**\n   * D alternate wysiwyg string literal\n   *\n   * @type {Object}\n   */\n  var D_ALTERNATE_WYSIWYG_STRING_MODE = {\n    className: 'string',\n    begin: '`',\n    end: '`[cwd]?'\n  };\n\n  /**\n   * D hexadecimal string literal\n   *\n   * @type {Object}\n   */\n  var D_HEX_STRING_MODE = {\n    className: 'string',\n    begin: 'x\"[\\\\da-fA-F\\\\s\\\\n\\\\r]*\"[cwd]?',\n    relevance: 10\n  };\n\n  /**\n   * D delimited string literal\n   *\n   * @type {Object}\n   */\n  var D_TOKEN_STRING_MODE = {\n    className: 'string',\n    begin: 'q\"\\\\{',\n    end: '\\\\}\"'\n  };\n\n  /**\n   * Hashbang support\n   *\n   * @type {Object}\n   */\n  var D_HASHBANG_MODE = {\n    className: 'shebang',\n    begin: '^#!',\n    end: '$',\n    relevance: 5\n  };\n\n  /**\n   * D special token sequence\n   *\n   * @type {Object}\n   */\n  var D_SPECIAL_TOKEN_SEQUENCE_MODE = {\n    className: 'preprocessor',\n    begin: '#(line)',\n    end: '$',\n    relevance: 5\n  };\n\n  /**\n   * D attributes\n   *\n   * @type {Object}\n   */\n  var D_ATTRIBUTE_MODE = {\n    className: 'keyword',\n    begin: '@[a-zA-Z_][a-zA-Z_\\\\d]*'\n  };\n\n  /**\n   * D nesting comment\n   *\n   * @type {Object}\n   */\n  var D_NESTING_COMMENT_MODE = hljs.COMMENT(\n    '\\\\/\\\\+',\n    '\\\\+\\\\/',\n    {\n      contains: ['self'],\n      relevance: 10\n    }\n  );\n\n  return {\n    lexemes: hljs.UNDERSCORE_IDENT_RE,\n    keywords: D_KEYWORDS,\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n        hljs.C_BLOCK_COMMENT_MODE,\n        D_NESTING_COMMENT_MODE,\n        D_HEX_STRING_MODE,\n        D_STRING_MODE,\n        D_WYSIWYG_DELIMITED_STRING_MODE,\n        D_ALTERNATE_WYSIWYG_STRING_MODE,\n        D_TOKEN_STRING_MODE,\n        D_FLOAT_MODE,\n        D_INTEGER_MODE,\n        D_CHARACTER_MODE,\n        D_HASHBANG_MODE,\n        D_SPECIAL_TOKEN_SEQUENCE_MODE,\n        D_ATTRIBUTE_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('markdown', function(hljs) {\n  return {\n    aliases: ['md', 'mkdown', 'mkd'],\n    contains: [\n      // highlight headers\n      {\n        className: 'header',\n        variants: [\n          { begin: '^#{1,6}', end: '$' },\n          { begin: '^.+?\\\\n[=-]{2,}$' }\n        ]\n      },\n      // inline html\n      {\n        begin: '<', end: '>',\n        subLanguage: 'xml',\n        relevance: 0\n      },\n      // lists (indicators only)\n      {\n        className: 'bullet',\n        begin: '^([*+-]|(\\\\d+\\\\.))\\\\s+'\n      },\n      // strong segments\n      {\n        className: 'strong',\n        begin: '[*_]{2}.+?[*_]{2}'\n      },\n      // emphasis segments\n      {\n        className: 'emphasis',\n        variants: [\n          { begin: '\\\\*.+?\\\\*' },\n          { begin: '_.+?_'\n          , relevance: 0\n          }\n        ]\n      },\n      // blockquotes\n      {\n        className: 'blockquote',\n        begin: '^>\\\\s+', end: '$'\n      },\n      // code snippets\n      {\n        className: 'code',\n        variants: [\n          { begin: '`.+?`' },\n          { begin: '^( {4}|\\t)', end: '$'\n          , relevance: 0\n          }\n        ]\n      },\n      // horizontal rules\n      {\n        className: 'horizontal_rule',\n        begin: '^[-\\\\*]{3,}', end: '$'\n      },\n      // using links - title and link\n      {\n        begin: '\\\\[.+?\\\\][\\\\(\\\\[].*?[\\\\)\\\\]]',\n        returnBegin: true,\n        contains: [\n          {\n            className: 'link_label',\n            begin: '\\\\[', end: '\\\\]',\n            excludeBegin: true,\n            returnEnd: true,\n            relevance: 0\n          },\n          {\n            className: 'link_url',\n            begin: '\\\\]\\\\(', end: '\\\\)',\n            excludeBegin: true, excludeEnd: true\n          },\n          {\n            className: 'link_reference',\n            begin: '\\\\]\\\\[', end: '\\\\]',\n            excludeBegin: true, excludeEnd: true\n          }\n        ],\n        relevance: 10\n      },\n      {\n        begin: '^\\\\[\\.+\\\\]:',\n        returnBegin: true,\n        contains: [\n          {\n            className: 'link_reference',\n            begin: '\\\\[', end: '\\\\]:',\n            excludeBegin: true, excludeEnd: true,\n            starts: {\n              className: 'link_url',\n              end: '$'\n            }\n          }\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('dart', function (hljs) {\n  var SUBST = {\n    className: 'subst',\n    begin: '\\\\$\\\\{', end: '}',\n    keywords: 'true false null this is new super'\n  };\n\n  var STRING = {\n    className: 'string',\n    variants: [\n      {\n        begin: 'r\\'\\'\\'', end: '\\'\\'\\''\n      },\n      {\n        begin: 'r\"\"\"', end: '\"\"\"'\n      },\n      {\n        begin: 'r\\'', end: '\\'',\n        illegal: '\\\\n'\n      },\n      {\n        begin: 'r\"', end: '\"',\n        illegal: '\\\\n'\n      },\n      {\n        begin: '\\'\\'\\'', end: '\\'\\'\\'',\n        contains: [hljs.BACKSLASH_ESCAPE, SUBST]\n      },\n      {\n        begin: '\"\"\"', end: '\"\"\"',\n        contains: [hljs.BACKSLASH_ESCAPE, SUBST]\n      },\n      {\n        begin: '\\'', end: '\\'',\n        illegal: '\\\\n',\n        contains: [hljs.BACKSLASH_ESCAPE, SUBST]\n      },\n      {\n        begin: '\"', end: '\"',\n        illegal: '\\\\n',\n        contains: [hljs.BACKSLASH_ESCAPE, SUBST]\n      }\n    ]\n  };\n  SUBST.contains = [\n    hljs.C_NUMBER_MODE, STRING\n  ];\n\n  var KEYWORDS = {\n    keyword: 'assert break case catch class const continue default do else enum extends false final finally for if ' +\n      'in is new null rethrow return super switch this throw true try var void while with',\n    literal: 'abstract as dynamic export external factory get implements import library operator part set static typedef',\n    built_in:\n      // dart:core\n      'print Comparable DateTime Duration Function Iterable Iterator List Map Match Null Object Pattern RegExp Set ' +\n      'Stopwatch String StringBuffer StringSink Symbol Type Uri bool double int num ' +\n      // dart:html\n      'document window querySelector querySelectorAll Element ElementList'\n  };\n\n  return {\n    keywords: KEYWORDS,\n    contains: [\n      STRING,\n      hljs.COMMENT(\n        '/\\\\*\\\\*',\n        '\\\\*/',\n        {\n          subLanguage: 'markdown'\n        }\n      ),\n      hljs.COMMENT(\n        '///',\n        '$',\n        {\n          subLanguage: 'markdown'\n        }\n      ),\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: '{', excludeEnd: true,\n        contains: [\n          {\n            beginKeywords: 'extends implements'\n          },\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'annotation', begin: '@[A-Za-z]+'\n      },\n      {\n        begin: '=>' // No markup, just a relevance booster\n      }\n    ]\n  }\n});\n\nhljs.registerLanguage('delphi', function(hljs) {\n  var KEYWORDS =\n    'exports register file shl array record property for mod while set ally label uses raise not ' +\n    'stored class safecall var interface or private static exit index inherited to else stdcall ' +\n    'override shr asm far resourcestring finalization packed virtual out and protected library do ' +\n    'xorwrite goto near function end div overload object unit begin string on inline repeat until ' +\n    'destructor write message program with read initialization except default nil if case cdecl in ' +\n    'downto threadvar of try pascal const external constructor type public then implementation ' +\n    'finally published procedure';\n  var COMMENT_MODES = [\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.COMMENT(\n      /\\{/,\n      /\\}/,\n      {\n        relevance: 0\n      }\n    ),\n    hljs.COMMENT(\n      /\\(\\*/,\n      /\\*\\)/,\n      {\n        relevance: 10\n      }\n    )\n  ];\n  var STRING = {\n    className: 'string',\n    begin: /'/, end: /'/,\n    contains: [{begin: /''/}]\n  };\n  var CHAR_STRING = {\n    className: 'string', begin: /(#\\d+)+/\n  };\n  var CLASS = {\n    begin: hljs.IDENT_RE + '\\\\s*=\\\\s*class\\\\s*\\\\(', returnBegin: true,\n    contains: [\n      hljs.TITLE_MODE\n    ]\n  };\n  var FUNCTION = {\n    className: 'function',\n    beginKeywords: 'function constructor destructor procedure', end: /[:;]/,\n    keywords: 'function constructor|10 destructor|10 procedure|10',\n    contains: [\n      hljs.TITLE_MODE,\n      {\n        className: 'params',\n        begin: /\\(/, end: /\\)/,\n        keywords: KEYWORDS,\n        contains: [STRING, CHAR_STRING]\n      }\n    ].concat(COMMENT_MODES)\n  };\n  return {\n    case_insensitive: true,\n    keywords: KEYWORDS,\n    illegal: /\"|\\$[G-Zg-z]|\\/\\*|<\\/|\\|/,\n    contains: [\n      STRING, CHAR_STRING,\n      hljs.NUMBER_MODE,\n      CLASS,\n      FUNCTION\n    ].concat(COMMENT_MODES)\n  };\n});\n\nhljs.registerLanguage('diff', function(hljs) {\n  return {\n    aliases: ['patch'],\n    contains: [\n      {\n        className: 'chunk',\n        relevance: 10,\n        variants: [\n          {begin: /^@@ +\\-\\d+,\\d+ +\\+\\d+,\\d+ +@@$/},\n          {begin: /^\\*\\*\\* +\\d+,\\d+ +\\*\\*\\*\\*$/},\n          {begin: /^\\-\\-\\- +\\d+,\\d+ +\\-\\-\\-\\-$/}\n        ]\n      },\n      {\n        className: 'header',\n        variants: [\n          {begin: /Index: /, end: /$/},\n          {begin: /=====/, end: /=====$/},\n          {begin: /^\\-\\-\\-/, end: /$/},\n          {begin: /^\\*{3} /, end: /$/},\n          {begin: /^\\+\\+\\+/, end: /$/},\n          {begin: /\\*{5}/, end: /\\*{5}$/}\n        ]\n      },\n      {\n        className: 'addition',\n        begin: '^\\\\+', end: '$'\n      },\n      {\n        className: 'deletion',\n        begin: '^\\\\-', end: '$'\n      },\n      {\n        className: 'change',\n        begin: '^\\\\!', end: '$'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('django', function(hljs) {\n  var FILTER = {\n    className: 'filter',\n    begin: /\\|[A-Za-z]+:?/,\n    keywords:\n      'truncatewords removetags linebreaksbr yesno get_digit timesince random striptags ' +\n      'filesizeformat escape linebreaks length_is ljust rjust cut urlize fix_ampersands ' +\n      'title floatformat capfirst pprint divisibleby add make_list unordered_list urlencode ' +\n      'timeuntil urlizetrunc wordcount stringformat linenumbers slice date dictsort ' +\n      'dictsortreversed default_if_none pluralize lower join center default ' +\n      'truncatewords_html upper length phone2numeric wordwrap time addslashes slugify first ' +\n      'escapejs force_escape iriencode last safe safeseq truncatechars localize unlocalize ' +\n      'localtime utc timezone',\n    contains: [\n      {className: 'argument', begin: /\"/, end: /\"/},\n      {className: 'argument', begin: /'/, end: /'/}\n    ]\n  };\n\n  return {\n    aliases: ['jinja'],\n    case_insensitive: true,\n    subLanguage: 'xml',\n    contains: [\n      hljs.COMMENT(/\\{%\\s*comment\\s*%}/, /\\{%\\s*endcomment\\s*%}/),\n      hljs.COMMENT(/\\{#/, /#}/),\n      {\n        className: 'template_tag',\n        begin: /\\{%/, end: /%}/,\n        keywords:\n          'comment endcomment load templatetag ifchanged endifchanged if endif firstof for ' +\n          'endfor in ifnotequal endifnotequal widthratio extends include spaceless ' +\n          'endspaceless regroup by as ifequal endifequal ssi now with cycle url filter ' +\n          'endfilter debug block endblock else autoescape endautoescape csrf_token empty elif ' +\n          'endwith static trans blocktrans endblocktrans get_static_prefix get_media_prefix ' +\n          'plural get_current_language language get_available_languages ' +\n          'get_current_language_bidi get_language_info get_language_info_list localize ' +\n          'endlocalize localtime endlocaltime timezone endtimezone get_current_timezone ' +\n          'verbatim',\n        contains: [FILTER]\n      },\n      {\n        className: 'variable',\n        begin: /\\{\\{/, end: /}}/,\n        contains: [FILTER]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('dns', function(hljs) {\n  return {\n    aliases: ['bind', 'zone'],\n    keywords: {\n      keyword:\n        'IN A AAAA AFSDB APL CAA CDNSKEY CDS CERT CNAME DHCID DLV DNAME DNSKEY DS HIP IPSECKEY KEY KX ' +\n        'LOC MX NAPTR NS NSEC NSEC3 NSEC3PARAM PTR RRSIG RP SIG SOA SRV SSHFP TA TKEY TLSA TSIG TXT'\n    },\n    contains: [\n      hljs.COMMENT(';', '$'),\n      {\n        className: 'operator',\n        beginKeywords: '$TTL $GENERATE $INCLUDE $ORIGIN'\n      },\n      // IPv6\n      {\n        className: 'number',\n        begin: '((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:)))'\n      },\n      // IPv4\n      {\n        className: 'number',\n        begin: '((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('dockerfile', function(hljs) {\n  return {\n    aliases: ['docker'],\n    case_insensitive: true,\n    keywords: {\n      built_ins: 'from maintainer cmd expose add copy entrypoint volume user workdir onbuild run env label'\n    },\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      {\n        keywords : {\n          built_in: 'run cmd entrypoint volume add copy workdir onbuild label'\n        },\n        begin: /^ *(onbuild +)?(run|cmd|entrypoint|volume|add|copy|workdir|label) +/,\n        starts: {\n          end: /[^\\\\]\\n/,\n          subLanguage: 'bash'\n        }\n      },\n      {\n        keywords: {\n          built_in: 'from maintainer expose env user onbuild'\n        },\n        begin: /^ *(onbuild +)?(from|maintainer|expose|env|user|onbuild) +/, end: /[^\\\\]\\n/,\n        contains: [\n          hljs.APOS_STRING_MODE,\n          hljs.QUOTE_STRING_MODE,\n          hljs.NUMBER_MODE,\n          hljs.HASH_COMMENT_MODE\n        ]\n      }\n    ]\n  }\n});\n\nhljs.registerLanguage('dos', function(hljs) {\n  var COMMENT = hljs.COMMENT(\n    /@?rem\\b/, /$/,\n    {\n      relevance: 10\n    }\n  );\n  var LABEL = {\n    className: 'label',\n    begin: '^\\\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\\\s+label)',\n    relevance: 0\n  };\n  return {\n    aliases: ['bat', 'cmd'],\n    case_insensitive: true,\n    illegal: /\\/\\*/,\n    keywords: {\n      flow: 'if else goto for in do call exit not exist errorlevel defined',\n      operator: 'equ neq lss leq gtr geq',\n      keyword: 'shift cd dir echo setlocal endlocal set pause copy',\n      stream: 'prn nul lpt3 lpt2 lpt1 con com4 com3 com2 com1 aux',\n      winutils: 'ping net ipconfig taskkill xcopy ren del',\n      built_in: 'append assoc at attrib break cacls cd chcp chdir chkdsk chkntfs cls cmd color ' +\n        'comp compact convert date dir diskcomp diskcopy doskey erase fs ' +\n        'find findstr format ftype graftabl help keyb label md mkdir mode more move path ' +\n        'pause print popd pushd promt rd recover rem rename replace restore rmdir shift' +\n        'sort start subst time title tree type ver verify vol'\n    },\n    contains: [\n      {\n        className: 'envvar', begin: /%%[^ ]|%[^ ]+?%|![^ ]+?!/\n      },\n      {\n        className: 'function',\n        begin: LABEL.begin, end: 'goto:eof',\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {begin: '([_a-zA-Z]\\\\w*\\\\.)*([_a-zA-Z]\\\\w*:)?[_a-zA-Z]\\\\w*'}),\n          COMMENT\n        ]\n      },\n      {\n        className: 'number', begin: '\\\\b\\\\d+',\n        relevance: 0\n      },\n      COMMENT\n    ]\n  };\n});\n\nhljs.registerLanguage('dust', function(hljs) {\n  var EXPRESSION_KEYWORDS = 'if eq ne lt lte gt gte select default math sep';\n  return {\n    aliases: ['dst'],\n    case_insensitive: true,\n    subLanguage: 'xml',\n    contains: [\n      {\n        className: 'expression',\n        begin: '{', end: '}',\n        relevance: 0,\n        contains: [\n          {\n            className: 'begin-block', begin: '\\#[a-zA-Z\\-\\ \\.]+',\n            keywords: EXPRESSION_KEYWORDS\n          },\n          {\n            className: 'string',\n            begin: '\"', end: '\"'\n          },\n          {\n            className: 'end-block', begin: '\\\\\\/[a-zA-Z\\-\\ \\.]+',\n            keywords: EXPRESSION_KEYWORDS\n          },\n          {\n            className: 'variable', begin: '[a-zA-Z\\-\\.]+',\n            keywords: EXPRESSION_KEYWORDS,\n            relevance: 0\n          }\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('elixir', function(hljs) {\n  var ELIXIR_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*(\\\\!|\\\\?)?';\n  var ELIXIR_METHOD_RE = '[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?';\n  var ELIXIR_KEYWORDS =\n    'and false then defined module in return redo retry end for true self when ' +\n    'next until do begin unless nil break not case cond alias while ensure or ' +\n    'include use alias fn quote';\n  var SUBST = {\n    className: 'subst',\n    begin: '#\\\\{', end: '}',\n    lexemes: ELIXIR_IDENT_RE,\n    keywords: ELIXIR_KEYWORDS\n  };\n  var STRING = {\n    className: 'string',\n    contains: [hljs.BACKSLASH_ESCAPE, SUBST],\n    variants: [\n      {\n        begin: /'/, end: /'/\n      },\n      {\n        begin: /\"/, end: /\"/\n      }\n    ]\n  };\n  var FUNCTION = {\n    className: 'function',\n    beginKeywords: 'def defp defmacro', end: /\\B\\b/, // the mode is ended by the title\n    contains: [\n      hljs.inherit(hljs.TITLE_MODE, {\n        begin: ELIXIR_IDENT_RE,\n        endsParent: true\n      })\n    ]\n  };\n  var CLASS = hljs.inherit(FUNCTION, {\n    className: 'class',\n    beginKeywords: 'defmodule defrecord', end: /\\bdo\\b|$|;/\n  });\n  var ELIXIR_DEFAULT_CONTAINS = [\n    STRING,\n    hljs.HASH_COMMENT_MODE,\n    CLASS,\n    FUNCTION,\n    {\n      className: 'constant',\n      begin: '(\\\\b[A-Z_]\\\\w*(.)?)+',\n      relevance: 0\n    },\n    {\n      className: 'symbol',\n      begin: ':',\n      contains: [STRING, {begin: ELIXIR_METHOD_RE}],\n      relevance: 0\n    },\n    {\n      className: 'symbol',\n      begin: ELIXIR_IDENT_RE + ':',\n      relevance: 0\n    },\n    {\n      className: 'number',\n      begin: '(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b',\n      relevance: 0\n    },\n    {\n      className: 'variable',\n      begin: '(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?)(\\\\w+))'\n    },\n    {\n      begin: '->'\n    },\n    { // regexp container\n      begin: '(' + hljs.RE_STARTERS_RE + ')\\\\s*',\n      contains: [\n        hljs.HASH_COMMENT_MODE,\n        {\n          className: 'regexp',\n          illegal: '\\\\n',\n          contains: [hljs.BACKSLASH_ESCAPE, SUBST],\n          variants: [\n            {\n              begin: '/', end: '/[a-z]*'\n            },\n            {\n              begin: '%r\\\\[', end: '\\\\][a-z]*'\n            }\n          ]\n        }\n      ],\n      relevance: 0\n    }\n  ];\n  SUBST.contains = ELIXIR_DEFAULT_CONTAINS;\n\n  return {\n    lexemes: ELIXIR_IDENT_RE,\n    keywords: ELIXIR_KEYWORDS,\n    contains: ELIXIR_DEFAULT_CONTAINS\n  };\n});\n\nhljs.registerLanguage('elm', function(hljs) {\n  var COMMENT_MODES = [\n    hljs.COMMENT('--', '$'),\n    hljs.COMMENT(\n      '{-',\n      '-}',\n      {\n        contains: ['self']\n      }\n    )\n  ];\n\n  var CONSTRUCTOR = {\n    className: 'type',\n    begin: '\\\\b[A-Z][\\\\w\\']*', // TODO: other constructors (build-in, infix).\n    relevance: 0\n  };\n\n  var LIST = {\n    className: 'container',\n    begin: '\\\\(', end: '\\\\)',\n    illegal: '\"',\n    contains: [\n      {className: 'type', begin: '\\\\b[A-Z][\\\\w]*(\\\\((\\\\.\\\\.|,|\\\\w+)\\\\))?'}\n    ].concat(COMMENT_MODES)\n  };\n\n  var RECORD = {\n    className: 'container',\n    begin: '{', end: '}',\n    contains: LIST.contains\n  };\n\n  return {\n    keywords:\n      'let in if then else case of where module import exposing ' +\n      'type alias as infix infixl infixr port',\n    contains: [\n\n      // Top-level constructions.\n\n      {\n        className: 'module',\n        begin: '\\\\bmodule\\\\b', end: 'where',\n        keywords: 'module where',\n        contains: [LIST].concat(COMMENT_MODES),\n        illegal: '\\\\W\\\\.|;'\n      },\n      {\n        className: 'import',\n        begin: '\\\\bimport\\\\b', end: '$',\n        keywords: 'import|0 as exposing',\n        contains: [LIST].concat(COMMENT_MODES),\n        illegal: '\\\\W\\\\.|;'\n      },\n      {\n        className: 'typedef',\n        begin: '\\\\btype\\\\b', end: '$',\n        keywords: 'type alias',\n        contains: [CONSTRUCTOR, LIST, RECORD].concat(COMMENT_MODES)\n      },\n      {\n        className: 'infix',\n        beginKeywords: 'infix infixl infixr', end: '$',\n        contains: [hljs.C_NUMBER_MODE].concat(COMMENT_MODES)\n      },\n      {\n        className: 'foreign',\n        begin: '\\\\bport\\\\b', end: '$',\n        keywords: 'port',\n        contains: COMMENT_MODES\n      },\n\n      // Literals and names.\n\n      // TODO: characters.\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      CONSTRUCTOR,\n      hljs.inherit(hljs.TITLE_MODE, {begin: '^[_a-z][\\\\w\\']*'}),\n\n      {begin: '->|<-'} // No markup, relevance booster\n    ].concat(COMMENT_MODES)\n  };\n});\n\nhljs.registerLanguage('ruby', function(hljs) {\n  var RUBY_METHOD_RE = '[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?';\n  var RUBY_KEYWORDS =\n    'and false then defined module in return redo if BEGIN retry end for true self when ' +\n    'next until do begin unless END rescue nil else break undef not super class case ' +\n    'require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor';\n  var YARDOCTAG = {\n    className: 'doctag',\n    begin: '@[A-Za-z]+'\n  };\n  var IRB_OBJECT = {\n    className: 'value',\n    begin: '#<', end: '>'\n  };\n  var COMMENT_MODES = [\n    hljs.COMMENT(\n      '#',\n      '$',\n      {\n        contains: [YARDOCTAG]\n      }\n    ),\n    hljs.COMMENT(\n      '^\\\\=begin',\n      '^\\\\=end',\n      {\n        contains: [YARDOCTAG],\n        relevance: 10\n      }\n    ),\n    hljs.COMMENT('^__END__', '\\\\n$')\n  ];\n  var SUBST = {\n    className: 'subst',\n    begin: '#\\\\{', end: '}',\n    keywords: RUBY_KEYWORDS\n  };\n  var STRING = {\n    className: 'string',\n    contains: [hljs.BACKSLASH_ESCAPE, SUBST],\n    variants: [\n      {begin: /'/, end: /'/},\n      {begin: /\"/, end: /\"/},\n      {begin: /`/, end: /`/},\n      {begin: '%[qQwWx]?\\\\(', end: '\\\\)'},\n      {begin: '%[qQwWx]?\\\\[', end: '\\\\]'},\n      {begin: '%[qQwWx]?{', end: '}'},\n      {begin: '%[qQwWx]?<', end: '>'},\n      {begin: '%[qQwWx]?/', end: '/'},\n      {begin: '%[qQwWx]?%', end: '%'},\n      {begin: '%[qQwWx]?-', end: '-'},\n      {begin: '%[qQwWx]?\\\\|', end: '\\\\|'},\n      {\n        // \\B in the beginning suppresses recognition of ?-sequences where ?\n        // is the last character of a preceding identifier, as in: `func?4`\n        begin: /\\B\\?(\\\\\\d{1,3}|\\\\x[A-Fa-f0-9]{1,2}|\\\\u[A-Fa-f0-9]{4}|\\\\?\\S)\\b/\n      }\n    ]\n  };\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\(', end: '\\\\)',\n    keywords: RUBY_KEYWORDS\n  };\n\n  var RUBY_DEFAULT_CONTAINS = [\n    STRING,\n    IRB_OBJECT,\n    {\n      className: 'class',\n      beginKeywords: 'class module', end: '$|;',\n      illegal: /=/,\n      contains: [\n        hljs.inherit(hljs.TITLE_MODE, {begin: '[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?'}),\n        {\n          className: 'inheritance',\n          begin: '<\\\\s*',\n          contains: [{\n            className: 'parent',\n            begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE\n          }]\n        }\n      ].concat(COMMENT_MODES)\n    },\n    {\n      className: 'function',\n      beginKeywords: 'def', end: '$|;',\n      contains: [\n        hljs.inherit(hljs.TITLE_MODE, {begin: RUBY_METHOD_RE}),\n        PARAMS\n      ].concat(COMMENT_MODES)\n    },\n    {\n      className: 'constant',\n      begin: '(::)?(\\\\b[A-Z]\\\\w*(::)?)+',\n      relevance: 0\n    },\n    {\n      className: 'symbol',\n      begin: hljs.UNDERSCORE_IDENT_RE + '(\\\\!|\\\\?)?:',\n      relevance: 0\n    },\n    {\n      className: 'symbol',\n      begin: ':',\n      contains: [STRING, {begin: RUBY_METHOD_RE}],\n      relevance: 0\n    },\n    {\n      className: 'number',\n      begin: '(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b',\n      relevance: 0\n    },\n    {\n      className: 'variable',\n      begin: '(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?)(\\\\w+))'\n    },\n    { // regexp container\n      begin: '(' + hljs.RE_STARTERS_RE + ')\\\\s*',\n      contains: [\n        IRB_OBJECT,\n        {\n          className: 'regexp',\n          contains: [hljs.BACKSLASH_ESCAPE, SUBST],\n          illegal: /\\n/,\n          variants: [\n            {begin: '/', end: '/[a-z]*'},\n            {begin: '%r{', end: '}[a-z]*'},\n            {begin: '%r\\\\(', end: '\\\\)[a-z]*'},\n            {begin: '%r!', end: '![a-z]*'},\n            {begin: '%r\\\\[', end: '\\\\][a-z]*'}\n          ]\n        }\n      ].concat(COMMENT_MODES),\n      relevance: 0\n    }\n  ].concat(COMMENT_MODES);\n\n  SUBST.contains = RUBY_DEFAULT_CONTAINS;\n  PARAMS.contains = RUBY_DEFAULT_CONTAINS;\n\n  var SIMPLE_PROMPT = \"[>?]>\";\n  var DEFAULT_PROMPT = \"[\\\\w#]+\\\\(\\\\w+\\\\):\\\\d+:\\\\d+>\";\n  var RVM_PROMPT = \"(\\\\w+-)?\\\\d+\\\\.\\\\d+\\\\.\\\\d(p\\\\d+)?[^>]+>\";\n\n  var IRB_DEFAULT = [\n    {\n      begin: /^\\s*=>/,\n      className: 'status',\n      starts: {\n        end: '$', contains: RUBY_DEFAULT_CONTAINS\n      }\n    },\n    {\n      className: 'prompt',\n      begin: '^('+SIMPLE_PROMPT+\"|\"+DEFAULT_PROMPT+'|'+RVM_PROMPT+')',\n      starts: {\n        end: '$', contains: RUBY_DEFAULT_CONTAINS\n      }\n    }\n  ];\n\n  return {\n    aliases: ['rb', 'gemspec', 'podspec', 'thor', 'irb'],\n    keywords: RUBY_KEYWORDS,\n    illegal: /\\/\\*/,\n    contains: COMMENT_MODES.concat(IRB_DEFAULT).concat(RUBY_DEFAULT_CONTAINS)\n  };\n});\n\nhljs.registerLanguage('erb', function(hljs) {\n  return {\n    subLanguage: 'xml',\n    contains: [\n      hljs.COMMENT('<%#', '%>'),\n      {\n        begin: '<%[%=-]?', end: '[%-]?%>',\n        subLanguage: 'ruby',\n        excludeBegin: true,\n        excludeEnd: true\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('erlang-repl', function(hljs) {\n  return {\n    keywords: {\n      special_functions:\n        'spawn spawn_link self',\n      reserved:\n        'after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if ' +\n        'let not of or orelse|10 query receive rem try when xor'\n    },\n    contains: [\n      {\n        className: 'prompt', begin: '^[0-9]+> ',\n        relevance: 10\n      },\n      hljs.COMMENT('%', '$'),\n      {\n        className: 'number',\n        begin: '\\\\b(\\\\d+#[a-fA-F0-9]+|\\\\d+(\\\\.\\\\d+)?([eE][-+]?\\\\d+)?)',\n        relevance: 0\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'constant', begin: '\\\\?(::)?([A-Z]\\\\w*(::)?)+'\n      },\n      {\n        className: 'arrow', begin: '->'\n      },\n      {\n        className: 'ok', begin: 'ok'\n      },\n      {\n        className: 'exclamation_mark', begin: '!'\n      },\n      {\n        className: 'function_or_atom',\n        begin: '(\\\\b[a-z\\'][a-zA-Z0-9_\\']*:[a-z\\'][a-zA-Z0-9_\\']*)|(\\\\b[a-z\\'][a-zA-Z0-9_\\']*)',\n        relevance: 0\n      },\n      {\n        className: 'variable',\n        begin: '[A-Z][a-zA-Z0-9_\\']*',\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('erlang', function(hljs) {\n  var BASIC_ATOM_RE = '[a-z\\'][a-zA-Z0-9_\\']*';\n  var FUNCTION_NAME_RE = '(' + BASIC_ATOM_RE + ':' + BASIC_ATOM_RE + '|' + BASIC_ATOM_RE + ')';\n  var ERLANG_RESERVED = {\n    keyword:\n      'after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if ' +\n      'let not of orelse|10 query receive rem try when xor',\n    literal:\n      'false true'\n  };\n\n  var COMMENT = hljs.COMMENT('%', '$');\n  var NUMBER = {\n    className: 'number',\n    begin: '\\\\b(\\\\d+#[a-fA-F0-9]+|\\\\d+(\\\\.\\\\d+)?([eE][-+]?\\\\d+)?)',\n    relevance: 0\n  };\n  var NAMED_FUN = {\n    begin: 'fun\\\\s+' + BASIC_ATOM_RE + '/\\\\d+'\n  };\n  var FUNCTION_CALL = {\n    begin: FUNCTION_NAME_RE + '\\\\(', end: '\\\\)',\n    returnBegin: true,\n    relevance: 0,\n    contains: [\n      {\n        className: 'function_name', begin: FUNCTION_NAME_RE,\n        relevance: 0\n      },\n      {\n        begin: '\\\\(', end: '\\\\)', endsWithParent: true,\n        returnEnd: true,\n        relevance: 0\n        // \"contains\" defined later\n      }\n    ]\n  };\n  var TUPLE = {\n    className: 'tuple',\n    begin: '{', end: '}',\n    relevance: 0\n    // \"contains\" defined later\n  };\n  var VAR1 = {\n    className: 'variable',\n    begin: '\\\\b_([A-Z][A-Za-z0-9_]*)?',\n    relevance: 0\n  };\n  var VAR2 = {\n    className: 'variable',\n    begin: '[A-Z][a-zA-Z0-9_]*',\n    relevance: 0\n  };\n  var RECORD_ACCESS = {\n    begin: '#' + hljs.UNDERSCORE_IDENT_RE,\n    relevance: 0,\n    returnBegin: true,\n    contains: [\n      {\n        className: 'record_name',\n        begin: '#' + hljs.UNDERSCORE_IDENT_RE,\n        relevance: 0\n      },\n      {\n        begin: '{', end: '}',\n        relevance: 0\n        // \"contains\" defined later\n      }\n    ]\n  };\n\n  var BLOCK_STATEMENTS = {\n    beginKeywords: 'fun receive if try case', end: 'end',\n    keywords: ERLANG_RESERVED\n  };\n  BLOCK_STATEMENTS.contains = [\n    COMMENT,\n    NAMED_FUN,\n    hljs.inherit(hljs.APOS_STRING_MODE, {className: ''}),\n    BLOCK_STATEMENTS,\n    FUNCTION_CALL,\n    hljs.QUOTE_STRING_MODE,\n    NUMBER,\n    TUPLE,\n    VAR1, VAR2,\n    RECORD_ACCESS\n  ];\n\n  var BASIC_MODES = [\n    COMMENT,\n    NAMED_FUN,\n    BLOCK_STATEMENTS,\n    FUNCTION_CALL,\n    hljs.QUOTE_STRING_MODE,\n    NUMBER,\n    TUPLE,\n    VAR1, VAR2,\n    RECORD_ACCESS\n  ];\n  FUNCTION_CALL.contains[1].contains = BASIC_MODES;\n  TUPLE.contains = BASIC_MODES;\n  RECORD_ACCESS.contains[1].contains = BASIC_MODES;\n\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\(', end: '\\\\)',\n    contains: BASIC_MODES\n  };\n  return {\n    aliases: ['erl'],\n    keywords: ERLANG_RESERVED,\n    illegal: '(</|\\\\*=|\\\\+=|-=|/\\\\*|\\\\*/|\\\\(\\\\*|\\\\*\\\\))',\n    contains: [\n      {\n        className: 'function',\n        begin: '^' + BASIC_ATOM_RE + '\\\\s*\\\\(', end: '->',\n        returnBegin: true,\n        illegal: '\\\\(|#|//|/\\\\*|\\\\\\\\|:|;',\n        contains: [\n          PARAMS,\n          hljs.inherit(hljs.TITLE_MODE, {begin: BASIC_ATOM_RE})\n        ],\n        starts: {\n          end: ';|\\\\.',\n          keywords: ERLANG_RESERVED,\n          contains: BASIC_MODES\n        }\n      },\n      COMMENT,\n      {\n        className: 'pp',\n        begin: '^-', end: '\\\\.',\n        relevance: 0,\n        excludeEnd: true,\n        returnBegin: true,\n        lexemes: '-' + hljs.IDENT_RE,\n        keywords:\n          '-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn ' +\n          '-import -include -include_lib -compile -define -else -endif -file -behaviour ' +\n          '-behavior -spec',\n        contains: [PARAMS]\n      },\n      NUMBER,\n      hljs.QUOTE_STRING_MODE,\n      RECORD_ACCESS,\n      VAR1, VAR2,\n      TUPLE,\n      {begin: /\\.$/} // relevance booster\n    ]\n  };\n});\n\nhljs.registerLanguage('fix', function(hljs) {\n  return {\n    contains: [\n    {\n      begin: /[^\\u2401\\u0001]+/,\n      end: /[\\u2401\\u0001]/,\n      excludeEnd: true,\n      returnBegin: true,\n      returnEnd: false,\n      contains: [\n      {\n        begin: /([^\\u2401\\u0001=]+)/,\n        end: /=([^\\u2401\\u0001=]+)/,\n        returnEnd: true,\n        returnBegin: false,\n        className: 'attribute'\n      },\n      {\n        begin: /=/,\n        end: /([\\u2401\\u0001])/,\n        excludeEnd: true,\n        excludeBegin: true,\n        className: 'string'\n      }]\n    }],\n    case_insensitive: true\n  };\n});\n\nhljs.registerLanguage('fortran', function(hljs) {\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\(', end: '\\\\)'\n  };\n\n  var F_KEYWORDS = {\n    constant: '.False. .True.',\n    type: 'integer real character complex logical dimension allocatable|10 parameter ' +\n      'external implicit|10 none double precision assign intent optional pointer ' +\n      'target in out common equivalence data',\n    keyword: 'kind do while private call intrinsic where elsewhere ' +\n      'type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then ' +\n      'public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. ' +\n      'goto save else use module select case ' +\n      'access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit ' +\n      'continue format pause cycle exit ' +\n      'c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg ' +\n      'synchronous nopass non_overridable pass protected volatile abstract extends import ' +\n      'non_intrinsic value deferred generic final enumerator class associate bind enum ' +\n      'c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t ' +\n      'c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double ' +\n      'c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr ' +\n      'c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer ' +\n      'c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor ' +\n      'numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ' +\n      'ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive ' +\n      'pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure',\n    built_in: 'alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint ' +\n      'dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl ' +\n      'algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama ' +\n      'iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod ' +\n      'qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log ' +\n      'log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate ' +\n      'adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product ' +\n      'eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul ' +\n      'maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product ' +\n      'radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind ' +\n      'set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer ' +\n      'dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ' +\n      'ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode ' +\n      'is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_of'  +\n      'acosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 ' +\n      'atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits ' +\n      'bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr ' +\n      'num_images parity popcnt poppar shifta shiftl shiftr this_image'\n  };\n  return {\n    case_insensitive: true,\n    aliases: ['f90', 'f95'],\n    keywords: F_KEYWORDS,\n    illegal: /\\/\\*/,\n    contains: [\n      hljs.inherit(hljs.APOS_STRING_MODE, {className: 'string', relevance: 0}),\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {className: 'string', relevance: 0}),\n      {\n        className: 'function',\n        beginKeywords: 'subroutine function program',\n        illegal: '[${=\\\\n]',\n        contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS]\n      },\n      hljs.COMMENT('!', '$', {relevance: 0}),\n      {\n        className: 'number',\n        begin: '(?=\\\\b|\\\\+|\\\\-|\\\\.)(?=\\\\.\\\\d|\\\\d)(?:\\\\d+)?(?:\\\\.?\\\\d*)(?:[de][+-]?\\\\d+)?\\\\b\\\\.?',\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('fsharp', function(hljs) {\n  var TYPEPARAM = {\n    begin: '<', end: '>',\n    contains: [\n      hljs.inherit(hljs.TITLE_MODE, {begin: /'[a-zA-Z0-9_]+/})\n    ]\n  };\n\n  return {\n    aliases: ['fs'],\n    keywords:\n      'abstract and as assert base begin class default delegate do done ' +\n      'downcast downto elif else end exception extern false finally for ' +\n      'fun function global if in inherit inline interface internal lazy let ' +\n      'match member module mutable namespace new null of open or ' +\n      'override private public rec return sig static struct then to ' +\n      'true try type upcast use val void when while with yield',\n    illegal: /\\/\\*/,\n    contains: [\n      {\n        // monad builder keywords (matches before non-bang kws)\n        className: 'keyword',\n        begin: /\\b(yield|return|let|do)!/\n      },\n      {\n        className: 'string',\n        begin: '@\"', end: '\"',\n        contains: [{begin: '\"\"'}]\n      },\n      {\n        className: 'string',\n        begin: '\"\"\"', end: '\"\"\"'\n      },\n      hljs.COMMENT('\\\\(\\\\*', '\\\\*\\\\)'),\n      {\n        className: 'class',\n        beginKeywords: 'type', end: '\\\\(|=|$', excludeEnd: true,\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE,\n          TYPEPARAM\n        ]\n      },\n      {\n        className: 'annotation',\n        begin: '\\\\[<', end: '>\\\\]',\n        relevance: 10\n      },\n      {\n        className: 'attribute',\n        begin: '\\\\B(\\'[A-Za-z])\\\\b',\n        contains: [hljs.BACKSLASH_ESCAPE]\n      },\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),\n      hljs.C_NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('gams', function (hljs) {\n  var KEYWORDS =\n    'abort acronym acronyms alias all and assign binary card diag display else1 eps eq equation equations file files ' +\n    'for1 free ge gt if inf integer le loop lt maximizing minimizing model models na ne negative no not option ' +\n    'options or ord parameter parameters positive prod putpage puttl repeat sameas scalar scalars semicont semiint ' +\n    'set1 sets smax smin solve sos1 sos2 sum system table then until using variable variables while1 xor yes';\n\n  return {\n    aliases: ['gms'],\n    case_insensitive: true,\n    keywords: KEYWORDS,\n    contains: [\n      {\n        className: 'section',\n        beginKeywords: 'sets parameters variables equations',\n        end: ';',\n        contains: [\n          {\n            begin: '/',\n            end: '/',\n            contains: [hljs.NUMBER_MODE]\n          }\n        ]\n      },\n      {\n        className: 'string',\n        begin: '\\\\*{3}', end: '\\\\*{3}'\n      },\n      hljs.NUMBER_MODE,\n      {\n        className: 'number',\n        begin: '\\\\$[a-zA-Z0-9]+'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('gcode', function(hljs) {\n    var GCODE_IDENT_RE = '[A-Z_][A-Z0-9_.]*';\n    var GCODE_CLOSE_RE = '\\\\%';\n    var GCODE_KEYWORDS = {\n        literal:\n            '',\n        built_in:\n            '',\n        keyword:\n            'IF DO WHILE ENDWHILE CALL ENDIF SUB ENDSUB GOTO REPEAT ENDREPEAT ' +\n            'EQ LT GT NE GE LE OR XOR'\n    };\n    var GCODE_START = {\n        className: 'preprocessor',\n        begin: '([O])([0-9]+)'\n    };\n    var GCODE_CODE = [\n        hljs.C_LINE_COMMENT_MODE,\n        hljs.C_BLOCK_COMMENT_MODE,\n        hljs.COMMENT(/\\(/, /\\)/),\n        hljs.inherit(hljs.C_NUMBER_MODE, {begin: '([-+]?([0-9]*\\\\.?[0-9]+\\\\.?))|' + hljs.C_NUMBER_RE}),\n        hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),\n        hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),\n        {\n            className: 'keyword',\n            begin: '([G])([0-9]+\\\\.?[0-9]?)'\n        },\n        {\n            className: 'title',\n            begin: '([M])([0-9]+\\\\.?[0-9]?)'\n        },\n        {\n            className: 'title',\n            begin: '(VC|VS|#)',\n            end: '(\\\\d+)'\n        },\n        {\n            className: 'title',\n            begin: '(VZOFX|VZOFY|VZOFZ)'\n        },\n        {\n            className: 'built_in',\n            begin: '(ATAN|ABS|ACOS|ASIN|SIN|COS|EXP|FIX|FUP|ROUND|LN|TAN)(\\\\[)',\n            end: '([-+]?([0-9]*\\\\.?[0-9]+\\\\.?))(\\\\])'\n        },\n        {\n            className: 'label',\n            variants: [\n                {\n                    begin: 'N', end: '\\\\d+',\n                    illegal: '\\\\W'\n                }\n            ]\n        }\n    ];\n\n    return {\n        aliases: ['nc'],\n        // Some implementations (CNC controls) of G-code are interoperable with uppercase and lowercase letters seamlessly.\n        // However, most prefer all uppercase and uppercase is customary.\n        case_insensitive: true,\n        lexemes: GCODE_IDENT_RE,\n        keywords: GCODE_KEYWORDS,\n        contains: [\n            {\n                className: 'preprocessor',\n                begin: GCODE_CLOSE_RE\n            },\n            GCODE_START\n        ].concat(GCODE_CODE)\n    };\n});\n\nhljs.registerLanguage('gherkin', function (hljs) {\n  return {\n    aliases: ['feature'],\n    keywords: 'Feature Background Ability Business\\ Need Scenario Scenarios Scenario\\ Outline Scenario\\ Template Examples Given And Then But When',\n    contains: [\n      {\n        className: 'keyword',\n        begin: '\\\\*'\n      },\n      hljs.COMMENT('@[^@\\r\\n\\t ]+', '$'),\n      {\n        begin: '\\\\|', end: '\\\\|\\\\w*$',\n        contains: [\n          {\n            className: 'string',\n            begin: '[^|]+'\n          }\n        ]\n      },\n      {\n        className: 'variable',\n        begin: '<', end: '>'\n      },\n      hljs.HASH_COMMENT_MODE,\n      {\n        className: 'string',\n        begin: '\"\"\"', end: '\"\"\"'\n      },\n      hljs.QUOTE_STRING_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('glsl', function(hljs) {\n  return {\n    keywords: {\n      keyword:\n        'atomic_uint attribute bool break bvec2 bvec3 bvec4 case centroid coherent const continue default ' +\n        'discard dmat2 dmat2x2 dmat2x3 dmat2x4 dmat3 dmat3x2 dmat3x3 dmat3x4 dmat4 dmat4x2 dmat4x3 ' +\n        'dmat4x4 do double dvec2 dvec3 dvec4 else flat float for highp if iimage1D iimage1DArray ' +\n        'iimage2D iimage2DArray iimage2DMS iimage2DMSArray iimage2DRect iimage3D iimageBuffer iimageCube ' +\n        'iimageCubeArray image1D image1DArray image2D image2DArray image2DMS image2DMSArray image2DRect ' +\n        'image3D imageBuffer imageCube imageCubeArray in inout int invariant isampler1D isampler1DArray ' +\n        'isampler2D isampler2DArray isampler2DMS isampler2DMSArray isampler2DRect isampler3D isamplerBuffer ' +\n        'isamplerCube isamplerCubeArray ivec2 ivec3 ivec4 layout lowp mat2 mat2x2 mat2x3 mat2x4 mat3 mat3x2 ' +\n        'mat3x3 mat3x4 mat4 mat4x2 mat4x3 mat4x4 mediump noperspective out patch precision readonly restrict ' +\n        'return sample sampler1D sampler1DArray sampler1DArrayShadow sampler1DShadow sampler2D sampler2DArray ' +\n        'sampler2DArrayShadow sampler2DMS sampler2DMSArray sampler2DRect sampler2DRectShadow sampler2DShadow ' +\n        'sampler3D samplerBuffer samplerCube samplerCubeArray samplerCubeArrayShadow samplerCubeShadow smooth ' +\n        'struct subroutine switch uimage1D uimage1DArray uimage2D uimage2DArray uimage2DMS uimage2DMSArray ' +\n        'uimage2DRect uimage3D uimageBuffer uimageCube uimageCubeArray uint uniform usampler1D usampler1DArray ' +\n        'usampler2D usampler2DArray usampler2DMS usampler2DMSArray usampler2DRect usampler3D usamplerBuffer ' +\n        'usamplerCube usamplerCubeArray uvec2 uvec3 uvec4 varying vec2 vec3 vec4 void volatile while writeonly',\n      built_in:\n        'gl_BackColor gl_BackLightModelProduct gl_BackLightProduct gl_BackMaterial ' +\n        'gl_BackSecondaryColor gl_ClipDistance gl_ClipPlane gl_ClipVertex gl_Color ' +\n        'gl_DepthRange gl_EyePlaneQ gl_EyePlaneR gl_EyePlaneS gl_EyePlaneT gl_Fog gl_FogCoord ' +\n        'gl_FogFragCoord gl_FragColor gl_FragCoord gl_FragData gl_FragDepth gl_FrontColor ' +\n        'gl_FrontFacing gl_FrontLightModelProduct gl_FrontLightProduct gl_FrontMaterial ' +\n        'gl_FrontSecondaryColor gl_InstanceID gl_InvocationID gl_Layer gl_LightModel ' +\n        'gl_LightSource gl_MaxAtomicCounterBindings gl_MaxAtomicCounterBufferSize ' +\n        'gl_MaxClipDistances gl_MaxClipPlanes gl_MaxCombinedAtomicCounterBuffers ' +\n        'gl_MaxCombinedAtomicCounters gl_MaxCombinedImageUniforms gl_MaxCombinedImageUnitsAndFragmentOutputs ' +\n        'gl_MaxCombinedTextureImageUnits gl_MaxDrawBuffers gl_MaxFragmentAtomicCounterBuffers ' +\n        'gl_MaxFragmentAtomicCounters gl_MaxFragmentImageUniforms gl_MaxFragmentInputComponents ' +\n        'gl_MaxFragmentUniformComponents gl_MaxFragmentUniformVectors gl_MaxGeometryAtomicCounterBuffers ' +\n        'gl_MaxGeometryAtomicCounters gl_MaxGeometryImageUniforms gl_MaxGeometryInputComponents ' +\n        'gl_MaxGeometryOutputComponents gl_MaxGeometryOutputVertices gl_MaxGeometryTextureImageUnits ' +\n        'gl_MaxGeometryTotalOutputComponents gl_MaxGeometryUniformComponents gl_MaxGeometryVaryingComponents ' +\n        'gl_MaxImageSamples gl_MaxImageUnits gl_MaxLights gl_MaxPatchVertices gl_MaxProgramTexelOffset ' +\n        'gl_MaxTessControlAtomicCounterBuffers gl_MaxTessControlAtomicCounters gl_MaxTessControlImageUniforms ' +\n        'gl_MaxTessControlInputComponents gl_MaxTessControlOutputComponents gl_MaxTessControlTextureImageUnits ' +\n        'gl_MaxTessControlTotalOutputComponents gl_MaxTessControlUniformComponents ' +\n        'gl_MaxTessEvaluationAtomicCounterBuffers gl_MaxTessEvaluationAtomicCounters ' +\n        'gl_MaxTessEvaluationImageUniforms gl_MaxTessEvaluationInputComponents gl_MaxTessEvaluationOutputComponents ' +\n        'gl_MaxTessEvaluationTextureImageUnits gl_MaxTessEvaluationUniformComponents ' +\n        'gl_MaxTessGenLevel gl_MaxTessPatchComponents gl_MaxTextureCoords gl_MaxTextureImageUnits ' +\n        'gl_MaxTextureUnits gl_MaxVaryingComponents gl_MaxVaryingFloats gl_MaxVaryingVectors ' +\n        'gl_MaxVertexAtomicCounterBuffers gl_MaxVertexAtomicCounters gl_MaxVertexAttribs ' +\n        'gl_MaxVertexImageUniforms gl_MaxVertexOutputComponents gl_MaxVertexTextureImageUnits ' +\n        'gl_MaxVertexUniformComponents gl_MaxVertexUniformVectors gl_MaxViewports gl_MinProgramTexelOffset'+\n        'gl_ModelViewMatrix gl_ModelViewMatrixInverse gl_ModelViewMatrixInverseTranspose ' +\n        'gl_ModelViewMatrixTranspose gl_ModelViewProjectionMatrix gl_ModelViewProjectionMatrixInverse ' +\n        'gl_ModelViewProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixTranspose ' +\n        'gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 ' +\n        'gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_Normal gl_NormalMatrix ' +\n        'gl_NormalScale gl_ObjectPlaneQ gl_ObjectPlaneR gl_ObjectPlaneS gl_ObjectPlaneT gl_PatchVerticesIn ' +\n        'gl_PerVertex gl_Point gl_PointCoord gl_PointSize gl_Position gl_PrimitiveID gl_PrimitiveIDIn ' +\n        'gl_ProjectionMatrix gl_ProjectionMatrixInverse gl_ProjectionMatrixInverseTranspose ' +\n        'gl_ProjectionMatrixTranspose gl_SampleID gl_SampleMask gl_SampleMaskIn gl_SamplePosition ' +\n        'gl_SecondaryColor gl_TessCoord gl_TessLevelInner gl_TessLevelOuter gl_TexCoord gl_TextureEnvColor ' +\n        'gl_TextureMatrixInverseTranspose gl_TextureMatrixTranspose gl_Vertex gl_VertexID ' +\n        'gl_ViewportIndex gl_in gl_out EmitStreamVertex EmitVertex EndPrimitive EndStreamPrimitive ' +\n        'abs acos acosh all any asin asinh atan atanh atomicCounter atomicCounterDecrement ' +\n        'atomicCounterIncrement barrier bitCount bitfieldExtract bitfieldInsert bitfieldReverse ' +\n        'ceil clamp cos cosh cross dFdx dFdy degrees determinant distance dot equal exp exp2 faceforward ' +\n        'findLSB findMSB floatBitsToInt floatBitsToUint floor fma fract frexp ftransform fwidth greaterThan ' +\n        'greaterThanEqual imageAtomicAdd imageAtomicAnd imageAtomicCompSwap imageAtomicExchange ' +\n        'imageAtomicMax imageAtomicMin imageAtomicOr imageAtomicXor imageLoad imageStore imulExtended ' +\n        'intBitsToFloat interpolateAtCentroid interpolateAtOffset interpolateAtSample inverse inversesqrt ' +\n        'isinf isnan ldexp length lessThan lessThanEqual log log2 matrixCompMult max memoryBarrier ' +\n        'min mix mod modf noise1 noise2 noise3 noise4 normalize not notEqual outerProduct packDouble2x32 ' +\n        'packHalf2x16 packSnorm2x16 packSnorm4x8 packUnorm2x16 packUnorm4x8 pow radians reflect refract ' +\n        'round roundEven shadow1D shadow1DLod shadow1DProj shadow1DProjLod shadow2D shadow2DLod shadow2DProj ' +\n        'shadow2DProjLod sign sin sinh smoothstep sqrt step tan tanh texelFetch texelFetchOffset texture ' +\n        'texture1D texture1DLod texture1DProj texture1DProjLod texture2D texture2DLod texture2DProj ' +\n        'texture2DProjLod texture3D texture3DLod texture3DProj texture3DProjLod textureCube textureCubeLod ' +\n        'textureGather textureGatherOffset textureGatherOffsets textureGrad textureGradOffset textureLod ' +\n        'textureLodOffset textureOffset textureProj textureProjGrad textureProjGradOffset textureProjLod ' +\n        'textureProjLodOffset textureProjOffset textureQueryLod textureSize transpose trunc uaddCarry ' +\n        'uintBitsToFloat umulExtended unpackDouble2x32 unpackHalf2x16 unpackSnorm2x16 unpackSnorm4x8 ' +\n        'unpackUnorm2x16 unpackUnorm4x8 usubBorrow gl_TextureMatrix gl_TextureMatrixInverse',\n      literal: 'true false'\n    },\n    illegal: '\"',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'preprocessor',\n        begin: '#', end: '$'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('go', function(hljs) {\n  var GO_KEYWORDS = {\n    keyword:\n      'break default func interface select case map struct chan else goto package switch ' +\n      'const fallthrough if range type continue for import return var go defer',\n    constant:\n       'true false iota nil',\n    typename:\n      'bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 ' +\n      'uint16 uint32 uint64 int uint uintptr rune',\n    built_in:\n      'append cap close complex copy imag len make new panic print println real recover delete'\n  };\n  return {\n    aliases: [\"golang\"],\n    keywords: GO_KEYWORDS,\n    illegal: '</',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        begin: '\\'', end: '[^\\\\\\\\]\\''\n      },\n      {\n        className: 'string',\n        begin: '`', end: '`'\n      },\n      {\n        className: 'number',\n        begin: hljs.C_NUMBER_RE + '[dflsi]?',\n        relevance: 0\n      },\n      hljs.C_NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('golo', function(hljs) {\n    return {\n      keywords: {\n        keyword:\n          'println readln print import module function local return let var ' +\n          'while for foreach times in case when match with break continue ' +\n          'augment augmentation each find filter reduce ' +\n          'if then else otherwise try catch finally raise throw orIfNull',\n        typename:\n          'DynamicObject|10 DynamicVariable struct Observable map set vector list array',\n        literal:\n          'true false null'\n      },\n      contains: [\n        hljs.HASH_COMMENT_MODE,\n        hljs.QUOTE_STRING_MODE,\n        hljs.C_NUMBER_MODE,\n        {\n          className: 'annotation', begin: '@[A-Za-z]+'\n        }\n      ]\n    }\n});\n\nhljs.registerLanguage('gradle', function(hljs) {\n  return {\n    case_insensitive: true,\n    keywords: {\n      keyword:\n        'task project allprojects subprojects artifacts buildscript configurations ' +\n        'dependencies repositories sourceSets description delete from into include ' +\n        'exclude source classpath destinationDir includes options sourceCompatibility ' +\n        'targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant ' +\n        'def abstract break case catch continue default do else extends final finally ' +\n        'for if implements instanceof native new private protected public return static ' +\n        'switch synchronized throw throws transient try volatile while strictfp package ' +\n        'import false null super this true antlrtask checkstyle codenarc copy boolean ' +\n        'byte char class double float int interface long short void compile runTime ' +\n        'file fileTree abs any append asList asWritable call collect compareTo count ' +\n        'div dump each eachByte eachFile eachLine every find findAll flatten getAt ' +\n        'getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods ' +\n        'isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter ' +\n        'newReader newWriter next plus pop power previous print println push putAt read ' +\n        'readBytes readLines reverse reverseEach round size sort splitEachLine step subMap ' +\n        'times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader ' +\n        'withStream withWriter withWriterAppend write writeLine'\n    },\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.NUMBER_MODE,\n      hljs.REGEXP_MODE\n\n    ]\n  }\n});\n\nhljs.registerLanguage('groovy', function(hljs) {\n    return {\n        keywords: {\n            typename: 'byte short char int long boolean float double void',\n            literal : 'true false null',\n            keyword:\n            // groovy specific keywords\n            'def as in assert trait ' +\n            // common keywords with Java\n            'super this abstract static volatile transient public private protected synchronized final ' +\n            'class interface enum if else for while switch case break default continue ' +\n            'throw throws try catch finally implements extends new import package return instanceof'\n        },\n\n        contains: [\n            hljs.COMMENT(\n                '/\\\\*\\\\*',\n                '\\\\*/',\n                {\n                    relevance : 0,\n                    contains : [{\n                        className : 'doctag',\n                        begin : '@[A-Za-z]+'\n                    }]\n                }\n            ),\n            hljs.C_LINE_COMMENT_MODE,\n            hljs.C_BLOCK_COMMENT_MODE,\n            {\n                className: 'string',\n                begin: '\"\"\"', end: '\"\"\"'\n            },\n            {\n                className: 'string',\n                begin: \"'''\", end: \"'''\"\n            },\n            {\n                className: 'string',\n                begin: \"\\\\$/\", end: \"/\\\\$\",\n                relevance: 10\n            },\n            hljs.APOS_STRING_MODE,\n            {\n                className: 'regexp',\n                begin: /~?\\/[^\\/\\n]+\\//,\n                contains: [\n                    hljs.BACKSLASH_ESCAPE\n                ]\n            },\n            hljs.QUOTE_STRING_MODE,\n            {\n                className: 'shebang',\n                begin: \"^#!/usr/bin/env\", end: '$',\n                illegal: '\\n'\n            },\n            hljs.BINARY_NUMBER_MODE,\n            {\n                className: 'class',\n                beginKeywords: 'class interface trait enum', end: '{',\n                illegal: ':',\n                contains: [\n                    {beginKeywords: 'extends implements'},\n                    hljs.UNDERSCORE_TITLE_MODE,\n                ]\n            },\n            hljs.C_NUMBER_MODE,\n            {\n                className: 'annotation', begin: '@[A-Za-z]+'\n            },\n            {\n                // highlight map keys and named parameters as strings\n                className: 'string', begin: /[^\\?]{0}[A-Za-z0-9_$]+ *:/\n            },\n            {\n                // catch middle element of the ternary operator\n                // to avoid highlight it as a label, named parameter, or map key\n                begin: /\\?/, end: /\\:/\n            },\n            {\n                // highlight labeled statements\n                className: 'label', begin: '^\\\\s*[A-Za-z0-9_$]+:',\n                relevance: 0\n            },\n        ],\n        illegal: /#/\n    }\n});\n\nhljs.registerLanguage('haml', // TODO support filter tags like :javascript, support inline HTML\nfunction(hljs) {\n  return {\n    case_insensitive: true,\n    contains: [\n      {\n        className: 'doctype',\n        begin: '^!!!( (5|1\\\\.1|Strict|Frameset|Basic|Mobile|RDFa|XML\\\\b.*))?$',\n        relevance: 10\n      },\n      // FIXME these comments should be allowed to span indented lines\n      hljs.COMMENT(\n        '^\\\\s*(!=#|=#|-#|/).*$',\n        false,\n        {\n          relevance: 0\n        }\n      ),\n      {\n        begin: '^\\\\s*(-|=|!=)(?!#)',\n        starts: {\n          end: '\\\\n',\n          subLanguage: 'ruby'\n        }\n      },\n      {\n        className: 'tag',\n        begin: '^\\\\s*%',\n        contains: [\n          {\n            className: 'title',\n            begin: '\\\\w+'\n          },\n          {\n            className: 'value',\n            begin: '[#\\\\.][\\\\w-]+'\n          },\n          {\n            begin: '{\\\\s*',\n            end: '\\\\s*}',\n            excludeEnd: true,\n            contains: [\n              {\n                //className: 'attribute',\n                begin: ':\\\\w+\\\\s*=>',\n                end: ',\\\\s+',\n                returnBegin: true,\n                endsWithParent: true,\n                contains: [\n                  {\n                    className: 'symbol',\n                    begin: ':\\\\w+'\n                  },\n                  hljs.APOS_STRING_MODE,\n                  hljs.QUOTE_STRING_MODE,\n                  {\n                    begin: '\\\\w+',\n                    relevance: 0\n                  }\n                ]\n              }\n            ]\n          },\n          {\n            begin: '\\\\(\\\\s*',\n            end: '\\\\s*\\\\)',\n            excludeEnd: true,\n            contains: [\n              {\n                //className: 'attribute',\n                begin: '\\\\w+\\\\s*=',\n                end: '\\\\s+',\n                returnBegin: true,\n                endsWithParent: true,\n                contains: [\n                  {\n                    className: 'attribute',\n                    begin: '\\\\w+',\n                    relevance: 0\n                  },\n                  hljs.APOS_STRING_MODE,\n                  hljs.QUOTE_STRING_MODE,\n                  {\n                    begin: '\\\\w+',\n                    relevance: 0\n                  }\n                ]\n              }\n            ]\n          }\n        ]\n      },\n      {\n        className: 'bullet',\n        begin: '^\\\\s*[=~]\\\\s*',\n        relevance: 0\n      },\n      {\n        begin: '#{',\n        starts: {\n          end: '}',\n          subLanguage: 'ruby'\n        }\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('handlebars', function(hljs) {\n  var EXPRESSION_KEYWORDS = 'each in with if else unless bindattr action collection debugger log outlet template unbound view yield';\n  return {\n    aliases: ['hbs', 'html.hbs', 'html.handlebars'],\n    case_insensitive: true,\n    subLanguage: 'xml',\n    contains: [\n      {\n        className: 'expression',\n        begin: '{{', end: '}}',\n        contains: [\n          {\n            className: 'begin-block', begin: '\\#[a-zA-Z\\-\\ \\.]+',\n            keywords: EXPRESSION_KEYWORDS\n          },\n          {\n            className: 'string',\n            begin: '\"', end: '\"'\n          },\n          {\n            className: 'end-block', begin: '\\\\\\/[a-zA-Z\\-\\ \\.]+',\n            keywords: EXPRESSION_KEYWORDS\n          },\n          {\n            className: 'variable', begin: '[a-zA-Z\\-\\.]+',\n            keywords: EXPRESSION_KEYWORDS\n          }\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('haskell', function(hljs) {\n  var COMMENT_MODES = [\n    hljs.COMMENT('--', '$'),\n    hljs.COMMENT(\n      '{-',\n      '-}',\n      {\n        contains: ['self']\n      }\n    )\n  ];\n\n  var PRAGMA = {\n    className: 'pragma',\n    begin: '{-#', end: '#-}'\n  };\n\n  var PREPROCESSOR = {\n    className: 'preprocessor',\n    begin: '^#', end: '$'\n  };\n\n  var CONSTRUCTOR = {\n    className: 'type',\n    begin: '\\\\b[A-Z][\\\\w\\']*', // TODO: other constructors (build-in, infix).\n    relevance: 0\n  };\n\n  var LIST = {\n    className: 'container',\n    begin: '\\\\(', end: '\\\\)',\n    illegal: '\"',\n    contains: [\n      PRAGMA,\n      PREPROCESSOR,\n      {className: 'type', begin: '\\\\b[A-Z][\\\\w]*(\\\\((\\\\.\\\\.|,|\\\\w+)\\\\))?'},\n      hljs.inherit(hljs.TITLE_MODE, {begin: '[_a-z][\\\\w\\']*'})\n    ].concat(COMMENT_MODES)\n  };\n\n  var RECORD = {\n    className: 'container',\n    begin: '{', end: '}',\n    contains: LIST.contains\n  };\n\n  return {\n    aliases: ['hs'],\n    keywords:\n      'let in if then else case of where do module import hiding ' +\n      'qualified type data newtype deriving class instance as default ' +\n      'infix infixl infixr foreign export ccall stdcall cplusplus ' +\n      'jvm dotnet safe unsafe family forall mdo proc rec',\n    contains: [\n\n      // Top-level constructions.\n\n      {\n        className: 'module',\n        begin: '\\\\bmodule\\\\b', end: 'where',\n        keywords: 'module where',\n        contains: [LIST].concat(COMMENT_MODES),\n        illegal: '\\\\W\\\\.|;'\n      },\n      {\n        className: 'import',\n        begin: '\\\\bimport\\\\b', end: '$',\n        keywords: 'import|0 qualified as hiding',\n        contains: [LIST].concat(COMMENT_MODES),\n        illegal: '\\\\W\\\\.|;'\n      },\n\n      {\n        className: 'class',\n        begin: '^(\\\\s*)?(class|instance)\\\\b', end: 'where',\n        keywords: 'class family instance where',\n        contains: [CONSTRUCTOR, LIST].concat(COMMENT_MODES)\n      },\n      {\n        className: 'typedef',\n        begin: '\\\\b(data|(new)?type)\\\\b', end: '$',\n        keywords: 'data family type newtype deriving',\n        contains: [PRAGMA, CONSTRUCTOR, LIST, RECORD].concat(COMMENT_MODES)\n      },\n      {\n        className: 'default',\n        beginKeywords: 'default', end: '$',\n        contains: [CONSTRUCTOR, LIST].concat(COMMENT_MODES)\n      },\n      {\n        className: 'infix',\n        beginKeywords: 'infix infixl infixr', end: '$',\n        contains: [hljs.C_NUMBER_MODE].concat(COMMENT_MODES)\n      },\n      {\n        className: 'foreign',\n        begin: '\\\\bforeign\\\\b', end: '$',\n        keywords: 'foreign import export ccall stdcall cplusplus jvm ' +\n                  'dotnet safe unsafe',\n        contains: [CONSTRUCTOR, hljs.QUOTE_STRING_MODE].concat(COMMENT_MODES)\n      },\n      {\n        className: 'shebang',\n        begin: '#!\\\\/usr\\\\/bin\\\\/env\\ runhaskell', end: '$'\n      },\n\n      // \"Whitespaces\".\n\n      PRAGMA,\n      PREPROCESSOR,\n\n      // Literals and names.\n\n      // TODO: characters.\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      CONSTRUCTOR,\n      hljs.inherit(hljs.TITLE_MODE, {begin: '^[_a-z][\\\\w\\']*'}),\n\n      {begin: '->|<-'} // No markup, relevance booster\n    ].concat(COMMENT_MODES)\n  };\n});\n\nhljs.registerLanguage('haxe', function(hljs) {\n  var IDENT_RE = '[a-zA-Z_$][a-zA-Z0-9_$]*';\n  var IDENT_FUNC_RETURN_TYPE_RE = '([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)';\n\n  return {\n    aliases: ['hx'],\n    keywords: {\n      keyword: 'break callback case cast catch class continue default do dynamic else enum extends extern ' +\n    'for function here if implements import in inline interface never new override package private ' +\n    'public return static super switch this throw trace try typedef untyped using var while',\n      literal: 'true false null'\n    },\n    contains: [\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: '{', excludeEnd: true,\n        contains: [\n          {\n            beginKeywords: 'extends implements'\n          },\n          hljs.TITLE_MODE\n        ]\n      },\n      {\n        className: 'preprocessor',\n        begin: '#', end: '$',\n        keywords: 'if else elseif end error'\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function', end: '[{;]', excludeEnd: true,\n        illegal: '\\\\S',\n        contains: [\n          hljs.TITLE_MODE,\n          {\n            className: 'params',\n            begin: '\\\\(', end: '\\\\)',\n            contains: [\n              hljs.APOS_STRING_MODE,\n              hljs.QUOTE_STRING_MODE,\n              hljs.C_LINE_COMMENT_MODE,\n              hljs.C_BLOCK_COMMENT_MODE\n            ]\n          },\n          {\n            className: 'type',\n            begin: ':',\n            end: IDENT_FUNC_RETURN_TYPE_RE,\n            relevance: 10\n          }\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('http', function(hljs) {\n  return {\n    aliases: ['https'],\n    illegal: '\\\\S',\n    contains: [\n      {\n        className: 'status',\n        begin: '^HTTP/[0-9\\\\.]+', end: '$',\n        contains: [{className: 'number', begin: '\\\\b\\\\d{3}\\\\b'}]\n      },\n      {\n        className: 'request',\n        begin: '^[A-Z]+ (.*?) HTTP/[0-9\\\\.]+$', returnBegin: true, end: '$',\n        contains: [\n          {\n            className: 'string',\n            begin: ' ', end: ' ',\n            excludeBegin: true, excludeEnd: true\n          }\n        ]\n      },\n      {\n        className: 'attribute',\n        begin: '^\\\\w', end: ': ', excludeEnd: true,\n        illegal: '\\\\n|\\\\s|=',\n        starts: {className: 'string', end: '$'}\n      },\n      {\n        begin: '\\\\n\\\\n',\n        starts: {subLanguage: [], endsWithParent: true}\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('inform7', function(hljs) {\n  var START_BRACKET = '\\\\[';\n  var END_BRACKET = '\\\\]';\n  return {\n    aliases: ['i7'],\n    case_insensitive: true,\n    keywords: {\n      // Some keywords more or less unique to I7, for relevance.\n      keyword:\n        // kind:\n        'thing room person man woman animal container ' +\n        'supporter backdrop door ' +\n        // characteristic:\n        'scenery open closed locked inside gender ' +\n        // verb:\n        'is are say understand ' +\n        // misc keyword:\n        'kind of rule'\n    },\n    contains: [\n      {\n        className: 'string',\n        begin: '\"', end: '\"',\n        relevance: 0,\n        contains: [\n          {\n            className: 'subst',\n            begin: START_BRACKET, end: END_BRACKET\n          }\n        ]\n      },\n      {\n        className: 'title',\n        begin: /^(Volume|Book|Part|Chapter|Section|Table)\\b/,\n        end: '$'\n      },\n      {\n        // Rule definition\n        // This is here for relevance.\n        begin: /^(Check|Carry out|Report|Instead of|To|Rule|When|Before|After)\\b/,\n        end: ':',\n        contains: [\n          {\n            //Rule name\n            begin: '\\\\b\\\\(This',\n            end: '\\\\)'\n          }\n        ]\n      },\n      {\n        className: 'comment',\n        begin: START_BRACKET, end: END_BRACKET,\n        contains: ['self']\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('ini', function(hljs) {\n  var STRING = {\n    className: \"string\",\n    contains: [hljs.BACKSLASH_ESCAPE],\n    variants: [\n      {\n        begin: \"'''\", end: \"'''\",\n        relevance: 10\n      }, {\n        begin: '\"\"\"', end: '\"\"\"',\n        relevance: 10\n      }, {\n        begin: '\"', end: '\"'\n      }, {\n        begin: \"'\", end: \"'\"\n      }\n    ]\n  };\n  return {\n    aliases: ['toml'],\n    case_insensitive: true,\n    illegal: /\\S/,\n    contains: [\n      hljs.COMMENT(';', '$'),\n      hljs.HASH_COMMENT_MODE,\n      {\n        className: 'title',\n        begin: /^\\s*\\[+/, end: /\\]+/\n      },\n      {\n        className: 'setting',\n        begin: /^[a-z0-9\\[\\]_-]+\\s*=\\s*/, end: '$',\n        contains: [\n          {\n            className: 'value',\n            endsWithParent: true,\n            keywords: 'on off true false yes no',\n            contains: [\n              {\n                className: 'variable',\n                variants: [\n                  {begin: /\\$[\\w\\d\"][\\w\\d_]*/},\n                  {begin: /\\$\\{(.*?)}/}\n                ]\n              },\n              STRING,\n              {\n                className: 'number',\n                begin: /([\\+\\-]+)?[\\d]+_[\\d_]+/\n              },\n              hljs.NUMBER_MODE\n            ],\n            relevance: 0\n          }\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('irpf90', function(hljs) {\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\(', end: '\\\\)'\n  };\n\n  var F_KEYWORDS = {\n    constant: '.False. .True.',\n    type: 'integer real character complex logical dimension allocatable|10 parameter ' +\n      'external implicit|10 none double precision assign intent optional pointer ' +\n      'target in out common equivalence data',\n    keyword: 'kind do while private call intrinsic where elsewhere ' +\n      'type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then ' +\n      'public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. ' +\n      'goto save else use module select case ' +\n      'access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit ' +\n      'continue format pause cycle exit ' +\n      'c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg ' +\n      'synchronous nopass non_overridable pass protected volatile abstract extends import ' +\n      'non_intrinsic value deferred generic final enumerator class associate bind enum ' +\n      'c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t ' +\n      'c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double ' +\n      'c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr ' +\n      'c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer ' +\n      'c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor ' +\n      'numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ' +\n      'ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive ' +\n      'pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure ' +\n      // IRPF90 special keywords\n      'begin_provider &begin_provider end_provider begin_shell end_shell begin_template end_template subst assert touch ' +\n      'soft_touch provide no_dep free irp_if irp_else irp_endif irp_write irp_read',\n    built_in: 'alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint ' +\n      'dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl ' +\n      'algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama ' +\n      'iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod ' +\n      'qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log ' +\n      'log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate ' +\n      'adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product ' +\n      'eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul ' +\n      'maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product ' +\n      'radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind ' +\n      'set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer ' +\n      'dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ' +\n      'ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode ' +\n      'is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_of'  +\n      'acosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 ' +\n      'atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits ' +\n      'bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr ' +\n      'num_images parity popcnt poppar shifta shiftl shiftr this_image ' +\n      // IRPF90 special built_ins\n      'IRP_ALIGN irp_here'\n  };\n  return {\n    case_insensitive: true,\n    keywords: F_KEYWORDS,\n    illegal: /\\/\\*/,\n    contains: [\n      hljs.inherit(hljs.APOS_STRING_MODE, {className: 'string', relevance: 0}),\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {className: 'string', relevance: 0}),\n      {\n        className: 'function',\n        beginKeywords: 'subroutine function program',\n        illegal: '[${=\\\\n]',\n        contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS]\n      },\n      hljs.COMMENT('!', '$', {relevance: 0}),\n      hljs.COMMENT('begin_doc', 'end_doc', {relevance: 10}),\n      {\n        className: 'number',\n        begin: '(?=\\\\b|\\\\+|\\\\-|\\\\.)(?=\\\\.\\\\d|\\\\d)(?:\\\\d+)?(?:\\\\.?\\\\d*)(?:[de][+-]?\\\\d+)?\\\\b\\\\.?',\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('java', function(hljs) {\n  var GENERIC_IDENT_RE = hljs.UNDERSCORE_IDENT_RE + '(<' + hljs.UNDERSCORE_IDENT_RE + '>)?';\n  var KEYWORDS =\n    'false synchronized int abstract float private char boolean static null if const ' +\n    'for true while long strictfp finally protected import native final void ' +\n    'enum else break transient catch instanceof byte super volatile case assert short ' +\n    'package default double public try this switch continue throws protected public private';\n\n  // https://docs.oracle.com/javase/7/docs/technotes/guides/language/underscores-literals.html\n  var JAVA_NUMBER_RE = '\\\\b' +\n    '(' +\n      '0[bB]([01]+[01_]+[01]+|[01]+)' + // 0b...\n      '|' +\n      '0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)' + // 0x...\n      '|' +\n      '(' +\n        '([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+)(\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))?' +\n        '|' +\n        '\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+)' +\n      ')' +\n      '([eE][-+]?\\\\d+)?' + // octal, decimal, float\n    ')' +\n    '[lLfF]?';\n  var JAVA_NUMBER_MODE = {\n    className: 'number',\n    begin: JAVA_NUMBER_RE,\n    relevance: 0\n  };\n\n  return {\n    aliases: ['jsp'],\n    keywords: KEYWORDS,\n    illegal: /<\\/|#/,\n    contains: [\n      hljs.COMMENT(\n        '/\\\\*\\\\*',\n        '\\\\*/',\n        {\n          relevance : 0,\n          contains : [{\n            className : 'doctag',\n            begin : '@[A-Za-z]+'\n          }]\n        }\n      ),\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: /[{;=]/, excludeEnd: true,\n        keywords: 'class interface',\n        illegal: /[:\"\\[\\]]/,\n        contains: [\n          {beginKeywords: 'extends implements'},\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        // Expression keywords prevent 'keyword Name(...)' from being\n        // recognized as a function definition\n        beginKeywords: 'new throw return else',\n        relevance: 0\n      },\n      {\n        className: 'function',\n        begin: '(' + GENERIC_IDENT_RE + '\\\\s+)+' + hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(', returnBegin: true, end: /[{;=]/,\n        excludeEnd: true,\n        keywords: KEYWORDS,\n        contains: [\n          {\n            begin: hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(', returnBegin: true,\n            relevance: 0,\n            contains: [hljs.UNDERSCORE_TITLE_MODE]\n          },\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            keywords: KEYWORDS,\n            relevance: 0,\n            contains: [\n              hljs.APOS_STRING_MODE,\n              hljs.QUOTE_STRING_MODE,\n              hljs.C_NUMBER_MODE,\n              hljs.C_BLOCK_COMMENT_MODE\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      },\n      JAVA_NUMBER_MODE,\n      {\n        className: 'annotation', begin: '@[A-Za-z]+'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('javascript', function(hljs) {\n  return {\n    aliases: ['js'],\n    keywords: {\n      keyword:\n        'in of if for while finally var new function do return void else break catch ' +\n        'instanceof with throw case default try this switch continue typeof delete ' +\n        'let yield const export super debugger as async await',\n      literal:\n        'true false null undefined NaN Infinity',\n      built_in:\n        'eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent ' +\n        'encodeURI encodeURIComponent escape unescape Object Function Boolean Error ' +\n        'EvalError InternalError RangeError ReferenceError StopIteration SyntaxError ' +\n        'TypeError URIError Number Math Date String RegExp Array Float32Array ' +\n        'Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array ' +\n        'Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require ' +\n        'module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect ' +\n        'Promise'\n    },\n    contains: [\n      {\n        className: 'pi',\n        relevance: 10,\n        begin: /^\\s*['\"]use (strict|asm)['\"]/\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      { // template string\n        className: 'string',\n        begin: '`', end: '`',\n        contains: [\n          hljs.BACKSLASH_ESCAPE,\n          {\n            className: 'subst',\n            begin: '\\\\$\\\\{', end: '\\\\}'\n          }\n        ]\n      },\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'number',\n        variants: [\n          { begin: '\\\\b(0[bB][01]+)' },\n          { begin: '\\\\b(0[oO][0-7]+)' },\n          { begin: hljs.C_NUMBER_RE }\n        ],\n        relevance: 0\n      },\n      { // \"value\" container\n        begin: '(' + hljs.RE_STARTERS_RE + '|\\\\b(case|return|throw)\\\\b)\\\\s*',\n        keywords: 'return throw case',\n        contains: [\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE,\n          hljs.REGEXP_MODE,\n          { // E4X / JSX\n            begin: /</, end: />\\s*[);\\]]/,\n            relevance: 0,\n            subLanguage: 'xml'\n          }\n        ],\n        relevance: 0\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function', end: /\\{/, excludeEnd: true,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {begin: /[A-Za-z$_][0-9A-Za-z$_]*/}),\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            excludeBegin: true,\n            excludeEnd: true,\n            contains: [\n              hljs.C_LINE_COMMENT_MODE,\n              hljs.C_BLOCK_COMMENT_MODE\n            ]\n          }\n        ],\n        illegal: /\\[|%/\n      },\n      {\n        begin: /\\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`\n      },\n      {\n        begin: '\\\\.' + hljs.IDENT_RE, relevance: 0 // hack: prevents detection of keywords after dots\n      },\n      // ECMAScript 6 modules import\n      {\n        beginKeywords: 'import', end: '[;$]',\n        keywords: 'import from as',\n        contains: [\n          hljs.APOS_STRING_MODE,\n          hljs.QUOTE_STRING_MODE\n        ]\n      },\n      { // ES6 class\n        className: 'class',\n        beginKeywords: 'class', end: /[{;=]/, excludeEnd: true,\n        illegal: /[:\"\\[\\]]/,\n        contains: [\n          {beginKeywords: 'extends'},\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      }\n    ],\n    illegal: /#/\n  };\n});\n\nhljs.registerLanguage('json', function(hljs) {\n  var LITERALS = {literal: 'true false null'};\n  var TYPES = [\n    hljs.QUOTE_STRING_MODE,\n    hljs.C_NUMBER_MODE\n  ];\n  var VALUE_CONTAINER = {\n    className: 'value',\n    end: ',', endsWithParent: true, excludeEnd: true,\n    contains: TYPES,\n    keywords: LITERALS\n  };\n  var OBJECT = {\n    begin: '{', end: '}',\n    contains: [\n      {\n        className: 'attribute',\n        begin: '\\\\s*\"', end: '\"\\\\s*:\\\\s*', excludeBegin: true, excludeEnd: true,\n        contains: [hljs.BACKSLASH_ESCAPE],\n        illegal: '\\\\n',\n        starts: VALUE_CONTAINER\n      }\n    ],\n    illegal: '\\\\S'\n  };\n  var ARRAY = {\n    begin: '\\\\[', end: '\\\\]',\n    contains: [hljs.inherit(VALUE_CONTAINER, {className: null})], // inherit is also a workaround for a bug that makes shared modes with endsWithParent compile only the ending of one of the parents\n    illegal: '\\\\S'\n  };\n  TYPES.splice(TYPES.length, 0, OBJECT, ARRAY);\n  return {\n    contains: TYPES,\n    keywords: LITERALS,\n    illegal: '\\\\S'\n  };\n});\n\nhljs.registerLanguage('julia', function(hljs) {\n  // Since there are numerous special names in Julia, it is too much trouble\n  // to maintain them by hand. Hence these names (i.e. keywords, literals and\n  // built-ins) are automatically generated from Julia (v0.3.0) itself through\n  // following scripts for each.\n\n  var KEYWORDS = {\n    // # keyword generator\n    // println(\"\\\"in\\\",\")\n    // for kw in Base.REPLCompletions.complete_keyword(\"\")\n    //     println(\"\\\"$kw\\\",\")\n    // end\n    keyword:\n      'in abstract baremodule begin bitstype break catch ccall const continue do else elseif end export ' +\n      'finally for function global if immutable import importall let local macro module quote return try type ' +\n      'typealias using while',\n\n    // # literal generator\n    // println(\"\\\"true\\\",\\n\\\"false\\\"\")\n    // for name in Base.REPLCompletions.completions(\"\", 0)[1]\n    //     try\n    //         s = symbol(name)\n    //         v = eval(s)\n    //         if !isa(v, Function) &&\n    //            !isa(v, DataType) &&\n    //            !issubtype(typeof(v), Tuple) &&\n    //            !isa(v, UnionType) &&\n    //            !isa(v, Module) &&\n    //            !isa(v, TypeConstructor) &&\n    //            !isa(v, Colon)\n    //             println(\"\\\"$name\\\",\")\n    //         end\n    //     end\n    // end\n    literal:\n      'true false ANY ARGS CPU_CORES C_NULL DL_LOAD_PATH DevNull ENDIAN_BOM ENV I|0 Inf Inf16 Inf32 ' +\n      'InsertionSort JULIA_HOME LOAD_PATH MS_ASYNC MS_INVALIDATE MS_SYNC MergeSort NaN NaN16 NaN32 OS_NAME QuickSort ' +\n      'RTLD_DEEPBIND RTLD_FIRST RTLD_GLOBAL RTLD_LAZY RTLD_LOCAL RTLD_NODELETE RTLD_NOLOAD RTLD_NOW RoundDown ' +\n      'RoundFromZero RoundNearest RoundToZero RoundUp STDERR STDIN STDOUT VERSION WORD_SIZE catalan cglobal e|0 eu|0 ' +\n      'eulergamma golden im nothing pi γ π φ',\n\n    // # built_in generator:\n    // for name in Base.REPLCompletions.completions(\"\", 0)[1]\n    //     try\n    //         v = eval(symbol(name))\n    //         if isa(v, DataType)\n    //             println(\"\\\"$name\\\",\")\n    //         end\n    //     end\n    // end\n    built_in:\n      'ASCIIString AbstractArray AbstractRNG AbstractSparseArray Any ArgumentError Array Associative Base64Pipe ' +\n      'Bidiagonal BigFloat BigInt BitArray BitMatrix BitVector Bool BoundsError Box CFILE Cchar Cdouble Cfloat Char ' +\n      'CharString Cint Clong Clonglong ClusterManager Cmd Coff_t Colon Complex Complex128 Complex32 Complex64 ' +\n      'Condition Cptrdiff_t Cshort Csize_t Cssize_t Cuchar Cuint Culong Culonglong Cushort Cwchar_t DArray DataType ' +\n      'DenseArray Diagonal Dict DimensionMismatch DirectIndexString Display DivideError DomainError EOFError ' +\n      'EachLine Enumerate ErrorException Exception Expr Factorization FileMonitor FileOffset Filter Float16 Float32 ' +\n      'Float64 FloatRange FloatingPoint Function GetfieldNode GotoNode Hermitian IO IOBuffer IOStream IPv4 IPv6 ' +\n      'InexactError Int Int128 Int16 Int32 Int64 Int8 IntSet Integer InterruptException IntrinsicFunction KeyError ' +\n      'LabelNode LambdaStaticData LineNumberNode LoadError LocalProcess MIME MathConst MemoryError MersenneTwister ' +\n      'Method MethodError MethodTable Module NTuple NewvarNode Nothing Number ObjectIdDict OrdinalRange ' +\n      'OverflowError ParseError PollingFileWatcher ProcessExitedException ProcessGroup Ptr QuoteNode Range Range1 ' +\n      'Ranges Rational RawFD Real Regex RegexMatch RemoteRef RepString RevString RopeString RoundingMode Set ' +\n      'SharedArray Signed SparseMatrixCSC StackOverflowError Stat StatStruct StepRange String SubArray SubString ' +\n      'SymTridiagonal Symbol SymbolNode Symmetric SystemError Task TextDisplay Timer TmStruct TopNode Triangular ' +\n      'Tridiagonal Type TypeConstructor TypeError TypeName TypeVar UTF16String UTF32String UTF8String UdpSocket ' +\n      'Uint Uint128 Uint16 Uint32 Uint64 Uint8 UndefRefError UndefVarError UniformScaling UnionType UnitRange ' +\n      'Unsigned Vararg VersionNumber WString WeakKeyDict WeakRef Woodbury Zip'\n  };\n\n  // ref: http://julia.readthedocs.org/en/latest/manual/variables/#allowed-variable-names\n  var VARIABLE_NAME_RE = \"[A-Za-z_\\\\u00A1-\\\\uFFFF][A-Za-z_0-9\\\\u00A1-\\\\uFFFF]*\";\n\n  // placeholder for recursive self-reference\n  var DEFAULT = { lexemes: VARIABLE_NAME_RE, keywords: KEYWORDS };\n\n  var TYPE_ANNOTATION = {\n    className: \"type-annotation\",\n    begin: /::/\n  };\n\n  var SUBTYPE = {\n    className: \"subtype\",\n    begin: /<:/\n  };\n\n  // ref: http://julia.readthedocs.org/en/latest/manual/integers-and-floating-point-numbers/\n  var NUMBER = {\n    className: \"number\",\n    // supported numeric literals:\n    //  * binary literal (e.g. 0x10)\n    //  * octal literal (e.g. 0o76543210)\n    //  * hexadecimal literal (e.g. 0xfedcba876543210)\n    //  * hexadecimal floating point literal (e.g. 0x1p0, 0x1.2p2)\n    //  * decimal literal (e.g. 9876543210, 100_000_000)\n    //  * floating pointe literal (e.g. 1.2, 1.2f, .2, 1., 1.2e10, 1.2e-10)\n    begin: /(\\b0x[\\d_]*(\\.[\\d_]*)?|0x\\.\\d[\\d_]*)p[-+]?\\d+|\\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\\b\\d[\\d_]*(\\.[\\d_]*)?|\\.\\d[\\d_]*)([eEfF][-+]?\\d+)?/,\n    relevance: 0\n  };\n\n  var CHAR = {\n    className: \"char\",\n    begin: /'(.|\\\\[xXuU][a-zA-Z0-9]+)'/\n  };\n\n  var INTERPOLATION = {\n    className: 'subst',\n    begin: /\\$\\(/, end: /\\)/,\n    keywords: KEYWORDS\n  };\n\n  var INTERPOLATED_VARIABLE = {\n    className: 'variable',\n    begin: \"\\\\$\" + VARIABLE_NAME_RE\n  };\n\n  // TODO: neatly escape normal code in string literal\n  var STRING = {\n    className: \"string\",\n    contains: [hljs.BACKSLASH_ESCAPE, INTERPOLATION, INTERPOLATED_VARIABLE],\n    variants: [\n      { begin: /\\w*\"/, end: /\"\\w*/ },\n      { begin: /\\w*\"\"\"/, end: /\"\"\"\\w*/ }\n    ]\n  };\n\n  var COMMAND = {\n    className: \"string\",\n    contains: [hljs.BACKSLASH_ESCAPE, INTERPOLATION, INTERPOLATED_VARIABLE],\n    begin: '`', end: '`'\n  };\n\n  var MACROCALL = {\n    className: \"macrocall\",\n    begin: \"@\" + VARIABLE_NAME_RE\n  };\n\n  var COMMENT = {\n    className: \"comment\",\n    variants: [\n      { begin: \"#=\", end: \"=#\", relevance: 10 },\n      { begin: '#', end: '$' }\n    ]\n  };\n\n  DEFAULT.contains = [\n    NUMBER,\n    CHAR,\n    TYPE_ANNOTATION,\n    SUBTYPE,\n    STRING,\n    COMMAND,\n    MACROCALL,\n    COMMENT,\n    hljs.HASH_COMMENT_MODE\n  ];\n  INTERPOLATION.contains = DEFAULT.contains;\n\n  return DEFAULT;\n});\n\nhljs.registerLanguage('kotlin', function (hljs) {\n  var KEYWORDS = 'val var get set class trait object public open private protected ' +\n    'final enum if else do while for when break continue throw try catch finally ' +\n    'import package is as in return fun override default companion reified inline volatile transient native';\n\n  return {\n    keywords: {\n      typename: 'Byte Short Char Int Long Boolean Float Double Void Unit Nothing',\n      literal: 'true false null',\n      keyword: KEYWORDS\n    },\n    contains : [\n      hljs.COMMENT(\n        '/\\\\*\\\\*',\n        '\\\\*/',\n        {\n          relevance : 0,\n          contains : [{\n            className : 'doctag',\n            begin : '@[A-Za-z]+'\n          }]\n        }\n      ),\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'type',\n        begin: /</, end: />/,\n        returnBegin: true,\n        excludeEnd: false,\n        relevance: 0\n      },\n      {\n        className: 'function',\n        beginKeywords: 'fun', end: '[(]|$',\n        returnBegin: true,\n        excludeEnd: true,\n        keywords: KEYWORDS,\n        illegal: /fun\\s+(<.*>)?[^\\s\\(]+(\\s+[^\\s\\(]+)\\s*=/,\n        relevance: 5,\n        contains: [\n          {\n            begin: hljs.UNDERSCORE_IDENT_RE + '\\\\s*\\\\(', returnBegin: true,\n            relevance: 0,\n            contains: [hljs.UNDERSCORE_TITLE_MODE]\n          },\n          {\n            className: 'type',\n            begin: /</, end: />/, keywords: 'reified',\n            relevance: 0\n          },\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            keywords: KEYWORDS,\n            relevance: 0,\n            illegal: /\\([^\\(,\\s:]+,/,\n            contains: [\n              {\n                className: 'typename',\n                begin: /:\\s*/, end: /\\s*[=\\)]/, excludeBegin: true, returnEnd: true,\n                relevance: 0\n              }\n            ]\n          },\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class trait', end: /[:\\{(]|$/,\n        excludeEnd: true,\n        illegal: 'extends implements',\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE,\n          {\n            className: 'type',\n            begin: /</, end: />/, excludeBegin: true, excludeEnd: true,\n            relevance: 0\n          },\n          {\n            className: 'typename',\n            begin: /[,:]\\s*/, end: /[<\\(,]|$/, excludeBegin: true, returnEnd: true\n          }\n        ]\n      },\n      {\n        className: 'variable', beginKeywords: 'var val', end: /\\s*[=:$]/, excludeEnd: true\n      },\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'shebang',\n        begin: \"^#!/usr/bin/env\", end: '$',\n        illegal: '\\n'\n      },\n      hljs.C_NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('lasso', function(hljs) {\n  var LASSO_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_.]*';\n  var LASSO_ANGLE_RE = '<\\\\?(lasso(script)?|=)';\n  var LASSO_CLOSE_RE = '\\\\]|\\\\?>';\n  var LASSO_KEYWORDS = {\n    literal:\n      'true false none minimal full all void ' +\n      'bw nbw ew new cn ncn lt lte gt gte eq neq rx nrx ft',\n    built_in:\n      'array date decimal duration integer map pair string tag xml null ' +\n      'boolean bytes keyword list locale queue set stack staticarray ' +\n      'local var variable global data self inherited currentcapture givenblock',\n    keyword:\n      'error_code error_msg error_pop error_push error_reset cache ' +\n      'database_names database_schemanames database_tablenames define_tag ' +\n      'define_type email_batch encode_set html_comment handle handle_error ' +\n      'header if inline iterate ljax_target link link_currentaction ' +\n      'link_currentgroup link_currentrecord link_detail link_firstgroup ' +\n      'link_firstrecord link_lastgroup link_lastrecord link_nextgroup ' +\n      'link_nextrecord link_prevgroup link_prevrecord log loop ' +\n      'namespace_using output_none portal private protect records referer ' +\n      'referrer repeating resultset rows search_args search_arguments ' +\n      'select sort_args sort_arguments thread_atomic value_list while ' +\n      'abort case else if_empty if_false if_null if_true loop_abort ' +\n      'loop_continue loop_count params params_up return return_value ' +\n      'run_children soap_definetag soap_lastrequest soap_lastresponse ' +\n      'tag_name ascending average by define descending do equals ' +\n      'frozen group handle_failure import in into join let match max ' +\n      'min on order parent protected provide public require returnhome ' +\n      'skip split_thread sum take thread to trait type where with ' +\n      'yield yieldhome'\n  };\n  var HTML_COMMENT = hljs.COMMENT(\n    '<!--',\n    '-->',\n    {\n      relevance: 0\n    }\n  );\n  var LASSO_NOPROCESS = {\n    className: 'preprocessor',\n    begin: '\\\\[noprocess\\\\]',\n    starts: {\n      className: 'markup',\n      end: '\\\\[/noprocess\\\\]',\n      returnEnd: true,\n      contains: [HTML_COMMENT]\n    }\n  };\n  var LASSO_START = {\n    className: 'preprocessor',\n    begin: '\\\\[/noprocess|' + LASSO_ANGLE_RE\n  };\n  var LASSO_DATAMEMBER = {\n    className: 'variable',\n    begin: '\\'' + LASSO_IDENT_RE + '\\''\n  };\n  var LASSO_CODE = [\n    hljs.COMMENT(\n      '/\\\\*\\\\*!',\n      '\\\\*/'\n    ),\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    hljs.inherit(hljs.C_NUMBER_MODE, {begin: hljs.C_NUMBER_RE + '|(infinity|nan)\\\\b'}),\n    hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),\n    hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),\n    {\n      className: 'string',\n      begin: '`', end: '`'\n    },\n    {\n      className: 'variable',\n      variants: [\n        {\n          begin: '[#$]' + LASSO_IDENT_RE\n        },\n        {\n          begin: '#', end: '\\\\d+',\n          illegal: '\\\\W'\n        }\n      ]\n    },\n    {\n      className: 'tag',\n      begin: '::\\\\s*', end: LASSO_IDENT_RE,\n      illegal: '\\\\W'\n    },\n    {\n      className: 'attribute',\n      variants: [\n        {\n          begin: '-(?!infinity)' + hljs.UNDERSCORE_IDENT_RE,\n          relevance: 0\n        },\n        {\n          begin: '(\\\\.\\\\.\\\\.)'\n        }\n      ]\n    },\n    {\n      className: 'subst',\n      variants: [\n        {\n          begin: '->\\\\s*',\n          contains: [LASSO_DATAMEMBER]\n        },\n        {\n          begin: '->|\\\\\\\\|&&?|\\\\|\\\\||!(?!=|>)|(and|or|not)\\\\b',\n          relevance: 0\n        }\n      ]\n    },\n    {\n      className: 'built_in',\n      begin: '\\\\.\\\\.?\\\\s*',\n      relevance: 0,\n      contains: [LASSO_DATAMEMBER]\n    },\n    {\n      className: 'class',\n      beginKeywords: 'define',\n      returnEnd: true, end: '\\\\(|=>',\n      contains: [\n        hljs.inherit(hljs.TITLE_MODE, {begin: hljs.UNDERSCORE_IDENT_RE + '(=(?!>))?'})\n      ]\n    }\n  ];\n  return {\n    aliases: ['ls', 'lassoscript'],\n    case_insensitive: true,\n    lexemes: LASSO_IDENT_RE + '|&[lg]t;',\n    keywords: LASSO_KEYWORDS,\n    contains: [\n      {\n        className: 'preprocessor',\n        begin: LASSO_CLOSE_RE,\n        relevance: 0,\n        starts: {\n          className: 'markup',\n          end: '\\\\[|' + LASSO_ANGLE_RE,\n          returnEnd: true,\n          relevance: 0,\n          contains: [HTML_COMMENT]\n        }\n      },\n      LASSO_NOPROCESS,\n      LASSO_START,\n      {\n        className: 'preprocessor',\n        begin: '\\\\[no_square_brackets',\n        starts: {\n          end: '\\\\[/no_square_brackets\\\\]', // not implemented in the language\n          lexemes: LASSO_IDENT_RE + '|&[lg]t;',\n          keywords: LASSO_KEYWORDS,\n          contains: [\n            {\n              className: 'preprocessor',\n              begin: LASSO_CLOSE_RE,\n              relevance: 0,\n              starts: {\n                className: 'markup',\n                end: '\\\\[noprocess\\\\]|' + LASSO_ANGLE_RE,\n                returnEnd: true,\n                contains: [HTML_COMMENT]\n              }\n            },\n            LASSO_NOPROCESS,\n            LASSO_START\n          ].concat(LASSO_CODE)\n        }\n      },\n      {\n        className: 'preprocessor',\n        begin: '\\\\[',\n        relevance: 0\n      },\n      {\n        className: 'shebang',\n        begin: '^#!.+lasso9\\\\b',\n        relevance: 10\n      }\n    ].concat(LASSO_CODE)\n  };\n});\n\nhljs.registerLanguage('less', function(hljs) {\n  var IDENT_RE        = '[\\\\w-]+'; // yes, Less identifiers may begin with a digit\n  var INTERP_IDENT_RE = '(' + IDENT_RE + '|@{' + IDENT_RE + '})';\n\n  /* Generic Modes */\n\n  var RULES = [], VALUE = []; // forward def. for recursive modes\n\n  var STRING_MODE = function(c) { return {\n    // Less strings are not multiline (also include '~' for more consistent coloring of \"escaped\" strings)\n    className: 'string', begin: '~?' + c + '.*?' + c\n  };};\n\n  var IDENT_MODE = function(name, begin, relevance) { return {\n    className: name, begin: begin, relevance: relevance\n  };};\n\n  var FUNCT_MODE = function(name, ident, obj) {\n    return hljs.inherit({\n        className: name, begin: ident + '\\\\(', end: '\\\\(',\n        returnBegin: true, excludeEnd: true, relevance: 0\n    }, obj);\n  };\n\n  var PARENS_MODE = {\n    // used only to properly balance nested parens inside mixin call, def. arg list\n    begin: '\\\\(', end: '\\\\)', contains: VALUE, relevance: 0\n  };\n\n  // generic Less highlighter (used almost everywhere except selectors):\n  VALUE.push(\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    STRING_MODE(\"'\"),\n    STRING_MODE('\"'),\n    hljs.CSS_NUMBER_MODE, // fixme: it does not include dot for numbers like .5em :(\n    IDENT_MODE('hexcolor', '#[0-9A-Fa-f]+\\\\b'),\n    FUNCT_MODE('function', '(url|data-uri)', {\n      starts: {className: 'string', end: '[\\\\)\\\\n]', excludeEnd: true}\n    }),\n    FUNCT_MODE('function', IDENT_RE),\n    PARENS_MODE,\n    IDENT_MODE('variable', '@@?' + IDENT_RE, 10),\n    IDENT_MODE('variable', '@{'  + IDENT_RE + '}'),\n    IDENT_MODE('built_in', '~?`[^`]*?`'), // inline javascript (or whatever host language) *multiline* string\n    { // @media features (it’s here to not duplicate things in AT_RULE_MODE with extra PARENS_MODE overriding):\n      className: 'attribute', begin: IDENT_RE + '\\\\s*:', end: ':', returnBegin: true, excludeEnd: true\n    }\n  );\n\n  var VALUE_WITH_RULESETS = VALUE.concat({\n    begin: '{', end: '}', contains: RULES\n  });\n\n  var MIXIN_GUARD_MODE = {\n    beginKeywords: 'when', endsWithParent: true,\n    contains: [{beginKeywords: 'and not'}].concat(VALUE) // using this form to override VALUE’s 'function' match\n  };\n\n  /* Rule-Level Modes */\n\n  var RULE_MODE = {\n    className: 'attribute',\n    begin: INTERP_IDENT_RE, end: ':', excludeEnd: true,\n    contains: [hljs.C_LINE_COMMENT_MODE, hljs.C_BLOCK_COMMENT_MODE],\n    illegal: /\\S/,\n    starts: {end: '[;}]', returnEnd: true, contains: VALUE, illegal: '[<=$]'}\n  };\n\n  var AT_RULE_MODE = {\n    className: 'at_rule', // highlight only at-rule keyword\n    begin: '@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\\\b',\n    starts: {end: '[;{}]', returnEnd: true, contains: VALUE, relevance: 0}\n  };\n\n  // variable definitions and calls\n  var VAR_RULE_MODE = {\n    className: 'variable',\n    variants: [\n      // using more strict pattern for higher relevance to increase chances of Less detection.\n      // this is *the only* Less specific statement used in most of the sources, so...\n      // (we’ll still often loose to the css-parser unless there's '//' comment,\n      // simply because 1 variable just can't beat 99 properties :)\n      {begin: '@' + IDENT_RE + '\\\\s*:', relevance: 15},\n      {begin: '@' + IDENT_RE}\n    ],\n    starts: {end: '[;}]', returnEnd: true, contains: VALUE_WITH_RULESETS}\n  };\n\n  var SELECTOR_MODE = {\n    // first parse unambiguous selectors (i.e. those not starting with tag)\n    // then fall into the scary lookahead-discriminator variant.\n    // this mode also handles mixin definitions and calls\n    variants: [{\n      begin: '[\\\\.#:&\\\\[]', end: '[;{}]'  // mixin calls end with ';'\n      }, {\n      begin: INTERP_IDENT_RE + '[^;]*{',\n      end: '{'\n    }],\n    returnBegin: true,\n    returnEnd:   true,\n    illegal: '[<=\\'$\"]',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      MIXIN_GUARD_MODE,\n      IDENT_MODE('keyword',  'all\\\\b'),\n      IDENT_MODE('variable', '@{'  + IDENT_RE + '}'),     // otherwise it’s identified as tag\n      IDENT_MODE('tag',       INTERP_IDENT_RE + '%?', 0), // '%' for more consistent coloring of @keyframes \"tags\"\n      IDENT_MODE('id',       '#'   + INTERP_IDENT_RE),\n      IDENT_MODE('class',    '\\\\.' + INTERP_IDENT_RE, 0),\n      IDENT_MODE('keyword',  '&', 0),\n      FUNCT_MODE('pseudo',   ':not'),\n      FUNCT_MODE('keyword',  ':extend'),\n      IDENT_MODE('pseudo',   '::?' + INTERP_IDENT_RE),\n      {className: 'attr_selector', begin: '\\\\[', end: '\\\\]'},\n      {begin: '\\\\(', end: '\\\\)', contains: VALUE_WITH_RULESETS}, // argument list of parametric mixins\n      {begin: '!important'} // eat !important after mixin call or it will be colored as tag\n    ]\n  };\n\n  RULES.push(\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    AT_RULE_MODE,\n    VAR_RULE_MODE,\n    SELECTOR_MODE,\n    RULE_MODE\n  );\n\n  return {\n    case_insensitive: true,\n    illegal: '[=>\\'/<($\"]',\n    contains: RULES\n  };\n});\n\nhljs.registerLanguage('lisp', function(hljs) {\n  var LISP_IDENT_RE = '[a-zA-Z_\\\\-\\\\+\\\\*\\\\/\\\\<\\\\=\\\\>\\\\&\\\\#][a-zA-Z0-9_\\\\-\\\\+\\\\*\\\\/\\\\<\\\\=\\\\>\\\\&\\\\#!]*';\n  var MEC_RE = '\\\\|[^]*?\\\\|';\n  var LISP_SIMPLE_NUMBER_RE = '(\\\\-|\\\\+)?\\\\d+(\\\\.\\\\d+|\\\\/\\\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\\\+|\\\\-)?\\\\d+)?';\n  var SHEBANG = {\n    className: 'shebang',\n    begin: '^#!', end: '$'\n  };\n  var LITERAL = {\n    className: 'literal',\n    begin: '\\\\b(t{1}|nil)\\\\b'\n  };\n  var NUMBER = {\n    className: 'number',\n    variants: [\n      {begin: LISP_SIMPLE_NUMBER_RE, relevance: 0},\n      {begin: '#(b|B)[0-1]+(/[0-1]+)?'},\n      {begin: '#(o|O)[0-7]+(/[0-7]+)?'},\n      {begin: '#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?'},\n      {begin: '#(c|C)\\\\(' + LISP_SIMPLE_NUMBER_RE + ' +' + LISP_SIMPLE_NUMBER_RE, end: '\\\\)'}\n    ]\n  };\n  var STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null});\n  var COMMENT = hljs.COMMENT(\n    ';', '$',\n    {\n      relevance: 0\n    }\n  );\n  var VARIABLE = {\n    className: 'variable',\n    begin: '\\\\*', end: '\\\\*'\n  };\n  var KEYWORD = {\n    className: 'keyword',\n    begin: '[:&]' + LISP_IDENT_RE\n  };\n  var IDENT = {\n    begin: LISP_IDENT_RE,\n    relevance: 0\n  };\n  var MEC = {\n    begin: MEC_RE\n  };\n  var QUOTED_LIST = {\n    begin: '\\\\(', end: '\\\\)',\n    contains: ['self', LITERAL, STRING, NUMBER, IDENT]\n  };\n  var QUOTED = {\n    className: 'quoted',\n    contains: [NUMBER, STRING, VARIABLE, KEYWORD, QUOTED_LIST, IDENT],\n    variants: [\n      {\n        begin: '[\\'`]\\\\(', end: '\\\\)'\n      },\n      {\n        begin: '\\\\(quote ', end: '\\\\)',\n        keywords: 'quote'\n      },\n      {\n        begin: '\\'' + MEC_RE\n      }\n    ]\n  };\n  var QUOTED_ATOM = {\n    className: 'quoted',\n    variants: [\n      {begin: '\\'' + LISP_IDENT_RE},\n      {begin: '#\\'' + LISP_IDENT_RE + '(::' + LISP_IDENT_RE + ')*'}\n    ]\n  };\n  var LIST = {\n    className: 'list',\n    begin: '\\\\(\\\\s*', end: '\\\\)'\n  };\n  var BODY = {\n    endsWithParent: true,\n    relevance: 0\n  };\n  LIST.contains = [\n    {\n      className: 'keyword',\n      variants: [\n        {begin: LISP_IDENT_RE},\n        {begin: MEC_RE}\n      ]\n    },\n    BODY\n  ];\n  BODY.contains = [QUOTED, QUOTED_ATOM, LIST, LITERAL, NUMBER, STRING, COMMENT, VARIABLE, KEYWORD, MEC, IDENT];\n\n  return {\n    illegal: /\\S/,\n    contains: [\n      NUMBER,\n      SHEBANG,\n      LITERAL,\n      STRING,\n      COMMENT,\n      QUOTED,\n      QUOTED_ATOM,\n      LIST,\n      IDENT\n    ]\n  };\n});\n\nhljs.registerLanguage('livecodeserver', function(hljs) {\n  var VARIABLE = {\n    className: 'variable', begin: '\\\\b[gtps][A-Z]+[A-Za-z0-9_\\\\-]*\\\\b|\\\\$_[A-Z]+',\n    relevance: 0\n  };\n  var COMMENT_MODES = [\n    hljs.C_BLOCK_COMMENT_MODE,\n    hljs.HASH_COMMENT_MODE,\n    hljs.COMMENT('--', '$'),\n    hljs.COMMENT('[^:]//', '$')\n  ];\n  var TITLE1 = hljs.inherit(hljs.TITLE_MODE, {\n    variants: [\n      {begin: '\\\\b_*rig[A-Z]+[A-Za-z0-9_\\\\-]*'},\n      {begin: '\\\\b_[a-z0-9\\\\-]+'}\n    ]\n  });\n  var TITLE2 = hljs.inherit(hljs.TITLE_MODE, {begin: '\\\\b([A-Za-z0-9_\\\\-]+)\\\\b'});\n  return {\n    case_insensitive: false,\n    keywords: {\n      keyword:\n        '$_COOKIE $_FILES $_GET $_GET_BINARY $_GET_RAW $_POST $_POST_BINARY $_POST_RAW $_SESSION $_SERVER ' +\n        'codepoint codepoints segment segments codeunit codeunits sentence sentences trueWord trueWords paragraph ' +\n        'after byte bytes english the until http forever descending using line real8 with seventh ' +\n        'for stdout finally element word words fourth before black ninth sixth characters chars stderr ' +\n        'uInt1 uInt1s uInt2 uInt2s stdin string lines relative rel any fifth items from middle mid ' +\n        'at else of catch then third it file milliseconds seconds second secs sec int1 int1s int4 ' +\n        'int4s internet int2 int2s normal text item last long detailed effective uInt4 uInt4s repeat ' +\n        'end repeat URL in try into switch to words https token binfile each tenth as ticks tick ' +\n        'system real4 by dateItems without char character ascending eighth whole dateTime numeric short ' +\n        'first ftp integer abbreviated abbr abbrev private case while if',\n      constant:\n        'SIX TEN FORMFEED NINE ZERO NONE SPACE FOUR FALSE COLON CRLF PI COMMA ENDOFFILE EOF EIGHT FIVE ' +\n        'QUOTE EMPTY ONE TRUE RETURN CR LINEFEED RIGHT BACKSLASH NULL SEVEN TAB THREE TWO ' +\n        'six ten formfeed nine zero none space four false colon crlf pi comma endoffile eof eight five ' +\n        'quote empty one true return cr linefeed right backslash null seven tab three two ' +\n        'RIVERSION RISTATE FILE_READ_MODE FILE_WRITE_MODE FILE_WRITE_MODE DIR_WRITE_MODE FILE_READ_UMASK ' +\n        'FILE_WRITE_UMASK DIR_READ_UMASK DIR_WRITE_UMASK',\n      operator:\n        'div mod wrap and or bitAnd bitNot bitOr bitXor among not in a an within ' +\n        'contains ends with begins the keys of keys',\n      built_in:\n        'put abs acos aliasReference annuity arrayDecode arrayEncode asin atan atan2 average avg avgDev base64Decode ' +\n        'base64Encode baseConvert binaryDecode binaryEncode byteOffset byteToNum cachedURL cachedURLs charToNum ' +\n        'cipherNames codepointOffset codepointProperty codepointToNum codeunitOffset commandNames compound compress ' +\n        'constantNames cos date dateFormat decompress directories ' +\n        'diskSpace DNSServers exp exp1 exp2 exp10 extents files flushEvents folders format functionNames geometricMean global ' +\n        'globals hasMemory harmonicMean hostAddress hostAddressToName hostName hostNameToAddress isNumber ISOToMac itemOffset ' +\n        'keys len length libURLErrorData libUrlFormData libURLftpCommand libURLLastHTTPHeaders libURLLastRHHeaders ' +\n        'libUrlMultipartFormAddPart libUrlMultipartFormData libURLVersion lineOffset ln ln1 localNames log log2 log10 ' +\n        'longFilePath lower macToISO matchChunk matchText matrixMultiply max md5Digest median merge millisec ' +\n        'millisecs millisecond milliseconds min monthNames nativeCharToNum normalizeText num number numToByte numToChar ' +\n        'numToCodepoint numToNativeChar offset open openfiles openProcesses openProcessIDs openSockets ' +\n        'paragraphOffset paramCount param params peerAddress pendingMessages platform popStdDev populationStandardDeviation ' +\n        'populationVariance popVariance processID random randomBytes replaceText result revCreateXMLTree revCreateXMLTreeFromFile ' +\n        'revCurrentRecord revCurrentRecordIsFirst revCurrentRecordIsLast revDatabaseColumnCount revDatabaseColumnIsNull ' +\n        'revDatabaseColumnLengths revDatabaseColumnNames revDatabaseColumnNamed revDatabaseColumnNumbered ' +\n        'revDatabaseColumnTypes revDatabaseConnectResult revDatabaseCursors revDatabaseID revDatabaseTableNames ' +\n        'revDatabaseType revDataFromQuery revdb_closeCursor revdb_columnbynumber revdb_columncount revdb_columnisnull ' +\n        'revdb_columnlengths revdb_columnnames revdb_columntypes revdb_commit revdb_connect revdb_connections ' +\n        'revdb_connectionerr revdb_currentrecord revdb_cursorconnection revdb_cursorerr revdb_cursors revdb_dbtype ' +\n        'revdb_disconnect revdb_execute revdb_iseof revdb_isbof revdb_movefirst revdb_movelast revdb_movenext ' +\n        'revdb_moveprev revdb_query revdb_querylist revdb_recordcount revdb_rollback revdb_tablenames ' +\n        'revGetDatabaseDriverPath revNumberOfRecords revOpenDatabase revOpenDatabases revQueryDatabase ' +\n        'revQueryDatabaseBlob revQueryResult revQueryIsAtStart revQueryIsAtEnd revUnixFromMacPath revXMLAttribute ' +\n        'revXMLAttributes revXMLAttributeValues revXMLChildContents revXMLChildNames revXMLCreateTreeFromFileWithNamespaces ' +\n        'revXMLCreateTreeWithNamespaces revXMLDataFromXPathQuery revXMLEvaluateXPath revXMLFirstChild revXMLMatchingNode ' +\n        'revXMLNextSibling revXMLNodeContents revXMLNumberOfChildren revXMLParent revXMLPreviousSibling ' +\n        'revXMLRootNode revXMLRPC_CreateRequest revXMLRPC_Documents revXMLRPC_Error ' +\n        'revXMLRPC_GetHost revXMLRPC_GetMethod revXMLRPC_GetParam revXMLText revXMLRPC_Execute ' +\n        'revXMLRPC_GetParamCount revXMLRPC_GetParamNode revXMLRPC_GetParamType revXMLRPC_GetPath revXMLRPC_GetPort ' +\n        'revXMLRPC_GetProtocol revXMLRPC_GetRequest revXMLRPC_GetResponse revXMLRPC_GetSocket revXMLTree ' +\n        'revXMLTrees revXMLValidateDTD revZipDescribeItem revZipEnumerateItems revZipOpenArchives round sampVariance ' +\n        'sec secs seconds sentenceOffset sha1Digest shell shortFilePath sin specialFolderPath sqrt standardDeviation statRound ' +\n        'stdDev sum sysError systemVersion tan tempName textDecode textEncode tick ticks time to tokenOffset toLower toUpper ' +\n        'transpose truewordOffset trunc uniDecode uniEncode upper URLDecode URLEncode URLStatus uuid value variableNames ' +\n        'variance version waitDepth weekdayNames wordOffset xsltApplyStylesheet xsltApplyStylesheetFromFile xsltLoadStylesheet ' +\n        'xsltLoadStylesheetFromFile add breakpoint cancel clear local variable file word line folder directory URL close socket process ' +\n        'combine constant convert create new alias folder directory decrypt delete variable word line folder ' +\n        'directory URL dispatch divide do encrypt filter get include intersect kill libURLDownloadToFile ' +\n        'libURLFollowHttpRedirects libURLftpUpload libURLftpUploadFile libURLresetAll libUrlSetAuthCallback ' +\n        'libURLSetCustomHTTPHeaders libUrlSetExpect100 libURLSetFTPListCommand libURLSetFTPMode libURLSetFTPStopTime ' +\n        'libURLSetStatusCallback load multiply socket prepare process post seek rel relative read from process rename ' +\n        'replace require resetAll resolve revAddXMLNode revAppendXML revCloseCursor revCloseDatabase revCommitDatabase ' +\n        'revCopyFile revCopyFolder revCopyXMLNode revDeleteFolder revDeleteXMLNode revDeleteAllXMLTrees ' +\n        'revDeleteXMLTree revExecuteSQL revGoURL revInsertXMLNode revMoveFolder revMoveToFirstRecord revMoveToLastRecord ' +\n        'revMoveToNextRecord revMoveToPreviousRecord revMoveToRecord revMoveXMLNode revPutIntoXMLNode revRollBackDatabase ' +\n        'revSetDatabaseDriverPath revSetXMLAttribute revXMLRPC_AddParam revXMLRPC_DeleteAllDocuments revXMLAddDTD ' +\n        'revXMLRPC_Free revXMLRPC_FreeAll revXMLRPC_DeleteDocument revXMLRPC_DeleteParam revXMLRPC_SetHost ' +\n        'revXMLRPC_SetMethod revXMLRPC_SetPort revXMLRPC_SetProtocol revXMLRPC_SetSocket revZipAddItemWithData ' +\n        'revZipAddItemWithFile revZipAddUncompressedItemWithData revZipAddUncompressedItemWithFile revZipCancel ' +\n        'revZipCloseArchive revZipDeleteItem revZipExtractItemToFile revZipExtractItemToVariable revZipSetProgressCallback ' +\n        'revZipRenameItem revZipReplaceItemWithData revZipReplaceItemWithFile revZipOpenArchive send set sort split start stop ' +\n        'subtract union unload wait write'\n    },\n    contains: [\n      VARIABLE,\n      {\n        className: 'keyword',\n        begin: '\\\\bend\\\\sif\\\\b'\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function', end: '$',\n        contains: [\n          VARIABLE,\n          TITLE2,\n          hljs.APOS_STRING_MODE,\n          hljs.QUOTE_STRING_MODE,\n          hljs.BINARY_NUMBER_MODE,\n          hljs.C_NUMBER_MODE,\n          TITLE1\n        ]\n      },\n      {\n        className: 'function',\n        begin: '\\\\bend\\\\s+', end: '$',\n        keywords: 'end',\n        contains: [\n          TITLE2,\n          TITLE1\n        ]\n      },\n      {\n        className: 'command',\n        beginKeywords: 'command on', end: '$',\n        contains: [\n          VARIABLE,\n          TITLE2,\n          hljs.APOS_STRING_MODE,\n          hljs.QUOTE_STRING_MODE,\n          hljs.BINARY_NUMBER_MODE,\n          hljs.C_NUMBER_MODE,\n          TITLE1\n        ]\n      },\n      {\n        className: 'preprocessor',\n        variants: [\n          {\n            begin: '<\\\\?(rev|lc|livecode)',\n            relevance: 10\n          },\n          { begin: '<\\\\?' },\n          { begin: '\\\\?>' }\n        ]\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.BINARY_NUMBER_MODE,\n      hljs.C_NUMBER_MODE,\n      TITLE1\n    ].concat(COMMENT_MODES),\n    illegal: ';$|^\\\\[|^='\n  };\n});\n\nhljs.registerLanguage('livescript', function(hljs) {\n  var KEYWORDS = {\n    keyword:\n      // JS keywords\n      'in if for while finally new do return else break catch instanceof throw try this ' +\n      'switch continue typeof delete debugger case default function var with ' +\n      // LiveScript keywords\n      'then unless until loop of by when and or is isnt not it that otherwise from to til fallthrough super ' +\n      'case default function var void const let enum export import native ' +\n      '__hasProp __extends __slice __bind __indexOf',\n    literal:\n      // JS literals\n      'true false null undefined ' +\n      // LiveScript literals\n      'yes no on off it that void',\n    built_in:\n      'npm require console print module global window document'\n  };\n  var JS_IDENT_RE = '[A-Za-z$_](?:\\-[0-9A-Za-z$_]|[0-9A-Za-z$_])*';\n  var TITLE = hljs.inherit(hljs.TITLE_MODE, {begin: JS_IDENT_RE});\n  var SUBST = {\n    className: 'subst',\n    begin: /#\\{/, end: /}/,\n    keywords: KEYWORDS\n  };\n  var SUBST_SIMPLE = {\n    className: 'subst',\n    begin: /#[A-Za-z$_]/, end: /(?:\\-[0-9A-Za-z$_]|[0-9A-Za-z$_])*/,\n    keywords: KEYWORDS\n  };\n  var EXPRESSIONS = [\n    hljs.BINARY_NUMBER_MODE,\n    {\n      className: 'number',\n      begin: '(\\\\b0[xX][a-fA-F0-9_]+)|(\\\\b\\\\d(\\\\d|_\\\\d)*(\\\\.(\\\\d(\\\\d|_\\\\d)*)?)?(_*[eE]([-+]\\\\d(_\\\\d|\\\\d)*)?)?[_a-z]*)',\n      relevance: 0,\n      starts: {end: '(\\\\s*/)?', relevance: 0} // a number tries to eat the following slash to prevent treating it as a regexp\n    },\n    {\n      className: 'string',\n      variants: [\n        {\n          begin: /'''/, end: /'''/,\n          contains: [hljs.BACKSLASH_ESCAPE]\n        },\n        {\n          begin: /'/, end: /'/,\n          contains: [hljs.BACKSLASH_ESCAPE]\n        },\n        {\n          begin: /\"\"\"/, end: /\"\"\"/,\n          contains: [hljs.BACKSLASH_ESCAPE, SUBST, SUBST_SIMPLE]\n        },\n        {\n          begin: /\"/, end: /\"/,\n          contains: [hljs.BACKSLASH_ESCAPE, SUBST, SUBST_SIMPLE]\n        },\n        {\n          begin: /\\\\/, end: /(\\s|$)/,\n          excludeEnd: true\n        }\n      ]\n    },\n    {\n      className: 'pi',\n      variants: [\n        {\n          begin: '//', end: '//[gim]*',\n          contains: [SUBST, hljs.HASH_COMMENT_MODE]\n        },\n        {\n          // regex can't start with space to parse x / 2 / 3 as two divisions\n          // regex can't start with *, and it supports an \"illegal\" in the main mode\n          begin: /\\/(?![ *])(\\\\\\/|.)*?\\/[gim]*(?=\\W|$)/\n        }\n      ]\n    },\n    {\n      className: 'property',\n      begin: '@' + JS_IDENT_RE\n    },\n    {\n      begin: '``', end: '``',\n      excludeBegin: true, excludeEnd: true,\n      subLanguage: 'javascript'\n    }\n  ];\n  SUBST.contains = EXPRESSIONS;\n\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\(', returnBegin: true,\n    /* We need another contained nameless mode to not have every nested\n    pair of parens to be called \"params\" */\n    contains: [\n      {\n        begin: /\\(/, end: /\\)/,\n        keywords: KEYWORDS,\n        contains: ['self'].concat(EXPRESSIONS)\n      }\n    ]\n  };\n\n  return {\n    aliases: ['ls'],\n    keywords: KEYWORDS,\n    illegal: /\\/\\*/,\n    contains: EXPRESSIONS.concat([\n      hljs.COMMENT('\\\\/\\\\*', '\\\\*\\\\/'),\n      hljs.HASH_COMMENT_MODE,\n      {\n        className: 'function',\n        contains: [TITLE, PARAMS],\n        returnBegin: true,\n        variants: [\n          {\n            begin: '(' + JS_IDENT_RE + '\\\\s*(?:=|:=)\\\\s*)?(\\\\(.*\\\\))?\\\\s*\\\\B\\\\->\\\\*?', end: '\\\\->\\\\*?'\n          },\n          {\n            begin: '(' + JS_IDENT_RE + '\\\\s*(?:=|:=)\\\\s*)?!?(\\\\(.*\\\\))?\\\\s*\\\\B[-~]{1,2}>\\\\*?', end: '[-~]{1,2}>\\\\*?'\n          },\n          {\n            begin: '(' + JS_IDENT_RE + '\\\\s*(?:=|:=)\\\\s*)?(\\\\(.*\\\\))?\\\\s*\\\\B!?[-~]{1,2}>\\\\*?', end: '!?[-~]{1,2}>\\\\*?'\n          }\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class',\n        end: '$',\n        illegal: /[:=\"\\[\\]]/,\n        contains: [\n          {\n            beginKeywords: 'extends',\n            endsWithParent: true,\n            illegal: /[:=\"\\[\\]]/,\n            contains: [TITLE]\n          },\n          TITLE\n        ]\n      },\n      {\n        className: 'attribute',\n        begin: JS_IDENT_RE + ':', end: ':',\n        returnBegin: true, returnEnd: true,\n        relevance: 0\n      }\n    ])\n  };\n});\n\nhljs.registerLanguage('lua', function(hljs) {\n  var OPENING_LONG_BRACKET = '\\\\[=*\\\\[';\n  var CLOSING_LONG_BRACKET = '\\\\]=*\\\\]';\n  var LONG_BRACKETS = {\n    begin: OPENING_LONG_BRACKET, end: CLOSING_LONG_BRACKET,\n    contains: ['self']\n  };\n  var COMMENTS = [\n    hljs.COMMENT('--(?!' + OPENING_LONG_BRACKET + ')', '$'),\n    hljs.COMMENT(\n      '--' + OPENING_LONG_BRACKET,\n      CLOSING_LONG_BRACKET,\n      {\n        contains: [LONG_BRACKETS],\n        relevance: 10\n      }\n    )\n  ];\n  return {\n    lexemes: hljs.UNDERSCORE_IDENT_RE,\n    keywords: {\n      keyword:\n        'and break do else elseif end false for if in local nil not or repeat return then ' +\n        'true until while',\n      built_in:\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 coroutine debug ' +\n        'io math os package string table'\n    },\n    contains: COMMENTS.concat([\n      {\n        className: 'function',\n        beginKeywords: 'function', end: '\\\\)',\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {begin: '([_a-zA-Z]\\\\w*\\\\.)*([_a-zA-Z]\\\\w*:)?[_a-zA-Z]\\\\w*'}),\n          {\n            className: 'params',\n            begin: '\\\\(', endsWithParent: true,\n            contains: COMMENTS\n          }\n        ].concat(COMMENTS)\n      },\n      hljs.C_NUMBER_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        begin: OPENING_LONG_BRACKET, end: CLOSING_LONG_BRACKET,\n        contains: [LONG_BRACKETS],\n        relevance: 5\n      }\n    ])\n  };\n});\n\nhljs.registerLanguage('makefile', function(hljs) {\n  var VARIABLE = {\n    className: 'variable',\n    begin: /\\$\\(/, end: /\\)/,\n    contains: [hljs.BACKSLASH_ESCAPE]\n  };\n  return {\n    aliases: ['mk', 'mak'],\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      {\n        begin: /^\\w+\\s*\\W*=/, returnBegin: true,\n        relevance: 0,\n        starts: {\n          className: 'constant',\n          end: /\\s*\\W*=/, excludeEnd: true,\n          starts: {\n            end: /$/,\n            relevance: 0,\n            contains: [\n              VARIABLE\n            ]\n          }\n        }\n      },\n      {\n        className: 'title',\n        begin: /^[\\w]+:\\s*$/\n      },\n      {\n        className: 'phony',\n        begin: /^\\.PHONY:/, end: /$/,\n        keywords: '.PHONY', lexemes: /[\\.\\w]+/\n      },\n      {\n        begin: /^\\t+/, end: /$/,\n        relevance: 0,\n        contains: [\n          hljs.QUOTE_STRING_MODE,\n          VARIABLE\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('mathematica', function(hljs) {\n  return {\n    aliases: ['mma'],\n    lexemes: '(\\\\$|\\\\b)' + hljs.IDENT_RE + '\\\\b',\n    keywords: 'AbelianGroup Abort AbortKernels AbortProtect Above Abs Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Active ActiveItem ActiveStyle AcyclicGraphQ AddOnHelpPath AddTo AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AffineTransform After AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowedDimensions AllowGroupClose AllowInlineCells AllowKernelInitialization AllowReverseGroupClose AllowScriptLevelChange AlphaChannel AlternatingGroup AlternativeHypothesis Alternatives AmbientLight Analytic AnchoredSearch And AndersonDarlingTest AngerJ AngleBracket AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotation Annuity AnnuityDue Antialiasing Antisymmetric Apart ApartSquareFree Appearance AppearanceElements AppellF1 Append AppendTo Apply ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess ARProcess Array ArrayComponents ArrayDepth ArrayFlatten ArrayPad ArrayPlot ArrayQ ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads AspectRatio AspectRatioFixed Assert Assuming Assumptions AstronomicalData Asynchronous AsynchronousTaskObject AsynchronousTasks AtomQ Attributes AugmentedSymmetricPolynomial AutoAction AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords Axes AxesEdge AxesLabel AxesOrigin AxesStyle Axis ' +\n      'BabyMonsterGroupB Back Background BackgroundTasksSettings Backslash Backsubstitution Backward Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseForm Baseline BaselinePosition BaseStyle BatesDistribution BattleLemarieWavelet Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized BetweennessCentrality BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms Booleans BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryStyle Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BubbleChart BubbleChart3D BubbleScale BubbleSizes BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteCount ByteOrdering ' +\n      'C CachedValue CacheGraphics CalendarData CalendarType CallPacket CanberraDistance Cancel CancelButton CandlestickChart Cap CapForm CapitalDifferentialD CardinalBSplineBasis CarmichaelLambda Cases Cashflow Casoratian Catalan CatalanNumber Catch CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterDot CentralMoment CentralMomentGeneratingFunction CForm ChampernowneNumber ChanVeseBinarize Character CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop Circle CircleBox CircleDot CircleMinus CirclePlus CircleTimes CirculantGraph CityData Clear ClearAll ClearAttributes ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent ClusteringComponents CMYKColor Coarse Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorCombine ColorConvert ColorData ColorDataFunction ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorSpace Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CommonDefaultFormatTypes Commonest CommonestFilter CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledFunction Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComponentMeasurements ' +\n      'ComponentwiseContextMenu Compose ComposeList ComposeSeries Composition CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath Congruent Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphQ ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray Constants ConstrainedMax ConstrainedMin ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFilename ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean Control ControlActive ControlAlignment ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateDialog CreateDirectory CreateDocument CreateIntermediateDirectories CreatePalette CreatePalettePacket CreateScheduledTask CreateTemporary CreateWindow CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossingDetect CrossMatrix Csc Csch CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrentImage CurrentlySpeakingPacket CurrentValue CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecomposition ' +\n      'D DagumDistribution DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DataCompression DataDistribution DataRange DataReversed Date DateDelimiters DateDifference DateFunction DateList DateListLogPlot DateListPlot DatePattern DatePlus DateRange DateString DateTicksFormat DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayMatchQ DayName DayPlus DayRange DayRound DeBruijnGraph Debug DebugTag Decimal DeclareKnownSymbols DeclarePackage Decompose Decrement DedekindEta Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic Deinitialization Del Deletable Delete DeleteBorderComponents DeleteCases DeleteContents DeleteDirectory DeleteDuplicates DeleteFile DeleteSmallComponents DeleteWithContents DeletionWarning Delimiter DelimiterFlashTime DelimiterMatching Delimiters Denominator DensityGraphics DensityHistogram DensityPlot DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DescriptorStateSpace DesignMatrix Det DGaussianWavelet DiacriticalPositioning Diagonal DiagonalMatrix Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DifferenceDelta DifferenceOrder DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralGroup Dilation Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletCharacter DirichletConvolve DirichletDistribution DirichletL DirichletTransform DirichletWindow DisableConsolePrintPacket DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform ' +\n      'DiscreteWaveletTransform Discriminant Disjunction Disk DiskBox DiskMatrix Dispatch DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentNotebook DominantColors DOSTextFormat Dot DotDashed DotEqual Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DSolve Dt DualLinearProgramming DualSystemsModel DumpGet DumpSave DuplicateFreeQ Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptions ' +\n      'E EccentricityCentrality EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeCost EdgeCount EdgeCoverQ EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData Eliminate EliminationOrder EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EnableConsolePrintPacket Enabled Encode End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfFile EndOfLine EndOfString EndPackage EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entropy EntropyFilter Environment Epilog Equal EqualColumns EqualRows EqualTilde EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerE EulerGamma EulerianGraphQ EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluationCell EvaluationCompletionAction EvaluationElements EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpToTrig ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalCall ExternalDataCharacterEncoding Extract ExtractArchive ExtremeValueDistribution ' +\n      'FaceForm FaceGrids FaceGridsStyle Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail FailureDistribution False FARIMAProcess FEDisableConsolePrintPacket FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket Fibonacci FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileDate FileExistsQ FileExtension FileFormat FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileType FilledCurve FilledCurveBox Filling FillingStyle FillingTransform FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindArgMax FindArgMin FindClique FindClusters FindCurvePath FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEulerianCycle FindFaces FindFile FindFit FindGeneratingFunction FindGeoLocation FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMaximum FindMaximumFlow FindMaxValue FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindPermutation FindPostmanTour FindProcessParameters FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindThreshold FindVertexCover FindVertexCut Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstPassageTimeDistribution FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FittedModel FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlatTopWindow FlipView Floor FlushPrintOutputPacket Fold FoldList Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrequencySamplingFilterKernel FresnelC FresnelS Friday FrobeniusNumber FrobeniusSolve ' +\n      'FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullOptions FullSimplify Function FunctionExpand FunctionInterpolation FunctionSpace FussellVeselyImportance ' +\n      'GaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins Gamma GammaDistribution GammaRegularized GapPenalty Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateConditions GeneratedCell GeneratedParameters GeneratingFunction Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDistance GeoGridPosition GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoPosition GeoPositionENU GeoPositionXYZ GeoProjectionData GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter Graph GraphAssortativity GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion ' +\n      'GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel GreatCircleDistance Greater GreaterEqual GreaterEqualLess GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterTilde Green Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain Gudermannian GumbelDistribution ' +\n      'HaarWavelet HadamardMatrix HalfNormalDistribution HamiltonianGraphQ HammingDistance HammingWindow HankelH1 HankelH2 HankelMatrix HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash HashTable Haversine HazardFunction Head HeadCompose Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenSurface HighlightGraph HighlightImage HighpassFilter HigmanSimsGroupHS HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HitMissTransform HITSCentrality HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HotellingTSquareDistribution HoytDistribution HTMLSave Hue HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestData ' +\n      'I Identity IdentityMatrix If IgnoreCase Im Image Image3D Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageAspectRatio ImageAssemble ImageCache ImageCacheValid ImageCapture ImageChannels ImageClip ImageColorSpace ImageCompose ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDataPacket ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDistance ImageEffect ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageForestingComponents ImageForwardTransformation ImageHistogram ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarkers ImageMeasurements ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImageQ ImageRangeCache ImageReflect ImageRegion ImageResize ImageResolution ImageRotate ImageRotated ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions Implies Import ImportAutoReplacements ImportString ImprovementImportance In IncidenceGraph IncidenceList IncidenceMatrix IncludeConstantBasis IncludeFileExtension IncludePods IncludeSingularTerm Increment Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentUnit IndependentVertexSetQ Indeterminate IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers Infinity Infix Information Inherited InheritScope Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InlineCounterAssignments InlineCounterIncrements InlineRules Inner Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionPointObject InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Install InstallService InString Integer IntegerDigits IntegerExponent IntegerLength IntegerPart IntegerPartitions IntegerQ Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction ' +\n      'InterpretTemplate InterquartileRange Interrupt InterruptSettings Intersection Interval IntervalIntersection IntervalMemberQ IntervalUnion Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHaversine InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InversePermutation InverseRadon InverseSeries InverseSurvivalFunction InverseWaveletTransform InverseWeierstrassP InverseZTransform Invisible InvisibleApplication InvisibleTimes IrreduciblePolynomialQ IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcess ' +\n      'JaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join Joined JoinedCurve JoinedCurveBox JoinForm JordanDecomposition JordanModelDecomposition ' +\n      'K KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelMixtureDistribution KernelObject Kernels Ket Khinchin KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnightTourGraph KnotData KnownUnitQ KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter ' +\n      'Label Labeled LabeledSlider LabelingFunction LabelStyle LaguerreL LambdaComponents LambertW LanczosWindow LandauDistribution Language LanguageCategory LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCM LeafCount LeapYearQ LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessFullEqual LessGreater LessLess LessSlantEqual LessTilde LetterCharacter LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox LinearFilter LinearFractionalTransform LinearModelFit LinearOffsetFunction LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBreak LinebreakAdjustments LineBreakChart LineBreakWithin LineColor LineForm LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRead LinkReadHeld LinkReadyQ Links LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot Listen ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalClusteringCoefficient LocalizeVariables LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions ' +\n      'LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestAscendingSequence LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow Loopback LoopFreeGraphQ LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LyapunovSolve LyonsGroupLy ' +\n      'MachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules MangoldtLambda ManhattanDistance Manipulate Manipulator MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixPlot MatrixPower MatrixQ MatrixRank Max MaxBend MaxDetect MaxExtraBandwidths MaxExtraConditions MaxFeatures MaxFilter Maximize MaxIterations MaxMemoryUsed MaxMixtureKernels MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxValue MaxwellDistribution McLaughlinGroupMcL Mean MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter Median MedianDeviation MedianFilter Medium MeijerG MeixnerDistribution MemberQ MemoryConstrained MemoryInUse Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuPacket MenuSortingValue MenuStyle MenuView MergeDifferences Mesh MeshFunctions MeshRange MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation Method MethodOptions MexicanHatWavelet MeyerWavelet Min MinDetect MinFilter MinimalPolynomial MinimalStateSpaceModel Minimize Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingDataMethod MittagLefflerE MixedRadix MixedRadixQuantity MixtureDistribution Mod Modal Mode Modular ModularLambda Module Modulus MoebiusMu Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction Monday Monitor MonomialList MonomialOrder MonsterGroupM MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform Most MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovingAverage MovingMedian MoyalDistribution MultiedgeStyle MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistribution ' +\n      'N NakagamiDistribution NameQ Names NamespaceBox Nand NArgMax NArgMin NBernoulliB NCache NDSolve NDSolveValue Nearest NearestFunction NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeMultinomialDistribution NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestList NestWhile NestWhileList NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextPrime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants None NonlinearModelFit NonlocalMeansFilter NonNegative NonPositive Nor NorlundB Norm Normal NormalDistribution NormalGrouping Normalize NormalizedSquaredEuclideanDistance NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde NotHumpDownHump NotHumpEqual NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms Null NullRecords NullSpace NullWords Number NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator ' +\n      'NumberSigns NumberString Numerator NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlot ' +\n      'O ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OddQ Off Offset OLEData On ONanGroupON OneIdentity Opacity Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering Orderless OrnsteinUhlenbeckProcess Orthogonalize Out Outer OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OwenT OwnValues ' +\n      'PackingMethod PaddedForm Padding PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageWidth PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParetoDistribution Part PartialCorrelationFunction PartialD ParticleData Partition PartitionsP PartitionsQ ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PerformanceGoal PeriodicInterpolation Periodogram PeriodogramArray PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PERTDistribution PetersenGraph PhaseMargins Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest Pink Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarGraphQ Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangePadding PlotRegion PlotStyle Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox PointBox PointFigureChart PointForm PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonBox PolygonBoxOptions PolygonHoleScale PolygonIntersections PolygonScale PolyhedronData PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position Positive PositiveDefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList ' +\n      'PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement PredictionRoot PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependTo PreserveImageOptions Previous PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitiveRoot PrincipalComponents PrincipalValue Print PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessEstimator ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptions ' +\n      'QBinomial QFactorial QGamma QHypergeometricPFQ QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ Quantile QuantilePlot Quantity QuantityForm QuantityMagnitude QuantityQ QuantityUnit Quartics QuartileDeviation Quartiles QuartileSkewness QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainder ' +\n      'RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Random RandomChoice RandomComplex RandomFunction RandomGraph RandomImage RandomInteger RandomPermutation RandomPrime RandomReal RandomSample RandomSeed RandomVariate RandomWalkProcess Range RangeFilter RangeSpecification RankedMax RankedMin Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios Raw RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadList ReadProtected Real RealBlockDiagonalForm RealDigits RealExponent Reals Reap Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate RegionBinarize RegionFunction RegionPlot RegionPlot3D RegularExpression Regularization Reinstall Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot Remove RemoveAlphaChannel RemoveAsynchronousTask Removed RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart Repeated RepeatedNull RepeatedString Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated Resampling Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask Residue Resolve Rest Resultant ResumePacket Return ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulerUnits Run RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilarity ' +\n      'SameQ SameTest SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveDefinitions SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTaskActiveQ ScheduledTaskData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition Sec Sech SechDistribution SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemialgebraicComponentInstances SendMail Sequence SequenceAlignment SequenceForm SequenceHold SequenceLimit Series SeriesCoefficient SeriesData SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPrecision SetProperty SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share Sharpen ShearingMatrix ShearingTransform ShenCastanMatrix Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortUpArrow Show ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiegelTheta SiegelTukeyTest Sign Signature SignedRankTest SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution Skip SliceDistribution Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDelayCompensator SmithWatermanSimilarity ' +\n      'SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SocialMediaData Socket SokalSneathDissimilarity Solve SolveAlways SolveDelayed Sort SortBy Sound SoundAndGraphics SoundNote SoundVolume Sow Space SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution Speak SpeakTextPacket SpearmanRankTest SpearmanRho Spectrogram SpectrogramArray Specularity SpellingCorrection SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackInhibit StandardDeviation StandardDeviationFilter StandardForm Standardize StandbyDistribution Star StarGraph StartAsynchronousTask StartingStepSize StartOfLine StartOfString StartScheduledTask StartupSound StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringCount StringDrop StringExpression StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPosition StringQ StringReplace StringReplaceList StringReplacePart StringReverse StringRotateLeft StringRotateRight StringSkeleton StringSplit StringTake StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleBoxOptions StyleData StyleDefinitions StyleForm StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders ' +\n      'SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subset SubsetEqual Subsets SubStar Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde SuchThat Sum SumConvergence Sunday SuperDagger SuperMinus SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceColor SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SystemDialogInput SystemException SystemHelpPath SystemInformation SystemInformationData SystemOpen SystemOptions SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemStub ' +\n      'Tab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeWhile Tally Tan Tanh TargetFunctions TargetUnits TautologyQ TelegraphProcess TemplateBox TemplateBoxOptions TemplateSlotSequence TemporalData Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCell TextClipboardType TextData TextForm TextJustification TextLine TextPacket TextParagraph TextRecognize TextRendering TextStyle Texture TextureCoordinateFunction TextureCoordinateScaling Therefore ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreeJSymbol Threshold Through Throw Thumbnail Thursday Ticks TicksStyle Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint Times TimesBy TimeSeriesForecast TimeSeriesInvertibility TimeUsed TimeValue TimeZone Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate ToDiscreteTimeModel ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform TopologicalSort ToRadicals ToRules ToString Total TotalHeight TotalVariationFilter TotalWidth TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField Translate TranslationTransform TransparentColor Transpose TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle TriangleWave TriangularDistribution Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean True TrueQ TruncatedDistribution TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow Tuples TuranGraph TuringMachine ' +\n      'Transparent ' +\n      'UnateQ Uncompress Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UndirectedEdge UndirectedGraph UndirectedGraphQ UndocumentedTestFEParserPacket UndocumentedTestGetSelectionPacket Unequal Unevaluated UniformDistribution UniformGraphDistribution UniformSumDistribution Uninstall Union UnionPlus Unique UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitTriangle UnitVector Unprotect UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpValues URL URLFetch URLFetchAsynchronous URLSave URLSaveAsynchronous UseGraphicsRange Using UsingFrontEnd ' +\n      'V2Get ValidationLength Value ValueBox ValueBoxOptions ValueForm ValueQ ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerifyConvergence VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoigtDistribution VonMisesDistribution ' +\n      'WaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeberE Wedge Wednesday WeibullDistribution WeierstrassHalfPeriods WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WilksW WilksWTest WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult Word WordBoundary WordCharacter WordData WordSearch WordSeparators WorkingPrecision Write WriteString Wronskian ' +\n      'XMLElement XMLObject Xnor Xor ' +\n      'Yellow YuleDissimilarity ' +\n      'ZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZipfDistribution ZTest ZTransform ' +\n      '$Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AssertFunction $Assumptions $AsynchronousTask $BaseDirectory $BatchInput $BatchOutput $BoxForms $ByteOrdering $Canceled $CharacterEncoding $CharacterEncodings $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $CreationDate $CurrentLink $DateStringFormat $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $Epilog $ExportFormats $Failed $FinancialDataSource $FormatType $FrontEnd $FrontEndSession $GeoLocation $HistoryLength $HomeDirectory $HTTPCookies $IgnoreEOF $ImagingDevices $ImportFormats $InitialDirectory $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $ModuleNumber $NetworkLicense $NewMessage $NewSymbol $Notebooks $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $PipeSupported $Post $Pre $PreferencesDirectory $PrePrint $PreRead $PrintForms $PrintLiteral $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $RandomState $RecursionLimit $ReleaseNumber $RootDirectory $ScheduledTask $ScriptCommandLine $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemWordLength $TemporaryDirectory $TemporaryPrefix $TextStyle $TimedOut $TimeUnit $TimeZone $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $Urgent $UserAddOnsDirectory $UserBaseDirectory $UserDocumentsDirectory $UserName $Version $VersionNumber',\n    contains: [\n      {\n        className: \"comment\",\n        begin: /\\(\\*/, end: /\\*\\)/\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'list',\n        begin: /\\{/, end: /\\}/,\n        illegal: /:/\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('matlab', function(hljs) {\n  var COMMON_CONTAINS = [\n    hljs.C_NUMBER_MODE,\n    {\n      className: 'string',\n      begin: '\\'', end: '\\'',\n      contains: [hljs.BACKSLASH_ESCAPE, {begin: '\\'\\''}]\n    }\n  ];\n  var TRANSPOSE = {\n    relevance: 0,\n    contains: [\n      {\n        className: 'operator', begin: /'['\\.]*/\n      }\n    ]\n  };\n\n  return {\n    keywords: {\n      keyword:\n        'break case catch classdef continue else elseif end enumerated events for function ' +\n        'global if methods otherwise parfor persistent properties return spmd switch try while',\n      built_in:\n        'sin sind sinh asin asind asinh cos cosd cosh acos acosd acosh tan tand tanh atan ' +\n        'atand atan2 atanh sec secd sech asec asecd asech csc cscd csch acsc acscd acsch cot ' +\n        'cotd coth acot acotd acoth hypot exp expm1 log log1p log10 log2 pow2 realpow reallog ' +\n        'realsqrt sqrt nthroot nextpow2 abs angle complex conj imag real unwrap isreal ' +\n        'cplxpair fix floor ceil round mod rem sign airy besselj bessely besselh besseli ' +\n        'besselk beta betainc betaln ellipj ellipke erf erfc erfcx erfinv expint gamma ' +\n        'gammainc gammaln psi legendre cross dot factor isprime primes gcd lcm rat rats perms ' +\n        'nchoosek factorial cart2sph cart2pol pol2cart sph2cart hsv2rgb rgb2hsv zeros ones ' +\n        'eye repmat rand randn linspace logspace freqspace meshgrid accumarray size length ' +\n        'ndims numel disp isempty isequal isequalwithequalnans cat reshape diag blkdiag tril ' +\n        'triu fliplr flipud flipdim rot90 find sub2ind ind2sub bsxfun ndgrid permute ipermute ' +\n        'shiftdim circshift squeeze isscalar isvector ans eps realmax realmin pi i inf nan ' +\n        'isnan isinf isfinite j why compan gallery hadamard hankel hilb invhilb magic pascal ' +\n        'rosser toeplitz vander wilkinson'\n    },\n    illegal: '(//|\"|#|/\\\\*|\\\\s+/\\\\w+)',\n    contains: [\n      {\n        className: 'function',\n        beginKeywords: 'function', end: '$',\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE,\n          {\n              className: 'params',\n              begin: '\\\\(', end: '\\\\)'\n          },\n          {\n              className: 'params',\n              begin: '\\\\[', end: '\\\\]'\n          }\n        ]\n      },\n      {\n        begin: /[a-zA-Z_][a-zA-Z_0-9]*'['\\.]*/,\n        returnBegin: true,\n        relevance: 0,\n        contains: [\n          {begin: /[a-zA-Z_][a-zA-Z_0-9]*/, relevance: 0},\n          TRANSPOSE.contains[0]\n        ]\n      },\n      {\n        className: 'matrix',\n        begin: '\\\\[', end: '\\\\]',\n        contains: COMMON_CONTAINS,\n        relevance: 0,\n        starts: TRANSPOSE\n      },\n      {\n        className: 'cell',\n        begin: '\\\\{', end: /}/,\n        contains: COMMON_CONTAINS,\n        relevance: 0,\n        starts: TRANSPOSE\n      },\n      {\n        // transpose operators at the end of a function call\n        begin: /\\)/,\n        relevance: 0,\n        starts: TRANSPOSE\n      },\n      hljs.COMMENT('^\\\\s*\\\\%\\\\{\\\\s*$', '^\\\\s*\\\\%\\\\}\\\\s*$'),\n      hljs.COMMENT('\\\\%', '$')\n    ].concat(COMMON_CONTAINS)\n  };\n});\n\nhljs.registerLanguage('mel', function(hljs) {\n  return {\n    keywords:\n      'int float string vector matrix if else switch case default while do for in break ' +\n      'continue global proc return about abs addAttr addAttributeEditorNodeHelp addDynamic ' +\n      'addNewShelfTab addPP addPanelCategory addPrefixToName advanceToNextDrivenKey ' +\n      'affectedNet affects aimConstraint air alias aliasAttr align alignCtx alignCurve ' +\n      'alignSurface allViewFit ambientLight angle angleBetween animCone animCurveEditor ' +\n      'animDisplay animView annotate appendStringArray applicationName applyAttrPreset ' +\n      'applyTake arcLenDimContext arcLengthDimension arclen arrayMapper art3dPaintCtx ' +\n      'artAttrCtx artAttrPaintVertexCtx artAttrSkinPaintCtx artAttrTool artBuildPaintMenu ' +\n      'artFluidAttrCtx artPuttyCtx artSelectCtx artSetPaintCtx artUserPaintCtx assignCommand ' +\n      'assignInputDevice assignViewportFactories attachCurve attachDeviceAttr attachSurface ' +\n      'attrColorSliderGrp attrCompatibility attrControlGrp attrEnumOptionMenu ' +\n      'attrEnumOptionMenuGrp attrFieldGrp attrFieldSliderGrp attrNavigationControlGrp ' +\n      'attrPresetEditWin attributeExists attributeInfo attributeMenu attributeQuery ' +\n      'autoKeyframe autoPlace bakeClip bakeFluidShading bakePartialHistory bakeResults ' +\n      'bakeSimulation basename basenameEx batchRender bessel bevel bevelPlus binMembership ' +\n      'bindSkin blend2 blendShape blendShapeEditor blendShapePanel blendTwoAttr blindDataType ' +\n      'boneLattice boundary boxDollyCtx boxZoomCtx bufferCurve buildBookmarkMenu ' +\n      'buildKeyframeMenu button buttonManip CBG cacheFile cacheFileCombine cacheFileMerge ' +\n      'cacheFileTrack camera cameraView canCreateManip canvas capitalizeString catch ' +\n      'catchQuiet ceil changeSubdivComponentDisplayLevel changeSubdivRegion channelBox ' +\n      'character characterMap characterOutlineEditor characterize chdir checkBox checkBoxGrp ' +\n      'checkDefaultRenderGlobals choice circle circularFillet clamp clear clearCache clip ' +\n      'clipEditor clipEditorCurrentTimeCtx clipSchedule clipSchedulerOutliner clipTrimBefore ' +\n      'closeCurve closeSurface cluster cmdFileOutput cmdScrollFieldExecuter ' +\n      'cmdScrollFieldReporter cmdShell coarsenSubdivSelectionList collision color ' +\n      'colorAtPoint colorEditor colorIndex colorIndexSliderGrp colorSliderButtonGrp ' +\n      'colorSliderGrp columnLayout commandEcho commandLine commandPort compactHairSystem ' +\n      'componentEditor compositingInterop computePolysetVolume condition cone confirmDialog ' +\n      'connectAttr connectControl connectDynamic connectJoint connectionInfo constrain ' +\n      'constrainValue constructionHistory container containsMultibyte contextInfo control ' +\n      'convertFromOldLayers convertIffToPsd convertLightmap convertSolidTx convertTessellation ' +\n      'convertUnit copyArray copyFlexor copyKey copySkinWeights cos cpButton cpCache ' +\n      'cpClothSet cpCollision cpConstraint cpConvClothToMesh cpForces cpGetSolverAttr cpPanel ' +\n      'cpProperty cpRigidCollisionFilter cpSeam cpSetEdit cpSetSolverAttr cpSolver ' +\n      'cpSolverTypes cpTool cpUpdateClothUVs createDisplayLayer createDrawCtx createEditor ' +\n      'createLayeredPsdFile createMotionField createNewShelf createNode createRenderLayer ' +\n      'createSubdivRegion cross crossProduct ctxAbort ctxCompletion ctxEditMode ctxTraverse ' +\n      'currentCtx currentTime currentTimeCtx currentUnit curve curveAddPtCtx ' +\n      'curveCVCtx curveEPCtx curveEditorCtx curveIntersect curveMoveEPCtx curveOnSurface ' +\n      'curveSketchCtx cutKey cycleCheck cylinder dagPose date defaultLightListCheckBox ' +\n      'defaultNavigation defineDataServer defineVirtualDevice deformer deg_to_rad delete ' +\n      'deleteAttr deleteShadingGroupsAndMaterials deleteShelfTab deleteUI deleteUnusedBrushes ' +\n      'delrandstr detachCurve detachDeviceAttr detachSurface deviceEditor devicePanel dgInfo ' +\n      'dgdirty dgeval dgtimer dimWhen directKeyCtx directionalLight dirmap dirname disable ' +\n      'disconnectAttr disconnectJoint diskCache displacementToPoly displayAffected ' +\n      'displayColor displayCull displayLevelOfDetail displayPref displayRGBColor ' +\n      'displaySmoothness displayStats displayString displaySurface distanceDimContext ' +\n      'distanceDimension doBlur dolly dollyCtx dopeSheetEditor dot dotProduct ' +\n      'doubleProfileBirailSurface drag dragAttrContext draggerContext dropoffLocator ' +\n      'duplicate duplicateCurve duplicateSurface dynCache dynControl dynExport dynExpression ' +\n      'dynGlobals dynPaintEditor dynParticleCtx dynPref dynRelEdPanel dynRelEditor ' +\n      'dynamicLoad editAttrLimits editDisplayLayerGlobals editDisplayLayerMembers ' +\n      'editRenderLayerAdjustment editRenderLayerGlobals editRenderLayerMembers editor ' +\n      'editorTemplate effector emit emitter enableDevice encodeString endString endsWith env ' +\n      'equivalent equivalentTol erf error eval evalDeferred evalEcho event ' +\n      'exactWorldBoundingBox exclusiveLightCheckBox exec executeForEachObject exists exp ' +\n      'expression expressionEditorListen extendCurve extendSurface extrude fcheck fclose feof ' +\n      'fflush fgetline fgetword file fileBrowserDialog fileDialog fileExtension fileInfo ' +\n      'filetest filletCurve filter filterCurve filterExpand filterStudioImport ' +\n      'findAllIntersections findAnimCurves findKeyframe findMenuItem findRelatedSkinCluster ' +\n      'finder firstParentOf fitBspline flexor floatEq floatField floatFieldGrp floatScrollBar ' +\n      'floatSlider floatSlider2 floatSliderButtonGrp floatSliderGrp floor flow fluidCacheInfo ' +\n      'fluidEmitter fluidVoxelInfo flushUndo fmod fontDialog fopen formLayout format fprint ' +\n      'frameLayout fread freeFormFillet frewind fromNativePath fwrite gamma gauss ' +\n      'geometryConstraint getApplicationVersionAsFloat getAttr getClassification ' +\n      'getDefaultBrush getFileList getFluidAttr getInputDeviceRange getMayaPanelTypes ' +\n      'getModifiers getPanel getParticleAttr getPluginResource getenv getpid glRender ' +\n      'glRenderEditor globalStitch gmatch goal gotoBindPose grabColor gradientControl ' +\n      'gradientControlNoAttr graphDollyCtx graphSelectContext graphTrackCtx gravity grid ' +\n      'gridLayout group groupObjectsByName HfAddAttractorToAS HfAssignAS HfBuildEqualMap ' +\n      'HfBuildFurFiles HfBuildFurImages HfCancelAFR HfConnectASToHF HfCreateAttractor ' +\n      'HfDeleteAS HfEditAS HfPerformCreateAS HfRemoveAttractorFromAS HfSelectAttached ' +\n      'HfSelectAttractors HfUnAssignAS hardenPointCurve hardware hardwareRenderPanel ' +\n      'headsUpDisplay headsUpMessage help helpLine hermite hide hilite hitTest hotBox hotkey ' +\n      'hotkeyCheck hsv_to_rgb hudButton hudSlider hudSliderButton hwReflectionMap hwRender ' +\n      'hwRenderLoad hyperGraph hyperPanel hyperShade hypot iconTextButton iconTextCheckBox ' +\n      'iconTextRadioButton iconTextRadioCollection iconTextScrollList iconTextStaticLabel ' +\n      'ikHandle ikHandleCtx ikHandleDisplayScale ikSolver ikSplineHandleCtx ikSystem ' +\n      'ikSystemInfo ikfkDisplayMethod illustratorCurves image imfPlugins inheritTransform ' +\n      'insertJoint insertJointCtx insertKeyCtx insertKnotCurve insertKnotSurface instance ' +\n      'instanceable instancer intField intFieldGrp intScrollBar intSlider intSliderGrp ' +\n      'interToUI internalVar intersect iprEngine isAnimCurve isConnected isDirty isParentOf ' +\n      'isSameObject isTrue isValidObjectName isValidString isValidUiName isolateSelect ' +\n      'itemFilter itemFilterAttr itemFilterRender itemFilterType joint jointCluster jointCtx ' +\n      'jointDisplayScale jointLattice keyTangent keyframe keyframeOutliner ' +\n      'keyframeRegionCurrentTimeCtx keyframeRegionDirectKeyCtx keyframeRegionDollyCtx ' +\n      'keyframeRegionInsertKeyCtx keyframeRegionMoveKeyCtx keyframeRegionScaleKeyCtx ' +\n      'keyframeRegionSelectKeyCtx keyframeRegionSetKeyCtx keyframeRegionTrackCtx ' +\n      'keyframeStats lassoContext lattice latticeDeformKeyCtx launch launchImageEditor ' +\n      'layerButton layeredShaderPort layeredTexturePort layout layoutDialog lightList ' +\n      'lightListEditor lightListPanel lightlink lineIntersection linearPrecision linstep ' +\n      'listAnimatable listAttr listCameras listConnections listDeviceAttachments listHistory ' +\n      'listInputDeviceAxes listInputDeviceButtons listInputDevices listMenuAnnotation ' +\n      'listNodeTypes listPanelCategories listRelatives listSets listTransforms ' +\n      'listUnselected listerEditor loadFluid loadNewShelf loadPlugin ' +\n      'loadPluginLanguageResources loadPrefObjects localizedPanelLabel lockNode loft log ' +\n      'longNameOf lookThru ls lsThroughFilter lsType lsUI Mayatomr mag makeIdentity makeLive ' +\n      'makePaintable makeRoll makeSingleSurface makeTubeOn makebot manipMoveContext ' +\n      'manipMoveLimitsCtx manipOptions manipRotateContext manipRotateLimitsCtx ' +\n      'manipScaleContext manipScaleLimitsCtx marker match max memory menu menuBarLayout ' +\n      'menuEditor menuItem menuItemToShelf menuSet menuSetPref messageLine min minimizeApp ' +\n      'mirrorJoint modelCurrentTimeCtx modelEditor modelPanel mouse movIn movOut move ' +\n      'moveIKtoFK moveKeyCtx moveVertexAlongDirection multiProfileBirailSurface mute ' +\n      'nParticle nameCommand nameField namespace namespaceInfo newPanelItems newton nodeCast ' +\n      'nodeIconButton nodeOutliner nodePreset nodeType noise nonLinear normalConstraint ' +\n      'normalize nurbsBoolean nurbsCopyUVSet nurbsCube nurbsEditUV nurbsPlane nurbsSelect ' +\n      'nurbsSquare nurbsToPoly nurbsToPolygonsPref nurbsToSubdiv nurbsToSubdivPref ' +\n      'nurbsUVSet nurbsViewDirectionVector objExists objectCenter objectLayer objectType ' +\n      'objectTypeUI obsoleteProc oceanNurbsPreviewPlane offsetCurve offsetCurveOnSurface ' +\n      'offsetSurface openGLExtension openMayaPref optionMenu optionMenuGrp optionVar orbit ' +\n      'orbitCtx orientConstraint outlinerEditor outlinerPanel overrideModifier ' +\n      'paintEffectsDisplay pairBlend palettePort paneLayout panel panelConfiguration ' +\n      'panelHistory paramDimContext paramDimension paramLocator parent parentConstraint ' +\n      'particle particleExists particleInstancer particleRenderInfo partition pasteKey ' +\n      'pathAnimation pause pclose percent performanceOptions pfxstrokes pickWalk picture ' +\n      'pixelMove planarSrf plane play playbackOptions playblast plugAttr plugNode pluginInfo ' +\n      'pluginResourceUtil pointConstraint pointCurveConstraint pointLight pointMatrixMult ' +\n      'pointOnCurve pointOnSurface pointPosition poleVectorConstraint polyAppend ' +\n      'polyAppendFacetCtx polyAppendVertex polyAutoProjection polyAverageNormal ' +\n      'polyAverageVertex polyBevel polyBlendColor polyBlindData polyBoolOp polyBridgeEdge ' +\n      'polyCacheMonitor polyCheck polyChipOff polyClipboard polyCloseBorder polyCollapseEdge ' +\n      'polyCollapseFacet polyColorBlindData polyColorDel polyColorPerVertex polyColorSet ' +\n      'polyCompare polyCone polyCopyUV polyCrease polyCreaseCtx polyCreateFacet ' +\n      'polyCreateFacetCtx polyCube polyCut polyCutCtx polyCylinder polyCylindricalProjection ' +\n      'polyDelEdge polyDelFacet polyDelVertex polyDuplicateAndConnect polyDuplicateEdge ' +\n      'polyEditUV polyEditUVShell polyEvaluate polyExtrudeEdge polyExtrudeFacet ' +\n      'polyExtrudeVertex polyFlipEdge polyFlipUV polyForceUV polyGeoSampler polyHelix ' +\n      'polyInfo polyInstallAction polyLayoutUV polyListComponentConversion polyMapCut ' +\n      'polyMapDel polyMapSew polyMapSewMove polyMergeEdge polyMergeEdgeCtx polyMergeFacet ' +\n      'polyMergeFacetCtx polyMergeUV polyMergeVertex polyMirrorFace polyMoveEdge ' +\n      'polyMoveFacet polyMoveFacetUV polyMoveUV polyMoveVertex polyNormal polyNormalPerVertex ' +\n      'polyNormalizeUV polyOptUvs polyOptions polyOutput polyPipe polyPlanarProjection ' +\n      'polyPlane polyPlatonicSolid polyPoke polyPrimitive polyPrism polyProjection ' +\n      'polyPyramid polyQuad polyQueryBlindData polyReduce polySelect polySelectConstraint ' +\n      'polySelectConstraintMonitor polySelectCtx polySelectEditCtx polySeparate ' +\n      'polySetToFaceNormal polySewEdge polyShortestPathCtx polySmooth polySoftEdge ' +\n      'polySphere polySphericalProjection polySplit polySplitCtx polySplitEdge polySplitRing ' +\n      'polySplitVertex polyStraightenUVBorder polySubdivideEdge polySubdivideFacet ' +\n      'polyToSubdiv polyTorus polyTransfer polyTriangulate polyUVSet polyUnite polyWedgeFace ' +\n      'popen popupMenu pose pow preloadRefEd print progressBar progressWindow projFileViewer ' +\n      'projectCurve projectTangent projectionContext projectionManip promptDialog propModCtx ' +\n      'propMove psdChannelOutliner psdEditTextureFile psdExport psdTextureFile putenv pwd ' +\n      'python querySubdiv quit rad_to_deg radial radioButton radioButtonGrp radioCollection ' +\n      'radioMenuItemCollection rampColorPort rand randomizeFollicles randstate rangeControl ' +\n      'readTake rebuildCurve rebuildSurface recordAttr recordDevice redo reference ' +\n      'referenceEdit referenceQuery refineSubdivSelectionList refresh refreshAE ' +\n      'registerPluginResource rehash reloadImage removeJoint removeMultiInstance ' +\n      'removePanelCategory rename renameAttr renameSelectionList renameUI render ' +\n      'renderGlobalsNode renderInfo renderLayerButton renderLayerParent ' +\n      'renderLayerPostProcess renderLayerUnparent renderManip renderPartition ' +\n      'renderQualityNode renderSettings renderThumbnailUpdate renderWindowEditor ' +\n      'renderWindowSelectContext renderer reorder reorderDeformers requires reroot ' +\n      'resampleFluid resetAE resetPfxToPolyCamera resetTool resolutionNode retarget ' +\n      'reverseCurve reverseSurface revolve rgb_to_hsv rigidBody rigidSolver roll rollCtx ' +\n      'rootOf rot rotate rotationInterpolation roundConstantRadius rowColumnLayout rowLayout ' +\n      'runTimeCommand runup sampleImage saveAllShelves saveAttrPreset saveFluid saveImage ' +\n      'saveInitialState saveMenu savePrefObjects savePrefs saveShelf saveToolSettings scale ' +\n      'scaleBrushBrightness scaleComponents scaleConstraint scaleKey scaleKeyCtx sceneEditor ' +\n      'sceneUIReplacement scmh scriptCtx scriptEditorInfo scriptJob scriptNode scriptTable ' +\n      'scriptToShelf scriptedPanel scriptedPanelType scrollField scrollLayout sculpt ' +\n      'searchPathArray seed selLoadSettings select selectContext selectCurveCV selectKey ' +\n      'selectKeyCtx selectKeyframeRegionCtx selectMode selectPref selectPriority selectType ' +\n      'selectedNodes selectionConnection separator setAttr setAttrEnumResource ' +\n      'setAttrMapping setAttrNiceNameResource setConstraintRestPosition ' +\n      'setDefaultShadingGroup setDrivenKeyframe setDynamic setEditCtx setEditor setFluidAttr ' +\n      'setFocus setInfinity setInputDeviceMapping setKeyCtx setKeyPath setKeyframe ' +\n      'setKeyframeBlendshapeTargetWts setMenuMode setNodeNiceNameResource setNodeTypeFlag ' +\n      'setParent setParticleAttr setPfxToPolyCamera setPluginResource setProject ' +\n      'setStampDensity setStartupMessage setState setToolTo setUITemplate setXformManip sets ' +\n      'shadingConnection shadingGeometryRelCtx shadingLightRelCtx shadingNetworkCompare ' +\n      'shadingNode shapeCompare shelfButton shelfLayout shelfTabLayout shellField ' +\n      'shortNameOf showHelp showHidden showManipCtx showSelectionInTitle ' +\n      'showShadingGroupAttrEditor showWindow sign simplify sin singleProfileBirailSurface ' +\n      'size sizeBytes skinCluster skinPercent smoothCurve smoothTangentSurface smoothstep ' +\n      'snap2to2 snapKey snapMode snapTogetherCtx snapshot soft softMod softModCtx sort sound ' +\n      'soundControl source spaceLocator sphere sphrand spotLight spotLightPreviewPort ' +\n      'spreadSheetEditor spring sqrt squareSurface srtContext stackTrace startString ' +\n      'startsWith stitchAndExplodeShell stitchSurface stitchSurfacePoints strcmp ' +\n      'stringArrayCatenate stringArrayContains stringArrayCount stringArrayInsertAtIndex ' +\n      'stringArrayIntersector stringArrayRemove stringArrayRemoveAtIndex ' +\n      'stringArrayRemoveDuplicates stringArrayRemoveExact stringArrayToString ' +\n      'stringToStringArray strip stripPrefixFromName stroke subdAutoProjection ' +\n      'subdCleanTopology subdCollapse subdDuplicateAndConnect subdEditUV ' +\n      'subdListComponentConversion subdMapCut subdMapSewMove subdMatchTopology subdMirror ' +\n      'subdToBlind subdToPoly subdTransferUVsToCache subdiv subdivCrease ' +\n      'subdivDisplaySmoothness substitute substituteAllString substituteGeometry substring ' +\n      'surface surfaceSampler surfaceShaderList swatchDisplayPort switchTable symbolButton ' +\n      'symbolCheckBox sysFile system tabLayout tan tangentConstraint texLatticeDeformContext ' +\n      'texManipContext texMoveContext texMoveUVShellContext texRotateContext texScaleContext ' +\n      'texSelectContext texSelectShortestPathCtx texSmudgeUVContext texWinToolCtx text ' +\n      'textCurves textField textFieldButtonGrp textFieldGrp textManip textScrollList ' +\n      'textToShelf textureDisplacePlane textureHairColor texturePlacementContext ' +\n      'textureWindow threadCount threePointArcCtx timeControl timePort timerX toNativePath ' +\n      'toggle toggleAxis toggleWindowVisibility tokenize tokenizeList tolerance tolower ' +\n      'toolButton toolCollection toolDropped toolHasOptions toolPropertyWindow torus toupper ' +\n      'trace track trackCtx transferAttributes transformCompare transformLimits translator ' +\n      'trim trunc truncateFluidCache truncateHairCache tumble tumbleCtx turbulence ' +\n      'twoPointArcCtx uiRes uiTemplate unassignInputDevice undo undoInfo ungroup uniform unit ' +\n      'unloadPlugin untangleUV untitledFileName untrim upAxis updateAE userCtx uvLink ' +\n      'uvSnapshot validateShelfName vectorize view2dToolCtx viewCamera viewClipPlane ' +\n      'viewFit viewHeadOn viewLookAt viewManip viewPlace viewSet visor volumeAxis vortex ' +\n      'waitCursor warning webBrowser webBrowserPrefs whatIs window windowPref wire ' +\n      'wireContext workspace wrinkle wrinkleContext writeTake xbmLangPathList xform',\n    illegal: '</',\n    contains: [\n      hljs.C_NUMBER_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        begin: '`', end: '`',\n        contains: [hljs.BACKSLASH_ESCAPE]\n      },\n      {\n        className: 'variable',\n        variants: [\n          {begin: '\\\\$\\\\d'},\n          {begin: '[\\\\$\\\\%\\\\@](\\\\^\\\\w\\\\b|#\\\\w+|[^\\\\s\\\\w{]|{\\\\w+}|\\\\w+)'},\n          {begin: '\\\\*(\\\\^\\\\w\\\\b|#\\\\w+|[^\\\\s\\\\w{]|{\\\\w+}|\\\\w+)', relevance: 0}\n        ]\n      },\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('mercury', function(hljs) {\n  var KEYWORDS = {\n    keyword:\n      'module use_module import_module include_module end_module initialise ' +\n      'mutable initialize finalize finalise interface implementation pred ' +\n      'mode func type inst solver any_pred any_func is semidet det nondet ' +\n      'multi erroneous failure cc_nondet cc_multi typeclass instance where ' +\n      'pragma promise external trace atomic or_else require_complete_switch ' +\n      'require_det require_semidet require_multi require_nondet ' +\n      'require_cc_multi require_cc_nondet require_erroneous require_failure',\n    pragma:\n      'inline no_inline type_spec source_file fact_table obsolete memo ' +\n      'loop_check minimal_model terminates does_not_terminate ' +\n      'check_termination promise_equivalent_clauses',\n    preprocessor:\n      'foreign_proc foreign_decl foreign_code foreign_type ' +\n      'foreign_import_module foreign_export_enum foreign_export ' +\n      'foreign_enum may_call_mercury will_not_call_mercury thread_safe ' +\n      'not_thread_safe maybe_thread_safe promise_pure promise_semipure ' +\n      'tabled_for_io local untrailed trailed attach_to_io_state ' +\n      'can_pass_as_mercury_type stable will_not_throw_exception ' +\n      'may_modify_trail will_not_modify_trail may_duplicate ' +\n      'may_not_duplicate affects_liveness does_not_affect_liveness ' +\n      'doesnt_affect_liveness no_sharing unknown_sharing sharing',\n    built_in:\n      'some all not if then else true fail false try catch catch_any ' +\n      'semidet_true semidet_false semidet_fail impure_true impure semipure'\n  };\n\n  var TODO = {\n    className: 'label',\n    begin: 'XXX', end: '$', endsWithParent: true,\n    relevance: 0\n  };\n  var COMMENT = hljs.inherit(hljs.C_LINE_COMMENT_MODE, {begin: '%'});\n  var CCOMMENT = hljs.inherit(hljs.C_BLOCK_COMMENT_MODE, {relevance: 0});\n  COMMENT.contains.push(TODO);\n  CCOMMENT.contains.push(TODO);\n\n  var NUMCODE = {\n    className: 'number',\n    begin: \"0'.\\\\|0[box][0-9a-fA-F]*\"\n  };\n\n  var ATOM = hljs.inherit(hljs.APOS_STRING_MODE, {relevance: 0});\n  var STRING = hljs.inherit(hljs.QUOTE_STRING_MODE, {relevance: 0});\n  var STRING_FMT = {\n    className: 'constant',\n    begin: '\\\\\\\\[abfnrtv]\\\\|\\\\\\\\x[0-9a-fA-F]*\\\\\\\\\\\\|%[-+# *.0-9]*[dioxXucsfeEgGp]',\n    relevance: 0\n  };\n  STRING.contains.push(STRING_FMT);\n\n  var IMPLICATION = {\n    className: 'built_in',\n    variants: [\n      {begin: '<=>'},\n      {begin: '<=', relevance: 0},\n      {begin: '=>', relevance: 0},\n      {begin: '/\\\\\\\\'},\n      {begin: '\\\\\\\\/'}\n    ]\n  };\n\n  var HEAD_BODY_CONJUNCTION = {\n    className: 'built_in',\n    variants: [\n      {begin: ':-\\\\|-->'},\n      {begin: '=', relevance: 0}\n    ]\n  };\n\n  return {\n    aliases: ['m', 'moo'],\n    keywords: KEYWORDS,\n    contains: [\n      IMPLICATION,\n      HEAD_BODY_CONJUNCTION,\n      COMMENT,\n      CCOMMENT,\n      NUMCODE,\n      hljs.NUMBER_MODE,\n      ATOM,\n      STRING,\n      {begin: /:-/} // relevance booster\n    ]\n  };\n});\n\nhljs.registerLanguage('mizar', function(hljs) {\n  return {\n    keywords:\n      'environ vocabularies notations constructors definitions ' +\n      'registrations theorems schemes requirements begin end definition ' +\n      'registration cluster existence pred func defpred deffunc theorem ' +\n      'proof let take assume then thus hence ex for st holds consider ' +\n      'reconsider such that and in provided of as from be being by means ' +\n      'equals implies iff redefine define now not or attr is mode ' +\n      'suppose per cases set thesis contradiction scheme reserve struct ' +\n      'correctness compatibility coherence symmetry assymetry ' +\n      'reflexivity irreflexivity connectedness uniqueness commutativity ' +\n      'idempotence involutiveness projectivity',\n    contains: [\n      hljs.COMMENT('::', '$')\n    ]\n  };\n});\n\nhljs.registerLanguage('perl', function(hljs) {\n  var PERL_KEYWORDS = 'getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ' +\n    'ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime ' +\n    'readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq' +\n    'fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent ' +\n    'shutdown dump chomp connect getsockname die socketpair close flock exists index shmget' +\n    'sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr ' +\n    'unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 ' +\n    'getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline ' +\n    'endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand ' +\n    'mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink ' +\n    'getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr ' +\n    'untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link ' +\n    'getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller ' +\n    'lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and ' +\n    'sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 ' +\n    'chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach ' +\n    'tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir' +\n    'ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe ' +\n    'atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when';\n  var SUBST = {\n    className: 'subst',\n    begin: '[$@]\\\\{', end: '\\\\}',\n    keywords: PERL_KEYWORDS\n  };\n  var METHOD = {\n    begin: '->{', end: '}'\n    // contains defined later\n  };\n  var VAR = {\n    className: 'variable',\n    variants: [\n      {begin: /\\$\\d/},\n      {begin: /[\\$%@](\\^\\w\\b|#\\w+(::\\w+)*|{\\w+}|\\w+(::\\w*)*)/},\n      {begin: /[\\$%@][^\\s\\w{]/, relevance: 0}\n    ]\n  };\n  var STRING_CONTAINS = [hljs.BACKSLASH_ESCAPE, SUBST, VAR];\n  var PERL_DEFAULT_CONTAINS = [\n    VAR,\n    hljs.HASH_COMMENT_MODE,\n    hljs.COMMENT(\n      '^\\\\=\\\\w',\n      '\\\\=cut',\n      {\n        endsWithParent: true\n      }\n    ),\n    METHOD,\n    {\n      className: 'string',\n      contains: STRING_CONTAINS,\n      variants: [\n        {\n          begin: 'q[qwxr]?\\\\s*\\\\(', end: '\\\\)',\n          relevance: 5\n        },\n        {\n          begin: 'q[qwxr]?\\\\s*\\\\[', end: '\\\\]',\n          relevance: 5\n        },\n        {\n          begin: 'q[qwxr]?\\\\s*\\\\{', end: '\\\\}',\n          relevance: 5\n        },\n        {\n          begin: 'q[qwxr]?\\\\s*\\\\|', end: '\\\\|',\n          relevance: 5\n        },\n        {\n          begin: 'q[qwxr]?\\\\s*\\\\<', end: '\\\\>',\n          relevance: 5\n        },\n        {\n          begin: 'qw\\\\s+q', end: 'q',\n          relevance: 5\n        },\n        {\n          begin: '\\'', end: '\\'',\n          contains: [hljs.BACKSLASH_ESCAPE]\n        },\n        {\n          begin: '\"', end: '\"'\n        },\n        {\n          begin: '`', end: '`',\n          contains: [hljs.BACKSLASH_ESCAPE]\n        },\n        {\n          begin: '{\\\\w+}',\n          contains: [],\n          relevance: 0\n        },\n        {\n          begin: '\\-?\\\\w+\\\\s*\\\\=\\\\>',\n          contains: [],\n          relevance: 0\n        }\n      ]\n    },\n    {\n      className: 'number',\n      begin: '(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b',\n      relevance: 0\n    },\n    { // regexp container\n      begin: '(\\\\/\\\\/|' + hljs.RE_STARTERS_RE + '|\\\\b(split|return|print|reverse|grep)\\\\b)\\\\s*',\n      keywords: 'split return print reverse grep',\n      relevance: 0,\n      contains: [\n        hljs.HASH_COMMENT_MODE,\n        {\n          className: 'regexp',\n          begin: '(s|tr|y)/(\\\\\\\\.|[^/])*/(\\\\\\\\.|[^/])*/[a-z]*',\n          relevance: 10\n        },\n        {\n          className: 'regexp',\n          begin: '(m|qr)?/', end: '/[a-z]*',\n          contains: [hljs.BACKSLASH_ESCAPE],\n          relevance: 0 // allows empty \"//\" which is a common comment delimiter in other languages\n        }\n      ]\n    },\n    {\n      className: 'sub',\n      beginKeywords: 'sub', end: '(\\\\s*\\\\(.*?\\\\))?[;{]',\n      relevance: 5\n    },\n    {\n      className: 'operator',\n      begin: '-\\\\w\\\\b',\n      relevance: 0\n    },\n    {\n      begin: \"^__DATA__$\",\n      end: \"^__END__$\",\n      subLanguage: 'mojolicious',\n      contains: [\n        {\n            begin: \"^@@.*\",\n            end: \"$\",\n            className: \"comment\"\n        }\n      ]\n    }\n  ];\n  SUBST.contains = PERL_DEFAULT_CONTAINS;\n  METHOD.contains = PERL_DEFAULT_CONTAINS;\n\n  return {\n    aliases: ['pl'],\n    keywords: PERL_KEYWORDS,\n    contains: PERL_DEFAULT_CONTAINS\n  };\n});\n\nhljs.registerLanguage('mojolicious', function(hljs) {\n  return {\n    subLanguage: 'xml',\n    contains: [\n      {\n        className: 'preprocessor',\n        begin: '^__(END|DATA)__$'\n      },\n    // mojolicious line\n      {\n        begin: \"^\\\\s*%{1,2}={0,2}\", end: '$',\n        subLanguage: 'perl'\n      },\n    // mojolicious block\n      {\n        begin: \"<%{1,2}={0,2}\",\n        end: \"={0,1}%>\",\n        subLanguage: 'perl',\n        excludeBegin: true,\n        excludeEnd: true\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('monkey', function(hljs) {\n  var NUMBER = {\n    className: 'number', relevance: 0,\n    variants: [\n      {\n        begin: '[$][a-fA-F0-9]+'\n      },\n      hljs.NUMBER_MODE\n    ]\n  };\n\n  return {\n    case_insensitive: true,\n    keywords: {\n      keyword: 'public private property continue exit extern new try catch ' +\n        'eachin not abstract final select case default const local global field ' +\n        'end if then else elseif endif while wend repeat until forever for to step next return module inline throw',\n\n      built_in: 'DebugLog DebugStop Error Print ACos ACosr ASin ASinr ATan ATan2 ATan2r ATanr Abs Abs Ceil ' +\n        'Clamp Clamp Cos Cosr Exp Floor Log Max Max Min Min Pow Sgn Sgn Sin Sinr Sqrt Tan Tanr Seed PI HALFPI TWOPI',\n\n      literal: 'true false null and or shl shr mod'\n    },\n    illegal: /\\/\\*/,\n    contains: [\n      hljs.COMMENT('#rem', '#end'),\n      hljs.COMMENT(\n        \"'\",\n        '$',\n        {\n          relevance: 0\n        }\n      ),\n      {\n        className: 'function',\n        beginKeywords: 'function method', end: '[(=:]|$',\n        illegal: /\\n/,\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: '$',\n        contains: [\n          {\n            beginKeywords: 'extends implements'\n          },\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        className: 'variable',\n        begin: '\\\\b(self|super)\\\\b'\n      },\n      {\n        className: 'preprocessor',\n        beginKeywords: 'import',\n        end: '$'\n      },\n      {\n        className: 'preprocessor',\n        begin: '\\\\s*#', end: '$',\n        keywords: 'if else elseif endif end then'\n      },\n      {\n        className: 'pi',\n        begin: '^\\\\s*strict\\\\b'\n      },\n      {\n        beginKeywords: 'alias', end: '=',\n        contains: [hljs.UNDERSCORE_TITLE_MODE]\n      },\n      hljs.QUOTE_STRING_MODE,\n      NUMBER\n    ]\n  }\n});\n\nhljs.registerLanguage('nginx', function(hljs) {\n  var VAR = {\n    className: 'variable',\n    variants: [\n      {begin: /\\$\\d+/},\n      {begin: /\\$\\{/, end: /}/},\n      {begin: '[\\\\$\\\\@]' + hljs.UNDERSCORE_IDENT_RE}\n    ]\n  };\n  var DEFAULT = {\n    endsWithParent: true,\n    lexemes: '[a-z/_]+',\n    keywords: {\n      built_in:\n        'on off yes no true false none blocked debug info notice warn error crit ' +\n        'select break last permanent redirect kqueue rtsig epoll poll /dev/poll'\n    },\n    relevance: 0,\n    illegal: '=>',\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      {\n        className: 'string',\n        contains: [hljs.BACKSLASH_ESCAPE, VAR],\n        variants: [\n          {begin: /\"/, end: /\"/},\n          {begin: /'/, end: /'/}\n        ]\n      },\n      {\n        className: 'url',\n        begin: '([a-z]+):/', end: '\\\\s', endsWithParent: true, excludeEnd: true,\n        contains: [VAR]\n      },\n      {\n        className: 'regexp',\n        contains: [hljs.BACKSLASH_ESCAPE, VAR],\n        variants: [\n          {begin: \"\\\\s\\\\^\", end: \"\\\\s|{|;\", returnEnd: true},\n          // regexp locations (~, ~*)\n          {begin: \"~\\\\*?\\\\s+\", end: \"\\\\s|{|;\", returnEnd: true},\n          // *.example.com\n          {begin: \"\\\\*(\\\\.[a-z\\\\-]+)+\"},\n          // sub.example.*\n          {begin: \"([a-z\\\\-]+\\\\.)+\\\\*\"}\n        ]\n      },\n      // IP\n      {\n        className: 'number',\n        begin: '\\\\b\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}(:\\\\d{1,5})?\\\\b'\n      },\n      // units\n      {\n        className: 'number',\n        begin: '\\\\b\\\\d+[kKmMgGdshdwy]*\\\\b',\n        relevance: 0\n      },\n      VAR\n    ]\n  };\n\n  return {\n    aliases: ['nginxconf'],\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      {\n        begin: hljs.UNDERSCORE_IDENT_RE + '\\\\s', end: ';|{', returnBegin: true,\n        contains: [\n          {\n            className: 'title',\n            begin: hljs.UNDERSCORE_IDENT_RE,\n            starts: DEFAULT\n          }\n        ],\n        relevance: 0\n      }\n    ],\n    illegal: '[^\\\\s\\\\}]'\n  };\n});\n\nhljs.registerLanguage('nimrod', function(hljs) {\n  return {\n    aliases: ['nim'],\n    keywords: {\n      keyword: 'addr and as asm bind block break|0 case|0 cast const|0 continue|0 converter discard distinct|10 div do elif else|0 end|0 enum|0 except export finally for from generic if|0 import|0 in include|0 interface is isnot|10 iterator|10 let|0 macro method|10 mixin mod nil not notin|10 object|0 of or out proc|10 ptr raise ref|10 return shl shr static template try|0 tuple type|0 using|0 var|0 when while|0 with without xor yield',\n      literal: 'shared guarded stdin stdout stderr result|10 true false'\n    },\n    contains: [ {\n        className: 'decorator', // Actually pragma\n        begin: /{\\./,\n        end: /\\.}/,\n        relevance: 10\n      }, {\n        className: 'string',\n        begin: /[a-zA-Z]\\w*\"/,\n        end: /\"/,\n        contains: [{begin: /\"\"/}]\n      }, {\n        className: 'string',\n        begin: /([a-zA-Z]\\w*)?\"\"\"/,\n        end: /\"\"\"/\n      },\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'type',\n        begin: /\\b[A-Z]\\w+\\b/,\n        relevance: 0\n      }, {\n        className: 'type',\n        begin: /\\b(int|int8|int16|int32|int64|uint|uint8|uint16|uint32|uint64|float|float32|float64|bool|char|string|cstring|pointer|expr|stmt|void|auto|any|range|array|openarray|varargs|seq|set|clong|culong|cchar|cschar|cshort|cint|csize|clonglong|cfloat|cdouble|clongdouble|cuchar|cushort|cuint|culonglong|cstringarray|semistatic)\\b/\n      }, {\n        className: 'number',\n        begin: /\\b(0[xX][0-9a-fA-F][_0-9a-fA-F]*)('?[iIuU](8|16|32|64))?/,\n        relevance: 0\n      }, {\n        className: 'number',\n        begin: /\\b(0o[0-7][_0-7]*)('?[iIuUfF](8|16|32|64))?/,\n        relevance: 0\n      }, {\n        className: 'number',\n        begin: /\\b(0(b|B)[01][_01]*)('?[iIuUfF](8|16|32|64))?/,\n        relevance: 0\n      }, {\n        className: 'number',\n        begin: /\\b(\\d[_\\d]*)('?[iIuUfF](8|16|32|64))?/,\n        relevance: 0\n      },\n      hljs.HASH_COMMENT_MODE\n    ]\n  }\n});\n\nhljs.registerLanguage('nix', function(hljs) {\n  var NIX_KEYWORDS = {\n    keyword: 'rec with let in inherit assert if else then',\n    constant: 'true false or and null',\n    built_in:\n      'import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation'\n  };\n  var ANTIQUOTE = {\n    className: 'subst',\n    begin: /\\$\\{/,\n    end: /}/,\n    keywords: NIX_KEYWORDS\n  };\n  var ATTRS = {\n    className: 'variable',\n    // TODO: we have to figure out a way how to exclude \\s*=\n    begin: /[a-zA-Z0-9-_]+(\\s*=)/,\n    relevance: 0\n  };\n  var SINGLE_QUOTE = {\n    className: 'string',\n    begin: \"''\",\n    end: \"''\",\n    contains: [\n      ANTIQUOTE\n    ]\n  };\n  var DOUBLE_QUOTE = {\n    className: 'string',\n    begin: '\"',\n    end: '\"',\n    contains: [\n      ANTIQUOTE\n    ]\n  };\n  var EXPRESSIONS = [\n    hljs.NUMBER_MODE,\n    hljs.HASH_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    SINGLE_QUOTE,\n    DOUBLE_QUOTE,\n    ATTRS\n  ];\n  ANTIQUOTE.contains = EXPRESSIONS;\n  return {\n    aliases: [\"nixos\"],\n    keywords: NIX_KEYWORDS,\n    contains: EXPRESSIONS\n  };\n});\n\nhljs.registerLanguage('nsis', function(hljs) {\n  var CONSTANTS = {\n    className: 'symbol',\n    begin: '\\\\$(ADMINTOOLS|APPDATA|CDBURN_AREA|CMDLINE|COMMONFILES32|COMMONFILES64|COMMONFILES|COOKIES|DESKTOP|DOCUMENTS|EXEDIR|EXEFILE|EXEPATH|FAVORITES|FONTS|HISTORY|HWNDPARENT|INSTDIR|INTERNET_CACHE|LANGUAGE|LOCALAPPDATA|MUSIC|NETHOOD|OUTDIR|PICTURES|PLUGINSDIR|PRINTHOOD|PROFILE|PROGRAMFILES32|PROGRAMFILES64|PROGRAMFILES|QUICKLAUNCH|RECENT|RESOURCES_LOCALIZED|RESOURCES|SENDTO|SMPROGRAMS|SMSTARTUP|STARTMENU|SYSDIR|TEMP|TEMPLATES|VIDEOS|WINDIR)'\n  };\n\n  var DEFINES = {\n    // ${defines}\n    className: 'constant',\n    begin: '\\\\$+{[a-zA-Z0-9_]+}'\n  };\n\n  var VARIABLES = {\n    // $variables\n    className: 'variable',\n    begin: '\\\\$+[a-zA-Z0-9_]+',\n    illegal: '\\\\(\\\\){}'\n  };\n\n  var LANGUAGES = {\n    // $(language_strings)\n    className: 'constant',\n    begin: '\\\\$+\\\\([a-zA-Z0-9_]+\\\\)'\n  };\n\n  var PARAMETERS = {\n    // command parameters\n    className: 'params',\n    begin: '(ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)'\n  };\n\n  var COMPILER ={\n    // !compiler_flags\n    className: 'constant',\n    begin: '\\\\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversionsystem|ifdef|ifmacrodef|ifmacrondef|ifndef|if|include|insertmacro|macroend|macro|makensis|packhdr|searchparse|searchreplace|tempfile|undef|verbose|warning)'\n  };\n\n  return {\n    case_insensitive: false,\n    keywords: {\n      keyword:\n      'Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ChangeUI CheckBitmap ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exch Exec ExecShell ExecWait ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileReadUTF16LE FileReadWord FileSeek FileWrite FileWriteByte FileWriteUTF16LE FileWriteWord FindClose FindFirst FindNext FindWindow FlushINI FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LockWindow LogSet LogText ManifestDPIAware ManifestSupportedOS MessageBox MiscButtonText Name Nop OutFile Page PageCallbacks PageExEnd Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename RequestExecutionLevel ReserveFile Return RMDir SearchPath SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionGroupEnd SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetPluginUnload SetRebootFlag SetRegView SetShellVarContext SetSilent ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCmpS StrCpy StrLen SubCaption SubSectionEnd Unicode UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL Var VIAddVersionKey VIFileVersion VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle',\n      literal:\n      'admin all auto both colored current false force hide highest lastused leave listonly none normal notset off on open print show silent silentlog smooth textonly true user '\n    },\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'string',\n        begin: '\"', end: '\"',\n        illegal: '\\\\n',\n        contains: [\n          { // $\\n, $\\r, $\\t, $$\n            className: 'symbol',\n            begin: '\\\\$(\\\\\\\\(n|r|t)|\\\\$)'\n          },\n          CONSTANTS,\n          DEFINES,\n          VARIABLES,\n          LANGUAGES\n        ]\n      },\n      hljs.COMMENT(\n        ';',\n        '$',\n        {\n          relevance: 0\n        }\n      ),\n      {\n        className: 'function',\n        beginKeywords: 'Function PageEx Section SectionGroup SubSection', end: '$'\n      },\n      COMPILER,\n      DEFINES,\n      VARIABLES,\n      LANGUAGES,\n      PARAMETERS,\n      hljs.NUMBER_MODE,\n      { // plug::ins\n        className: 'literal',\n        begin: hljs.IDENT_RE + '::' + hljs.IDENT_RE\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('objectivec', function(hljs) {\n  var API_CLASS = {\n    className: 'built_in',\n    begin: '(AV|CA|CF|CG|CI|MK|MP|NS|UI)\\\\w+',\n  };\n  var OBJC_KEYWORDS = {\n    keyword:\n      'int float while char export sizeof typedef const struct for union ' +\n      'unsigned long volatile static bool mutable if do return goto void ' +\n      'enum else break extern asm case short default double register explicit ' +\n      'signed typename this switch continue wchar_t inline readonly assign ' +\n      'readwrite self @synchronized id typeof ' +\n      'nonatomic super unichar IBOutlet IBAction strong weak copy ' +\n      'in out inout bycopy byref oneway __strong __weak __block __autoreleasing ' +\n      '@private @protected @public @try @property @end @throw @catch @finally ' +\n      '@autoreleasepool @synthesize @dynamic @selector @optional @required',\n    literal:\n      'false true FALSE TRUE nil YES NO NULL',\n    built_in:\n      'BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once'\n  };\n  var LEXEMES = /[a-zA-Z@][a-zA-Z0-9_]*/;\n  var CLASS_KEYWORDS = '@interface @class @protocol @implementation';\n  return {\n    aliases: ['mm', 'objc', 'obj-c'],\n    keywords: OBJC_KEYWORDS,\n    lexemes: LEXEMES,\n    illegal: '</',\n    contains: [\n      API_CLASS,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.C_NUMBER_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        variants: [\n          {\n            begin: '@\"', end: '\"',\n            illegal: '\\\\n',\n            contains: [hljs.BACKSLASH_ESCAPE]\n          },\n          {\n            begin: '\\'', end: '[^\\\\\\\\]\\'',\n            illegal: '[^\\\\\\\\][^\\']'\n          }\n        ]\n      },\n      {\n        className: 'preprocessor',\n        begin: '#',\n        end: '$',\n        contains: [\n          {\n            className: 'title',\n            variants: [\n              { begin: '\\\"', end: '\\\"' },\n              { begin: '<', end: '>' }\n            ]\n          }\n        ]\n      },\n      {\n        className: 'class',\n        begin: '(' + CLASS_KEYWORDS.split(' ').join('|') + ')\\\\b', end: '({|$)', excludeEnd: true,\n        keywords: CLASS_KEYWORDS, lexemes: LEXEMES,\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        className: 'variable',\n        begin: '\\\\.'+hljs.UNDERSCORE_IDENT_RE,\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('ocaml', function(hljs) {\n  /* missing support for heredoc-like string (OCaml 4.0.2+) */\n  return {\n    aliases: ['ml'],\n    keywords: {\n      keyword:\n        'and as assert asr begin class constraint do done downto else end ' +\n        'exception external for fun function functor if in include ' +\n        'inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method ' +\n        'mod module mutable new object of open! open or private rec sig struct ' +\n        'then to try type val! val virtual when while with ' +\n        /* camlp4 */\n        'parser value',\n      built_in:\n        /* built-in types */\n        'array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit ' +\n        /* (some) types in Pervasives */\n        'in_channel out_channel ref',\n      literal:\n        'true false'\n    },\n    illegal: /\\/\\/|>>/,\n    lexemes: '[a-z_]\\\\w*!?',\n    contains: [\n      {\n        className: 'literal',\n        begin: '\\\\[(\\\\|\\\\|)?\\\\]|\\\\(\\\\)',\n        relevance: 0\n      },\n      hljs.COMMENT(\n        '\\\\(\\\\*',\n        '\\\\*\\\\)',\n        {\n          contains: ['self']\n        }\n      ),\n      { /* type variable */\n        className: 'symbol',\n        begin: '\\'[A-Za-z_](?!\\')[\\\\w\\']*'\n        /* the grammar is ambiguous on how 'a'b should be interpreted but not the compiler */\n      },\n      { /* polymorphic variant */\n        className: 'tag',\n        begin: '`[A-Z][\\\\w\\']*'\n      },\n      { /* module or constructor */\n        className: 'type',\n        begin: '\\\\b[A-Z][\\\\w\\']*',\n        relevance: 0\n      },\n      { /* don't color identifiers, but safely catch all identifiers with '*/\n        begin: '[a-z_]\\\\w*\\'[\\\\w\\']*'\n      },\n      hljs.inherit(hljs.APOS_STRING_MODE, {className: 'char', relevance: 0}),\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),\n      {\n        className: 'number',\n        begin:\n          '\\\\b(0[xX][a-fA-F0-9_]+[Lln]?|' +\n          '0[oO][0-7_]+[Lln]?|' +\n          '0[bB][01_]+[Lln]?|' +\n          '[0-9][0-9_]*([Lln]|(\\\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)',\n        relevance: 0\n      },\n      {\n        begin: /[-=]>/ // relevance booster\n      }\n    ]\n  }\n});\n\nhljs.registerLanguage('openscad', function(hljs) {\n\tvar SPECIAL_VARS = {\n\t\tclassName: 'keyword',\n\t\tbegin: '\\\\$(f[asn]|t|vp[rtd]|children)'\n\t},\n\tLITERALS = {\n\t\tclassName: 'literal',\n\t\tbegin: 'false|true|PI|undef'\n\t},\n\tNUMBERS = {\n\t\tclassName: 'number',\n\t\tbegin: '\\\\b\\\\d+(\\\\.\\\\d+)?(e-?\\\\d+)?', //adds 1e5, 1e-10\n\t\trelevance: 0\n\t},\n\tSTRING = hljs.inherit(hljs.QUOTE_STRING_MODE,{illegal: null}),\n\tPREPRO = {\n\t\tclassName: 'preprocessor',\n\t\tkeywords: 'include use',\n\t\tbegin: 'include|use <',\n\t\tend: '>'\n\t},\n\tPARAMS = {\n\t\tclassName: 'params',\n\t\tbegin: '\\\\(', end: '\\\\)',\n\t\tcontains: ['self', NUMBERS, STRING, SPECIAL_VARS, LITERALS]\n\t},\n\tMODIFIERS = {\n\t\tclassName: 'built_in',\n\t\tbegin: '[*!#%]',\n\t\trelevance: 0\n\t},\n\tFUNCTIONS = {\n\t\tclassName: 'function',\n\t\tbeginKeywords: 'module function',\n\t\tend: '\\\\=|\\\\{',\n\t\tcontains: [PARAMS, hljs.UNDERSCORE_TITLE_MODE]\n\t};\n\n\treturn {\n\t\taliases: ['scad'],\n\t\tkeywords: {\n\t\t\tkeyword: 'function module include use for intersection_for if else \\\\%',\n\t\t\tliteral: 'false true PI undef',\n\t\t\tbuilt_in: 'circle square polygon text sphere cube cylinder polyhedron translate rotate scale resize mirror multmatrix color offset hull minkowski union difference intersection abs sign sin cos tan acos asin atan atan2 floor round ceil ln log pow sqrt exp rands min max concat lookup str chr search version version_num norm cross parent_module echo import import_dxf dxf_linear_extrude linear_extrude rotate_extrude surface projection render children dxf_cross dxf_dim let assign'\n\t\t},\n\t\tcontains: [\n\t\t\thljs.C_LINE_COMMENT_MODE,\n\t\t\thljs.C_BLOCK_COMMENT_MODE,\n\t\t\tNUMBERS,\n\t\t\tPREPRO,\n\t\t\tSTRING,\n\t\t\tSPECIAL_VARS,\n\t\t\tMODIFIERS,\n\t\t\tFUNCTIONS\n\t\t]\n\t}\n});\n\nhljs.registerLanguage('oxygene', function(hljs) {\n  var OXYGENE_KEYWORDS = 'abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue '+\n    'create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false '+\n    'final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited '+\n    'inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of '+\n    'old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly '+\n    'record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple '+\n    'type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal '+\n    'register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained';\n  var CURLY_COMMENT =  hljs.COMMENT(\n    '{',\n    '}',\n    {\n      relevance: 0\n    }\n  );\n  var PAREN_COMMENT = hljs.COMMENT(\n    '\\\\(\\\\*',\n    '\\\\*\\\\)',\n    {\n      relevance: 10\n    }\n  );\n  var STRING = {\n    className: 'string',\n    begin: '\\'', end: '\\'',\n    contains: [{begin: '\\'\\''}]\n  };\n  var CHAR_STRING = {\n    className: 'string', begin: '(#\\\\d+)+'\n  };\n  var FUNCTION = {\n    className: 'function',\n    beginKeywords: 'function constructor destructor procedure method', end: '[:;]',\n    keywords: 'function constructor|10 destructor|10 procedure|10 method|10',\n    contains: [\n      hljs.TITLE_MODE,\n      {\n        className: 'params',\n        begin: '\\\\(', end: '\\\\)',\n        keywords: OXYGENE_KEYWORDS,\n        contains: [STRING, CHAR_STRING]\n      },\n      CURLY_COMMENT, PAREN_COMMENT\n    ]\n  };\n  return {\n    case_insensitive: true,\n    keywords: OXYGENE_KEYWORDS,\n    illegal: '(\"|\\\\$[G-Zg-z]|\\\\/\\\\*|</|=>|->)',\n    contains: [\n      CURLY_COMMENT, PAREN_COMMENT, hljs.C_LINE_COMMENT_MODE,\n      STRING, CHAR_STRING,\n      hljs.NUMBER_MODE,\n      FUNCTION,\n      {\n        className: 'class',\n        begin: '=\\\\bclass\\\\b', end: 'end;',\n        keywords: OXYGENE_KEYWORDS,\n        contains: [\n          STRING, CHAR_STRING,\n          CURLY_COMMENT, PAREN_COMMENT, hljs.C_LINE_COMMENT_MODE,\n          FUNCTION\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('parser3', function(hljs) {\n  var CURLY_SUBCOMMENT = hljs.COMMENT(\n    '{',\n    '}',\n    {\n      contains: ['self']\n    }\n  );\n  return {\n    subLanguage: 'xml', relevance: 0,\n    contains: [\n      hljs.COMMENT('^#', '$'),\n      hljs.COMMENT(\n        '\\\\^rem{',\n        '}',\n        {\n          relevance: 10,\n          contains: [\n            CURLY_SUBCOMMENT\n          ]\n        }\n      ),\n      {\n        className: 'preprocessor',\n        begin: '^@(?:BASE|USE|CLASS|OPTIONS)$',\n        relevance: 10\n      },\n      {\n        className: 'title',\n        begin: '@[\\\\w\\\\-]+\\\\[[\\\\w^;\\\\-]*\\\\](?:\\\\[[\\\\w^;\\\\-]*\\\\])?(?:.*)$'\n      },\n      {\n        className: 'variable',\n        begin: '\\\\$\\\\{?[\\\\w\\\\-\\\\.\\\\:]+\\\\}?'\n      },\n      {\n        className: 'keyword',\n        begin: '\\\\^[\\\\w\\\\-\\\\.\\\\:]+'\n      },\n      {\n        className: 'number',\n        begin: '\\\\^#[0-9a-fA-F]+'\n      },\n      hljs.C_NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('pf', function(hljs) {\n  var MACRO = {\n    className: 'variable',\n    begin: /\\$[\\w\\d#@][\\w\\d_]*/\n  };\n  var TABLE = {\n    className: 'variable',\n    begin: /</, end: />/\n  };\n  var QUOTE_STRING = {\n    className: 'string',\n    begin: /\"/, end: /\"/\n  };\n\n  return {\n    aliases: ['pf.conf'],\n    lexemes: /[a-z0-9_<>-]+/,\n    keywords: {\n      built_in: /* block match pass are \"actions\" in pf.conf(5), the rest are\n                 * lexically similar top-level commands.\n                 */\n        'block match pass load anchor|5 antispoof|10 set table',\n      keyword:\n        'in out log quick on rdomain inet inet6 proto from port os to route' +\n        'allow-opts divert-packet divert-reply divert-to flags group icmp-type' +\n        'icmp6-type label once probability recieved-on rtable prio queue' +\n        'tos tag tagged user keep fragment for os drop' +\n        'af-to|10 binat-to|10 nat-to|10 rdr-to|10 bitmask least-stats random round-robin' +\n        'source-hash static-port' +\n        'dup-to reply-to route-to' +\n        'parent bandwidth default min max qlimit' +\n        'block-policy debug fingerprints hostid limit loginterface optimization' +\n        'reassemble ruleset-optimization basic none profile skip state-defaults' +\n        'state-policy timeout' +\n        'const counters persist' +\n        'no modulate synproxy state|5 floating if-bound no-sync pflow|10 sloppy' +\n        'source-track global rule max-src-nodes max-src-states max-src-conn' +\n        'max-src-conn-rate overload flush' +\n        'scrub|5 max-mss min-ttl no-df|10 random-id',\n      literal:\n        'all any no-route self urpf-failed egress|5 unknown'\n    },\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      hljs.NUMBER_MODE,\n      hljs.QUOTE_STRING_MODE,\n      MACRO,\n      TABLE\n    ]\n  };\n});\n\nhljs.registerLanguage('php', function(hljs) {\n  var VARIABLE = {\n    className: 'variable', begin: '\\\\$+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*'\n  };\n  var PREPROCESSOR = {\n    className: 'preprocessor', begin: /<\\?(php)?|\\?>/\n  };\n  var STRING = {\n    className: 'string',\n    contains: [hljs.BACKSLASH_ESCAPE, PREPROCESSOR],\n    variants: [\n      {\n        begin: 'b\"', end: '\"'\n      },\n      {\n        begin: 'b\\'', end: '\\''\n      },\n      hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null})\n    ]\n  };\n  var NUMBER = {variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]};\n  return {\n    aliases: ['php3', 'php4', 'php5', 'php6'],\n    case_insensitive: true,\n    keywords:\n      'and include_once list abstract global private echo interface as static endswitch ' +\n      'array null if endwhile or const for endforeach self var while isset public ' +\n      'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' +\n      'return parent clone use __CLASS__ __LINE__ else break print eval new ' +\n      'catch __METHOD__ case exception default die require __FUNCTION__ ' +\n      'enddeclare final try switch continue endfor endif declare unset true false ' +\n      'trait goto instanceof insteadof __DIR__ __NAMESPACE__ ' +\n      'yield finally',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.HASH_COMMENT_MODE,\n      hljs.COMMENT(\n        '/\\\\*',\n        '\\\\*/',\n        {\n          contains: [\n            {\n              className: 'doctag',\n              begin: '@[A-Za-z]+'\n            },\n            PREPROCESSOR\n          ]\n        }\n      ),\n      hljs.COMMENT(\n        '__halt_compiler.+?;',\n        false,\n        {\n          endsWithParent: true,\n          keywords: '__halt_compiler',\n          lexemes: hljs.UNDERSCORE_IDENT_RE\n        }\n      ),\n      {\n        className: 'string',\n        begin: /<<<['\"]?\\w+['\"]?$/, end: /^\\w+;?$/,\n        contains: [\n          hljs.BACKSLASH_ESCAPE,\n          {\n            className: 'subst',\n            variants: [\n              {begin: /\\$\\w+/},\n              {begin: /\\{\\$/, end: /\\}/}\n            ]\n          }\n        ]\n      },\n      PREPROCESSOR,\n      VARIABLE,\n      {\n        // swallow composed identifiers to avoid parsing them as keywords\n        begin: /(::|->)+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function', end: /[;{]/, excludeEnd: true,\n        illegal: '\\\\$|\\\\[|%',\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE,\n          {\n            className: 'params',\n            begin: '\\\\(', end: '\\\\)',\n            contains: [\n              'self',\n              VARIABLE,\n              hljs.C_BLOCK_COMMENT_MODE,\n              STRING,\n              NUMBER\n            ]\n          }\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: '{', excludeEnd: true,\n        illegal: /[:\\(\\$\"]/,\n        contains: [\n          {beginKeywords: 'extends implements'},\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        beginKeywords: 'namespace', end: ';',\n        illegal: /[\\.']/,\n        contains: [hljs.UNDERSCORE_TITLE_MODE]\n      },\n      {\n        beginKeywords: 'use', end: ';',\n        contains: [hljs.UNDERSCORE_TITLE_MODE]\n      },\n      {\n        begin: '=>' // No markup, just a relevance booster\n      },\n      STRING,\n      NUMBER\n    ]\n  };\n});\n\nhljs.registerLanguage('powershell', function(hljs) {\n  var backtickEscape = {\n    begin: '`[\\\\s\\\\S]',\n    relevance: 0\n  };\n  var VAR = {\n    className: 'variable',\n    variants: [\n      {begin: /\\$[\\w\\d][\\w\\d_:]*/}\n    ]\n  };\n  var QUOTE_STRING = {\n    className: 'string',\n    begin: /\"/, end: /\"/,\n    contains: [\n      backtickEscape,\n      VAR,\n      {\n        className: 'variable',\n        begin: /\\$[A-z]/, end: /[^A-z]/\n      }\n    ]\n  };\n  var APOS_STRING = {\n    className: 'string',\n    begin: /'/, end: /'/\n  };\n\n  return {\n    aliases: ['ps'],\n    lexemes: /-?[A-z\\.\\-]+/,\n    case_insensitive: true,\n    keywords: {\n      keyword: 'if else foreach return function do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch',\n      literal: '$null $true $false',\n      built_in: 'Add-Content Add-History Add-Member Add-PSSnapin Clear-Content Clear-Item Clear-Item Property Clear-Variable Compare-Object ConvertFrom-SecureString Convert-Path ConvertTo-Html ConvertTo-SecureString Copy-Item Copy-ItemProperty Export-Alias Export-Clixml Export-Console Export-Csv ForEach-Object Format-Custom Format-List Format-Table Format-Wide Get-Acl Get-Alias Get-AuthenticodeSignature Get-ChildItem Get-Command Get-Content Get-Credential Get-Culture Get-Date Get-EventLog Get-ExecutionPolicy Get-Help Get-History Get-Host Get-Item Get-ItemProperty Get-Location Get-Member Get-PfxCertificate Get-Process Get-PSDrive Get-PSProvider Get-PSSnapin Get-Service Get-TraceSource Get-UICulture Get-Unique Get-Variable Get-WmiObject Group-Object Import-Alias Import-Clixml Import-Csv Invoke-Expression Invoke-History Invoke-Item Join-Path Measure-Command Measure-Object Move-Item Move-ItemProperty New-Alias New-Item New-ItemProperty New-Object New-PSDrive New-Service New-TimeSpan New-Variable Out-Default Out-File Out-Host Out-Null Out-Printer Out-String Pop-Location Push-Location Read-Host Remove-Item Remove-ItemProperty Remove-PSDrive Remove-PSSnapin Remove-Variable Rename-Item Rename-ItemProperty Resolve-Path Restart-Service Resume-Service Select-Object Select-String Set-Acl Set-Alias Set-AuthenticodeSignature Set-Content Set-Date Set-ExecutionPolicy Set-Item Set-ItemProperty Set-Location Set-PSDebug Set-Service Set-TraceSource Set-Variable Sort-Object Split-Path Start-Service Start-Sleep Start-Transcript Stop-Process Stop-Service Stop-Transcript Suspend-Service Tee-Object Test-Path Trace-Command Update-FormatData Update-TypeData Where-Object Write-Debug Write-Error Write-Host Write-Output Write-Progress Write-Verbose Write-Warning',\n      operator: '-ne -eq -lt -gt -ge -le -not -like -notlike -match -notmatch -contains -notcontains -in -notin -replace'\n    },\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      hljs.NUMBER_MODE,\n      QUOTE_STRING,\n      APOS_STRING,\n      VAR\n    ]\n  };\n});\n\nhljs.registerLanguage('processing', function(hljs) {\n  return {\n    keywords: {\n      keyword: 'BufferedReader PVector PFont PImage PGraphics HashMap boolean byte char color ' +\n        'double float int long String Array FloatDict FloatList IntDict IntList JSONArray JSONObject ' +\n        'Object StringDict StringList Table TableRow XML ' +\n        // Java keywords\n        'false synchronized int abstract float private char boolean static null if const ' +\n        'for true while long throw strictfp finally protected import native final return void ' +\n        'enum else break transient new catch instanceof byte super volatile case assert short ' +\n        'package default double public try this switch continue throws protected public private',\n      constant: 'P2D P3D HALF_PI PI QUARTER_PI TAU TWO_PI',\n      variable: 'displayHeight displayWidth mouseY mouseX mousePressed pmouseX pmouseY key ' +\n        'keyCode pixels focused frameCount frameRate height width',\n      title: 'setup draw',\n      built_in: 'size createGraphics beginDraw createShape loadShape PShape arc ellipse line point ' +\n        'quad rect triangle bezier bezierDetail bezierPoint bezierTangent curve curveDetail curvePoint ' +\n        'curveTangent curveTightness shape shapeMode beginContour beginShape bezierVertex curveVertex ' +\n        'endContour endShape quadraticVertex vertex ellipseMode noSmooth rectMode smooth strokeCap ' +\n        'strokeJoin strokeWeight mouseClicked mouseDragged mouseMoved mousePressed mouseReleased ' +\n        'mouseWheel keyPressed keyPressedkeyReleased keyTyped print println save saveFrame day hour ' +\n        'millis minute month second year background clear colorMode fill noFill noStroke stroke alpha ' +\n        'blue brightness color green hue lerpColor red saturation modelX modelY modelZ screenX screenY ' +\n        'screenZ ambient emissive shininess specular add createImage beginCamera camera endCamera frustum ' +\n        'ortho perspective printCamera printProjection cursor frameRate noCursor exit loop noLoop popStyle ' +\n        'pushStyle redraw binary boolean byte char float hex int str unbinary unhex join match matchAll nf ' +\n        'nfc nfp nfs split splitTokens trim append arrayCopy concat expand reverse shorten sort splice subset ' +\n        'box sphere sphereDetail createInput createReader loadBytes loadJSONArray loadJSONObject loadStrings ' +\n        'loadTable loadXML open parseXML saveTable selectFolder selectInput beginRaw beginRecord createOutput ' +\n        'createWriter endRaw endRecord PrintWritersaveBytes saveJSONArray saveJSONObject saveStream saveStrings ' +\n        'saveXML selectOutput popMatrix printMatrix pushMatrix resetMatrix rotate rotateX rotateY rotateZ scale ' +\n        'shearX shearY translate ambientLight directionalLight lightFalloff lights lightSpecular noLights normal ' +\n        'pointLight spotLight image imageMode loadImage noTint requestImage tint texture textureMode textureWrap ' +\n        'blend copy filter get loadPixels set updatePixels blendMode loadShader PShaderresetShader shader createFont ' +\n        'loadFont text textFont textAlign textLeading textMode textSize textWidth textAscent textDescent abs ceil ' +\n        'constrain dist exp floor lerp log mag map max min norm pow round sq sqrt acos asin atan atan2 cos degrees ' +\n        'radians sin tan noise noiseDetail noiseSeed random randomGaussian randomSeed'\n    },\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('profile', function(hljs) {\n  return {\n    contains: [\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'built_in',\n        begin: '{', end: '}$',\n        excludeBegin: true, excludeEnd: true,\n        contains: [hljs.APOS_STRING_MODE, hljs.QUOTE_STRING_MODE],\n        relevance: 0\n      },\n      {\n        className: 'filename',\n        begin: '[a-zA-Z_][\\\\da-zA-Z_]+\\\\.[\\\\da-zA-Z_]{1,3}', end: ':',\n        excludeEnd: true\n      },\n      {\n        className: 'header',\n        begin: '(ncalls|tottime|cumtime)', end: '$',\n        keywords: 'ncalls tottime|10 cumtime|10 filename',\n        relevance: 10\n      },\n      {\n        className: 'summary',\n        begin: 'function calls', end: '$',\n        contains: [hljs.C_NUMBER_MODE],\n        relevance: 10\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'function',\n        begin: '\\\\(', end: '\\\\)$',\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE\n        ],\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('prolog', function(hljs) {\n\n  var ATOM = {\n\n    className: 'atom',\n    begin: /[a-z][A-Za-z0-9_]*/,\n    relevance: 0\n  };\n\n  var VAR = {\n\n    className: 'name',\n    variants: [\n      {begin: /[A-Z][a-zA-Z0-9_]*/},\n      {begin: /_[A-Za-z0-9_]*/},\n    ],\n    relevance: 0\n  };\n\n  var PARENTED = {\n\n    begin: /\\(/,\n    end: /\\)/,\n    relevance: 0\n  };\n\n  var LIST = {\n\n    begin: /\\[/,\n    end: /\\]/\n  };\n\n  var LINE_COMMENT = {\n\n    className: 'comment',\n    begin: /%/, end: /$/,\n    contains: [hljs.PHRASAL_WORDS_MODE]\n  };\n\n  var BACKTICK_STRING = {\n\n    className: 'string',\n    begin: /`/, end: /`/,\n    contains: [hljs.BACKSLASH_ESCAPE]\n  };\n\n  var CHAR_CODE = {\n\n    className: 'string', // 0'a etc.\n    begin: /0\\'(\\\\\\'|.)/\n  };\n\n  var SPACE_CODE = {\n\n    className: 'string',\n    begin: /0\\'\\\\s/ // 0'\\s\n  };\n\n  var PRED_OP = { // relevance booster\n    begin: /:-/\n  };\n\n  var inner = [\n\n    ATOM,\n    VAR,\n    PARENTED,\n    PRED_OP,\n    LIST,\n    LINE_COMMENT,\n    hljs.C_BLOCK_COMMENT_MODE,\n    hljs.QUOTE_STRING_MODE,\n    hljs.APOS_STRING_MODE,\n    BACKTICK_STRING,\n    CHAR_CODE,\n    SPACE_CODE,\n    hljs.C_NUMBER_MODE\n  ];\n\n  PARENTED.contains = inner;\n  LIST.contains = inner;\n\n  return {\n    contains: inner.concat([\n      {begin: /\\.$/} // relevance booster\n    ])\n  };\n});\n\nhljs.registerLanguage('protobuf', function(hljs) {\n  return {\n    keywords: {\n      keyword: 'package import option optional required repeated group',\n      built_in: 'double float int32 int64 uint32 uint64 sint32 sint64 ' +\n        'fixed32 fixed64 sfixed32 sfixed64 bool string bytes',\n      literal: 'true false'\n    },\n    contains: [\n      hljs.QUOTE_STRING_MODE,\n      hljs.NUMBER_MODE,\n      hljs.C_LINE_COMMENT_MODE,\n      {\n        className: 'class',\n        beginKeywords: 'message enum service', end: /\\{/,\n        illegal: /\\n/,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {\n            starts: {endsWithParent: true, excludeEnd: true} // hack: eating everything after the first title\n          })\n        ]\n      },\n      {\n        className: 'function',\n        beginKeywords: 'rpc',\n        end: /;/, excludeEnd: true,\n        keywords: 'rpc returns'\n      },\n      {\n        className: 'constant',\n        begin: /^\\s*[A-Z_]+/,\n        end: /\\s*=/, excludeEnd: true\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('puppet', function(hljs) {\n\n  var PUPPET_KEYWORDS = {\n    keyword:\n    /* language keywords */\n      'and case default else elsif false if in import enherits node or true undef unless main settings $string ',\n    literal:\n    /* metaparameters */\n      'alias audit before loglevel noop require subscribe tag ' +\n    /* normal attributes */\n      'owner ensure group mode name|0 changes context force incl lens load_path onlyif provider returns root show_diff type_check ' +\n      'en_address ip_address realname command environment hour monute month monthday special target weekday '+\n      'creates cwd ogoutput refresh refreshonly tries try_sleep umask backup checksum content ctime force ignore ' +\n      'links mtime purge recurse recurselimit replace selinux_ignore_defaults selrange selrole seltype seluser source ' +\n      'souirce_permissions sourceselect validate_cmd validate_replacement allowdupe attribute_membership auth_membership forcelocal gid '+\n      'ia_load_module members system host_aliases ip allowed_trunk_vlans description device_url duplex encapsulation etherchannel ' +\n      'native_vlan speed principals allow_root auth_class auth_type authenticate_user k_of_n mechanisms rule session_owner shared options ' +\n      'device fstype enable hasrestart directory present absent link atboot blockdevice device dump pass remounts poller_tag use ' +\n      'message withpath adminfile allow_virtual allowcdrom category configfiles flavor install_options instance package_settings platform ' +\n      'responsefile status uninstall_options vendor unless_system_user unless_uid binary control flags hasstatus manifest pattern restart running ' +\n      'start stop allowdupe auths expiry gid groups home iterations key_membership keys managehome membership password password_max_age ' +\n      'password_min_age profile_membership profiles project purge_ssh_keys role_membership roles salt shell uid baseurl cost descr enabled ' +\n      'enablegroups exclude failovermethod gpgcheck gpgkey http_caching include includepkgs keepalive metadata_expire metalink mirrorlist ' +\n      'priority protect proxy proxy_password proxy_username repo_gpgcheck s3_enabled skip_if_unavailable sslcacert sslclientcert sslclientkey ' +\n      'sslverify mounted',\n    built_in:\n    /* core facts */\n      'architecture augeasversion blockdevices boardmanufacturer boardproductname boardserialnumber cfkey dhcp_servers ' +\n      'domain ec2_ ec2_userdata facterversion filesystems ldom fqdn gid hardwareisa hardwaremodel hostname id|0 interfaces '+\n      'ipaddress ipaddress_ ipaddress6 ipaddress6_ iphostnumber is_virtual kernel kernelmajversion kernelrelease kernelversion ' +\n      'kernelrelease kernelversion lsbdistcodename lsbdistdescription lsbdistid lsbdistrelease lsbmajdistrelease lsbminordistrelease ' +\n      'lsbrelease macaddress macaddress_ macosx_buildversion macosx_productname macosx_productversion macosx_productverson_major ' +\n      'macosx_productversion_minor manufacturer memoryfree memorysize netmask metmask_ network_ operatingsystem operatingsystemmajrelease '+\n      'operatingsystemrelease osfamily partitions path physicalprocessorcount processor processorcount productname ps puppetversion '+\n      'rubysitedir rubyversion selinux selinux_config_mode selinux_config_policy selinux_current_mode selinux_current_mode selinux_enforced '+\n      'selinux_policyversion serialnumber sp_ sshdsakey sshecdsakey sshrsakey swapencrypted swapfree swapsize timezone type uniqueid uptime '+\n      'uptime_days uptime_hours uptime_seconds uuid virtual vlans xendomains zfs_version zonenae zones zpool_version'\n  };\n\n  var COMMENT = hljs.COMMENT('#', '$');\n\n  var IDENT_RE = '([A-Za-z_]|::)(\\\\w|::)*';\n\n  var TITLE = hljs.inherit(hljs.TITLE_MODE, {begin: IDENT_RE});\n\n  var VARIABLE = {className: 'variable', begin: '\\\\$' + IDENT_RE};\n\n  var STRING = {\n    className: 'string',\n    contains: [hljs.BACKSLASH_ESCAPE, VARIABLE],\n    variants: [\n      {begin: /'/, end: /'/},\n      {begin: /\"/, end: /\"/}\n    ]\n  };\n\n  return {\n    aliases: ['pp'],\n    contains: [\n      COMMENT,\n      VARIABLE,\n      STRING,\n      {\n        beginKeywords: 'class', end: '\\\\{|;',\n        illegal: /=/,\n        contains: [TITLE, COMMENT]\n      },\n      {\n        beginKeywords: 'define', end: /\\{/,\n        contains: [\n          {\n            className: 'title', begin: hljs.IDENT_RE, endsParent: true\n          }\n        ]\n      },\n      {\n        begin: hljs.IDENT_RE + '\\\\s+\\\\{', returnBegin: true,\n        end: /\\S/,\n        contains: [\n          {\n            className: 'name',\n            begin: hljs.IDENT_RE\n          },\n          {\n            begin: /\\{/, end: /\\}/,\n            keywords: PUPPET_KEYWORDS,\n            relevance: 0,\n            contains: [\n              STRING,\n              COMMENT,\n              {\n                begin:'[a-zA-Z_]+\\\\s*=>'\n              },\n              {\n                className: 'number',\n                begin: '(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b',\n                relevance: 0\n              },\n              VARIABLE\n            ]\n          }\n        ],\n        relevance: 0\n      }\n    ]\n  }\n});\n\nhljs.registerLanguage('python', function(hljs) {\n  var PROMPT = {\n    className: 'prompt',  begin: /^(>>>|\\.\\.\\.) /\n  };\n  var STRING = {\n    className: 'string',\n    contains: [hljs.BACKSLASH_ESCAPE],\n    variants: [\n      {\n        begin: /(u|b)?r?'''/, end: /'''/,\n        contains: [PROMPT],\n        relevance: 10\n      },\n      {\n        begin: /(u|b)?r?\"\"\"/, end: /\"\"\"/,\n        contains: [PROMPT],\n        relevance: 10\n      },\n      {\n        begin: /(u|r|ur)'/, end: /'/,\n        relevance: 10\n      },\n      {\n        begin: /(u|r|ur)\"/, end: /\"/,\n        relevance: 10\n      },\n      {\n        begin: /(b|br)'/, end: /'/\n      },\n      {\n        begin: /(b|br)\"/, end: /\"/\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE\n    ]\n  };\n  var NUMBER = {\n    className: 'number', relevance: 0,\n    variants: [\n      {begin: hljs.BINARY_NUMBER_RE + '[lLjJ]?'},\n      {begin: '\\\\b(0o[0-7]+)[lLjJ]?'},\n      {begin: hljs.C_NUMBER_RE + '[lLjJ]?'}\n    ]\n  };\n  var PARAMS = {\n    className: 'params',\n    begin: /\\(/, end: /\\)/,\n    contains: ['self', PROMPT, NUMBER, STRING]\n  };\n  return {\n    aliases: ['py', 'gyp'],\n    keywords: {\n      keyword:\n        'and elif is global as in if from raise for except finally print import pass return ' +\n        'exec else break not with class assert yield try while continue del or def lambda ' +\n        'async await nonlocal|10 None True False',\n      built_in:\n        'Ellipsis NotImplemented'\n    },\n    illegal: /(<\\/|->|\\?)/,\n    contains: [\n      PROMPT,\n      NUMBER,\n      STRING,\n      hljs.HASH_COMMENT_MODE,\n      {\n        variants: [\n          {className: 'function', beginKeywords: 'def', relevance: 10},\n          {className: 'class', beginKeywords: 'class'}\n        ],\n        end: /:/,\n        illegal: /[${=;\\n,]/,\n        contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS]\n      },\n      {\n        className: 'decorator',\n        begin: /^[\\t ]*@/, end: /$/\n      },\n      {\n        begin: /\\b(print|exec)\\(/ // don’t highlight keywords-turned-functions in Python 3\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('q', function(hljs) {\n  var Q_KEYWORDS = {\n  keyword:\n    'do while select delete by update from',\n  constant:\n    '0b 1b',\n  built_in:\n    'neg not null string reciprocal floor ceiling signum mod xbar xlog and or each scan over prior mmu lsq inv md5 ltime gtime count first var dev med cov cor all any rand sums prds mins maxs fills deltas ratios avgs differ prev next rank reverse iasc idesc asc desc msum mcount mavg mdev xrank mmin mmax xprev rotate distinct group where flip type key til get value attr cut set upsert raze union inter except cross sv vs sublist enlist read0 read1 hopen hclose hdel hsym hcount peach system ltrim rtrim trim lower upper ssr view tables views cols xcols keys xkey xcol xasc xdesc fkeys meta lj aj aj0 ij pj asof uj ww wj wj1 fby xgroup ungroup ej save load rsave rload show csv parse eval min max avg wavg wsum sin cos tan sum',\n  typename:\n    '`float `double int `timestamp `timespan `datetime `time `boolean `symbol `char `byte `short `long `real `month `date `minute `second `guid'\n  };\n  return {\n  aliases:['k', 'kdb'],\n  keywords: Q_KEYWORDS,\n  lexemes: /\\b(`?)[A-Za-z0-9_]+\\b/,\n  contains: [\n  hljs.C_LINE_COMMENT_MODE,\n    hljs.QUOTE_STRING_MODE,\n    hljs.C_NUMBER_MODE\n     ]\n  };\n});\n\nhljs.registerLanguage('r', function(hljs) {\n  var IDENT_RE = '([a-zA-Z]|\\\\.[a-zA-Z.])[a-zA-Z0-9._]*';\n\n  return {\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      {\n        begin: IDENT_RE,\n        lexemes: IDENT_RE,\n        keywords: {\n          keyword:\n            'function if in break next repeat else for return switch while try tryCatch ' +\n            'stop warning require library attach detach source setMethod setGeneric ' +\n            'setGroupGeneric setClass ...',\n          literal:\n            'NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 ' +\n            'NA_complex_|10'\n        },\n        relevance: 0\n      },\n      {\n        // hex value\n        className: 'number',\n        begin: \"0[xX][0-9a-fA-F]+[Li]?\\\\b\",\n        relevance: 0\n      },\n      {\n        // explicit integer\n        className: 'number',\n        begin: \"\\\\d+(?:[eE][+\\\\-]?\\\\d*)?L\\\\b\",\n        relevance: 0\n      },\n      {\n        // number with trailing decimal\n        className: 'number',\n        begin: \"\\\\d+\\\\.(?!\\\\d)(?:i\\\\b)?\",\n        relevance: 0\n      },\n      {\n        // number\n        className: 'number',\n        begin: \"\\\\d+(?:\\\\.\\\\d*)?(?:[eE][+\\\\-]?\\\\d*)?i?\\\\b\",\n        relevance: 0\n      },\n      {\n        // number with leading decimal\n        className: 'number',\n        begin: \"\\\\.\\\\d+(?:[eE][+\\\\-]?\\\\d*)?i?\\\\b\",\n        relevance: 0\n      },\n\n      {\n        // escaped identifier\n        begin: '`',\n        end: '`',\n        relevance: 0\n      },\n\n      {\n        className: 'string',\n        contains: [hljs.BACKSLASH_ESCAPE],\n        variants: [\n          {begin: '\"', end: '\"'},\n          {begin: \"'\", end: \"'\"}\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('rib', function(hljs) {\n  return {\n    keywords:\n      'ArchiveRecord AreaLightSource Atmosphere Attribute AttributeBegin AttributeEnd Basis ' +\n      'Begin Blobby Bound Clipping ClippingPlane Color ColorSamples ConcatTransform Cone ' +\n      'CoordinateSystem CoordSysTransform CropWindow Curves Cylinder DepthOfField Detail ' +\n      'DetailRange Disk Displacement Display End ErrorHandler Exposure Exterior Format ' +\n      'FrameAspectRatio FrameBegin FrameEnd GeneralPolygon GeometricApproximation Geometry ' +\n      'Hider Hyperboloid Identity Illuminate Imager Interior LightSource ' +\n      'MakeCubeFaceEnvironment MakeLatLongEnvironment MakeShadow MakeTexture Matte ' +\n      'MotionBegin MotionEnd NuPatch ObjectBegin ObjectEnd ObjectInstance Opacity Option ' +\n      'Orientation Paraboloid Patch PatchMesh Perspective PixelFilter PixelSamples ' +\n      'PixelVariance Points PointsGeneralPolygons PointsPolygons Polygon Procedural Projection ' +\n      'Quantize ReadArchive RelativeDetail ReverseOrientation Rotate Scale ScreenWindow ' +\n      'ShadingInterpolation ShadingRate Shutter Sides Skew SolidBegin SolidEnd Sphere ' +\n      'SubdivisionMesh Surface TextureCoordinates Torus Transform TransformBegin TransformEnd ' +\n      'TransformPoints Translate TrimCurve WorldBegin WorldEnd',\n    illegal: '</',\n    contains: [\n      hljs.HASH_COMMENT_MODE,\n      hljs.C_NUMBER_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('roboconf', function(hljs) {\n  var IDENTIFIER = '[a-zA-Z-_][^\\n{\\r\\n]+\\\\{';\n\n  return {\n    aliases: ['graph', 'instances'],\n    case_insensitive: true,\n    keywords: 'import',\n    contains: [\n      // Facet sections\n      {\n        className: 'facet',\n        begin: '^facet ' + IDENTIFIER,\n        end: '}',\n        keywords: 'facet installer exports children extends',\n        contains: [\n          hljs.HASH_COMMENT_MODE\n        ]\n      },\n\n      // Instance sections\n      {\n        className: 'instance-of',\n        begin: '^instance of ' + IDENTIFIER,\n        end: '}',\n        keywords: 'name count channels instance-data instance-state instance of',\n        contains: [\n          // Instance overridden properties\n          {\n            className: 'keyword',\n            begin: '[a-zA-Z-_]+( |\\t)*:'\n          },\n          hljs.HASH_COMMENT_MODE\n        ]\n      },\n\n      // Component sections\n      {\n        className: 'component',\n        begin: '^' + IDENTIFIER,\n        end: '}',\n        lexemes: '\\\\(?[a-zA-Z]+\\\\)?',\n        keywords: 'installer exports children extends imports facets alias (optional)',\n        contains: [\n          // Imported component variables\n          {\n            className: 'string',\n            begin: '\\\\.[a-zA-Z-_]+',\n            end: '\\\\s|,|;',\n            excludeEnd: true\n          },\n          hljs.HASH_COMMENT_MODE\n        ]\n      },\n\n      // Comments\n      hljs.HASH_COMMENT_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('rsl', function(hljs) {\n  return {\n    keywords: {\n      keyword:\n        'float color point normal vector matrix while for if do return else break extern continue',\n      built_in:\n        'abs acos ambient area asin atan atmosphere attribute calculatenormal ceil cellnoise ' +\n        'clamp comp concat cos degrees depth Deriv diffuse distance Du Dv environment exp ' +\n        'faceforward filterstep floor format fresnel incident length lightsource log match ' +\n        'max min mod noise normalize ntransform opposite option phong pnoise pow printf ' +\n        'ptlined radians random reflect refract renderinfo round setcomp setxcomp setycomp ' +\n        'setzcomp shadow sign sin smoothstep specular specularbrdf spline sqrt step tan ' +\n        'texture textureinfo trace transform vtransform xcomp ycomp zcomp'\n    },\n    illegal: '</',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'preprocessor',\n        begin: '#', end: '$'\n      },\n      {\n        className: 'shader',\n        beginKeywords: 'surface displacement light volume imager', end: '\\\\('\n      },\n      {\n        className: 'shading',\n        beginKeywords: 'illuminate illuminance gather', end: '\\\\('\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('ruleslanguage', function(hljs) {\n  return {\n    keywords: {\n       keyword: 'BILL_PERIOD BILL_START BILL_STOP RS_EFFECTIVE_START RS_EFFECTIVE_STOP RS_JURIS_CODE RS_OPCO_CODE ' +\n         'INTDADDATTRIBUTE|5 INTDADDVMSG|5 INTDBLOCKOP|5 INTDBLOCKOPNA|5 INTDCLOSE|5 INTDCOUNT|5 ' +\n         'INTDCOUNTSTATUSCODE|5 INTDCREATEMASK|5 INTDCREATEDAYMASK|5 INTDCREATEFACTORMASK|5 ' +\n         'INTDCREATEHANDLE|5 INTDCREATEOVERRIDEDAYMASK|5 INTDCREATEOVERRIDEMASK|5 ' +\n         'INTDCREATESTATUSCODEMASK|5 INTDCREATETOUPERIOD|5 INTDDELETE|5 INTDDIPTEST|5 INTDEXPORT|5 ' +\n         'INTDGETERRORCODE|5 INTDGETERRORMESSAGE|5 INTDISEQUAL|5 INTDJOIN|5 INTDLOAD|5 INTDLOADACTUALCUT|5 ' +\n         'INTDLOADDATES|5 INTDLOADHIST|5 INTDLOADLIST|5 INTDLOADLISTDATES|5 INTDLOADLISTENERGY|5 ' +\n         'INTDLOADLISTHIST|5 INTDLOADRELATEDCHANNEL|5 INTDLOADSP|5 INTDLOADSTAGING|5 INTDLOADUOM|5 ' +\n         'INTDLOADUOMDATES|5 INTDLOADUOMHIST|5 INTDLOADVERSION|5 INTDOPEN|5 INTDREADFIRST|5 INTDREADNEXT|5 ' +\n         'INTDRECCOUNT|5 INTDRELEASE|5 INTDREPLACE|5 INTDROLLAVG|5 INTDROLLPEAK|5 INTDSCALAROP|5 INTDSCALE|5 ' +\n         'INTDSETATTRIBUTE|5 INTDSETDSTPARTICIPANT|5 INTDSETSTRING|5 INTDSETVALUE|5 INTDSETVALUESTATUS|5 ' +\n         'INTDSHIFTSTARTTIME|5 INTDSMOOTH|5 INTDSORT|5 INTDSPIKETEST|5 INTDSUBSET|5 INTDTOU|5 ' +\n         'INTDTOURELEASE|5 INTDTOUVALUE|5 INTDUPDATESTATS|5 INTDVALUE|5 STDEV INTDDELETEEX|5 ' +\n         'INTDLOADEXACTUAL|5 INTDLOADEXCUT|5 INTDLOADEXDATES|5 INTDLOADEX|5 INTDLOADEXRELATEDCHANNEL|5 ' +\n         'INTDSAVEEX|5 MVLOAD|5 MVLOADACCT|5 MVLOADACCTDATES|5 MVLOADACCTHIST|5 MVLOADDATES|5 MVLOADHIST|5 ' +\n         'MVLOADLIST|5 MVLOADLISTDATES|5 MVLOADLISTHIST|5 IF FOR NEXT DONE SELECT END CALL ABORT CLEAR CHANNEL FACTOR LIST NUMBER ' +\n         'OVERRIDE SET WEEK DISTRIBUTIONNODE ELSE WHEN THEN OTHERWISE IENUM CSV INCLUDE LEAVE RIDER SAVE DELETE ' +\n         'NOVALUE SECTION WARN SAVE_UPDATE DETERMINANT LABEL REPORT REVENUE EACH ' +\n         'IN FROM TOTAL CHARGE BLOCK AND OR CSV_FILE RATE_CODE AUXILIARY_DEMAND ' +\n         'UIDACCOUNT RS BILL_PERIOD_SELECT HOURS_PER_MONTH INTD_ERROR_STOP SEASON_SCHEDULE_NAME ' +\n         'ACCOUNTFACTOR ARRAYUPPERBOUND CALLSTOREDPROC GETADOCONNECTION GETCONNECT GETDATASOURCE ' +\n         'GETQUALIFIER GETUSERID HASVALUE LISTCOUNT LISTOP LISTUPDATE LISTVALUE PRORATEFACTOR RSPRORATE ' +\n         'SETBINPATH SETDBMONITOR WQ_OPEN BILLINGHOURS DATE DATEFROMFLOAT DATETIMEFROMSTRING ' +\n         'DATETIMETOSTRING DATETOFLOAT DAY DAYDIFF DAYNAME DBDATETIME HOUR MINUTE MONTH MONTHDIFF ' +\n         'MONTHHOURS MONTHNAME ROUNDDATE SAMEWEEKDAYLASTYEAR SECOND WEEKDAY WEEKDIFF YEAR YEARDAY ' +\n         'YEARSTR COMPSUM HISTCOUNT HISTMAX HISTMIN HISTMINNZ HISTVALUE MAXNRANGE MAXRANGE MINRANGE ' +\n         'COMPIKVA COMPKVA COMPKVARFROMKQKW COMPLF IDATTR FLAG LF2KW LF2KWH MAXKW POWERFACTOR ' +\n         'READING2USAGE AVGSEASON MAXSEASON MONTHLYMERGE SEASONVALUE SUMSEASON ACCTREADDATES ' +\n         'ACCTTABLELOAD CONFIGADD CONFIGGET CREATEOBJECT CREATEREPORT EMAILCLIENT EXPBLKMDMUSAGE ' +\n         'EXPMDMUSAGE EXPORT_USAGE FACTORINEFFECT GETUSERSPECIFIEDSTOP INEFFECT ISHOLIDAY RUNRATE ' +\n         'SAVE_PROFILE SETREPORTTITLE USEREXIT WATFORRUNRATE TO TABLE ACOS ASIN ATAN ATAN2 BITAND CEIL ' +\n         'COS COSECANT COSH COTANGENT DIVQUOT DIVREM EXP FABS FLOOR FMOD FREPM FREXPN LOG LOG10 MAX MAXN ' +\n         'MIN MINNZ MODF POW ROUND ROUND2VALUE ROUNDINT SECANT SIN SINH SQROOT TAN TANH FLOAT2STRING ' +\n         'FLOAT2STRINGNC INSTR LEFT LEN LTRIM MID RIGHT RTRIM STRING STRINGNC TOLOWER TOUPPER TRIM ' +\n         'NUMDAYS READ_DATE STAGING',\n       built_in: 'IDENTIFIER OPTIONS XML_ELEMENT XML_OP XML_ELEMENT_OF DOMDOCCREATE DOMDOCLOADFILE DOMDOCLOADXML ' +\n         'DOMDOCSAVEFILE DOMDOCGETROOT DOMDOCADDPI DOMNODEGETNAME DOMNODEGETTYPE DOMNODEGETVALUE DOMNODEGETCHILDCT ' +\n         'DOMNODEGETFIRSTCHILD DOMNODEGETSIBLING DOMNODECREATECHILDELEMENT DOMNODESETATTRIBUTE ' +\n         'DOMNODEGETCHILDELEMENTCT DOMNODEGETFIRSTCHILDELEMENT DOMNODEGETSIBLINGELEMENT DOMNODEGETATTRIBUTECT ' +\n         'DOMNODEGETATTRIBUTEI DOMNODEGETATTRIBUTEBYNAME DOMNODEGETBYNAME'\n    },\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'array',\n        variants: [\n          {begin: '#\\\\s+[a-zA-Z\\\\ \\\\.]*', relevance: 0}, // looks like #-comment\n          {begin: '#[a-zA-Z\\\\ \\\\.]+'}\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('rust', function(hljs) {\n  var NUM_SUFFIX = '([uif](8|16|32|64|size))\\?';\n  var BLOCK_COMMENT = hljs.inherit(hljs.C_BLOCK_COMMENT_MODE);\n  BLOCK_COMMENT.contains.push('self');\n  return {\n    aliases: ['rs'],\n    keywords: {\n      keyword:\n        'alignof as be box break const continue crate do else enum extern ' +\n        'false fn for if impl in let loop match mod mut offsetof once priv ' +\n        'proc pub pure ref return self Self sizeof static struct super trait true ' +\n        'type typeof unsafe unsized use virtual while where yield ' +\n        'int i8 i16 i32 i64 ' +\n        'uint u8 u32 u64 ' +\n        'float f32 f64 ' +\n        'str char bool',\n      built_in:\n        // prelude\n        'Copy Send Sized Sync Drop Fn FnMut FnOnce drop Box ToOwned Clone ' +\n        'PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator ' +\n        'Extend IntoIterator DoubleEndedIterator ExactSizeIterator Option ' +\n        'Some None Result Ok Err SliceConcatExt String ToString Vec ' +\n        // macros\n        'assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! ' +\n        'debug_assert! debug_assert_eq! env! panic! file! format! format_args! ' +\n        'include_bin! include_str! line! local_data_key! module_path! ' +\n        'option_env! print! println! select! stringify! try! unimplemented! ' +\n        'unreachable! vec! write! writeln!'\n    },\n    lexemes: hljs.IDENT_RE + '!?',\n    illegal: '</',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      BLOCK_COMMENT,\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),\n      {\n        className: 'string',\n        variants: [\n           { begin: /r(#*)\".*?\"\\1(?!#)/ },\n           { begin: /'\\\\?(x\\w{2}|u\\w{4}|U\\w{8}|.)'/ },\n           { begin: /'[a-zA-Z_][a-zA-Z0-9_]*/ }\n        ]\n      },\n      {\n        className: 'number',\n        variants: [\n          { begin: '\\\\b0b([01_]+)' + NUM_SUFFIX },\n          { begin: '\\\\b0o([0-7_]+)' + NUM_SUFFIX },\n          { begin: '\\\\b0x([A-Fa-f0-9_]+)' + NUM_SUFFIX },\n          { begin: '\\\\b(\\\\d[\\\\d_]*(\\\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)' +\n                   NUM_SUFFIX\n          }\n        ],\n        relevance: 0\n      },\n      {\n        className: 'function',\n        beginKeywords: 'fn', end: '(\\\\(|<)', excludeEnd: true,\n        contains: [hljs.UNDERSCORE_TITLE_MODE]\n      },\n      {\n        className: 'preprocessor',\n        begin: '#\\\\!?\\\\[', end: '\\\\]'\n      },\n      {\n        beginKeywords: 'type', end: '(=|<)',\n        contains: [hljs.UNDERSCORE_TITLE_MODE],\n        illegal: '\\\\S'\n      },\n      {\n        beginKeywords: 'trait enum', end: '{',\n        contains: [\n          hljs.inherit(hljs.UNDERSCORE_TITLE_MODE, {endsParent: true})\n        ],\n        illegal: '[\\\\w\\\\d]'\n      },\n      {\n        begin: hljs.IDENT_RE + '::'\n      },\n      {\n        begin: '->'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('scala', function(hljs) {\n\n  var ANNOTATION = {\n    className: 'annotation', begin: '@[A-Za-z]+'\n  };\n\n  var STRING = {\n    className: 'string',\n    begin: 'u?r?\"\"\"', end: '\"\"\"',\n    relevance: 10\n  };\n\n  var SYMBOL = {\n    className: 'symbol',\n    begin: '\\'\\\\w[\\\\w\\\\d_]*(?!\\')'\n  };\n\n  var TYPE = {\n    className: 'type',\n    begin: '\\\\b[A-Z][A-Za-z0-9_]*',\n    relevance: 0\n  };\n\n  var NAME = {\n    className: 'title',\n    begin: /[^0-9\\n\\t \"'(),.`{}\\[\\]:;][^\\n\\t \"'(),.`{}\\[\\]:;]+|[^0-9\\n\\t \"'(),.`{}\\[\\]:;=]/,\n    relevance: 0\n  };\n\n  var CLASS = {\n    className: 'class',\n    beginKeywords: 'class object trait type',\n    end: /[:={\\[(\\n;]/,\n    contains: [{className: 'keyword', beginKeywords: 'extends with', relevance: 10}, NAME]\n  };\n\n  var METHOD = {\n    className: 'function',\n    beginKeywords: 'def',\n    end: /[:={\\[(\\n;]/,\n    contains: [NAME]\n  };\n\n  return {\n    keywords: {\n      literal: 'true false null',\n      keyword: 'type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit'\n    },\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      STRING,\n      hljs.QUOTE_STRING_MODE,\n      SYMBOL,\n      TYPE,\n      METHOD,\n      CLASS,\n      hljs.C_NUMBER_MODE,\n      ANNOTATION\n    ]\n  };\n});\n\nhljs.registerLanguage('scheme', function(hljs) {\n  var SCHEME_IDENT_RE = '[^\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}\",\\'`;#|\\\\\\\\\\\\s]+';\n  var SCHEME_SIMPLE_NUMBER_RE = '(\\\\-|\\\\+)?\\\\d+([./]\\\\d+)?';\n  var SCHEME_COMPLEX_NUMBER_RE = SCHEME_SIMPLE_NUMBER_RE + '[+\\\\-]' + SCHEME_SIMPLE_NUMBER_RE + 'i';\n  var BUILTINS = {\n    built_in:\n      'case-lambda call/cc class define-class exit-handler field import ' +\n      'inherit init-field interface let*-values let-values let/ec mixin ' +\n      'opt-lambda override protect provide public rename require ' +\n      'require-for-syntax syntax syntax-case syntax-error unit/sig unless ' +\n      'when with-syntax and begin call-with-current-continuation ' +\n      'call-with-input-file call-with-output-file case cond define ' +\n      'define-syntax delay do dynamic-wind else for-each if lambda let let* ' +\n      'let-syntax letrec letrec-syntax map or syntax-rules \\' * + , ,@ - ... / ' +\n      '; < <= = => > >= ` abs acos angle append apply asin assoc assq assv atan ' +\n      'boolean? caar cadr call-with-input-file call-with-output-file ' +\n      'call-with-values car cdddar cddddr cdr ceiling char->integer ' +\n      'char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? ' +\n      'char-downcase char-lower-case? char-numeric? char-ready? char-upcase ' +\n      'char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? ' +\n      'char? close-input-port close-output-port complex? cons cos ' +\n      'current-input-port current-output-port denominator display eof-object? ' +\n      'eq? equal? eqv? eval even? exact->inexact exact? exp expt floor ' +\n      'force gcd imag-part inexact->exact inexact? input-port? integer->char ' +\n      'integer? interaction-environment lcm length list list->string ' +\n      'list->vector list-ref list-tail list? load log magnitude make-polar ' +\n      'make-rectangular make-string make-vector max member memq memv min ' +\n      'modulo negative? newline not null-environment null? number->string ' +\n      'number? numerator odd? open-input-file open-output-file output-port? ' +\n      'pair? peek-char port? positive? procedure? quasiquote quote quotient ' +\n      'rational? rationalize read read-char real-part real? remainder reverse ' +\n      'round scheme-report-environment set! set-car! set-cdr! sin sqrt string ' +\n      'string->list string->number string->symbol string-append string-ci<=? ' +\n      'string-ci<? string-ci=? string-ci>=? string-ci>? string-copy ' +\n      'string-fill! string-length string-ref string-set! string<=? string<? ' +\n      'string=? string>=? string>? string? substring symbol->string symbol? ' +\n      'tan transcript-off transcript-on truncate values vector ' +\n      'vector->list vector-fill! vector-length vector-ref vector-set! ' +\n      'with-input-from-file with-output-to-file write write-char zero?'\n  };\n\n  var SHEBANG = {\n    className: 'shebang',\n    begin: '^#!',\n    end: '$'\n  };\n\n  var LITERAL = {\n    className: 'literal',\n    begin: '(#t|#f|#\\\\\\\\' + SCHEME_IDENT_RE + '|#\\\\\\\\.)'\n  };\n\n  var NUMBER = {\n    className: 'number',\n    variants: [\n      { begin: SCHEME_SIMPLE_NUMBER_RE, relevance: 0 },\n      { begin: SCHEME_COMPLEX_NUMBER_RE, relevance: 0 },\n      { begin: '#b[0-1]+(/[0-1]+)?' },\n      { begin: '#o[0-7]+(/[0-7]+)?' },\n      { begin: '#x[0-9a-f]+(/[0-9a-f]+)?' }\n    ]\n  };\n\n  var STRING = hljs.QUOTE_STRING_MODE;\n\n  var REGULAR_EXPRESSION = {\n    className: 'regexp',\n    begin: '#[pr]x\"',\n    end: '[^\\\\\\\\]\"'\n  };\n\n  var COMMENT_MODES = [\n    hljs.COMMENT(\n      ';',\n      '$',\n      {\n        relevance: 0\n      }\n    ),\n    hljs.COMMENT('#\\\\|', '\\\\|#')\n  ];\n\n  var IDENT = {\n    begin: SCHEME_IDENT_RE,\n    relevance: 0\n  };\n\n  var QUOTED_IDENT = {\n    className: 'variable',\n    begin: '\\'' + SCHEME_IDENT_RE\n  };\n\n  var BODY = {\n    endsWithParent: true,\n    relevance: 0\n  };\n\n  var LIST = {\n    className: 'list',\n    variants: [\n      { begin: '\\\\(', end: '\\\\)' },\n      { begin: '\\\\[', end: '\\\\]' }\n    ],\n    contains: [\n      {\n        className: 'keyword',\n        begin: SCHEME_IDENT_RE,\n        lexemes: SCHEME_IDENT_RE,\n        keywords: BUILTINS\n      },\n      BODY\n    ]\n  };\n\n  BODY.contains = [LITERAL, NUMBER, STRING, IDENT, QUOTED_IDENT, LIST].concat(COMMENT_MODES);\n\n  return {\n    illegal: /\\S/,\n    contains: [SHEBANG, NUMBER, STRING, QUOTED_IDENT, LIST].concat(COMMENT_MODES)\n  };\n});\n\nhljs.registerLanguage('scilab', function(hljs) {\n\n  var COMMON_CONTAINS = [\n    hljs.C_NUMBER_MODE,\n    {\n      className: 'string',\n      begin: '\\'|\\\"', end: '\\'|\\\"',\n      contains: [hljs.BACKSLASH_ESCAPE, {begin: '\\'\\''}]\n    }\n  ];\n\n  return {\n    aliases: ['sci'],\n    keywords: {\n      keyword: 'abort break case clear catch continue do elseif else endfunction end for function'+\n        'global if pause return resume select try then while'+\n        '%f %F %t %T %pi %eps %inf %nan %e %i %z %s',\n      built_in: // Scilab has more than 2000 functions. Just list the most commons\n       'abs and acos asin atan ceil cd chdir clearglobal cosh cos cumprod deff disp error'+\n       'exec execstr exists exp eye gettext floor fprintf fread fsolve imag isdef isempty'+\n       'isinfisnan isvector lasterror length load linspace list listfiles log10 log2 log'+\n       'max min msprintf mclose mopen ones or pathconvert poly printf prod pwd rand real'+\n       'round sinh sin size gsort sprintf sqrt strcat strcmps tring sum system tanh tan'+\n       'type typename warning zeros matrix'\n    },\n    illegal: '(\"|#|/\\\\*|\\\\s+/\\\\w+)',\n    contains: [\n      {\n        className: 'function',\n        beginKeywords: 'function endfunction', end: '$',\n        keywords: 'function endfunction|10',\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE,\n          {\n            className: 'params',\n            begin: '\\\\(', end: '\\\\)'\n          }\n        ]\n      },\n      {\n        className: 'transposed_variable',\n        begin: '[a-zA-Z_][a-zA-Z_0-9]*(\\'+[\\\\.\\']*|[\\\\.\\']+)', end: '',\n        relevance: 0\n      },\n      {\n        className: 'matrix',\n        begin: '\\\\[', end: '\\\\]\\'*[\\\\.\\']*',\n        relevance: 0,\n        contains: COMMON_CONTAINS\n      },\n      hljs.COMMENT('//', '$')\n    ].concat(COMMON_CONTAINS)\n  };\n});\n\nhljs.registerLanguage('scss', function(hljs) {\n  var IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*';\n  var VARIABLE = {\n    className: 'variable',\n    begin: '(\\\\$' + IDENT_RE + ')\\\\b'\n  };\n  var FUNCTION = {\n    className: 'function',\n    begin: IDENT_RE + '\\\\(',\n    returnBegin: true,\n    excludeEnd: true,\n    end: '\\\\('\n  };\n  var HEXCOLOR = {\n    className: 'hexcolor', begin: '#[0-9A-Fa-f]+'\n  };\n  var DEF_INTERNALS = {\n    className: 'attribute',\n    begin: '[A-Z\\\\_\\\\.\\\\-]+', end: ':',\n    excludeEnd: true,\n    illegal: '[^\\\\s]',\n    starts: {\n      className: 'value',\n      endsWithParent: true, excludeEnd: true,\n      contains: [\n        FUNCTION,\n        HEXCOLOR,\n        hljs.CSS_NUMBER_MODE,\n        hljs.QUOTE_STRING_MODE,\n        hljs.APOS_STRING_MODE,\n        hljs.C_BLOCK_COMMENT_MODE,\n        {\n          className: 'important', begin: '!important'\n        }\n      ]\n    }\n  };\n  return {\n    case_insensitive: true,\n    illegal: '[=/|\\']',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      FUNCTION,\n      {\n        className: 'id', begin: '\\\\#[A-Za-z0-9_-]+',\n        relevance: 0\n      },\n      {\n        className: 'class', begin: '\\\\.[A-Za-z0-9_-]+',\n        relevance: 0\n      },\n      {\n        className: 'attr_selector',\n        begin: '\\\\[', end: '\\\\]',\n        illegal: '$'\n      },\n      {\n        className: 'tag', // begin: IDENT_RE, end: '[,|\\\\s]'\n        begin: '\\\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\\\b',\n        relevance: 0\n      },\n      {\n        className: 'pseudo',\n        begin: ':(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)'\n      },\n      {\n        className: 'pseudo',\n        begin: '::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)'\n      },\n      VARIABLE,\n      {\n        className: 'attribute',\n        begin: '\\\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\\\b',\n        illegal: '[^\\\\s]'\n      },\n      {\n        className: 'value',\n        begin: '\\\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\\\b'\n      },\n      {\n        className: 'value',\n        begin: ':', end: ';',\n        contains: [\n          FUNCTION,\n          VARIABLE,\n          HEXCOLOR,\n          hljs.CSS_NUMBER_MODE,\n          hljs.QUOTE_STRING_MODE,\n          hljs.APOS_STRING_MODE,\n          {\n            className: 'important', begin: '!important'\n          }\n        ]\n      },\n      {\n        className: 'at_rule',\n        begin: '@', end: '[{;]',\n        keywords: 'mixin include extend for if else each while charset import debug media page content font-face namespace warn',\n        contains: [\n          FUNCTION,\n          VARIABLE,\n          hljs.QUOTE_STRING_MODE,\n          hljs.APOS_STRING_MODE,\n          HEXCOLOR,\n          hljs.CSS_NUMBER_MODE,\n          {\n            className: 'preprocessor',\n            begin: '\\\\s[A-Za-z0-9_.-]+',\n            relevance: 0\n          }\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('smali', function(hljs) {\n  var smali_instr_low_prio = ['add', 'and', 'cmp', 'cmpg', 'cmpl', 'const', 'div', 'double', 'float', 'goto', 'if', 'int', 'long', 'move', 'mul', 'neg', 'new', 'nop', 'not', 'or', 'rem', 'return', 'shl', 'shr', 'sput', 'sub', 'throw', 'ushr', 'xor'];\n  var smali_instr_high_prio = ['aget', 'aput', 'array', 'check', 'execute', 'fill', 'filled', 'goto/16', 'goto/32', 'iget', 'instance', 'invoke', 'iput', 'monitor', 'packed', 'sget', 'sparse'];\n  var smali_keywords = ['transient', 'constructor', 'abstract', 'final', 'synthetic', 'public', 'private', 'protected', 'static', 'bridge', 'system'];\n  return {\n    aliases: ['smali'],\n    contains: [\n      {\n        className: 'string',\n        begin: '\"', end: '\"',\n        relevance: 0\n      },\n      hljs.COMMENT(\n        '#',\n        '$',\n        {\n          relevance: 0\n        }\n      ),\n      {\n        className: 'keyword',\n        begin: '\\\\s*\\\\.end\\\\s[a-zA-Z0-9]*',\n        relevance: 1\n      },\n      {\n        className: 'keyword',\n        begin: '^[ ]*\\\\.[a-zA-Z]*',\n        relevance: 0\n      },\n      {\n        className: 'keyword',\n        begin: '\\\\s:[a-zA-Z_0-9]*',\n        relevance: 0\n      },\n      {\n        className: 'keyword',\n        begin: '\\\\s('+smali_keywords.join('|')+')',\n        relevance: 1\n      },\n      {\n        className: 'keyword',\n        begin: '\\\\[',\n        relevance: 0\n      },\n      {\n        className: 'instruction',\n        begin: '\\\\s('+smali_instr_low_prio.join('|')+')\\\\s',\n        relevance: 1\n      },\n      {\n        className: 'instruction',\n        begin: '\\\\s('+smali_instr_low_prio.join('|')+')((\\\\-|/)[a-zA-Z0-9]+)+\\\\s',\n        relevance: 10\n      },\n      {\n        className: 'instruction',\n        begin: '\\\\s('+smali_instr_high_prio.join('|')+')((\\\\-|/)[a-zA-Z0-9]+)*\\\\s',\n        relevance: 10\n      },\n      {\n        className: 'class',\n        begin: 'L[^\\(;:\\n]*;',\n        relevance: 0\n      },\n      {\n        className: 'function',\n        begin: '( |->)[^(\\n ;\"]*\\\\(',\n        relevance: 0\n      },\n      {\n        className: 'function',\n        begin: '\\\\)',\n        relevance: 0\n      },\n      {\n        className: 'variable',\n        begin: '[vp][0-9]+',\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('smalltalk', function(hljs) {\n  var VAR_IDENT_RE = '[a-z][a-zA-Z0-9_]*';\n  var CHAR = {\n    className: 'char',\n    begin: '\\\\$.{1}'\n  };\n  var SYMBOL = {\n    className: 'symbol',\n    begin: '#' + hljs.UNDERSCORE_IDENT_RE\n  };\n  return {\n    aliases: ['st'],\n    keywords: 'self super nil true false thisContext', // only 6\n    contains: [\n      hljs.COMMENT('\"', '\"'),\n      hljs.APOS_STRING_MODE,\n      {\n        className: 'class',\n        begin: '\\\\b[A-Z][A-Za-z0-9_]*',\n        relevance: 0\n      },\n      {\n        className: 'method',\n        begin: VAR_IDENT_RE + ':',\n        relevance: 0\n      },\n      hljs.C_NUMBER_MODE,\n      SYMBOL,\n      CHAR,\n      {\n        className: 'localvars',\n        // This looks more complicated than needed to avoid combinatorial\n        // explosion under V8. It effectively means `| var1 var2 ... |` with\n        // whitespace adjacent to `|` being optional.\n        begin: '\\\\|[ ]*' + VAR_IDENT_RE + '([ ]+' + VAR_IDENT_RE + ')*[ ]*\\\\|',\n        returnBegin: true, end: /\\|/,\n        illegal: /\\S/,\n        contains: [{begin: '(\\\\|[ ]*)?' + VAR_IDENT_RE}]\n      },\n      {\n        className: 'array',\n        begin: '\\\\#\\\\(', end: '\\\\)',\n        contains: [\n          hljs.APOS_STRING_MODE,\n          CHAR,\n          hljs.C_NUMBER_MODE,\n          SYMBOL\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('sml', function(hljs) {\n  return {\n    aliases: ['ml'],\n    keywords: {\n      keyword:\n        /* according to Definition of Standard ML 97  */\n        'abstype and andalso as case datatype do else end eqtype ' +\n        'exception fn fun functor handle if in include infix infixr ' +\n        'let local nonfix of op open orelse raise rec sharing sig ' +\n        'signature struct structure then type val with withtype where while',\n      built_in:\n        /* built-in types according to basis library */\n        'array bool char exn int list option order real ref string substring vector unit word',\n      literal:\n        'true false NONE SOME LESS EQUAL GREATER nil'\n    },\n    illegal: /\\/\\/|>>/,\n    lexemes: '[a-z_]\\\\w*!?',\n    contains: [\n      {\n        className: 'literal',\n        begin: '\\\\[(\\\\|\\\\|)?\\\\]|\\\\(\\\\)'\n      },\n      hljs.COMMENT(\n        '\\\\(\\\\*',\n        '\\\\*\\\\)',\n        {\n          contains: ['self']\n        }\n      ),\n      { /* type variable */\n        className: 'symbol',\n        begin: '\\'[A-Za-z_](?!\\')[\\\\w\\']*'\n        /* the grammar is ambiguous on how 'a'b should be interpreted but not the compiler */\n      },\n      { /* polymorphic variant */\n        className: 'tag',\n        begin: '`[A-Z][\\\\w\\']*'\n      },\n      { /* module or constructor */\n        className: 'type',\n        begin: '\\\\b[A-Z][\\\\w\\']*',\n        relevance: 0\n      },\n      { /* don't color identifiers, but safely catch all identifiers with '*/\n        begin: '[a-z_]\\\\w*\\'[\\\\w\\']*'\n      },\n      hljs.inherit(hljs.APOS_STRING_MODE, {className: 'char', relevance: 0}),\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),\n      {\n        className: 'number',\n        begin:\n          '\\\\b(0[xX][a-fA-F0-9_]+[Lln]?|' +\n          '0[oO][0-7_]+[Lln]?|' +\n          '0[bB][01_]+[Lln]?|' +\n          '[0-9][0-9_]*([Lln]|(\\\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)',\n        relevance: 0\n      },\n      {\n        begin: /[-=]>/ // relevance booster\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('sqf', function(hljs) {\n  var allCommands = ['!', '-', '+', '!=', '%', '&&', '*', '/', '=', '==', '>', '>=', '<', '<=', 'or', 'plus', '^', ':', '>>', 'abs', 'accTime', 'acos', 'action', 'actionKeys', 'actionKeysImages', 'actionKeysNames', 'actionKeysNamesArray', 'actionName', 'activateAddons', 'activatedAddons', 'activateKey', 'addAction', 'addBackpack', 'addBackpackCargo', 'addBackpackCargoGlobal', 'addBackpackGlobal', 'addCamShake', 'addCuratorAddons', 'addCuratorCameraArea', 'addCuratorEditableObjects', 'addCuratorEditingArea', 'addCuratorPoints', 'addEditorObject', 'addEventHandler', 'addGoggles', 'addGroupIcon', 'addHandgunItem', 'addHeadgear', 'addItem', 'addItemCargo', 'addItemCargoGlobal', 'addItemPool', 'addItemToBackpack', 'addItemToUniform', 'addItemToVest', 'addLiveStats', 'addMagazine', 'addMagazine array', 'addMagazineAmmoCargo', 'addMagazineCargo', 'addMagazineCargoGlobal', 'addMagazineGlobal', 'addMagazinePool', 'addMagazines', 'addMagazineTurret', 'addMenu', 'addMenuItem', 'addMissionEventHandler', 'addMPEventHandler', 'addMusicEventHandler', 'addPrimaryWeaponItem', 'addPublicVariableEventHandler', 'addRating', 'addResources', 'addScore', 'addScoreSide', 'addSecondaryWeaponItem', 'addSwitchableUnit', 'addTeamMember', 'addToRemainsCollector', 'addUniform', 'addVehicle', 'addVest', 'addWaypoint', 'addWeapon', 'addWeaponCargo', 'addWeaponCargoGlobal', 'addWeaponGlobal', 'addWeaponPool', 'addWeaponTurret', 'agent', 'agents', 'AGLToASL', 'aimedAtTarget', 'aimPos', 'airDensityRTD', 'airportSide', 'AISFinishHeal', 'alive', 'allControls', 'allCurators', 'allDead', 'allDeadMen', 'allDisplays', 'allGroups', 'allMapMarkers', 'allMines', 'allMissionObjects', 'allow3DMode', 'allowCrewInImmobile', 'allowCuratorLogicIgnoreAreas', 'allowDamage', 'allowDammage', 'allowFileOperations', 'allowFleeing', 'allowGetIn', 'allPlayers', 'allSites', 'allTurrets', 'allUnits', 'allUnitsUAV', 'allVariables', 'ammo', 'and', 'animate', 'animateDoor', 'animationPhase', 'animationState', 'append', 'armoryPoints', 'arrayIntersect', 'asin', 'ASLToAGL', 'ASLToATL', 'assert', 'assignAsCargo', 'assignAsCargoIndex', 'assignAsCommander', 'assignAsDriver', 'assignAsGunner', 'assignAsTurret', 'assignCurator', 'assignedCargo', 'assignedCommander', 'assignedDriver', 'assignedGunner', 'assignedItems', 'assignedTarget', 'assignedTeam', 'assignedVehicle', 'assignedVehicleRole', 'assignItem', 'assignTeam', 'assignToAirport', 'atan', 'atan2', 'atg', 'ATLToASL', 'attachedObject', 'attachedObjects', 'attachedTo', 'attachObject', 'attachTo', 'attackEnabled', 'backpack', 'backpackCargo', 'backpackContainer', 'backpackItems', 'backpackMagazines', 'backpackSpaceFor', 'behaviour', 'benchmark', 'binocular', 'blufor', 'boundingBox', 'boundingBoxReal', 'boundingCenter', 'breakOut', 'breakTo', 'briefingName', 'buildingExit', 'buildingPos', 'buttonAction', 'buttonSetAction', 'cadetMode', 'call', 'callExtension', 'camCommand', 'camCommit', 'camCommitPrepared', 'camCommitted', 'camConstuctionSetParams', 'camCreate', 'camDestroy', 'cameraEffect', 'cameraEffectEnableHUD', 'cameraInterest', 'cameraOn', 'cameraView', 'campaignConfigFile', 'camPreload', 'camPreloaded', 'camPrepareBank', 'camPrepareDir', 'camPrepareDive', 'camPrepareFocus', 'camPrepareFov', 'camPrepareFovRange', 'camPreparePos', 'camPrepareRelPos', 'camPrepareTarget', 'camSetBank', 'camSetDir', 'camSetDive', 'camSetFocus', 'camSetFov', 'camSetFovRange', 'camSetPos', 'camSetRelPos', 'camSetTarget', 'camTarget', 'camUseNVG', 'canAdd', 'canAddItemToBackpack', 'canAddItemToUniform', 'canAddItemToVest', 'cancelSimpleTaskDestination', 'canFire', 'canMove', 'canSlingLoad', 'canStand', 'canUnloadInCombat', 'captive', 'captiveNum', 'case', 'catch', 'cbChecked', 'cbSetChecked', 'ceil', 'cheatsEnabled', 'checkAIFeature', 'civilian', 'className', 'clearAllItemsFromBackpack', 'clearBackpackCargo', 'clearBackpackCargoGlobal', 'clearGroupIcons', 'clearItemCargo', 'clearItemCargoGlobal', 'clearItemPool', 'clearMagazineCargo', 'clearMagazineCargoGlobal', 'clearMagazinePool', 'clearOverlay', 'clearRadio', 'clearWeaponCargo', 'clearWeaponCargoGlobal', 'clearWeaponPool', 'closeDialog', 'closeDisplay', 'closeOverlay', 'collapseObjectTree', 'combatMode', 'commandArtilleryFire', 'commandChat', 'commander', 'commandFire', 'commandFollow', 'commandFSM', 'commandGetOut', 'commandingMenu', 'commandMove', 'commandRadio', 'commandStop', 'commandTarget', 'commandWatch', 'comment', 'commitOverlay', 'compile', 'compileFinal', 'completedFSM', 'composeText', 'configClasses', 'configFile', 'configHierarchy', 'configName', 'configProperties', 'configSourceMod', 'configSourceModList', 'connectTerminalToUAV', 'controlNull', 'controlsGroupCtrl', 'copyFromClipboard', 'copyToClipboard', 'copyWaypoints', 'cos', 'count', 'countEnemy', 'countFriendly', 'countSide', 'countType', 'countUnknown', 'createAgent', 'createCenter', 'createDialog', 'createDiaryLink', 'createDiaryRecord', 'createDiarySubject', 'createDisplay', 'createGearDialog', 'createGroup', 'createGuardedPoint', 'createLocation', 'createMarker', 'createMarkerLocal', 'createMenu', 'createMine', 'createMissionDisplay', 'createSimpleTask', 'createSite', 'createSoundSource', 'createTask', 'createTeam', 'createTrigger', 'createUnit', 'createUnit array', 'createVehicle', 'createVehicle array', 'createVehicleCrew', 'createVehicleLocal', 'crew', 'ctrlActivate', 'ctrlAddEventHandler', 'ctrlAutoScrollDelay', 'ctrlAutoScrollRewind', 'ctrlAutoScrollSpeed', 'ctrlChecked', 'ctrlClassName', 'ctrlCommit', 'ctrlCommitted', 'ctrlCreate', 'ctrlDelete', 'ctrlEnable', 'ctrlEnabled', 'ctrlFade', 'ctrlHTMLLoaded', 'ctrlIDC', 'ctrlIDD', 'ctrlMapAnimAdd', 'ctrlMapAnimClear', 'ctrlMapAnimCommit', 'ctrlMapAnimDone', 'ctrlMapCursor', 'ctrlMapMouseOver', 'ctrlMapScale', 'ctrlMapScreenToWorld', 'ctrlMapWorldToScreen', 'ctrlModel', 'ctrlModelDirAndUp', 'ctrlModelScale', 'ctrlParent', 'ctrlPosition', 'ctrlRemoveAllEventHandlers', 'ctrlRemoveEventHandler', 'ctrlScale', 'ctrlSetActiveColor', 'ctrlSetAutoScrollDelay', 'ctrlSetAutoScrollRewind', 'ctrlSetAutoScrollSpeed', 'ctrlSetBackgroundColor', 'ctrlSetChecked', 'ctrlSetEventHandler', 'ctrlSetFade', 'ctrlSetFocus', 'ctrlSetFont', 'ctrlSetFontH1', 'ctrlSetFontH1B', 'ctrlSetFontH2', 'ctrlSetFontH2B', 'ctrlSetFontH3', 'ctrlSetFontH3B', 'ctrlSetFontH4', 'ctrlSetFontH4B', 'ctrlSetFontH5', 'ctrlSetFontH5B', 'ctrlSetFontH6', 'ctrlSetFontH6B', 'ctrlSetFontHeight', 'ctrlSetFontHeightH1', 'ctrlSetFontHeightH2', 'ctrlSetFontHeightH3', 'ctrlSetFontHeightH4', 'ctrlSetFontHeightH5', 'ctrlSetFontHeightH6', 'ctrlSetFontP', 'ctrlSetFontPB', 'ctrlSetForegroundColor', 'ctrlSetModel', 'ctrlSetModelDirAndUp', 'ctrlSetModelScale', 'ctrlSetPosition', 'ctrlSetScale', 'ctrlSetStructuredText', 'ctrlSetText', 'ctrlSetTextColor', 'ctrlSetTooltip', 'ctrlSetTooltipColorBox', 'ctrlSetTooltipColorShade', 'ctrlSetTooltipColorText', 'ctrlShow', 'ctrlShown', 'ctrlText', 'ctrlTextHeight', 'ctrlType', 'ctrlVisible', 'curatorAddons', 'curatorCamera', 'curatorCameraArea', 'curatorCameraAreaCeiling', 'curatorCoef', 'curatorEditableObjects', 'curatorEditingArea', 'curatorEditingAreaType', 'curatorMouseOver', 'curatorPoints', 'curatorRegisteredObjects', 'curatorSelected', 'curatorWaypointCost', 'currentChannel', 'currentCommand', 'currentMagazine', 'currentMagazineDetail', 'currentMagazineDetailTurret', 'currentMagazineTurret', 'currentMuzzle', 'currentNamespace', 'currentTask', 'currentTasks', 'currentThrowable', 'currentVisionMode', 'currentWaypoint', 'currentWeapon', 'currentWeaponMode', 'currentWeaponTurret', 'currentZeroing', 'cursorTarget', 'customChat', 'customRadio', 'cutFadeOut', 'cutObj', 'cutRsc', 'cutText', 'damage', 'date', 'dateToNumber', 'daytime', 'deActivateKey', 'debriefingText', 'debugFSM', 'debugLog', 'default', 'deg', 'deleteAt', 'deleteCenter', 'deleteCollection', 'deleteEditorObject', 'deleteGroup', 'deleteIdentity', 'deleteLocation', 'deleteMarker', 'deleteMarkerLocal', 'deleteRange', 'deleteResources', 'deleteSite', 'deleteStatus', 'deleteTeam', 'deleteVehicle', 'deleteVehicleCrew', 'deleteWaypoint', 'detach', 'detectedMines', 'diag activeMissionFSMs', 'diag activeSQFScripts', 'diag activeSQSScripts', 'diag captureFrame', 'diag captureSlowFrame', 'diag fps', 'diag fpsMin', 'diag frameNo', 'diag log', 'diag logSlowFrame', 'diag tickTime', 'dialog', 'diarySubjectExists', 'didJIP', 'didJIPOwner', 'difficulty', 'difficultyEnabled', 'difficultyEnabledRTD', 'direction', 'directSay', 'disableAI', 'disableCollisionWith', 'disableConversation', 'disableDebriefingStats', 'disableSerialization', 'disableTIEquipment', 'disableUAVConnectability', 'disableUserInput', 'displayAddEventHandler', 'displayCtrl', 'displayNull', 'displayRemoveAllEventHandlers', 'displayRemoveEventHandler', 'displaySetEventHandler', 'dissolveTeam', 'distance', 'distance2D', 'distanceSqr', 'distributionRegion', 'do', 'doArtilleryFire', 'doFire', 'doFollow', 'doFSM', 'doGetOut', 'doMove', 'doorPhase', 'doStop', 'doTarget', 'doWatch', 'drawArrow', 'drawEllipse', 'drawIcon', 'drawIcon3D', 'drawLine', 'drawLine3D', 'drawLink', 'drawLocation', 'drawRectangle', 'driver', 'drop', 'east', 'echo', 'editObject', 'editorSetEventHandler', 'effectiveCommander', 'else', 'emptyPositions', 'enableAI', 'enableAIFeature', 'enableAttack', 'enableCamShake', 'enableCaustics', 'enableCollisionWith', 'enableCopilot', 'enableDebriefingStats', 'enableDiagLegend', 'enableEndDialog', 'enableEngineArtillery', 'enableEnvironment', 'enableFatigue', 'enableGunLights', 'enableIRLasers', 'enableMimics', 'enablePersonTurret', 'enableRadio', 'enableReload', 'enableRopeAttach', 'enableSatNormalOnDetail', 'enableSaving', 'enableSentences', 'enableSimulation', 'enableSimulationGlobal', 'enableTeamSwitch', 'enableUAVConnectability', 'enableUAVWaypoints', 'endLoadingScreen', 'endMission', 'engineOn', 'enginesIsOnRTD', 'enginesRpmRTD', 'enginesTorqueRTD', 'entities', 'estimatedEndServerTime', 'estimatedTimeLeft', 'evalObjectArgument', 'everyBackpack', 'everyContainer', 'exec', 'execEditorScript', 'execFSM', 'execVM', 'exit', 'exitWith', 'exp', 'expectedDestination', 'eyeDirection', 'eyePos', 'face', 'faction', 'fadeMusic', 'fadeRadio', 'fadeSound', 'fadeSpeech', 'failMission', 'false', 'fillWeaponsFromPool', 'find', 'findCover', 'findDisplay', 'findEditorObject', 'findEmptyPosition', 'findEmptyPositionReady', 'findNearestEnemy', 'finishMissionInit', 'finite', 'fire', 'fireAtTarget', 'firstBackpack', 'flag', 'flagOwner', 'fleeing', 'floor', 'flyInHeight', 'fog', 'fogForecast', 'fogParams', 'for', 'forceAddUniform', 'forceEnd', 'forceMap', 'forceRespawn', 'forceSpeed', 'forceWalk', 'forceWeaponFire', 'forceWeatherChange', 'forEach', 'forEachMember', 'forEachMemberAgent', 'forEachMemberTeam', 'format', 'formation', 'formationDirection', 'formationLeader', 'formationMembers', 'formationPosition', 'formationTask', 'formatText', 'formLeader', 'freeLook', 'from', 'fromEditor', 'fuel', 'fullCrew', 'gearSlotAmmoCount', 'gearSlotData', 'getAllHitPointsDamage', 'getAmmoCargo', 'getArray', 'getArtilleryAmmo', 'getArtilleryComputerSettings', 'getArtilleryETA', 'getAssignedCuratorLogic', 'getAssignedCuratorUnit', 'getBackpackCargo', 'getBleedingRemaining', 'getBurningValue', 'getCargoIndex', 'getCenterOfMass', 'getClientState', 'getConnectedUAV', 'getDammage', 'getDescription', 'getDir', 'getDirVisual', 'getDLCs', 'getEditorCamera', 'getEditorMode', 'getEditorObjectScope', 'getElevationOffset', 'getFatigue', 'getFriend', 'getFSMVariable', 'getFuelCargo', 'getGroupIcon', 'getGroupIconParams', 'getGroupIcons', 'getHideFrom', 'getHit', 'getHitIndex', 'getHitPointDamage', 'getItemCargo', 'getMagazineCargo', 'getMarkerColor', 'getMarkerPos', 'getMarkerSize', 'getMarkerType', 'getMass', 'getModelInfo', 'getNumber', 'getObjectArgument', 'getObjectChildren', 'getObjectDLC', 'getObjectMaterials', 'getObjectProxy', 'getObjectTextures', 'getObjectType', 'getObjectViewDistance', 'getOxygenRemaining', 'getPersonUsedDLCs', 'getPlayerChannel', 'getPlayerUID', 'getPos', 'getPosASL', 'getPosASLVisual', 'getPosASLW', 'getPosATL', 'getPosATLVisual', 'getPosVisual', 'getPosWorld', 'getRepairCargo', 'getResolution', 'getShadowDistance', 'getSlingLoad', 'getSpeed', 'getSuppression', 'getTerrainHeightASL', 'getText', 'getVariable', 'getWeaponCargo', 'getWPPos', 'glanceAt', 'globalChat', 'globalRadio', 'goggles', 'goto', 'group', 'groupChat', 'groupFromNetId', 'groupIconSelectable', 'groupIconsVisible', 'groupId', 'groupOwner', 'groupRadio', 'groupSelectedUnits', 'groupSelectUnit', 'grpNull', 'gunner', 'gusts', 'halt', 'handgunItems', 'handgunMagazine', 'handgunWeapon', 'handsHit', 'hasInterface', 'hasWeapon', 'hcAllGroups', 'hcGroupParams', 'hcLeader', 'hcRemoveAllGroups', 'hcRemoveGroup', 'hcSelected', 'hcSelectGroup', 'hcSetGroup', 'hcShowBar', 'hcShownBar', 'headgear', 'hideBody', 'hideObject', 'hideObjectGlobal', 'hint', 'hintC', 'hintCadet', 'hintSilent', 'hmd', 'hostMission', 'htmlLoad', 'HUDMovementLevels', 'humidity', 'if', 'image', 'importAllGroups', 'importance', 'in', 'incapacitatedState', 'independent', 'inflame', 'inflamed', 'inGameUISetEventHandler', 'inheritsFrom', 'initAmbientLife', 'inputAction', 'inRangeOfArtillery', 'insertEditorObject', 'intersect', 'isAbleToBreathe', 'isAgent', 'isArray', 'isAutoHoverOn', 'isAutonomous', 'isAutotest', 'isBleeding', 'isBurning', 'isClass', 'isCollisionLightOn', 'isCopilotEnabled', 'isDedicated', 'isDLCAvailable', 'isEngineOn', 'isEqualTo', 'isFlashlightOn', 'isFlatEmpty', 'isForcedWalk', 'isFormationLeader', 'isHidden', 'isInRemainsCollector', 'isInstructorFigureEnabled', 'isIRLaserOn', 'isKeyActive', 'isKindOf', 'isLightOn', 'isLocalized', 'isManualFire', 'isMarkedForCollection', 'isMultiplayer', 'isNil', 'isNull', 'isNumber', 'isObjectHidden', 'isObjectRTD', 'isOnRoad', 'isPipEnabled', 'isPlayer', 'isRealTime', 'isServer', 'isShowing3DIcons', 'isSteamMission', 'isStreamFriendlyUIEnabled', 'isText', 'isTouchingGround', 'isTurnedOut', 'isTutHintsEnabled', 'isUAVConnectable', 'isUAVConnected', 'isUniformAllowed', 'isWalking', 'isWeaponDeployed', 'isWeaponRested', 'itemCargo', 'items', 'itemsWithMagazines', 'join', 'joinAs', 'joinAsSilent', 'joinSilent', 'joinString', 'kbAddDatabase', 'kbAddDatabaseTargets', 'kbAddTopic', 'kbHasTopic', 'kbReact', 'kbRemoveTopic', 'kbTell', 'kbWasSaid', 'keyImage', 'keyName', 'knowsAbout', 'land', 'landAt', 'landResult', 'language', 'laserTarget', 'lbAdd', 'lbClear', 'lbColor', 'lbCurSel', 'lbData', 'lbDelete', 'lbIsSelected', 'lbPicture', 'lbSelection', 'lbSetColor', 'lbSetCurSel', 'lbSetData', 'lbSetPicture', 'lbSetPictureColor', 'lbSetPictureColorDisabled', 'lbSetPictureColorSelected', 'lbSetSelectColor', 'lbSetSelectColorRight', 'lbSetSelected', 'lbSetTooltip', 'lbSetValue', 'lbSize', 'lbSort', 'lbSortByValue', 'lbText', 'lbValue', 'leader', 'leaderboardDeInit', 'leaderboardGetRows', 'leaderboardInit', 'leaveVehicle', 'libraryCredits', 'libraryDisclaimers', 'lifeState', 'lightAttachObject', 'lightDetachObject', 'lightIsOn', 'lightnings', 'limitSpeed', 'linearConversion', 'lineBreak', 'lineIntersects', 'lineIntersectsObjs', 'lineIntersectsSurfaces', 'lineIntersectsWith', 'linkItem', 'list', 'listObjects', 'ln', 'lnbAddArray', 'lnbAddColumn', 'lnbAddRow', 'lnbClear', 'lnbColor', 'lnbCurSelRow', 'lnbData', 'lnbDeleteColumn', 'lnbDeleteRow', 'lnbGetColumnsPosition', 'lnbPicture', 'lnbSetColor', 'lnbSetColumnsPos', 'lnbSetCurSelRow', 'lnbSetData', 'lnbSetPicture', 'lnbSetText', 'lnbSetValue', 'lnbSize', 'lnbText', 'lnbValue', 'load', 'loadAbs', 'loadBackpack', 'loadFile', 'loadGame', 'loadIdentity', 'loadMagazine', 'loadOverlay', 'loadStatus', 'loadUniform', 'loadVest', 'local', 'localize', 'locationNull', 'locationPosition', 'lock', 'lockCameraTo', 'lockCargo', 'lockDriver', 'locked', 'lockedCargo', 'lockedDriver', 'lockedTurret', 'lockTurret', 'lockWP', 'log', 'logEntities', 'lookAt', 'lookAtPos', 'magazineCargo', 'magazines', 'magazinesAllTurrets', 'magazinesAmmo', 'magazinesAmmoCargo', 'magazinesAmmoFull', 'magazinesDetail', 'magazinesDetailBackpack', 'magazinesDetailUniform', 'magazinesDetailVest', 'magazinesTurret', 'magazineTurretAmmo', 'mapAnimAdd', 'mapAnimClear', 'mapAnimCommit', 'mapAnimDone', 'mapCenterOnCamera', 'mapGridPosition', 'markAsFinishedOnSteam', 'markerAlpha', 'markerBrush', 'markerColor', 'markerDir', 'markerPos', 'markerShape', 'markerSize', 'markerText', 'markerType', 'max', 'members', 'min', 'mineActive', 'mineDetectedBy', 'missionConfigFile', 'missionName', 'missionNamespace', 'missionStart', 'mod', 'modelToWorld', 'modelToWorldVisual', 'moonIntensity', 'morale', 'move', 'moveInAny', 'moveInCargo', 'moveInCommander', 'moveInDriver', 'moveInGunner', 'moveInTurret', 'moveObjectToEnd', 'moveOut', 'moveTime', 'moveTo', 'moveToCompleted', 'moveToFailed', 'musicVolume', 'name', 'name location', 'nameSound', 'nearEntities', 'nearestBuilding', 'nearestLocation', 'nearestLocations', 'nearestLocationWithDubbing', 'nearestObject', 'nearestObjects', 'nearObjects', 'nearObjectsReady', 'nearRoads', 'nearSupplies', 'nearTargets', 'needReload', 'netId', 'netObjNull', 'newOverlay', 'nextMenuItemIndex', 'nextWeatherChange', 'nil', 'nMenuItems', 'not', 'numberToDate', 'objectCurators', 'objectFromNetId', 'objectParent', 'objNull', 'objStatus', 'onBriefingGroup', 'onBriefingNotes', 'onBriefingPlan', 'onBriefingTeamSwitch', 'onCommandModeChanged', 'onDoubleClick', 'onEachFrame', 'onGroupIconClick', 'onGroupIconOverEnter', 'onGroupIconOverLeave', 'onHCGroupSelectionChanged', 'onMapSingleClick', 'onPlayerConnected', 'onPlayerDisconnected', 'onPreloadFinished', 'onPreloadStarted', 'onShowNewObject', 'onTeamSwitch', 'openCuratorInterface', 'openMap', 'openYoutubeVideo', 'opfor', 'or', 'orderGetIn', 'overcast', 'overcastForecast', 'owner', 'param', 'params', 'parseNumber', 'parseText', 'parsingNamespace', 'particlesQuality', 'pi', 'pickWeaponPool', 'pitch', 'playableSlotsNumber', 'playableUnits', 'playAction', 'playActionNow', 'player', 'playerRespawnTime', 'playerSide', 'playersNumber', 'playGesture', 'playMission', 'playMove', 'playMoveNow', 'playMusic', 'playScriptedMission', 'playSound', 'playSound3D', 'position', 'positionCameraToWorld', 'posScreenToWorld', 'posWorldToScreen', 'ppEffectAdjust', 'ppEffectCommit', 'ppEffectCommitted', 'ppEffectCreate', 'ppEffectDestroy', 'ppEffectEnable', 'ppEffectForceInNVG', 'precision', 'preloadCamera', 'preloadObject', 'preloadSound', 'preloadTitleObj', 'preloadTitleRsc', 'preprocessFile', 'preprocessFileLineNumbers', 'primaryWeapon', 'primaryWeaponItems', 'primaryWeaponMagazine', 'priority', 'private', 'processDiaryLink', 'productVersion', 'profileName', 'profileNamespace', 'profileNameSteam', 'progressLoadingScreen', 'progressPosition', 'progressSetPosition', 'publicVariable', 'publicVariableClient', 'publicVariableServer', 'pushBack', 'putWeaponPool', 'queryItemsPool', 'queryMagazinePool', 'queryWeaponPool', 'rad', 'radioChannelAdd', 'radioChannelCreate', 'radioChannelRemove', 'radioChannelSetCallSign', 'radioChannelSetLabel', 'radioVolume', 'rain', 'rainbow', 'random', 'rank', 'rankId', 'rating', 'rectangular', 'registeredTasks', 'registerTask', 'reload', 'reloadEnabled', 'remoteControl', 'remoteExec', 'remoteExecCall', 'removeAction', 'removeAllActions', 'removeAllAssignedItems', 'removeAllContainers', 'removeAllCuratorAddons', 'removeAllCuratorCameraAreas', 'removeAllCuratorEditingAreas', 'removeAllEventHandlers', 'removeAllHandgunItems', 'removeAllItems', 'removeAllItemsWithMagazines', 'removeAllMissionEventHandlers', 'removeAllMPEventHandlers', 'removeAllMusicEventHandlers', 'removeAllPrimaryWeaponItems', 'removeAllWeapons', 'removeBackpack', 'removeBackpackGlobal', 'removeCuratorAddons', 'removeCuratorCameraArea', 'removeCuratorEditableObjects', 'removeCuratorEditingArea', 'removeDrawIcon', 'removeDrawLinks', 'removeEventHandler', 'removeFromRemainsCollector', 'removeGoggles', 'removeGroupIcon', 'removeHandgunItem', 'removeHeadgear', 'removeItem', 'removeItemFromBackpack', 'removeItemFromUniform', 'removeItemFromVest', 'removeItems', 'removeMagazine', 'removeMagazineGlobal', 'removeMagazines', 'removeMagazinesTurret', 'removeMagazineTurret', 'removeMenuItem', 'removeMissionEventHandler', 'removeMPEventHandler', 'removeMusicEventHandler', 'removePrimaryWeaponItem', 'removeSecondaryWeaponItem', 'removeSimpleTask', 'removeSwitchableUnit', 'removeTeamMember', 'removeUniform', 'removeVest', 'removeWeapon', 'removeWeaponGlobal', 'removeWeaponTurret', 'requiredVersion', 'resetCamShake', 'resetSubgroupDirection', 'resistance', 'resize', 'resources', 'respawnVehicle', 'restartEditorCamera', 'reveal', 'revealMine', 'reverse', 'reversedMouseY', 'roadsConnectedTo', 'roleDescription', 'ropeAttachedObjects', 'ropeAttachedTo', 'ropeAttachEnabled', 'ropeAttachTo', 'ropeCreate', 'ropeCut', 'ropeEndPosition', 'ropeLength', 'ropes', 'ropeUnwind', 'ropeUnwound', 'rotorsForcesRTD', 'rotorsRpmRTD', 'round', 'runInitScript', 'safeZoneH', 'safeZoneW', 'safeZoneWAbs', 'safeZoneX', 'safeZoneXAbs', 'safeZoneY', 'saveGame', 'saveIdentity', 'saveJoysticks', 'saveOverlay', 'saveProfileNamespace', 'saveStatus', 'saveVar', 'savingEnabled', 'say', 'say2D', 'say3D', 'scopeName', 'score', 'scoreSide', 'screenToWorld', 'scriptDone', 'scriptName', 'scriptNull', 'scudState', 'secondaryWeapon', 'secondaryWeaponItems', 'secondaryWeaponMagazine', 'select', 'selectBestPlaces', 'selectDiarySubject', 'selectedEditorObjects', 'selectEditorObject', 'selectionPosition', 'selectLeader', 'selectNoPlayer', 'selectPlayer', 'selectWeapon', 'selectWeaponTurret', 'sendAUMessage', 'sendSimpleCommand', 'sendTask', 'sendTaskResult', 'sendUDPMessage', 'serverCommand', 'serverCommandAvailable', 'serverCommandExecutable', 'serverName', 'serverTime', 'set', 'setAccTime', 'setAirportSide', 'setAmmo', 'setAmmoCargo', 'setAperture', 'setApertureNew', 'setArmoryPoints', 'setAttributes', 'setAutonomous', 'setBehaviour', 'setBleedingRemaining', 'setCameraInterest', 'setCamShakeDefParams', 'setCamShakeParams', 'setCamUseTi', 'setCaptive', 'setCenterOfMass', 'setCollisionLight', 'setCombatMode', 'setCompassOscillation', 'setCuratorCameraAreaCeiling', 'setCuratorCoef', 'setCuratorEditingAreaType', 'setCuratorWaypointCost', 'setCurrentChannel', 'setCurrentTask', 'setCurrentWaypoint', 'setDamage', 'setDammage', 'setDate', 'setDebriefingText', 'setDefaultCamera', 'setDestination', 'setDetailMapBlendPars', 'setDir', 'setDirection', 'setDrawIcon', 'setDropInterval', 'setEditorMode', 'setEditorObjectScope', 'setEffectCondition', 'setFace', 'setFaceAnimation', 'setFatigue', 'setFlagOwner', 'setFlagSide', 'setFlagTexture', 'setFog', 'setFog array', 'setFormation', 'setFormationTask', 'setFormDir', 'setFriend', 'setFromEditor', 'setFSMVariable', 'setFuel', 'setFuelCargo', 'setGroupIcon', 'setGroupIconParams', 'setGroupIconsSelectable', 'setGroupIconsVisible', 'setGroupId', 'setGroupIdGlobal', 'setGroupOwner', 'setGusts', 'setHideBehind', 'setHit', 'setHitIndex', 'setHitPointDamage', 'setHorizonParallaxCoef', 'setHUDMovementLevels', 'setIdentity', 'setImportance', 'setLeader', 'setLightAmbient', 'setLightAttenuation', 'setLightBrightness', 'setLightColor', 'setLightDayLight', 'setLightFlareMaxDistance', 'setLightFlareSize', 'setLightIntensity', 'setLightnings', 'setLightUseFlare', 'setLocalWindParams', 'setMagazineTurretAmmo', 'setMarkerAlpha', 'setMarkerAlphaLocal', 'setMarkerBrush', 'setMarkerBrushLocal', 'setMarkerColor', 'setMarkerColorLocal', 'setMarkerDir', 'setMarkerDirLocal', 'setMarkerPos', 'setMarkerPosLocal', 'setMarkerShape', 'setMarkerShapeLocal', 'setMarkerSize', 'setMarkerSizeLocal', 'setMarkerText', 'setMarkerTextLocal', 'setMarkerType', 'setMarkerTypeLocal', 'setMass', 'setMimic', 'setMousePosition', 'setMusicEffect', 'setMusicEventHandler', 'setName', 'setNameSound', 'setObjectArguments', 'setObjectMaterial', 'setObjectProxy', 'setObjectTexture', 'setObjectTextureGlobal', 'setObjectViewDistance', 'setOvercast', 'setOwner', 'setOxygenRemaining', 'setParticleCircle', 'setParticleClass', 'setParticleFire', 'setParticleParams', 'setParticleRandom', 'setPilotLight', 'setPiPEffect', 'setPitch', 'setPlayable', 'setPlayerRespawnTime', 'setPos', 'setPosASL', 'setPosASL2', 'setPosASLW', 'setPosATL', 'setPosition', 'setPosWorld', 'setRadioMsg', 'setRain', 'setRainbow', 'setRandomLip', 'setRank', 'setRectangular', 'setRepairCargo', 'setShadowDistance', 'setSide', 'setSimpleTaskDescription', 'setSimpleTaskDestination', 'setSimpleTaskTarget', 'setSimulWeatherLayers', 'setSize', 'setSkill', 'setSkill array', 'setSlingLoad', 'setSoundEffect', 'setSpeaker', 'setSpeech', 'setSpeedMode', 'setStatValue', 'setSuppression', 'setSystemOfUnits', 'setTargetAge', 'setTaskResult', 'setTaskState', 'setTerrainGrid', 'setText', 'setTimeMultiplier', 'setTitleEffect', 'setTriggerActivation', 'setTriggerArea', 'setTriggerStatements', 'setTriggerText', 'setTriggerTimeout', 'setTriggerType', 'setType', 'setUnconscious', 'setUnitAbility', 'setUnitPos', 'setUnitPosWeak', 'setUnitRank', 'setUnitRecoilCoefficient', 'setUnloadInCombat', 'setUserActionText', 'setVariable', 'setVectorDir', 'setVectorDirAndUp', 'setVectorUp', 'setVehicleAmmo', 'setVehicleAmmoDef', 'setVehicleArmor', 'setVehicleId', 'setVehicleLock', 'setVehiclePosition', 'setVehicleTiPars', 'setVehicleVarName', 'setVelocity', 'setVelocityTransformation', 'setViewDistance', 'setVisibleIfTreeCollapsed', 'setWaves', 'setWaypointBehaviour', 'setWaypointCombatMode', 'setWaypointCompletionRadius', 'setWaypointDescription', 'setWaypointFormation', 'setWaypointHousePosition', 'setWaypointLoiterRadius', 'setWaypointLoiterType', 'setWaypointName', 'setWaypointPosition', 'setWaypointScript', 'setWaypointSpeed', 'setWaypointStatements', 'setWaypointTimeout', 'setWaypointType', 'setWaypointVisible', 'setWeaponReloadingTime', 'setWind', 'setWindDir', 'setWindForce', 'setWindStr', 'setWPPos', 'show3DIcons', 'showChat', 'showCinemaBorder', 'showCommandingMenu', 'showCompass', 'showCuratorCompass', 'showGPS', 'showHUD', 'showLegend', 'showMap', 'shownArtilleryComputer', 'shownChat', 'shownCompass', 'shownCuratorCompass', 'showNewEditorObject', 'shownGPS', 'shownHUD', 'shownMap', 'shownPad', 'shownRadio', 'shownUAVFeed', 'shownWarrant', 'shownWatch', 'showPad', 'showRadio', 'showSubtitles', 'showUAVFeed', 'showWarrant', 'showWatch', 'showWaypoint', 'side', 'sideChat', 'sideEnemy', 'sideFriendly', 'sideLogic', 'sideRadio', 'sideUnknown', 'simpleTasks', 'simulationEnabled', 'simulCloudDensity', 'simulCloudOcclusion', 'simulInClouds', 'simulWeatherSync', 'sin', 'size', 'sizeOf', 'skill', 'skillFinal', 'skipTime', 'sleep', 'sliderPosition', 'sliderRange', 'sliderSetPosition', 'sliderSetRange', 'sliderSetSpeed', 'sliderSpeed', 'slingLoadAssistantShown', 'soldierMagazines', 'someAmmo', 'sort', 'soundVolume', 'spawn', 'speaker', 'speed', 'speedMode', 'splitString', 'sqrt', 'squadParams', 'stance', 'startLoadingScreen', 'step', 'stop', 'stopped', 'str', 'sunOrMoon', 'supportInfo', 'suppressFor', 'surfaceIsWater', 'surfaceNormal', 'surfaceType', 'swimInDepth', 'switch', 'switchableUnits', 'switchAction', 'switchCamera', 'switchGesture', 'switchLight', 'switchMove', 'synchronizedObjects', 'synchronizedTriggers', 'synchronizedWaypoints', 'synchronizeObjectsAdd', 'synchronizeObjectsRemove', 'synchronizeTrigger', 'synchronizeWaypoint', 'synchronizeWaypoint trigger', 'systemChat', 'systemOfUnits', 'tan', 'targetKnowledge', 'targetsAggregate', 'targetsQuery', 'taskChildren', 'taskCompleted', 'taskDescription', 'taskDestination', 'taskHint', 'taskNull', 'taskParent', 'taskResult', 'taskState', 'teamMember', 'teamMemberNull', 'teamName', 'teams', 'teamSwitch', 'teamSwitchEnabled', 'teamType', 'terminate', 'terrainIntersect', 'terrainIntersectASL', 'text', 'text location', 'textLog', 'textLogFormat', 'tg', 'then', 'throw', 'time', 'timeMultiplier', 'titleCut', 'titleFadeOut', 'titleObj', 'titleRsc', 'titleText', 'to', 'toArray', 'toLower', 'toString', 'toUpper', 'triggerActivated', 'triggerActivation', 'triggerArea', 'triggerAttachedVehicle', 'triggerAttachObject', 'triggerAttachVehicle', 'triggerStatements', 'triggerText', 'triggerTimeout', 'triggerTimeoutCurrent', 'triggerType', 'true', 'try', 'turretLocal', 'turretOwner', 'turretUnit', 'tvAdd', 'tvClear', 'tvCollapse', 'tvCount', 'tvCurSel', 'tvData', 'tvDelete', 'tvExpand', 'tvPicture', 'tvSetCurSel', 'tvSetData', 'tvSetPicture', 'tvSetPictureColor', 'tvSetTooltip', 'tvSetValue', 'tvSort', 'tvSortByValue', 'tvText', 'tvValue', 'type', 'typeName', 'typeOf', 'UAVControl', 'uiNamespace', 'uiSleep', 'unassignCurator', 'unassignItem', 'unassignTeam', 'unassignVehicle', 'underwater', 'uniform', 'uniformContainer', 'uniformItems', 'uniformMagazines', 'unitAddons', 'unitBackpack', 'unitPos', 'unitReady', 'unitRecoilCoefficient', 'units', 'unitsBelowHeight', 'unlinkItem', 'unlockAchievement', 'unregisterTask', 'updateDrawIcon', 'updateMenuItem', 'updateObjectTree', 'useAudioTimeForMoves', 'vectorAdd', 'vectorCos', 'vectorCrossProduct', 'vectorDiff', 'vectorDir', 'vectorDirVisual', 'vectorDistance', 'vectorDistanceSqr', 'vectorDotProduct', 'vectorFromTo', 'vectorMagnitude', 'vectorMagnitudeSqr', 'vectorMultiply', 'vectorNormalized', 'vectorUp', 'vectorUpVisual', 'vehicle', 'vehicleChat', 'vehicleRadio', 'vehicles', 'vehicleVarName', 'velocity', 'velocityModelSpace', 'verifySignature', 'vest', 'vestContainer', 'vestItems', 'vestMagazines', 'viewDistance', 'visibleCompass', 'visibleGPS', 'visibleMap', 'visiblePosition', 'visiblePositionASL', 'visibleWatch', 'waitUntil', 'waves', 'waypointAttachedObject', 'waypointAttachedVehicle', 'waypointAttachObject', 'waypointAttachVehicle', 'waypointBehaviour', 'waypointCombatMode', 'waypointCompletionRadius', 'waypointDescription', 'waypointFormation', 'waypointHousePosition', 'waypointLoiterRadius', 'waypointLoiterType', 'waypointName', 'waypointPosition', 'waypoints', 'waypointScript', 'waypointsEnabledUAV', 'waypointShow', 'waypointSpeed', 'waypointStatements', 'waypointTimeout', 'waypointTimeoutCurrent', 'waypointType', 'waypointVisible', 'weaponAccessories', 'weaponCargo', 'weaponDirection', 'weaponLowered', 'weapons', 'weaponsItems', 'weaponsItemsCargo', 'weaponState', 'weaponsTurret', 'weightRTD', 'west', 'WFSideText', 'while', 'wind', 'windDir', 'windStr', 'wingsForcesRTD', 'with', 'worldName', 'worldSize', 'worldToModel', 'worldToModelVisual', 'worldToScreen'];\n  var control = ['case', 'catch', 'default', 'do', 'else', 'exit', 'exitWith|5', 'for', 'forEach', 'from', 'if', 'switch', 'then', 'throw', 'to', 'try', 'while', 'with'];\n  var operators = ['!', '-', '+', '!=', '%', '&&', '*', '/', '=', '==', '>', '>=', '<', '<=', '^', ':', '>>'];\n  var specials = ['_forEachIndex|10', '_this|10', '_x|10'];\n  var literals = ['true', 'false', 'nil'];\n  var builtins = allCommands.filter(function (command) {\n    return control.indexOf(command) == -1 &&\n        literals.indexOf(command) == -1 &&\n        operators.indexOf(command) == -1;\n  });\n  //Note: operators will not be treated as builtins due to the lexeme rules\n  builtins = builtins.concat(specials);\n\n  // In SQF strings, quotes matching the start are escaped by adding a consecutive.\n  // Example of single escaped quotes: \" \"\" \" and  ' '' '.\n  var STRINGS = {\n    className: 'string',\n    relevance: 0,\n    variants: [\n      {\n        begin: '\"',\n        end: '\"',\n        contains: [{begin: '\"\"'}]\n      },\n      {\n        begin: '\\'',\n        end: '\\'',\n        contains: [{begin: '\\'\\''}]\n      }\n    ]\n  };\n\n  var NUMBERS = {\n    className: 'number',\n    begin: hljs.NUMBER_RE,\n    relevance: 0\n  };\n\n  // Preprocessor definitions borrowed from C++\n  var PREPROCESSOR_STRINGS = {\n    className: 'string',\n    variants: [\n      hljs.QUOTE_STRING_MODE,\n      {\n        begin: '\\'\\\\\\\\?.', end: '\\'',\n        illegal: '.'\n      }\n    ]\n  };\n\n  var PREPROCESSOR =       {\n    className: 'preprocessor',\n    begin: '#', end: '$',\n    keywords: 'if else elif endif define undef warning error line ' +\n              'pragma ifdef ifndef',\n    contains: [\n      {\n        begin: /\\\\\\n/, relevance: 0\n      },\n      {\n        beginKeywords: 'include', end: '$',\n        contains: [\n          PREPROCESSOR_STRINGS,\n          {\n            className: 'string',\n            begin: '<', end: '>',\n            illegal: '\\\\n',\n          }\n        ]\n      },\n      PREPROCESSOR_STRINGS,\n      NUMBERS,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE\n    ]\n  };\n\n  return {\n    aliases: ['sqf'],\n    case_insensitive: true,\n    keywords: {\n      keyword: control.join(' '),\n      built_in: builtins.join(' '),\n      literal: literals.join(' ')\n    },\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      NUMBERS,\n      STRINGS,\n      PREPROCESSOR\n    ]\n  };\n});\n\nhljs.registerLanguage('sql', function(hljs) {\n  var COMMENT_MODE = hljs.COMMENT('--', '$');\n  return {\n    case_insensitive: true,\n    illegal: /[<>{}*]/,\n    contains: [\n      {\n        className: 'operator',\n        beginKeywords:\n          'begin end start commit rollback savepoint lock alter create drop rename call ' +\n          'delete do handler insert load replace select truncate update set show pragma grant ' +\n          'merge describe use explain help declare prepare execute deallocate release ' +\n          'unlock purge reset change stop analyze cache flush optimize repair kill ' +\n          'install uninstall checksum restore check backup revoke',\n        end: /;/, endsWithParent: true,\n        keywords: {\n          keyword:\n            'abort abs absolute acc acce accep accept access accessed accessible account acos action activate add ' +\n            'addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias ' +\n            'allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply ' +\n            'archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan ' +\n            'atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid ' +\n            'authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile ' +\n            'before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float ' +\n            'binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound ' +\n            'buffer_cache buffer_pool build bulk by byte byteordermark bytes c cache caching call calling cancel ' +\n            'capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base ' +\n            'char_length character_length characters characterset charindex charset charsetform charsetid check ' +\n            'checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close ' +\n            'cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation ' +\n            'collect colu colum column column_value columns columns_updated comment commit compact compatibility ' +\n            'compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn ' +\n            'connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection ' +\n            'consider consistent constant constraint constraints constructor container content contents context ' +\n            'contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost ' +\n            'count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation ' +\n            'critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user ' +\n            'cursor curtime customdatum cycle d data database databases datafile datafiles datalength date_add ' +\n            'date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts ' +\n            'day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate ' +\n            'declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults ' +\n            'deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank ' +\n            'depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor ' +\n            'deterministic diagnostics difference dimension direct_load directory disable disable_all ' +\n            'disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div ' +\n            'do document domain dotnet double downgrade drop dumpfile duplicate duration e each edition editionable ' +\n            'editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt ' +\n            'end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors ' +\n            'escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding ' +\n            'execu execut execute exempt exists exit exp expire explain export export_set extended extent external ' +\n            'external_1 external_2 externally extract f failed failed_login_attempts failover failure far fast ' +\n            'feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final ' +\n            'finish first first_value fixed flash_cache flashback floor flush following follows for forall force ' +\n            'form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ' +\n            'ftp full function g general generated get get_format get_lock getdate getutcdate global global_name ' +\n            'globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups ' +\n            'gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex ' +\n            'hierarchy high high_priority hosts hour http i id ident_current ident_incr ident_seed identified ' +\n            'identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment ' +\n            'index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile ' +\n            'initial initialized initially initrans inmemory inner innodb input insert install instance instantiable ' +\n            'instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat ' +\n            'is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists ' +\n            'k keep keep_duplicates key keys kill l language large last last_day last_insert_id last_value lax lcase ' +\n            'lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit ' +\n            'lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate ' +\n            'locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call ' +\n            'logoff logon logs long loop low low_priority lower lpad lrtrim ltrim m main make_set makedate maketime ' +\n            'managed management manual map mapping mask master master_pos_wait match matched materialized max ' +\n            'maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans ' +\n            'md5 measures median medium member memcompress memory merge microsecond mid migration min minextents ' +\n            'minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month ' +\n            'months mount move movement multiset mutex n name name_const names nan national native natural nav nchar ' +\n            'nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile ' +\n            'nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile ' +\n            'nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder ' +\n            'nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck ' +\n            'noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe ' +\n            'nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ' +\n            'ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old ' +\n            'on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date ' +\n            'oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary ' +\n            'out outer outfile outline output over overflow overriding p package pad parallel parallel_enable ' +\n            'parameters parent parse partial partition partitions pascal passing password password_grace_time ' +\n            'password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex ' +\n            'pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc ' +\n            'performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin ' +\n            'policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction ' +\n            'prediction_cost prediction_details prediction_probability prediction_set prepare present preserve ' +\n            'prior priority private private_sga privileges procedural procedure procedure_analyze processlist ' +\n            'profiles project prompt protection public publishingservername purge quarter query quick quiesce quota ' +\n            'quotename radians raise rand range rank raw read reads readsize rebuild record records ' +\n            'recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh ' +\n            'regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy ' +\n            'reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename ' +\n            'repair repeat replace replicate replication required reset resetlogs resize resource respect restore ' +\n            'restricted result result_cache resumable resume retention return returning returns reuse reverse revoke ' +\n            'right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows ' +\n            'rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll ' +\n            'sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select ' +\n            'self sequence sequential serializable server servererror session session_user sessions_per_user set ' +\n            'sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor ' +\n            'si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin ' +\n            'size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex ' +\n            'source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows ' +\n            'sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone ' +\n            'standby start starting startup statement static statistics stats_binomial_test stats_crosstab ' +\n            'stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep ' +\n            'stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev ' +\n            'stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate ' +\n            'subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum ' +\n            'suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate ' +\n            'sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime t table tables tablespace tan tdo ' +\n            'template temporary terminated tertiary_weights test than then thread through tier ties time time_format ' +\n            'time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr ' +\n            'timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking ' +\n            'transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate ' +\n            'try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress ' +\n            'under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot ' +\n            'unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert ' +\n            'url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date ' +\n            'utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var ' +\n            'var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray ' +\n            'verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear ' +\n            'wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped ' +\n            'xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces ' +\n            'xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek',\n          literal:\n            'true false null',\n          built_in:\n            'array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number ' +\n            'numeric real record serial serial8 smallint text varchar varying void'\n        },\n        contains: [\n          {\n            className: 'string',\n            begin: '\\'', end: '\\'',\n            contains: [hljs.BACKSLASH_ESCAPE, {begin: '\\'\\''}]\n          },\n          {\n            className: 'string',\n            begin: '\"', end: '\"',\n            contains: [hljs.BACKSLASH_ESCAPE, {begin: '\"\"'}]\n          },\n          {\n            className: 'string',\n            begin: '`', end: '`',\n            contains: [hljs.BACKSLASH_ESCAPE]\n          },\n          hljs.C_NUMBER_MODE,\n          hljs.C_BLOCK_COMMENT_MODE,\n          COMMENT_MODE\n        ]\n      },\n      hljs.C_BLOCK_COMMENT_MODE,\n      COMMENT_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('stata', function(hljs) {\n  return {\n    aliases: ['do', 'ado'],\n    case_insensitive: true,\n    keywords: 'if else in foreach for forv forva forval forvalu forvalue forvalues by bys bysort xi quietly qui capture about ac ac_7 acprplot acprplot_7 adjust ado adopath adoupdate alpha ameans an ano anov anova anova_estat anova_terms anovadef aorder ap app appe appen append arch arch_dr arch_estat arch_p archlm areg areg_p args arima arima_dr arima_estat arima_p as asmprobit asmprobit_estat asmprobit_lf asmprobit_mfx__dlg asmprobit_p ass asse asser assert avplot avplot_7 avplots avplots_7 bcskew0 bgodfrey binreg bip0_lf biplot bipp_lf bipr_lf bipr_p biprobit bitest bitesti bitowt blogit bmemsize boot bootsamp bootstrap bootstrap_8 boxco_l boxco_p boxcox boxcox_6 boxcox_p bprobit br break brier bro brow brows browse brr brrstat bs bs_7 bsampl_w bsample bsample_7 bsqreg bstat bstat_7 bstat_8 bstrap bstrap_7 ca ca_estat ca_p cabiplot camat canon canon_8 canon_8_p canon_estat canon_p cap caprojection capt captu captur capture cat cc cchart cchart_7 cci cd censobs_table centile cf char chdir checkdlgfiles checkestimationsample checkhlpfiles checksum chelp ci cii cl class classutil clear cli clis clist clo clog clog_lf clog_p clogi clogi_sw clogit clogit_lf clogit_p clogitp clogl_sw cloglog clonevar clslistarray cluster cluster_measures cluster_stop cluster_tree cluster_tree_8 clustermat cmdlog cnr cnre cnreg cnreg_p cnreg_sw cnsreg codebook collaps4 collapse colormult_nb colormult_nw compare compress conf confi confir confirm conren cons const constr constra constrai constrain constraint continue contract copy copyright copysource cor corc corr corr2data corr_anti corr_kmo corr_smc corre correl correla correlat correlate corrgram cou coun count cox cox_p cox_sw coxbase coxhaz coxvar cprplot cprplot_7 crc cret cretu cretur creturn cross cs cscript cscript_log csi ct ct_is ctset ctst_5 ctst_st cttost cumsp cumsp_7 cumul cusum cusum_7 cutil d datasig datasign datasigna datasignat datasignatu datasignatur datasignature datetof db dbeta de dec deco decod decode deff des desc descr descri describ describe destring dfbeta dfgls dfuller di di_g dir dirstats dis discard disp disp_res disp_s displ displa display distinct do doe doed doedi doedit dotplot dotplot_7 dprobit drawnorm drop ds ds_util dstdize duplicates durbina dwstat dydx e ed edi edit egen eivreg emdef en enc enco encod encode eq erase ereg ereg_lf ereg_p ereg_sw ereghet ereghet_glf ereghet_glf_sh ereghet_gp ereghet_ilf ereghet_ilf_sh ereghet_ip eret eretu eretur ereturn err erro error est est_cfexist est_cfname est_clickable est_expand est_hold est_table est_unhold est_unholdok estat estat_default estat_summ estat_vce_only esti estimates etodow etof etomdy ex exi exit expand expandcl fac fact facto factor factor_estat factor_p factor_pca_rotated factor_rotate factormat fcast fcast_compute fcast_graph fdades fdadesc fdadescr fdadescri fdadescrib fdadescribe fdasav fdasave fdause fh_st file open file read file close file filefilter fillin find_hlp_file findfile findit findit_7 fit fl fli flis flist for5_0 form forma format fpredict frac_154 frac_adj frac_chk frac_cox frac_ddp frac_dis frac_dv frac_in frac_mun frac_pp frac_pq frac_pv frac_wgt frac_xo fracgen fracplot fracplot_7 fracpoly fracpred fron_ex fron_hn fron_p fron_tn fron_tn2 frontier ftodate ftoe ftomdy ftowdate g gamhet_glf gamhet_gp gamhet_ilf gamhet_ip gamma gamma_d2 gamma_p gamma_sw gammahet gdi_hexagon gdi_spokes ge gen gene gener genera generat generate genrank genstd genvmean gettoken gl gladder gladder_7 glim_l01 glim_l02 glim_l03 glim_l04 glim_l05 glim_l06 glim_l07 glim_l08 glim_l09 glim_l10 glim_l11 glim_l12 glim_lf glim_mu glim_nw1 glim_nw2 glim_nw3 glim_p glim_v1 glim_v2 glim_v3 glim_v4 glim_v5 glim_v6 glim_v7 glm glm_6 glm_p glm_sw glmpred glo glob globa global glogit glogit_8 glogit_p gmeans gnbre_lf gnbreg gnbreg_5 gnbreg_p gomp_lf gompe_sw gomper_p gompertz gompertzhet gomphet_glf gomphet_glf_sh gomphet_gp gomphet_ilf gomphet_ilf_sh gomphet_ip gphdot gphpen gphprint gprefs gprobi_p gprobit gprobit_8 gr gr7 gr_copy gr_current gr_db gr_describe gr_dir gr_draw gr_draw_replay gr_drop gr_edit gr_editviewopts gr_example gr_example2 gr_export gr_print gr_qscheme gr_query gr_read gr_rename gr_replay gr_save gr_set gr_setscheme gr_table gr_undo gr_use graph graph7 grebar greigen greigen_7 greigen_8 grmeanby grmeanby_7 gs_fileinfo gs_filetype gs_graphinfo gs_stat gsort gwood h hadimvo hareg hausman haver he heck_d2 heckma_p heckman heckp_lf heckpr_p heckprob hel help hereg hetpr_lf hetpr_p hetprob hettest hexdump hilite hist hist_7 histogram hlogit hlu hmeans hotel hotelling hprobit hreg hsearch icd9 icd9_ff icd9p iis impute imtest inbase include inf infi infil infile infix inp inpu input ins insheet insp inspe inspec inspect integ inten intreg intreg_7 intreg_p intrg2_ll intrg_ll intrg_ll2 ipolate iqreg ir irf irf_create irfm iri is_svy is_svysum isid istdize ivprob_1_lf ivprob_lf ivprobit ivprobit_p ivreg ivreg_footnote ivtob_1_lf ivtob_lf ivtobit ivtobit_p jackknife jacknife jknife jknife_6 jknife_8 jkstat joinby kalarma1 kap kap_3 kapmeier kappa kapwgt kdensity kdensity_7 keep ksm ksmirnov ktau kwallis l la lab labe label labelbook ladder levels levelsof leverage lfit lfit_p li lincom line linktest lis list lloghet_glf lloghet_glf_sh lloghet_gp lloghet_ilf lloghet_ilf_sh lloghet_ip llogi_sw llogis_p llogist llogistic llogistichet lnorm_lf lnorm_sw lnorma_p lnormal lnormalhet lnormhet_glf lnormhet_glf_sh lnormhet_gp lnormhet_ilf lnormhet_ilf_sh lnormhet_ip lnskew0 loadingplot loc loca local log logi logis_lf logistic logistic_p logit logit_estat logit_p loglogs logrank loneway lookfor lookup lowess lowess_7 lpredict lrecomp lroc lroc_7 lrtest ls lsens lsens_7 lsens_x lstat ltable ltable_7 ltriang lv lvr2plot lvr2plot_7 m ma mac macr macro makecns man manova manova_estat manova_p manovatest mantel mark markin markout marksample mat mat_capp mat_order mat_put_rr mat_rapp mata mata_clear mata_describe mata_drop mata_matdescribe mata_matsave mata_matuse mata_memory mata_mlib mata_mosave mata_rename mata_which matalabel matcproc matlist matname matr matri matrix matrix_input__dlg matstrik mcc mcci md0_ md1_ md1debug_ md2_ md2debug_ mds mds_estat mds_p mdsconfig mdslong mdsmat mdsshepard mdytoe mdytof me_derd mean means median memory memsize meqparse mer merg merge mfp mfx mhelp mhodds minbound mixed_ll mixed_ll_reparm mkassert mkdir mkmat mkspline ml ml_5 ml_adjs ml_bhhhs ml_c_d ml_check ml_clear ml_cnt ml_debug ml_defd ml_e0 ml_e0_bfgs ml_e0_cycle ml_e0_dfp ml_e0i ml_e1 ml_e1_bfgs ml_e1_bhhh ml_e1_cycle ml_e1_dfp ml_e2 ml_e2_cycle ml_ebfg0 ml_ebfr0 ml_ebfr1 ml_ebh0q ml_ebhh0 ml_ebhr0 ml_ebr0i ml_ecr0i ml_edfp0 ml_edfr0 ml_edfr1 ml_edr0i ml_eds ml_eer0i ml_egr0i ml_elf ml_elf_bfgs ml_elf_bhhh ml_elf_cycle ml_elf_dfp ml_elfi ml_elfs ml_enr0i ml_enrr0 ml_erdu0 ml_erdu0_bfgs ml_erdu0_bhhh ml_erdu0_bhhhq ml_erdu0_cycle ml_erdu0_dfp ml_erdu0_nrbfgs ml_exde ml_footnote ml_geqnr ml_grad0 ml_graph ml_hbhhh ml_hd0 ml_hold ml_init ml_inv ml_log ml_max ml_mlout ml_mlout_8 ml_model ml_nb0 ml_opt ml_p ml_plot ml_query ml_rdgrd ml_repor ml_s_e ml_score ml_searc ml_technique ml_unhold mleval mlf_ mlmatbysum mlmatsum mlog mlogi mlogit mlogit_footnote mlogit_p mlopts mlsum mlvecsum mnl0_ mor more mov move mprobit mprobit_lf mprobit_p mrdu0_ mrdu1_ mvdecode mvencode mvreg mvreg_estat n nbreg nbreg_al nbreg_lf nbreg_p nbreg_sw nestreg net newey newey_7 newey_p news nl nl_7 nl_9 nl_9_p nl_p nl_p_7 nlcom nlcom_p nlexp2 nlexp2_7 nlexp2a nlexp2a_7 nlexp3 nlexp3_7 nlgom3 nlgom3_7 nlgom4 nlgom4_7 nlinit nllog3 nllog3_7 nllog4 nllog4_7 nlog_rd nlogit nlogit_p nlogitgen nlogittree nlpred no nobreak noi nois noisi noisil noisily note notes notes_dlg nptrend numlabel numlist odbc old_ver olo olog ologi ologi_sw ologit ologit_p ologitp on one onew onewa oneway op_colnm op_comp op_diff op_inv op_str opr opro oprob oprob_sw oprobi oprobi_p oprobit oprobitp opts_exclusive order orthog orthpoly ou out outf outfi outfil outfile outs outsh outshe outshee outsheet ovtest pac pac_7 palette parse parse_dissim pause pca pca_8 pca_display pca_estat pca_p pca_rotate pcamat pchart pchart_7 pchi pchi_7 pcorr pctile pentium pergram pergram_7 permute permute_8 personal peto_st pkcollapse pkcross pkequiv pkexamine pkexamine_7 pkshape pksumm pksumm_7 pl plo plot plugin pnorm pnorm_7 poisgof poiss_lf poiss_sw poisso_p poisson poisson_estat post postclose postfile postutil pperron pr prais prais_e prais_e2 prais_p predict predictnl preserve print pro prob probi probit probit_estat probit_p proc_time procoverlay procrustes procrustes_estat procrustes_p profiler prog progr progra program prop proportion prtest prtesti pwcorr pwd q\\\\s qby qbys qchi qchi_7 qladder qladder_7 qnorm qnorm_7 qqplot qqplot_7 qreg qreg_c qreg_p qreg_sw qu quadchk quantile quantile_7 que quer query range ranksum ratio rchart rchart_7 rcof recast reclink recode reg reg3 reg3_p regdw regr regre regre_p2 regres regres_p regress regress_estat regriv_p remap ren rena renam rename renpfix repeat replace report reshape restore ret retu retur return rm rmdir robvar roccomp roccomp_7 roccomp_8 rocf_lf rocfit rocfit_8 rocgold rocplot rocplot_7 roctab roctab_7 rolling rologit rologit_p rot rota rotat rotate rotatemat rreg rreg_p ru run runtest rvfplot rvfplot_7 rvpplot rvpplot_7 sa safesum sample sampsi sav save savedresults saveold sc sca scal scala scalar scatter scm_mine sco scob_lf scob_p scobi_sw scobit scor score scoreplot scoreplot_help scree screeplot screeplot_help sdtest sdtesti se search separate seperate serrbar serrbar_7 serset set set_defaults sfrancia sh she shel shell shewhart shewhart_7 signestimationsample signrank signtest simul simul_7 simulate simulate_8 sktest sleep slogit slogit_d2 slogit_p smooth snapspan so sor sort spearman spikeplot spikeplot_7 spikeplt spline_x split sqreg sqreg_p sret sretu sretur sreturn ssc st st_ct st_hc st_hcd st_hcd_sh st_is st_issys st_note st_promo st_set st_show st_smpl st_subid stack statsby statsby_8 stbase stci stci_7 stcox stcox_estat stcox_fr stcox_fr_ll stcox_p stcox_sw stcoxkm stcoxkm_7 stcstat stcurv stcurve stcurve_7 stdes stem stepwise stereg stfill stgen stir stjoin stmc stmh stphplot stphplot_7 stphtest stphtest_7 stptime strate strate_7 streg streg_sw streset sts sts_7 stset stsplit stsum sttocc sttoct stvary stweib su suest suest_8 sum summ summa summar summari summariz summarize sunflower sureg survcurv survsum svar svar_p svmat svy svy_disp svy_dreg svy_est svy_est_7 svy_estat svy_get svy_gnbreg_p svy_head svy_header svy_heckman_p svy_heckprob_p svy_intreg_p svy_ivreg_p svy_logistic_p svy_logit_p svy_mlogit_p svy_nbreg_p svy_ologit_p svy_oprobit_p svy_poisson_p svy_probit_p svy_regress_p svy_sub svy_sub_7 svy_x svy_x_7 svy_x_p svydes svydes_8 svygen svygnbreg svyheckman svyheckprob svyintreg svyintreg_7 svyintrg svyivreg svylc svylog_p svylogit svymarkout svymarkout_8 svymean svymlog svymlogit svynbreg svyolog svyologit svyoprob svyoprobit svyopts svypois svypois_7 svypoisson svyprobit svyprobt svyprop svyprop_7 svyratio svyreg svyreg_p svyregress svyset svyset_7 svyset_8 svytab svytab_7 svytest svytotal sw sw_8 swcnreg swcox swereg swilk swlogis swlogit swologit swoprbt swpois swprobit swqreg swtobit swweib symmetry symmi symplot symplot_7 syntax sysdescribe sysdir sysuse szroeter ta tab tab1 tab2 tab_or tabd tabdi tabdis tabdisp tabi table tabodds tabodds_7 tabstat tabu tabul tabula tabulat tabulate te tempfile tempname tempvar tes test testnl testparm teststd tetrachoric time_it timer tis tob tobi tobit tobit_p tobit_sw token tokeni tokeniz tokenize tostring total translate translator transmap treat_ll treatr_p treatreg trim trnb_cons trnb_mean trpoiss_d2 trunc_ll truncr_p truncreg tsappend tset tsfill tsline tsline_ex tsreport tsrevar tsrline tsset tssmooth tsunab ttest ttesti tut_chk tut_wait tutorial tw tware_st two twoway twoway__fpfit_serset twoway__function_gen twoway__histogram_gen twoway__ipoint_serset twoway__ipoints_serset twoway__kdensity_gen twoway__lfit_serset twoway__normgen_gen twoway__pci_serset twoway__qfit_serset twoway__scatteri_serset twoway__sunflower_gen twoway_ksm_serset ty typ type typeof u unab unabbrev unabcmd update us use uselabel var var_mkcompanion var_p varbasic varfcast vargranger varirf varirf_add varirf_cgraph varirf_create varirf_ctable varirf_describe varirf_dir varirf_drop varirf_erase varirf_graph varirf_ograph varirf_rename varirf_set varirf_table varlist varlmar varnorm varsoc varstable varstable_w varstable_w2 varwle vce vec vec_fevd vec_mkphi vec_p vec_p_w vecirf_create veclmar veclmar_w vecnorm vecnorm_w vecrank vecstable verinst vers versi versio version view viewsource vif vwls wdatetof webdescribe webseek webuse weib1_lf weib2_lf weib_lf weib_lf0 weibhet_glf weibhet_glf_sh weibhet_glfa weibhet_glfa_sh weibhet_gp weibhet_ilf weibhet_ilf_sh weibhet_ilfa weibhet_ilfa_sh weibhet_ip weibu_sw weibul_p weibull weibull_c weibull_s weibullhet wh whelp whi which whil while wilc_st wilcoxon win wind windo window winexec wntestb wntestb_7 wntestq xchart xchart_7 xcorr xcorr_7 xi xi_6 xmlsav xmlsave xmluse xpose xsh xshe xshel xshell xt_iis xt_tis xtab_p xtabond xtbin_p xtclog xtcloglog xtcloglog_8 xtcloglog_d2 xtcloglog_pa_p xtcloglog_re_p xtcnt_p xtcorr xtdata xtdes xtfront_p xtfrontier xtgee xtgee_elink xtgee_estat xtgee_makeivar xtgee_p xtgee_plink xtgls xtgls_p xthaus xthausman xtht_p xthtaylor xtile xtint_p xtintreg xtintreg_8 xtintreg_d2 xtintreg_p xtivp_1 xtivp_2 xtivreg xtline xtline_ex xtlogit xtlogit_8 xtlogit_d2 xtlogit_fe_p xtlogit_pa_p xtlogit_re_p xtmixed xtmixed_estat xtmixed_p xtnb_fe xtnb_lf xtnbreg xtnbreg_pa_p xtnbreg_refe_p xtpcse xtpcse_p xtpois xtpoisson xtpoisson_d2 xtpoisson_pa_p xtpoisson_refe_p xtpred xtprobit xtprobit_8 xtprobit_d2 xtprobit_re_p xtps_fe xtps_lf xtps_ren xtps_ren_8 xtrar_p xtrc xtrc_p xtrchh xtrefe_p xtreg xtreg_be xtreg_fe xtreg_ml xtreg_pa_p xtreg_re xtregar xtrere_p xtset xtsf_ll xtsf_llti xtsum xttab xttest0 xttobit xttobit_8 xttobit_p xttrans yx yxview__barlike_draw yxview_area_draw yxview_bar_draw yxview_dot_draw yxview_dropline_draw yxview_function_draw yxview_iarrow_draw yxview_ilabels_draw yxview_normal_draw yxview_pcarrow_draw yxview_pcbarrow_draw yxview_pccapsym_draw yxview_pcscatter_draw yxview_pcspike_draw yxview_rarea_draw yxview_rbar_draw yxview_rbarm_draw yxview_rcap_draw yxview_rcapsym_draw yxview_rconnected_draw yxview_rline_draw yxview_rscatter_draw yxview_rspike_draw yxview_spike_draw yxview_sunflower_draw zap_s zinb zinb_llf zinb_plf zip zip_llf zip_p zip_plf zt_ct_5 zt_hc_5 zt_hcd_5 zt_is_5 zt_iss_5 zt_sho_5 zt_smp_5 ztbase_5 ztcox_5 ztdes_5 ztereg_5 ztfill_5 ztgen_5 ztir_5 ztjoin_5 ztnb ztnb_p ztp ztp_p zts_5 ztset_5 ztspli_5 ztsum_5 zttoct_5 ztvary_5 ztweib_5',\n        contains: [\n      {\n        className: 'label',\n        variants: [\n          {begin: \"\\\\$\\\\{?[a-zA-Z0-9_]+\\\\}?\"},\n          {begin: \"`[a-zA-Z0-9_]+'\"}\n\n        ]\n      },\n      {\n        className: 'string',\n        variants: [\n          {begin: '`\"[^\\r\\n]*?\"\\''},\n          {begin: '\"[^\\r\\n\"]*\"'}\n        ]\n      },\n\n      {\n        className: 'literal',\n        variants: [\n          {\n            begin: '\\\\b(abs|acos|asin|atan|atan2|atanh|ceil|cloglog|comb|cos|digamma|exp|floor|invcloglog|invlogit|ln|lnfact|lnfactorial|lngamma|log|log10|max|min|mod|reldif|round|sign|sin|sqrt|sum|tan|tanh|trigamma|trunc|betaden|Binomial|binorm|binormal|chi2|chi2tail|dgammapda|dgammapdada|dgammapdadx|dgammapdx|dgammapdxdx|F|Fden|Ftail|gammaden|gammap|ibeta|invbinomial|invchi2|invchi2tail|invF|invFtail|invgammap|invibeta|invnchi2|invnFtail|invnibeta|invnorm|invnormal|invttail|nbetaden|nchi2|nFden|nFtail|nibeta|norm|normal|normalden|normd|npnchi2|tden|ttail|uniform|abbrev|char|index|indexnot|length|lower|ltrim|match|plural|proper|real|regexm|regexr|regexs|reverse|rtrim|string|strlen|strlower|strltrim|strmatch|strofreal|strpos|strproper|strreverse|strrtrim|strtrim|strupper|subinstr|subinword|substr|trim|upper|word|wordcount|_caller|autocode|byteorder|chop|clip|cond|e|epsdouble|epsfloat|group|inlist|inrange|irecode|matrix|maxbyte|maxdouble|maxfloat|maxint|maxlong|mi|minbyte|mindouble|minfloat|minint|minlong|missing|r|recode|replay|return|s|scalar|d|date|day|dow|doy|halfyear|mdy|month|quarter|week|year|d|daily|dofd|dofh|dofm|dofq|dofw|dofy|h|halfyearly|hofd|m|mofd|monthly|q|qofd|quarterly|tin|twithin|w|weekly|wofd|y|yearly|yh|ym|yofd|yq|yw|cholesky|colnumb|colsof|corr|det|diag|diag0cnt|el|get|hadamard|I|inv|invsym|issym|issymmetric|J|matmissing|matuniform|mreldif|nullmat|rownumb|rowsof|sweep|syminv|trace|vec|vecdiag)(?=\\\\(|$)'\n          }\n        ]\n      },\n\n      hljs.COMMENT('^[ \\t]*\\\\*.*$', false),\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('step21', function(hljs) {\n  var STEP21_IDENT_RE = '[A-Z_][A-Z0-9_.]*';\n  var STEP21_CLOSE_RE = 'END-ISO-10303-21;';\n  var STEP21_KEYWORDS = {\n    literal: '',\n    built_in: '',\n    keyword:\n    'HEADER ENDSEC DATA'\n  };\n  var STEP21_START = {\n    className: 'preprocessor',\n    begin: 'ISO-10303-21;',\n    relevance: 10\n  };\n  var STEP21_CODE = [\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    hljs.COMMENT('/\\\\*\\\\*!', '\\\\*/'),\n    hljs.C_NUMBER_MODE,\n    hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),\n    hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),\n    {\n      className: 'string',\n      begin: \"'\", end: \"'\"\n    },\n    {\n      className: 'label',\n      variants: [\n        {\n          begin: '#', end: '\\\\d+',\n          illegal: '\\\\W'\n        }\n      ]\n    }\n  ];\n\n  return {\n    aliases: ['p21', 'step', 'stp'],\n    case_insensitive: true, // STEP 21 is case insensitive in theory, in practice all non-comments are capitalized.\n    lexemes: STEP21_IDENT_RE,\n    keywords: STEP21_KEYWORDS,\n    contains: [\n      {\n        className: 'preprocessor',\n        begin: STEP21_CLOSE_RE,\n        relevance: 10\n      },\n      STEP21_START\n    ].concat(STEP21_CODE)\n  };\n});\n\nhljs.registerLanguage('stylus', function(hljs) {\n\n  var VARIABLE = {\n    className: 'variable',\n    begin: '\\\\$' + hljs.IDENT_RE\n  };\n\n  var HEX_COLOR = {\n    className: 'hexcolor',\n    begin: '#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})',\n    relevance: 10\n  };\n\n  var AT_KEYWORDS = [\n    'charset',\n    'css',\n    'debug',\n    'extend',\n    'font-face',\n    'for',\n    'import',\n    'include',\n    'media',\n    'mixin',\n    'page',\n    'warn',\n    'while'\n  ];\n\n  var PSEUDO_SELECTORS = [\n    'after',\n    'before',\n    'first-letter',\n    'first-line',\n    'active',\n    'first-child',\n    'focus',\n    'hover',\n    'lang',\n    'link',\n    'visited'\n  ];\n\n  var TAGS = [\n    'a',\n    'abbr',\n    'address',\n    'article',\n    'aside',\n    'audio',\n    'b',\n    'blockquote',\n    'body',\n    'button',\n    'canvas',\n    'caption',\n    'cite',\n    'code',\n    'dd',\n    'del',\n    'details',\n    'dfn',\n    'div',\n    'dl',\n    'dt',\n    'em',\n    'fieldset',\n    'figcaption',\n    'figure',\n    'footer',\n    'form',\n    'h1',\n    'h2',\n    'h3',\n    'h4',\n    'h5',\n    'h6',\n    'header',\n    'hgroup',\n    'html',\n    'i',\n    'iframe',\n    'img',\n    'input',\n    'ins',\n    'kbd',\n    'label',\n    'legend',\n    'li',\n    'mark',\n    'menu',\n    'nav',\n    'object',\n    'ol',\n    'p',\n    'q',\n    'quote',\n    'samp',\n    'section',\n    'span',\n    'strong',\n    'summary',\n    'sup',\n    'table',\n    'tbody',\n    'td',\n    'textarea',\n    'tfoot',\n    'th',\n    'thead',\n    'time',\n    'tr',\n    'ul',\n    'var',\n    'video'\n  ];\n\n  var TAG_END = '[\\\\.\\\\s\\\\n\\\\[\\\\:,]';\n\n  var ATTRIBUTES = [\n    'align-content',\n    'align-items',\n    'align-self',\n    'animation',\n    'animation-delay',\n    'animation-direction',\n    'animation-duration',\n    'animation-fill-mode',\n    'animation-iteration-count',\n    'animation-name',\n    'animation-play-state',\n    'animation-timing-function',\n    'auto',\n    'backface-visibility',\n    'background',\n    'background-attachment',\n    'background-clip',\n    'background-color',\n    'background-image',\n    'background-origin',\n    'background-position',\n    'background-repeat',\n    'background-size',\n    'border',\n    'border-bottom',\n    'border-bottom-color',\n    'border-bottom-left-radius',\n    'border-bottom-right-radius',\n    'border-bottom-style',\n    'border-bottom-width',\n    'border-collapse',\n    'border-color',\n    'border-image',\n    'border-image-outset',\n    'border-image-repeat',\n    'border-image-slice',\n    'border-image-source',\n    'border-image-width',\n    'border-left',\n    'border-left-color',\n    'border-left-style',\n    'border-left-width',\n    'border-radius',\n    'border-right',\n    'border-right-color',\n    'border-right-style',\n    'border-right-width',\n    'border-spacing',\n    'border-style',\n    'border-top',\n    'border-top-color',\n    'border-top-left-radius',\n    'border-top-right-radius',\n    'border-top-style',\n    'border-top-width',\n    'border-width',\n    'bottom',\n    'box-decoration-break',\n    'box-shadow',\n    'box-sizing',\n    'break-after',\n    'break-before',\n    'break-inside',\n    'caption-side',\n    'clear',\n    'clip',\n    'clip-path',\n    'color',\n    'column-count',\n    'column-fill',\n    'column-gap',\n    'column-rule',\n    'column-rule-color',\n    'column-rule-style',\n    'column-rule-width',\n    'column-span',\n    'column-width',\n    'columns',\n    'content',\n    'counter-increment',\n    'counter-reset',\n    'cursor',\n    'direction',\n    'display',\n    'empty-cells',\n    'filter',\n    'flex',\n    'flex-basis',\n    'flex-direction',\n    'flex-flow',\n    'flex-grow',\n    'flex-shrink',\n    'flex-wrap',\n    'float',\n    'font',\n    'font-family',\n    'font-feature-settings',\n    'font-kerning',\n    'font-language-override',\n    'font-size',\n    'font-size-adjust',\n    'font-stretch',\n    'font-style',\n    'font-variant',\n    'font-variant-ligatures',\n    'font-weight',\n    'height',\n    'hyphens',\n    'icon',\n    'image-orientation',\n    'image-rendering',\n    'image-resolution',\n    'ime-mode',\n    'inherit',\n    'initial',\n    'justify-content',\n    'left',\n    'letter-spacing',\n    'line-height',\n    'list-style',\n    'list-style-image',\n    'list-style-position',\n    'list-style-type',\n    'margin',\n    'margin-bottom',\n    'margin-left',\n    'margin-right',\n    'margin-top',\n    'marks',\n    'mask',\n    'max-height',\n    'max-width',\n    'min-height',\n    'min-width',\n    'nav-down',\n    'nav-index',\n    'nav-left',\n    'nav-right',\n    'nav-up',\n    'none',\n    'normal',\n    'object-fit',\n    'object-position',\n    'opacity',\n    'order',\n    'orphans',\n    'outline',\n    'outline-color',\n    'outline-offset',\n    'outline-style',\n    'outline-width',\n    'overflow',\n    'overflow-wrap',\n    'overflow-x',\n    'overflow-y',\n    'padding',\n    'padding-bottom',\n    'padding-left',\n    'padding-right',\n    'padding-top',\n    'page-break-after',\n    'page-break-before',\n    'page-break-inside',\n    'perspective',\n    'perspective-origin',\n    'pointer-events',\n    'position',\n    'quotes',\n    'resize',\n    'right',\n    'tab-size',\n    'table-layout',\n    'text-align',\n    'text-align-last',\n    'text-decoration',\n    'text-decoration-color',\n    'text-decoration-line',\n    'text-decoration-style',\n    'text-indent',\n    'text-overflow',\n    'text-rendering',\n    'text-shadow',\n    'text-transform',\n    'text-underline-position',\n    'top',\n    'transform',\n    'transform-origin',\n    'transform-style',\n    'transition',\n    'transition-delay',\n    'transition-duration',\n    'transition-property',\n    'transition-timing-function',\n    'unicode-bidi',\n    'vertical-align',\n    'visibility',\n    'white-space',\n    'widows',\n    'width',\n    'word-break',\n    'word-spacing',\n    'word-wrap',\n    'z-index'\n  ];\n\n  // illegals\n  var ILLEGAL = [\n    '\\\\{',\n    '\\\\}',\n    '\\\\?',\n    '(\\\\bReturn\\\\b)', // monkey\n    '(\\\\bEnd\\\\b)', // monkey\n    '(\\\\bend\\\\b)', // vbscript\n    ';', // sql\n    '#\\\\s', // markdown\n    '\\\\*\\\\s', // markdown\n    '===\\\\s', // markdown\n    '\\\\|',\n    '%', // prolog\n  ];\n\n  return {\n    aliases: ['styl'],\n    case_insensitive: false,\n    illegal: '(' + ILLEGAL.join('|') + ')',\n    keywords: 'if else for in',\n    contains: [\n\n      // strings\n      hljs.QUOTE_STRING_MODE,\n      hljs.APOS_STRING_MODE,\n\n      // comments\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n\n      // hex colors\n      HEX_COLOR,\n\n      // class tag\n      {\n        begin: '\\\\.[a-zA-Z][a-zA-Z0-9_-]*' + TAG_END,\n        returnBegin: true,\n        contains: [\n          {className: 'class', begin: '\\\\.[a-zA-Z][a-zA-Z0-9_-]*'}\n        ]\n      },\n\n      // id tag\n      {\n        begin: '\\\\#[a-zA-Z][a-zA-Z0-9_-]*' + TAG_END,\n        returnBegin: true,\n        contains: [\n          {className: 'id', begin: '\\\\#[a-zA-Z][a-zA-Z0-9_-]*'}\n        ]\n      },\n\n      // tags\n      {\n        begin: '\\\\b(' + TAGS.join('|') + ')' + TAG_END,\n        returnBegin: true,\n        contains: [\n          {className: 'tag', begin: '\\\\b[a-zA-Z][a-zA-Z0-9_-]*'}\n        ]\n      },\n\n      // psuedo selectors\n      {\n        className: 'pseudo',\n        begin: '&?:?:\\\\b(' + PSEUDO_SELECTORS.join('|') + ')' + TAG_END\n      },\n\n      // @ keywords\n      {\n        className: 'at_rule',\n        begin: '\\@(' + AT_KEYWORDS.join('|') + ')\\\\b'\n      },\n\n      // variables\n      VARIABLE,\n\n      // dimension\n      hljs.CSS_NUMBER_MODE,\n\n      // number\n      hljs.NUMBER_MODE,\n\n      // functions\n      //  - only from beginning of line + whitespace\n      {\n        className: 'function',\n        begin: '\\\\b[a-zA-Z][a-zA-Z0-9_\\-]*\\\\(.*\\\\)',\n        illegal: '[\\\\n]',\n        returnBegin: true,\n        contains: [\n          {className: 'title', begin: '\\\\b[a-zA-Z][a-zA-Z0-9_\\-]*'},\n          {\n            className: 'params',\n            begin: /\\(/,\n            end: /\\)/,\n            contains: [\n              HEX_COLOR,\n              VARIABLE,\n              hljs.APOS_STRING_MODE,\n              hljs.CSS_NUMBER_MODE,\n              hljs.NUMBER_MODE,\n              hljs.QUOTE_STRING_MODE\n            ]\n          }\n        ]\n      },\n\n      // attributes\n      //  - only from beginning of line + whitespace\n      //  - must have whitespace after it\n      {\n        className: 'attribute',\n        begin: '\\\\b(' + ATTRIBUTES.reverse().join('|') + ')\\\\b'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('swift', function(hljs) {\n  var SWIFT_KEYWORDS = {\n      keyword: '__COLUMN__ __FILE__ __FUNCTION__ __LINE__ as as! as? associativity ' +\n        'break case catch class continue convenience default defer deinit didSet do ' +\n        'dynamic dynamicType else enum extension fallthrough false final for func ' +\n        'get guard if import in indirect infix init inout internal is lazy left let ' +\n        'mutating nil none nonmutating operator optional override postfix precedence ' +\n        'prefix private protocol Protocol public repeat required rethrows return ' +\n        'right self Self set static struct subscript super switch throw throws true ' +\n        'try try! try? Type typealias unowned var weak where while willSet',\n      literal: 'true false nil',\n      built_in: 'abs advance alignof alignofValue anyGenerator assert assertionFailure ' +\n        'bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC ' +\n        'bridgeToObjectiveCUnconditional c contains count countElements countLeadingZeros ' +\n        'debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords ' +\n        'enumerate equal fatalError filter find getBridgedObjectiveCType getVaList ' +\n        'indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC ' +\n        'isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare ' +\n        'map max maxElement min minElement numericCast overlaps partition posix ' +\n        'precondition preconditionFailure print println quickSort readLine reduce reflect ' +\n        'reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split ' +\n        'startsWith stride strideof strideofValue swap toString transcode ' +\n        'underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap ' +\n        'unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer ' +\n        'withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers ' +\n        'withUnsafePointer withUnsafePointers withVaList zip'\n    };\n\n  var TYPE = {\n    className: 'type',\n    begin: '\\\\b[A-Z][\\\\w\\']*',\n    relevance: 0\n  };\n  var BLOCK_COMMENT = hljs.COMMENT(\n    '/\\\\*',\n    '\\\\*/',\n    {\n      contains: ['self']\n    }\n  );\n  var SUBST = {\n    className: 'subst',\n    begin: /\\\\\\(/, end: '\\\\)',\n    keywords: SWIFT_KEYWORDS,\n    contains: [] // assigned later\n  };\n  var NUMBERS = {\n      className: 'number',\n      begin: '\\\\b([\\\\d_]+(\\\\.[\\\\deE_]+)?|0x[a-fA-F0-9_]+(\\\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\\\b',\n      relevance: 0\n  };\n  var QUOTE_STRING_MODE = hljs.inherit(hljs.QUOTE_STRING_MODE, {\n    contains: [SUBST, hljs.BACKSLASH_ESCAPE]\n  });\n  SUBST.contains = [NUMBERS];\n\n  return {\n    keywords: SWIFT_KEYWORDS,\n    contains: [\n      QUOTE_STRING_MODE,\n      hljs.C_LINE_COMMENT_MODE,\n      BLOCK_COMMENT,\n      TYPE,\n      NUMBERS,\n      {\n        className: 'func',\n        beginKeywords: 'func', end: '{', excludeEnd: true,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {\n            begin: /[A-Za-z$_][0-9A-Za-z$_]*/,\n            illegal: /\\(/\n          }),\n          {\n            className: 'generics',\n            begin: /</, end: />/,\n            illegal: />/\n          },\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/, endsParent: true,\n            keywords: SWIFT_KEYWORDS,\n            contains: [\n              'self',\n              NUMBERS,\n              QUOTE_STRING_MODE,\n              hljs.C_BLOCK_COMMENT_MODE,\n              {begin: ':'} // relevance booster\n            ],\n            illegal: /[\"']/\n          }\n        ],\n        illegal: /\\[|%/\n      },\n      {\n        className: 'class',\n        beginKeywords: 'struct protocol class extension enum',\n        keywords: SWIFT_KEYWORDS,\n        end: '\\\\{',\n        excludeEnd: true,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {begin: /[A-Za-z$_][0-9A-Za-z$_]*/})\n        ]\n      },\n      {\n        className: 'preprocessor', // @attributes\n        begin: '(@warn_unused_result|@exported|@lazy|@noescape|' +\n                  '@NSCopying|@NSManaged|@objc|@convention|@required|' +\n                  '@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|' +\n                  '@infix|@prefix|@postfix|@autoclosure|@testable|@available|' +\n                  '@nonobjc|@NSApplicationMain|@UIApplicationMain)'\n\n      },\n      {\n        beginKeywords: 'import', end: /$/,\n        contains: [hljs.C_LINE_COMMENT_MODE, BLOCK_COMMENT]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('tcl', function(hljs) {\n  return {\n    aliases: ['tk'],\n    keywords: 'after append apply array auto_execok auto_import auto_load auto_mkindex ' +\n      'auto_mkindex_old auto_qualify auto_reset bgerror binary break catch cd chan clock ' +\n      'close concat continue dde dict encoding eof error eval exec exit expr fblocked ' +\n      'fconfigure fcopy file fileevent filename flush for foreach format gets glob global ' +\n      'history http if incr info interp join lappend|10 lassign|10 lindex|10 linsert|10 list ' +\n      'llength|10 load lrange|10 lrepeat|10 lreplace|10 lreverse|10 lsearch|10 lset|10 lsort|10 '+\n      'mathfunc mathop memory msgcat namespace open package parray pid pkg::create pkg_mkIndex '+\n      'platform platform::shell proc puts pwd read refchan regexp registry regsub|10 rename '+\n      'return safe scan seek set socket source split string subst switch tcl_endOfWord '+\n      'tcl_findLibrary tcl_startOfNextWord tcl_startOfPreviousWord tcl_wordBreakAfter '+\n      'tcl_wordBreakBefore tcltest tclvars tell time tm trace unknown unload unset update '+\n      'uplevel upvar variable vwait while',\n    contains: [\n      hljs.COMMENT(';[ \\\\t]*#', '$'),\n      hljs.COMMENT('^[ \\\\t]*#', '$'),\n      {\n        beginKeywords: 'proc',\n        end: '[\\\\{]',\n        excludeEnd: true,\n        contains: [\n          {\n            className: 'symbol',\n            begin: '[ \\\\t\\\\n\\\\r]+(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*',\n            end: '[ \\\\t\\\\n\\\\r]',\n            endsWithParent: true,\n            excludeEnd: true\n          }\n        ]\n      },\n      {\n        className: 'variable',\n        excludeEnd: true,\n        variants: [\n          {\n            begin: '\\\\$(\\\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*\\\\(([a-zA-Z0-9_])*\\\\)',\n            end: '[^a-zA-Z0-9_\\\\}\\\\$]'\n          },\n          {\n            begin: '\\\\$(\\\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*',\n            end: '(\\\\))?[^a-zA-Z0-9_\\\\}\\\\$]'\n          }\n        ]\n      },\n      {\n        className: 'string',\n        contains: [hljs.BACKSLASH_ESCAPE],\n        variants: [\n          hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),\n          hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null})\n        ]\n      },\n      {\n        className: 'number',\n        variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]\n      }\n    ]\n  }\n});\n\nhljs.registerLanguage('tex', function(hljs) {\n  var COMMAND1 = {\n    className: 'command',\n    begin: '\\\\\\\\[a-zA-Zа-яА-я]+[\\\\*]?'\n  };\n  var COMMAND2 = {\n    className: 'command',\n    begin: '\\\\\\\\[^a-zA-Zа-яА-я0-9]'\n  };\n  var SPECIAL = {\n    className: 'special',\n    begin: '[{}\\\\[\\\\]\\\\&#~]',\n    relevance: 0\n  };\n\n  return {\n    contains: [\n      { // parameter\n        begin: '\\\\\\\\[a-zA-Zа-яА-я]+[\\\\*]? *= *-?\\\\d*\\\\.?\\\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?',\n        returnBegin: true,\n        contains: [\n          COMMAND1, COMMAND2,\n          {\n            className: 'number',\n            begin: ' *=', end: '-?\\\\d*\\\\.?\\\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?',\n            excludeBegin: true\n          }\n        ],\n        relevance: 10\n      },\n      COMMAND1, COMMAND2,\n      SPECIAL,\n      {\n        className: 'formula',\n        begin: '\\\\$\\\\$', end: '\\\\$\\\\$',\n        contains: [COMMAND1, COMMAND2, SPECIAL],\n        relevance: 0\n      },\n      {\n        className: 'formula',\n        begin: '\\\\$', end: '\\\\$',\n        contains: [COMMAND1, COMMAND2, SPECIAL],\n        relevance: 0\n      },\n      hljs.COMMENT(\n        '%',\n        '$',\n        {\n          relevance: 0\n        }\n      )\n    ]\n  };\n});\n\nhljs.registerLanguage('thrift', function(hljs) {\n  var BUILT_IN_TYPES = 'bool byte i16 i32 i64 double string binary';\n  return {\n    keywords: {\n      keyword:\n        'namespace const typedef struct enum service exception void oneway set list map required optional',\n      built_in:\n        BUILT_IN_TYPES,\n      literal:\n        'true false'\n    },\n    contains: [\n      hljs.QUOTE_STRING_MODE,\n      hljs.NUMBER_MODE,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'class',\n        beginKeywords: 'struct enum service exception', end: /\\{/,\n        illegal: /\\n/,\n        contains: [\n          hljs.inherit(hljs.TITLE_MODE, {\n            starts: {endsWithParent: true, excludeEnd: true} // hack: eating everything after the first title\n          })\n        ]\n      },\n      {\n        begin: '\\\\b(set|list|map)\\\\s*<', end: '>',\n        keywords: BUILT_IN_TYPES,\n        contains: ['self']\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('tp', function(hljs) {\n  var TPID = {\n    className: 'number',\n    begin: '[1-9][0-9]*', /* no leading zeros */\n    relevance: 0\n  };\n  var TPLABEL = {\n    className: 'comment',\n    begin: ':[^\\\\]]+'\n  };\n  var TPDATA = {\n    className: 'built_in',\n    begin: '(AR|P|PAYLOAD|PR|R|SR|RSR|LBL|VR|UALM|MESSAGE|UTOOL|UFRAME|TIMER|\\\n    TIMER_OVERFLOW|JOINT_MAX_SPEED|RESUME_PROG|DIAG_REC)\\\\[', end: '\\\\]',\n    contains: [\n      'self',\n      TPID,\n      TPLABEL\n    ]\n  };\n  var TPIO = {\n    className: 'built_in',\n    begin: '(AI|AO|DI|DO|F|RI|RO|UI|UO|GI|GO|SI|SO)\\\\[', end: '\\\\]',\n    contains: [\n      'self',\n      TPID,\n      hljs.QUOTE_STRING_MODE, /* for pos section at bottom */\n      TPLABEL\n    ]\n  };\n\n  return {\n    keywords: {\n      keyword:\n        'ABORT ACC ADJUST AND AP_LD BREAK CALL CNT COL CONDITION CONFIG DA DB ' +\n        'DIV DETECT ELSE END ENDFOR ERR_NUM ERROR_PROG FINE FOR GP GUARD INC ' +\n        'IF JMP LINEAR_MAX_SPEED LOCK MOD MONITOR OFFSET Offset OR OVERRIDE ' +\n        'PAUSE PREG PTH RT_LD RUN SELECT SKIP Skip TA TB TO TOOL_OFFSET ' +\n        'Tool_Offset UF UT UFRAME_NUM UTOOL_NUM UNLOCK WAIT X Y Z W P R STRLEN ' +\n        'SUBSTR FINDSTR VOFFSET',\n      constant:\n        'ON OFF max_speed LPOS JPOS ENABLE DISABLE START STOP RESET'\n    },\n    contains: [\n      TPDATA,\n      TPIO,\n      {\n        className: 'keyword',\n        begin: '/(PROG|ATTR|MN|POS|END)\\\\b'\n      },\n      {\n        /* this is for cases like ,CALL */\n        className: 'keyword',\n        begin: '(CALL|RUN|POINT_LOGIC|LBL)\\\\b'\n      },\n      {\n        /* this is for cases like CNT100 where the default lexemes do not\n         * separate the keyword and the number */\n        className: 'keyword',\n        begin: '\\\\b(ACC|CNT|Skip|Offset|PSPD|RT_LD|AP_LD|Tool_Offset)'\n      },\n      {\n        /* to catch numbers that do not have a word boundary on the left */\n        className: 'number',\n        begin: '\\\\d+(sec|msec|mm/sec|cm/min|inch/min|deg/sec|mm|in|cm)?\\\\b',\n        relevance: 0\n      },\n      hljs.COMMENT('//', '[;$]'),\n      hljs.COMMENT('!', '[;$]'),\n      hljs.COMMENT('--eg:', '$'),\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        begin: '\\'', end: '\\''\n      },\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'variable',\n        begin: '\\\\$[A-Za-z0-9_]+'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('twig', function(hljs) {\n  var PARAMS = {\n    className: 'params',\n    begin: '\\\\(', end: '\\\\)'\n  };\n\n  var FUNCTION_NAMES = 'attribute block constant cycle date dump include ' +\n                  'max min parent random range source template_from_string';\n\n  var FUNCTIONS = {\n    className: 'function',\n    beginKeywords: FUNCTION_NAMES,\n    relevance: 0,\n    contains: [\n      PARAMS\n    ]\n  };\n\n  var FILTER = {\n    className: 'filter',\n    begin: /\\|[A-Za-z_]+:?/,\n    keywords:\n      'abs batch capitalize convert_encoding date date_modify default ' +\n      'escape first format join json_encode keys last length lower ' +\n      'merge nl2br number_format raw replace reverse round slice sort split ' +\n      'striptags title trim upper url_encode',\n    contains: [\n      FUNCTIONS\n    ]\n  };\n\n  var TAGS = 'autoescape block do embed extends filter flush for ' +\n    'if import include macro sandbox set spaceless use verbatim';\n\n  TAGS = TAGS + ' ' + TAGS.split(' ').map(function(t){return 'end' + t}).join(' ');\n\n  return {\n    aliases: ['craftcms'],\n    case_insensitive: true,\n    subLanguage: 'xml',\n    contains: [\n      hljs.COMMENT(/\\{#/, /#}/),\n      {\n        className: 'template_tag',\n        begin: /\\{%/, end: /%}/,\n        keywords: TAGS,\n        contains: [FILTER, FUNCTIONS]\n      },\n      {\n        className: 'variable',\n        begin: /\\{\\{/, end: /}}/,\n        contains: [FILTER, FUNCTIONS]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('typescript', function(hljs) {\n  var KEYWORDS = {\n    keyword:\n      'in if for while finally var new function|0 do return void else break catch ' +\n      'instanceof with throw case default try this switch continue typeof delete ' +\n      'let yield const class public private protected get set super ' +\n      'static implements enum export import declare type namespace abstract',\n    literal:\n      'true false null undefined NaN Infinity',\n    built_in:\n      'eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent ' +\n      'encodeURI encodeURIComponent escape unescape Object Function Boolean Error ' +\n      'EvalError InternalError RangeError ReferenceError StopIteration SyntaxError ' +\n      'TypeError URIError Number Math Date String RegExp Array Float32Array ' +\n      'Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array ' +\n      'Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require ' +\n      'module console window document any number boolean string void'\n  };\n\n  return {\n    aliases: ['ts'],\n    keywords: KEYWORDS,\n    contains: [\n      {\n        className: 'pi',\n        begin: /^\\s*['\"]use strict['\"]/,\n        relevance: 0\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'number',\n        variants: [\n          { begin: '\\\\b(0[bB][01]+)' },\n          { begin: '\\\\b(0[oO][0-7]+)' },\n          { begin: hljs.C_NUMBER_RE }\n        ],\n        relevance: 0\n      },\n      { // \"value\" container\n        begin: '(' + hljs.RE_STARTERS_RE + '|\\\\b(case|return|throw)\\\\b)\\\\s*',\n        keywords: 'return throw case',\n        contains: [\n          hljs.C_LINE_COMMENT_MODE,\n          hljs.C_BLOCK_COMMENT_MODE,\n          hljs.REGEXP_MODE\n        ],\n        relevance: 0\n      },\n      {\n        className: 'function',\n        begin: 'function', end: /[\\{;]/, excludeEnd: true,\n        keywords: KEYWORDS,\n        contains: [\n          'self',\n          hljs.inherit(hljs.TITLE_MODE, {begin: /[A-Za-z$_][0-9A-Za-z$_]*/}),\n          {\n            className: 'params',\n            begin: /\\(/, end: /\\)/,\n            excludeBegin: true,\n            excludeEnd: true,\n            keywords: KEYWORDS,\n            contains: [\n              hljs.C_LINE_COMMENT_MODE,\n              hljs.C_BLOCK_COMMENT_MODE\n            ],\n            illegal: /[\"'\\(]/\n          }\n        ],\n        illegal: /\\[|%/,\n        relevance: 0 // () => {} is more typical in TypeScript\n      },\n      {\n        className: 'constructor',\n        beginKeywords: 'constructor', end: /\\{/, excludeEnd: true,\n        relevance: 10\n      },\n      {\n        className: 'module',\n        beginKeywords: 'module', end: /\\{/, excludeEnd: true\n      },\n      {\n        className: 'interface',\n        beginKeywords: 'interface', end: /\\{/, excludeEnd: true,\n        keywords: 'interface extends'\n      },\n      {\n        begin: /\\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`\n      },\n      {\n        begin: '\\\\.' + hljs.IDENT_RE, relevance: 0 // hack: prevents detection of keywords after dots\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('vala', function(hljs) {\n  return {\n    keywords: {\n      keyword:\n        // Value types\n        'char uchar unichar int uint long ulong short ushort int8 int16 int32 int64 uint8 ' +\n        'uint16 uint32 uint64 float double bool struct enum string void ' +\n        // Reference types\n        'weak unowned owned ' +\n        // Modifiers\n        'async signal static abstract interface override ' +\n        // Control Structures\n        'while do for foreach else switch case break default return try catch ' +\n        // Visibility\n        'public private protected internal ' +\n        // Other\n        'using new this get set const stdout stdin stderr var',\n      built_in:\n        'DBus GLib CCode Gee Object',\n      literal:\n        'false true null'\n    },\n    contains: [\n      {\n        className: 'class',\n        beginKeywords: 'class interface delegate namespace', end: '{', excludeEnd: true,\n        illegal: '[^,:\\\\n\\\\s\\\\.]',\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.C_BLOCK_COMMENT_MODE,\n      {\n        className: 'string',\n        begin: '\"\"\"', end: '\"\"\"',\n        relevance: 5\n      },\n      hljs.APOS_STRING_MODE,\n      hljs.QUOTE_STRING_MODE,\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'preprocessor',\n        begin: '^#', end: '$',\n        relevance: 2\n      },\n      {\n        className: 'constant',\n        begin: ' [A-Z_]+ ',\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('vbnet', function(hljs) {\n  return {\n    aliases: ['vb'],\n    case_insensitive: true,\n    keywords: {\n      keyword:\n        'addhandler addressof alias and andalso aggregate ansi as assembly auto binary by byref byval ' + /* a-b */\n        'call case catch class compare const continue custom declare default delegate dim distinct do ' + /* c-d */\n        'each equals else elseif end enum erase error event exit explicit finally for friend from function ' + /* e-f */\n        'get global goto group handles if implements imports in inherits interface into is isfalse isnot istrue ' + /* g-i */\n        'join key let lib like loop me mid mod module mustinherit mustoverride mybase myclass ' + /* j-m */\n        'namespace narrowing new next not notinheritable notoverridable ' + /* n */\n        'of off on operator option optional or order orelse overloads overridable overrides ' + /* o */\n        'paramarray partial preserve private property protected public ' + /* p */\n        'raiseevent readonly redim rem removehandler resume return ' + /* r */\n        'select set shadows shared skip static step stop structure strict sub synclock ' + /* s */\n        'take text then throw to try unicode until using when where while widening with withevents writeonly xor', /* t-x */\n      built_in:\n        'boolean byte cbool cbyte cchar cdate cdec cdbl char cint clng cobj csbyte cshort csng cstr ctype ' +  /* b-c */\n        'date decimal directcast double gettype getxmlnamespace iif integer long object ' + /* d-o */\n        'sbyte short single string trycast typeof uinteger ulong ushort', /* s-u */\n      literal:\n        'true false nothing'\n    },\n    illegal: '//|{|}|endif|gosub|variant|wend', /* reserved deprecated keywords */\n    contains: [\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {contains: [{begin: '\"\"'}]}),\n      hljs.COMMENT(\n        '\\'',\n        '$',\n        {\n          returnBegin: true,\n          contains: [\n            {\n              className: 'xmlDocTag',\n              begin: '\\'\\'\\'|<!--|-->',\n              contains: [hljs.PHRASAL_WORDS_MODE]\n            },\n            {\n              className: 'xmlDocTag',\n              begin: '</?', end: '>',\n              contains: [hljs.PHRASAL_WORDS_MODE]\n            }\n          ]\n        }\n      ),\n      hljs.C_NUMBER_MODE,\n      {\n        className: 'preprocessor',\n        begin: '#', end: '$',\n        keywords: 'if else elseif end region externalsource'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('vbscript', function(hljs) {\n  return {\n    aliases: ['vbs'],\n    case_insensitive: true,\n    keywords: {\n      keyword:\n        'call class const dim do loop erase execute executeglobal exit for each next function ' +\n        'if then else on error option explicit new private property let get public randomize ' +\n        'redim rem select case set stop sub while wend with end to elseif is or xor and not ' +\n        'class_initialize class_terminate default preserve in me byval byref step resume goto',\n      built_in:\n        'lcase month vartype instrrev ubound setlocale getobject rgb getref string ' +\n        'weekdayname rnd dateadd monthname now day minute isarray cbool round formatcurrency ' +\n        'conversions csng timevalue second year space abs clng timeserial fixs len asc ' +\n        'isempty maths dateserial atn timer isobject filter weekday datevalue ccur isdate ' +\n        'instr datediff formatdatetime replace isnull right sgn array snumeric log cdbl hex ' +\n        'chr lbound msgbox ucase getlocale cos cdate cbyte rtrim join hour oct typename trim ' +\n        'strcomp int createobject loadpicture tan formatnumber mid scriptenginebuildversion ' +\n        'scriptengine split scriptengineminorversion cint sin datepart ltrim sqr ' +\n        'scriptenginemajorversion time derived eval date formatpercent exp inputbox left ascw ' +\n        'chrw regexp server response request cstr err',\n      literal:\n        'true false null nothing empty'\n    },\n    illegal: '//',\n    contains: [\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {contains: [{begin: '\"\"'}]}),\n      hljs.COMMENT(\n        /'/,\n        /$/,\n        {\n          relevance: 0\n        }\n      ),\n      hljs.C_NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('vbscript-html', function(hljs) {\n  return {\n    subLanguage: 'xml',\n    contains: [\n      {\n        begin: '<%', end: '%>',\n        subLanguage: 'vbscript'\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('verilog', function(hljs) {\n  return {\n    aliases: ['v'],\n    case_insensitive: true,\n    keywords: {\n      keyword:\n        'always and assign begin buf bufif0 bufif1 case casex casez cmos deassign ' +\n        'default defparam disable edge else end endcase endfunction endmodule ' +\n        'endprimitive endspecify endtable endtask event for force forever fork ' +\n        'function if ifnone initial inout input join macromodule module nand ' +\n        'negedge nmos nor not notif0 notif1 or output parameter pmos posedge ' +\n        'primitive pulldown pullup rcmos release repeat rnmos rpmos rtran ' +\n        'rtranif0 rtranif1 specify specparam table task timescale tran ' +\n        'tranif0 tranif1 wait while xnor xor',\n      typename:\n        'highz0 highz1 integer large medium pull0 pull1 real realtime reg ' +\n        'scalared signed small strong0 strong1 supply0 supply0 supply1 supply1 ' +\n        'time tri tri0 tri1 triand trior trireg vectored wand weak0 weak1 wire wor'\n    },\n    contains: [\n      hljs.C_BLOCK_COMMENT_MODE,\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'number',\n        begin: '\\\\b(\\\\d+\\'(b|h|o|d|B|H|O|D))?[0-9xzXZ]+',\n        contains: [hljs.BACKSLASH_ESCAPE],\n        relevance: 0\n      },\n      /* ports in instances */\n      {\n        className: 'typename',\n        begin: '\\\\.\\\\w+',\n        relevance: 0\n      },\n      /* parameters to instances */\n      {\n        className: 'value',\n        begin: '#\\\\((?!parameter).+\\\\)'\n      },\n      /* operators */\n      {\n        className: 'keyword',\n        begin: '\\\\+|-|\\\\*|/|%|<|>|=|#|`|\\\\!|&|\\\\||@|:|\\\\^|~|\\\\{|\\\\}',\n        relevance: 0\n      }\n    ]\n  }; // return\n});\n\nhljs.registerLanguage('vhdl', function(hljs) {\n  // Regular expression for VHDL numeric literals.\n\n  // Decimal literal:\n  var INTEGER_RE = '\\\\d(_|\\\\d)*';\n  var EXPONENT_RE = '[eE][-+]?' + INTEGER_RE;\n  var DECIMAL_LITERAL_RE = INTEGER_RE + '(\\\\.' + INTEGER_RE + ')?' + '(' + EXPONENT_RE + ')?';\n  // Based literal:\n  var BASED_INTEGER_RE = '\\\\w+';\n  var BASED_LITERAL_RE = INTEGER_RE + '#' + BASED_INTEGER_RE + '(\\\\.' + BASED_INTEGER_RE + ')?' + '#' + '(' + EXPONENT_RE + ')?';\n\n  var NUMBER_RE = '\\\\b(' + BASED_LITERAL_RE + '|' + DECIMAL_LITERAL_RE + ')';\n\n  return {\n    case_insensitive: true,\n    keywords: {\n      keyword:\n        'abs access after alias all and architecture array assert attribute begin block ' +\n        'body buffer bus case component configuration constant context cover disconnect ' +\n        'downto default else elsif end entity exit fairness file for force function generate ' +\n        'generic group guarded if impure in inertial inout is label library linkage literal ' +\n        'loop map mod nand new next nor not null of on open or others out package port ' +\n        'postponed procedure process property protected pure range record register reject ' +\n        'release rem report restrict restrict_guarantee return rol ror select sequence ' +\n        'severity shared signal sla sll sra srl strong subtype then to transport type ' +\n        'unaffected units until use variable vmode vprop vunit wait when while with xnor xor',\n      typename:\n        'boolean bit character severity_level integer time delay_length natural positive ' +\n        'string bit_vector file_open_kind file_open_status std_ulogic std_ulogic_vector ' +\n        'std_logic std_logic_vector unsigned signed boolean_vector integer_vector ' +\n        'real_vector time_vector'\n    },\n    illegal: '{',\n    contains: [\n      hljs.C_BLOCK_COMMENT_MODE,        // VHDL-2008 block commenting.\n      hljs.COMMENT('--', '$'),\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'number',\n        begin: NUMBER_RE,\n        relevance: 0\n      },\n      {\n        className: 'literal',\n        begin: '\\'(U|X|0|1|Z|W|L|H|-)\\'',\n        contains: [hljs.BACKSLASH_ESCAPE]\n      },\n      {\n        className: 'attribute',\n        begin: '\\'[A-Za-z](_?[A-Za-z0-9])*',\n        contains: [hljs.BACKSLASH_ESCAPE]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('vim', function(hljs) {\n  return {\n    lexemes: /[!#@\\w]+/,\n    keywords: {\n      keyword: //ex command\n        // express version except: ! & * < = > !! # @ @@\n        'N|0 P|0 X|0 a|0 ab abc abo al am an|0 ar arga argd arge argdo argg argl argu as au aug aun b|0 bN ba bad bd be bel bf bl bm bn bo bp br brea breaka breakd breakl bro bufdo buffers bun bw c|0 cN cNf ca cabc caddb cad caddf cal cat cb cc ccl cd ce cex cf cfir cgetb cgete cg changes chd che checkt cl cla clo cm cmapc cme cn cnew cnf cno cnorea cnoreme co col colo com comc comp con conf cope '+\n        'cp cpf cq cr cs cst cu cuna cunme cw d|0 delm deb debugg delc delf dif diffg diffo diffp diffpu diffs diffthis dig di dl dell dj dli do doautoa dp dr ds dsp e|0 ea ec echoe echoh echom echon el elsei em en endfo endf endt endw ene ex exe exi exu f|0 files filet fin fina fini fir fix fo foldc foldd folddoc foldo for fu g|0 go gr grepa gu gv ha h|0 helpf helpg helpt hi hid his i|0 ia iabc if ij il im imapc '+\n        'ime ino inorea inoreme int is isp iu iuna iunme j|0 ju k|0 keepa kee keepj lN lNf l|0 lad laddb laddf la lan lat lb lc lch lcl lcs le lefta let lex lf lfir lgetb lgete lg lgr lgrepa lh ll lla lli lmak lm lmapc lne lnew lnf ln loadk lo loc lockv lol lope lp lpf lr ls lt lu lua luad luaf lv lvimgrepa lw m|0 ma mak map mapc marks mat me menut mes mk mks mksp mkv mkvie mod mz mzf nbc nb nbs n|0 new nm nmapc nme nn nnoreme noa no noh norea noreme norm nu nun nunme ol o|0 om omapc ome on ono onoreme opt ou ounme ow p|0 '+\n        'profd prof pro promptr pc ped pe perld po popu pp pre prev ps pt ptN ptf ptj ptl ptn ptp ptr pts pu pw py3 python3 py3d py3f py pyd pyf q|0 quita qa r|0 rec red redi redr redraws reg res ret retu rew ri rightb rub rubyd rubyf rund ru rv s|0 sN san sa sal sav sb sbN sba sbf sbl sbm sbn sbp sbr scrip scripte scs se setf setg setl sf sfir sh sim sig sil sl sla sm smap smapc sme sn sni sno snor snoreme sor '+\n        'so spelld spe spelli spellr spellu spellw sp spr sre st sta startg startr star stopi stj sts sun sunm sunme sus sv sw sy synti sync t|0 tN tabN tabc tabdo tabe tabf tabfir tabl tabm tabnew '+\n        'tabn tabo tabp tabr tabs tab ta tags tc tcld tclf te tf th tj tl tm tn to tp tr try ts tu u|0 undoj undol una unh unl unlo unm unme uns up v|0 ve verb vert vim vimgrepa vi viu vie vm vmapc vme vne vn vnoreme vs vu vunme windo w|0 wN wa wh wi winc winp wn wp wq wqa ws wu wv x|0 xa xmapc xm xme xn xnoreme xu xunme y|0 z|0 ~ '+\n        // full version\n        'Next Print append abbreviate abclear aboveleft all amenu anoremenu args argadd argdelete argedit argglobal arglocal argument ascii autocmd augroup aunmenu buffer bNext ball badd bdelete behave belowright bfirst blast bmodified bnext botright bprevious brewind break breakadd breakdel breaklist browse bunload '+\n        'bwipeout change cNext cNfile cabbrev cabclear caddbuffer caddexpr caddfile call catch cbuffer cclose center cexpr cfile cfirst cgetbuffer cgetexpr cgetfile chdir checkpath checktime clist clast close cmap cmapclear cmenu cnext cnewer cnfile cnoremap cnoreabbrev cnoremenu copy colder colorscheme command comclear compiler continue confirm copen cprevious cpfile cquit crewind cscope cstag cunmap '+\n        'cunabbrev cunmenu cwindow delete delmarks debug debuggreedy delcommand delfunction diffupdate diffget diffoff diffpatch diffput diffsplit digraphs display deletel djump dlist doautocmd doautoall deletep drop dsearch dsplit edit earlier echo echoerr echohl echomsg else elseif emenu endif endfor '+\n        'endfunction endtry endwhile enew execute exit exusage file filetype find finally finish first fixdel fold foldclose folddoopen folddoclosed foldopen function global goto grep grepadd gui gvim hardcopy help helpfind helpgrep helptags highlight hide history insert iabbrev iabclear ijump ilist imap '+\n        'imapclear imenu inoremap inoreabbrev inoremenu intro isearch isplit iunmap iunabbrev iunmenu join jumps keepalt keepmarks keepjumps lNext lNfile list laddexpr laddbuffer laddfile last language later lbuffer lcd lchdir lclose lcscope left leftabove lexpr lfile lfirst lgetbuffer lgetexpr lgetfile lgrep lgrepadd lhelpgrep llast llist lmake lmap lmapclear lnext lnewer lnfile lnoremap loadkeymap loadview '+\n        'lockmarks lockvar lolder lopen lprevious lpfile lrewind ltag lunmap luado luafile lvimgrep lvimgrepadd lwindow move mark make mapclear match menu menutranslate messages mkexrc mksession mkspell mkvimrc mkview mode mzscheme mzfile nbclose nbkey nbsart next nmap nmapclear nmenu nnoremap '+\n        'nnoremenu noautocmd noremap nohlsearch noreabbrev noremenu normal number nunmap nunmenu oldfiles open omap omapclear omenu only onoremap onoremenu options ounmap ounmenu ownsyntax print profdel profile promptfind promptrepl pclose pedit perl perldo pop popup ppop preserve previous psearch ptag ptNext '+\n        'ptfirst ptjump ptlast ptnext ptprevious ptrewind ptselect put pwd py3do py3file python pydo pyfile quit quitall qall read recover redo redir redraw redrawstatus registers resize retab return rewind right rightbelow ruby rubydo rubyfile rundo runtime rviminfo substitute sNext sandbox sargument sall saveas sbuffer sbNext sball sbfirst sblast sbmodified sbnext sbprevious sbrewind scriptnames scriptencoding '+\n        'scscope set setfiletype setglobal setlocal sfind sfirst shell simalt sign silent sleep slast smagic smapclear smenu snext sniff snomagic snoremap snoremenu sort source spelldump spellgood spellinfo spellrepall spellundo spellwrong split sprevious srewind stop stag startgreplace startreplace '+\n        'startinsert stopinsert stjump stselect sunhide sunmap sunmenu suspend sview swapname syntax syntime syncbind tNext tabNext tabclose tabedit tabfind tabfirst tablast tabmove tabnext tabonly tabprevious tabrewind tag tcl tcldo tclfile tearoff tfirst throw tjump tlast tmenu tnext topleft tprevious '+'trewind tselect tunmenu undo undojoin undolist unabbreviate unhide unlet unlockvar unmap unmenu unsilent update vglobal version verbose vertical vimgrep vimgrepadd visual viusage view vmap vmapclear vmenu vnew '+\n        'vnoremap vnoremenu vsplit vunmap vunmenu write wNext wall while winsize wincmd winpos wnext wprevious wqall wsverb wundo wviminfo xit xall xmapclear xmap xmenu xnoremap xnoremenu xunmap xunmenu yank',\n      built_in: //built in func\n        'abs acos add and append argc argidx argv asin atan atan2 browse browsedir bufexists buflisted bufloaded bufname bufnr bufwinnr byte2line byteidx call ceil changenr char2nr cindent clearmatches col complete complete_add complete_check confirm copy cos cosh count cscope_connection cursor '+\n        'deepcopy delete did_filetype diff_filler diff_hlID empty escape eval eventhandler executable exists exp expand extend feedkeys filereadable filewritable filter finddir findfile float2nr floor fmod fnameescape fnamemodify foldclosed foldclosedend foldlevel foldtext foldtextresult foreground function '+\n        'garbagecollect get getbufline getbufvar getchar getcharmod getcmdline getcmdpos getcmdtype getcwd getfontname getfperm getfsize getftime getftype getline getloclist getmatches getpid getpos getqflist getreg getregtype gettabvar gettabwinvar getwinposx getwinposy getwinvar glob globpath has has_key '+\n        'haslocaldir hasmapto histadd histdel histget histnr hlexists hlID hostname iconv indent index input inputdialog inputlist inputrestore inputsave inputsecret insert invert isdirectory islocked items join keys len libcall libcallnr line line2byte lispindent localtime log log10 luaeval map maparg mapcheck '+\n        'match matchadd matcharg matchdelete matchend matchlist matchstr max min mkdir mode mzeval nextnonblank nr2char or pathshorten pow prevnonblank printf pumvisible py3eval pyeval range readfile reltime reltimestr remote_expr remote_foreground remote_peek remote_read remote_send remove rename repeat '+\n        'resolve reverse round screenattr screenchar screencol screenrow search searchdecl searchpair searchpairpos searchpos server2client serverlist setbufvar setcmdpos setline setloclist setmatches setpos setqflist setreg settabvar settabwinvar setwinvar sha256 shellescape shiftwidth simplify sin '+\n        'sinh sort soundfold spellbadword spellsuggest split sqrt str2float str2nr strchars strdisplaywidth strftime stridx string strlen strpart strridx strtrans strwidth submatch substitute synconcealed synID synIDattr '+\n        'synIDtrans synstack system tabpagebuflist tabpagenr tabpagewinnr tagfiles taglist tan tanh tempname tolower toupper tr trunc type undofile undotree values virtcol visualmode wildmenumode winbufnr wincol winheight winline winnr winrestcmd winrestview winsaveview winwidth writefile xor'\n    },\n    illegal: /[{:]/,\n    contains: [\n      hljs.NUMBER_MODE,\n      hljs.APOS_STRING_MODE,\n      {\n        className: 'string',\n        // quote with escape, comment as quote\n        begin: /\"((\\\\\")|[^\"\\n])*(\"|\\n)/\n      },\n      {\n        className: 'variable',\n        begin: /[bwtglsav]:[\\w\\d_]*/\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function function!', end: '$',\n        relevance: 0,\n        contains: [\n          hljs.TITLE_MODE,\n          {\n            className: 'params',\n            begin: '\\\\(', end: '\\\\)'\n          }\n        ]\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('x86asm', function(hljs) {\n  return {\n    case_insensitive: true,\n    lexemes: '\\\\.?' + hljs.IDENT_RE,\n    keywords: {\n      keyword:\n        'lock rep repe repz repne repnz xaquire xrelease bnd nobnd ' +\n        'aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63',\n      literal:\n        // Instruction pointer\n        'ip eip rip ' +\n        // 8-bit registers\n        'al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ' +\n        // 16-bit registers\n        'ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w ' +\n        // 32-bit registers\n        'eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d ' +\n        // 64-bit registers\n        'rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 ' +\n        // Segment registers\n        'cs ds es fs gs ss ' +\n        // Floating point stack registers\n        'st st0 st1 st2 st3 st4 st5 st6 st7 ' +\n        // MMX Registers\n        'mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 ' +\n        // SSE registers\n        'xmm0  xmm1  xmm2  xmm3  xmm4  xmm5  xmm6  xmm7  xmm8  xmm9 xmm10  xmm11 xmm12 xmm13 xmm14 xmm15 ' +\n        'xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ' +\n        // AVX registers\n        'ymm0  ymm1  ymm2  ymm3  ymm4  ymm5  ymm6  ymm7  ymm8  ymm9 ymm10  ymm11 ymm12 ymm13 ymm14 ymm15 ' +\n        'ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 ' +\n        // AVX-512F registers\n        'zmm0  zmm1  zmm2  zmm3  zmm4  zmm5  zmm6  zmm7  zmm8  zmm9 zmm10  zmm11 zmm12 zmm13 zmm14 zmm15 ' +\n        'zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 ' +\n        // AVX-512F mask registers\n        'k0 k1 k2 k3 k4 k5 k6 k7 ' +\n        // Bound (MPX) register\n        'bnd0 bnd1 bnd2 bnd3 ' +\n        // Special register\n        'cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 ' +\n        // NASM altreg package\n        'r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b ' +\n        'r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d ' +\n        'r0h r1h r2h r3h ' +\n        'r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l',\n\n      pseudo:\n        'db dw dd dq dt ddq do dy dz ' +\n        'resb resw resd resq rest resdq reso resy resz ' +\n        'incbin equ times',\n\n      preprocessor:\n        '%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif ' +\n        '%ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep ' +\n        '%endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment ' +\n        '.nolist ' +\n        'byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr ' +\n        '__FILE__ __LINE__ __SECT__  __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ ' +\n        '__UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__  __PASS__ struc endstruc istruc at iend ' +\n        'align alignb sectalign daz nodaz up down zero default option assume public ',\n\n      built_in:\n        'bits use16 use32 use64 default section segment absolute extern global common cpu float ' +\n        '__utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ ' +\n        '__float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ ' +\n        '__Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e ' +\n        'float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__'\n    },\n    contains: [\n      hljs.COMMENT(\n        ';',\n        '$',\n        {\n          relevance: 0\n        }\n      ),\n      {\n        className: 'number',\n        variants: [\n          // Float number and x87 BCD\n          {\n            begin: '\\\\b(?:([0-9][0-9_]*)?\\\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|' +\n                   '(0[Xx])?[0-9][0-9_]*\\\\.?[0-9_]*(?:[pP](?:[+-]?[0-9_]+)?)?)\\\\b',\n            relevance: 0\n          },\n\n          // Hex number in $\n          { begin: '\\\\$[0-9][0-9A-Fa-f]*', relevance: 0 },\n\n          // Number in H,D,T,Q,O,B,Y suffix\n          { begin: '\\\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[Hh]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\\\b' },\n\n          // Number in X,D,T,Q,O,B,Y prefix\n          { begin: '\\\\b(?:0[Xx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\\\b'}\n        ]\n      },\n      // Double quote string\n      hljs.QUOTE_STRING_MODE,\n      {\n        className: 'string',\n        variants: [\n          // Single-quoted string\n          { begin: '\\'', end: '[^\\\\\\\\]\\'' },\n          // Backquoted string\n          { begin: '`', end: '[^\\\\\\\\]`' },\n          // Section name\n          { begin: '\\\\.[A-Za-z0-9]+' }\n        ],\n        relevance: 0\n      },\n      {\n        className: 'label',\n        variants: [\n          // Global label and local label\n          { begin: '^\\\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\\\s+label)' },\n          // Macro-local label\n          { begin: '^\\\\s*%%[A-Za-z0-9_$#@~.?]*:' }\n        ],\n        relevance: 0\n      },\n      // Macro parameter\n      {\n        className: 'argument',\n        begin: '%[0-9]+',\n        relevance: 0\n      },\n      // Macro parameter\n      {\n        className: 'built_in',\n        begin: '%!\\S+',\n        relevance: 0\n      }\n    ]\n  };\n});\n\nhljs.registerLanguage('xl', function(hljs) {\n  var BUILTIN_MODULES =\n    'ObjectLoader Animate MovieCredits Slides Filters Shading Materials LensFlare Mapping VLCAudioVideo ' +\n    'StereoDecoder PointCloud NetworkAccess RemoteControl RegExp ChromaKey Snowfall NodeJS Speech Charts';\n\n  var XL_KEYWORDS = {\n    keyword: 'if then else do while until for loop import with is as where when by data constant',\n    literal: 'true false nil',\n    type: 'integer real text name boolean symbol infix prefix postfix block tree',\n    built_in: 'in mod rem and or xor not abs sign floor ceil sqrt sin cos tan asin acos atan exp expm1 log log2 log10 log1p pi at',\n    module: BUILTIN_MODULES,\n    id:\n      'text_length text_range text_find text_replace contains page slide basic_slide title_slide title subtitle ' +\n      'fade_in fade_out fade_at clear_color color line_color line_width texture_wrap texture_transform texture ' +\n      'scale_?x scale_?y scale_?z? translate_?x translate_?y translate_?z? rotate_?x rotate_?y rotate_?z? rectangle ' +\n      'circle ellipse sphere path line_to move_to quad_to curve_to theme background contents locally time mouse_?x ' +\n      'mouse_?y mouse_buttons'\n  };\n\n  var XL_CONSTANT = {\n    className: 'constant',\n    begin: '[A-Z][A-Z_0-9]+',\n    relevance: 0\n  };\n  var XL_VARIABLE = {\n    className: 'variable',\n    begin: '([A-Z][a-z_0-9]+)+',\n    relevance: 0\n  };\n  var XL_ID = {\n    className: 'id',\n    begin: '[a-z][a-z_0-9]+',\n    relevance: 0\n  };\n\n  var DOUBLE_QUOTE_TEXT = {\n    className: 'string',\n    begin: '\"', end: '\"', illegal: '\\\\n'\n  };\n  var SINGLE_QUOTE_TEXT = {\n    className: 'string',\n    begin: '\\'', end: '\\'', illegal: '\\\\n'\n  };\n  var LONG_TEXT = {\n    className: 'string',\n    begin: '<<', end: '>>'\n  };\n  var BASED_NUMBER = {\n    className: 'number',\n    begin: '[0-9]+#[0-9A-Z_]+(\\\\.[0-9-A-Z_]+)?#?([Ee][+-]?[0-9]+)?',\n    relevance: 10\n  };\n  var IMPORT = {\n    className: 'import',\n    beginKeywords: 'import', end: '$',\n    keywords: {\n      keyword: 'import',\n      module: BUILTIN_MODULES\n    },\n    relevance: 0,\n    contains: [DOUBLE_QUOTE_TEXT]\n  };\n  var FUNCTION_DEFINITION = {\n    className: 'function',\n    begin: '[a-z].*->'\n  };\n  return {\n    aliases: ['tao'],\n    lexemes: /[a-zA-Z][a-zA-Z0-9_?]*/,\n    keywords: XL_KEYWORDS,\n    contains: [\n    hljs.C_LINE_COMMENT_MODE,\n    hljs.C_BLOCK_COMMENT_MODE,\n    DOUBLE_QUOTE_TEXT,\n    SINGLE_QUOTE_TEXT,\n    LONG_TEXT,\n    FUNCTION_DEFINITION,\n    IMPORT,\n    XL_CONSTANT,\n    XL_VARIABLE,\n    XL_ID,\n    BASED_NUMBER,\n    hljs.NUMBER_MODE\n    ]\n  };\n});\n\nhljs.registerLanguage('xquery', function(hljs) {\n  var KEYWORDS = 'for let if while then else return where group by xquery encoding version' +\n    'module namespace boundary-space preserve strip default collation base-uri ordering' +\n    'copy-namespaces order declare import schema namespace function option in allowing empty' +\n    'at tumbling window sliding window start when only end when previous next stable ascending' +\n    'descending empty greatest least some every satisfies switch case typeswitch try catch and' +\n    'or to union intersect instance of treat as castable cast map array delete insert into' +\n    'replace value rename copy modify update';\n  var LITERAL = 'false true xs:string xs:integer element item xs:date xs:datetime xs:float xs:double xs:decimal QName xs:anyURI xs:long xs:int xs:short xs:byte attribute';\n  var VAR = {\n    className: 'variable',\n    begin: /\\$[a-zA-Z0-9\\-]+/,\n    relevance: 5\n  };\n\n  var NUMBER = {\n    className: 'number',\n    begin: '(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b',\n    relevance: 0\n  };\n\n  var STRING = {\n    className: 'string',\n    variants: [\n      {begin: /\"/, end: /\"/, contains: [{begin: /\"\"/, relevance: 0}]},\n      {begin: /'/, end: /'/, contains: [{begin: /''/, relevance: 0}]}\n    ]\n  };\n\n  var ANNOTATION = {\n    className: 'decorator',\n    begin: '%\\\\w+'\n  };\n\n  var COMMENT = {\n    className: 'comment',\n    begin: '\\\\(:', end: ':\\\\)',\n    relevance: 10,\n    contains: [\n      {\n        className: 'doc', begin: '@\\\\w+'\n      }\n    ]\n  };\n\n  var METHOD = {\n    begin: '{', end: '}'\n  };\n\n  var CONTAINS = [\n    VAR,\n    STRING,\n    NUMBER,\n    COMMENT,\n    ANNOTATION,\n    METHOD\n  ];\n  METHOD.contains = CONTAINS;\n\n\n  return {\n    aliases: ['xpath', 'xq'],\n    case_insensitive: false,\n    lexemes: /[a-zA-Z\\$][a-zA-Z0-9_:\\-]*/,\n    illegal: /(proc)|(abstract)|(extends)|(until)|(#)/,\n    keywords: {\n      keyword: KEYWORDS,\n      literal: LITERAL\n    },\n    contains: CONTAINS\n  };\n});\n\nhljs.registerLanguage('zephir', function(hljs) {\n  var STRING = {\n    className: 'string',\n    contains: [hljs.BACKSLASH_ESCAPE],\n    variants: [\n      {\n        begin: 'b\"', end: '\"'\n      },\n      {\n        begin: 'b\\'', end: '\\''\n      },\n      hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),\n      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null})\n    ]\n  };\n  var NUMBER = {variants: [hljs.BINARY_NUMBER_MODE, hljs.C_NUMBER_MODE]};\n  return {\n    aliases: ['zep'],\n    case_insensitive: true,\n    keywords:\n    'and include_once list abstract global private echo interface as static endswitch ' +\n    'array null if endwhile or const for endforeach self var let while isset public ' +\n    'protected exit foreach throw elseif include __FILE__ empty require_once do xor ' +\n    'return parent clone use __CLASS__ __LINE__ else break print eval new ' +\n    'catch __METHOD__ case exception default die require __FUNCTION__ ' +\n    'enddeclare final try switch continue endfor endif declare unset true false ' +\n    'trait goto instanceof insteadof __DIR__ __NAMESPACE__ ' +\n    'yield finally int uint long ulong char uchar double float bool boolean string' +\n    'likely unlikely',\n    contains: [\n      hljs.C_LINE_COMMENT_MODE,\n      hljs.HASH_COMMENT_MODE,\n      hljs.COMMENT(\n        '/\\\\*',\n        '\\\\*/',\n        {\n          contains: [\n            {\n              className: 'doctag',\n              begin: '@[A-Za-z]+'\n            }\n          ]\n        }\n      ),\n      hljs.COMMENT(\n        '__halt_compiler.+?;',\n        false,\n        {\n          endsWithParent: true,\n          keywords: '__halt_compiler',\n          lexemes: hljs.UNDERSCORE_IDENT_RE\n        }\n      ),\n      {\n        className: 'string',\n        begin: '<<<[\\'\"]?\\\\w+[\\'\"]?$', end: '^\\\\w+;',\n        contains: [hljs.BACKSLASH_ESCAPE]\n      },\n      {\n        // swallow composed identifiers to avoid parsing them as keywords\n        begin: /(::|->)+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/\n      },\n      {\n        className: 'function',\n        beginKeywords: 'function', end: /[;{]/, excludeEnd: true,\n        illegal: '\\\\$|\\\\[|%',\n        contains: [\n          hljs.UNDERSCORE_TITLE_MODE,\n          {\n            className: 'params',\n            begin: '\\\\(', end: '\\\\)',\n            contains: [\n              'self',\n              hljs.C_BLOCK_COMMENT_MODE,\n              STRING,\n              NUMBER\n            ]\n          }\n        ]\n      },\n      {\n        className: 'class',\n        beginKeywords: 'class interface', end: '{', excludeEnd: true,\n        illegal: /[:\\(\\$\"]/,\n        contains: [\n          {beginKeywords: 'extends implements'},\n          hljs.UNDERSCORE_TITLE_MODE\n        ]\n      },\n      {\n        beginKeywords: 'namespace', end: ';',\n        illegal: /[\\.']/,\n        contains: [hljs.UNDERSCORE_TITLE_MODE]\n      },\n      {\n        beginKeywords: 'use', end: ';',\n        contains: [hljs.UNDERSCORE_TITLE_MODE]\n      },\n      {\n        begin: '=>' // No markup, just a relevance booster\n      },\n      STRING,\n      NUMBER\n    ]\n  };\n});\n\n  return hljs;\n}));\n\n/**\n * marked - a markdown parser\n * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)\n * https://github.com/chjj/marked\n */\n\n;(function() {\n\n/**\n * Block-Level Grammar\n */\n\nvar block = {\n  newline: /^\\n+/,\n  code: /^( {4}[^\\n]+\\n*)+/,\n  fences: noop,\n  hr: /^( *[-*_]){3,} *(?:\\n+|$)/,\n  heading: /^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)/,\n  nptable: noop,\n  lheading: /^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,\n  blockquote: /^( *>[^\\n]+(\\n(?!def)[^\\n]+)*\\n*)+/,\n  list: /^( *)(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,\n  html: /^ *(?:comment *(?:\\n|\\s*$)|closed *(?:\\n{2,}|\\s*$)|closing *(?:\\n{2,}|\\s*$))/,\n  def: /^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)/,\n  table: noop,\n  paragraph: /^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*/,\n  text: /^[^\\n]+/\n};\n\nblock.bullet = /(?:[*+-]|\\d+\\.)/;\nblock.item = /^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*/;\nblock.item = replace(block.item, 'gm')\n  (/bull/g, block.bullet)\n  ();\n\nblock.list = replace(block.list)\n  (/bull/g, block.bullet)\n  ('hr', '\\\\n+(?=\\\\1?(?:[-*_] *){3,}(?:\\\\n+|$))')\n  ('def', '\\\\n+(?=' + block.def.source + ')')\n  ();\n\nblock.blockquote = replace(block.blockquote)\n  ('def', block.def)\n  ();\n\nblock._tag = '(?!(?:'\n  + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'\n  + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'\n  + '|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:/|[^\\\\w\\\\s@]*@)\\\\b';\n\nblock.html = replace(block.html)\n  ('comment', /<!--[\\s\\S]*?-->/)\n  ('closed', /<(tag)[\\s\\S]+?<\\/\\1>/)\n  ('closing', /<tag(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/)\n  (/tag/g, block._tag)\n  ();\n\nblock.paragraph = replace(block.paragraph)\n  ('hr', block.hr)\n  ('heading', block.heading)\n  ('lheading', block.lheading)\n  ('blockquote', block.blockquote)\n  ('tag', '<' + block._tag)\n  ('def', block.def)\n  ();\n\n/**\n * Normal Block Grammar\n */\n\nblock.normal = merge({}, block);\n\n/**\n * GFM Block Grammar\n */\n\nblock.gfm = merge({}, block.normal, {\n  fences: /^ *(`{3,}|~{3,})[ \\.]*(\\S+)? *\\n([\\s\\S]*?)\\s*\\1 *(?:\\n+|$)/,\n  paragraph: /^/,\n  heading: /^ *(#{1,6}) +([^\\n]+?) *#* *(?:\\n+|$)/\n});\n\nblock.gfm.paragraph = replace(block.paragraph)\n  ('(?!', '(?!'\n    + block.gfm.fences.source.replace('\\\\1', '\\\\2') + '|'\n    + block.list.source.replace('\\\\1', '\\\\3') + '|')\n  ();\n\n/**\n * GFM + Tables Block Grammar\n */\n\nblock.tables = merge({}, block.gfm, {\n  nptable: /^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*/,\n  table: /^ *\\|(.+)\\n *\\|( *[-:]+[-| :]*)\\n((?: *\\|.*(?:\\n|$))*)\\n*/\n});\n\n/**\n * Block Lexer\n */\n\nfunction Lexer(options) {\n  this.tokens = [];\n  this.tokens.links = {};\n  this.options = options || marked.defaults;\n  this.rules = block.normal;\n\n  if (this.options.gfm) {\n    if (this.options.tables) {\n      this.rules = block.tables;\n    } else {\n      this.rules = block.gfm;\n    }\n  }\n}\n\n/**\n * Expose Block Rules\n */\n\nLexer.rules = block;\n\n/**\n * Static Lex Method\n */\n\nLexer.lex = function(src, options) {\n  var lexer = new Lexer(options);\n  return lexer.lex(src);\n};\n\n/**\n * Preprocessing\n */\n\nLexer.prototype.lex = function(src) {\n  src = src\n    .replace(/\\r\\n|\\r/g, '\\n')\n    .replace(/\\t/g, '    ')\n    .replace(/\\u00a0/g, ' ')\n    .replace(/\\u2424/g, '\\n');\n\n  return this.token(src, true);\n};\n\n/**\n * Lexing\n */\n\nLexer.prototype.token = function(src, top, bq) {\n  var src = src.replace(/^ +$/gm, '')\n    , next\n    , loose\n    , cap\n    , bull\n    , b\n    , item\n    , space\n    , i\n    , l;\n\n  while (src) {\n    // newline\n    if (cap = this.rules.newline.exec(src)) {\n      src = src.substring(cap[0].length);\n      if (cap[0].length > 1) {\n        this.tokens.push({\n          type: 'space'\n        });\n      }\n    }\n\n    // code\n    if (cap = this.rules.code.exec(src)) {\n      src = src.substring(cap[0].length);\n      cap = cap[0].replace(/^ {4}/gm, '');\n      this.tokens.push({\n        type: 'code',\n        text: !this.options.pedantic\n          ? cap.replace(/\\n+$/, '')\n          : cap\n      });\n      continue;\n    }\n\n    // fences (gfm)\n    if (cap = this.rules.fences.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'code',\n        lang: cap[2],\n        text: cap[3] || ''\n      });\n      continue;\n    }\n\n    // heading\n    if (cap = this.rules.heading.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'heading',\n        depth: cap[1].length,\n        text: cap[2]\n      });\n      continue;\n    }\n\n    // table no leading pipe (gfm)\n    if (top && (cap = this.rules.nptable.exec(src))) {\n      src = src.substring(cap[0].length);\n\n      item = {\n        type: 'table',\n        header: cap[1].replace(/^ *| *\\| *$/g, '').split(/ *\\| */),\n        align: cap[2].replace(/^ *|\\| *$/g, '').split(/ *\\| */),\n        cells: cap[3].replace(/\\n$/, '').split('\\n')\n      };\n\n      for (i = 0; i < item.align.length; i++) {\n        if (/^ *-+: *$/.test(item.align[i])) {\n          item.align[i] = 'right';\n        } else if (/^ *:-+: *$/.test(item.align[i])) {\n          item.align[i] = 'center';\n        } else if (/^ *:-+ *$/.test(item.align[i])) {\n          item.align[i] = 'left';\n        } else {\n          item.align[i] = null;\n        }\n      }\n\n      for (i = 0; i < item.cells.length; i++) {\n        item.cells[i] = item.cells[i].split(/ *\\| */);\n      }\n\n      this.tokens.push(item);\n\n      continue;\n    }\n\n    // lheading\n    if (cap = this.rules.lheading.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'heading',\n        depth: cap[2] === '=' ? 1 : 2,\n        text: cap[1]\n      });\n      continue;\n    }\n\n    // hr\n    if (cap = this.rules.hr.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'hr'\n      });\n      continue;\n    }\n\n    // blockquote\n    if (cap = this.rules.blockquote.exec(src)) {\n      src = src.substring(cap[0].length);\n\n      this.tokens.push({\n        type: 'blockquote_start'\n      });\n\n      cap = cap[0].replace(/^ *> ?/gm, '');\n\n      // Pass `top` to keep the current\n      // \"toplevel\" state. This is exactly\n      // how markdown.pl works.\n      this.token(cap, top, true);\n\n      this.tokens.push({\n        type: 'blockquote_end'\n      });\n\n      continue;\n    }\n\n    // list\n    if (cap = this.rules.list.exec(src)) {\n      src = src.substring(cap[0].length);\n      bull = cap[2];\n\n      this.tokens.push({\n        type: 'list_start',\n        ordered: bull.length > 1\n      });\n\n      // Get each top-level item.\n      cap = cap[0].match(this.rules.item);\n\n      next = false;\n      l = cap.length;\n      i = 0;\n\n      for (; i < l; i++) {\n        item = cap[i];\n\n        // Remove the list item's bullet\n        // so it is seen as the next token.\n        space = item.length;\n        item = item.replace(/^ *([*+-]|\\d+\\.) +/, '');\n\n        // Outdent whatever the\n        // list item contains. Hacky.\n        if (~item.indexOf('\\n ')) {\n          space -= item.length;\n          item = !this.options.pedantic\n            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')\n            : item.replace(/^ {1,4}/gm, '');\n        }\n\n        // Determine whether the next list item belongs here.\n        // Backpedal if it does not belong in this list.\n        if (this.options.smartLists && i !== l - 1) {\n          b = block.bullet.exec(cap[i + 1])[0];\n          if (bull !== b && !(bull.length > 1 && b.length > 1)) {\n            src = cap.slice(i + 1).join('\\n') + src;\n            i = l - 1;\n          }\n        }\n\n        // Determine whether item is loose or not.\n        // Use: /(^|\\n)(?! )[^\\n]+\\n\\n(?!\\s*$)/\n        // for discount behavior.\n        loose = next || /\\n\\n(?!\\s*$)/.test(item);\n        if (i !== l - 1) {\n          next = item.charAt(item.length - 1) === '\\n';\n          if (!loose) loose = next;\n        }\n\n        this.tokens.push({\n          type: loose\n            ? 'loose_item_start'\n            : 'list_item_start'\n        });\n\n        // Recurse.\n        this.token(item, false, bq);\n\n        this.tokens.push({\n          type: 'list_item_end'\n        });\n      }\n\n      this.tokens.push({\n        type: 'list_end'\n      });\n\n      continue;\n    }\n\n    // html\n    if (cap = this.rules.html.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: this.options.sanitize\n          ? 'paragraph'\n          : 'html',\n        pre: !this.options.sanitizer\n          && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),\n        text: cap[0]\n      });\n      continue;\n    }\n\n    // def\n    if ((!bq && top) && (cap = this.rules.def.exec(src))) {\n      src = src.substring(cap[0].length);\n      this.tokens.links[cap[1].toLowerCase()] = {\n        href: cap[2],\n        title: cap[3]\n      };\n      continue;\n    }\n\n    // table (gfm)\n    if (top && (cap = this.rules.table.exec(src))) {\n      src = src.substring(cap[0].length);\n\n      item = {\n        type: 'table',\n        header: cap[1].replace(/^ *| *\\| *$/g, '').split(/ *\\| */),\n        align: cap[2].replace(/^ *|\\| *$/g, '').split(/ *\\| */),\n        cells: cap[3].replace(/(?: *\\| *)?\\n$/, '').split('\\n')\n      };\n\n      for (i = 0; i < item.align.length; i++) {\n        if (/^ *-+: *$/.test(item.align[i])) {\n          item.align[i] = 'right';\n        } else if (/^ *:-+: *$/.test(item.align[i])) {\n          item.align[i] = 'center';\n        } else if (/^ *:-+ *$/.test(item.align[i])) {\n          item.align[i] = 'left';\n        } else {\n          item.align[i] = null;\n        }\n      }\n\n      for (i = 0; i < item.cells.length; i++) {\n        item.cells[i] = item.cells[i]\n          .replace(/^ *\\| *| *\\| *$/g, '')\n          .split(/ *\\| */);\n      }\n\n      this.tokens.push(item);\n\n      continue;\n    }\n\n    // top-level paragraph\n    if (top && (cap = this.rules.paragraph.exec(src))) {\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'paragraph',\n        text: cap[1].charAt(cap[1].length - 1) === '\\n'\n          ? cap[1].slice(0, -1)\n          : cap[1]\n      });\n      continue;\n    }\n\n    // text\n    if (cap = this.rules.text.exec(src)) {\n      // Top-level should never reach here.\n      src = src.substring(cap[0].length);\n      this.tokens.push({\n        type: 'text',\n        text: cap[0]\n      });\n      continue;\n    }\n\n    if (src) {\n      throw new\n        Error('Infinite loop on byte: ' + src.charCodeAt(0));\n    }\n  }\n\n  return this.tokens;\n};\n\n/**\n * Inline-Level Grammar\n */\n\nvar inline = {\n  escape: /^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])/,\n  autolink: /^<([^ >]+(@|:\\/)[^ >]+)>/,\n  url: noop,\n  tag: /^<!--[\\s\\S]*?-->|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/,\n  link: /^!?\\[(inside)\\]\\(href\\)/,\n  reflink: /^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]/,\n  nolink: /^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]/,\n  strong: /^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)/,\n  em: /^\\b_((?:[^_]|__)+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/,\n  code: /^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)/,\n  br: /^ {2,}\\n(?!\\s*$)/,\n  del: noop,\n  text: /^[\\s\\S]+?(?=[\\\\<!\\[_*`]| {2,}\\n|$)/\n};\n\ninline._inside = /(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*/;\ninline._href = /\\s*<?([\\s\\S]*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*/;\n\ninline.link = replace(inline.link)\n  ('inside', inline._inside)\n  ('href', inline._href)\n  ();\n\ninline.reflink = replace(inline.reflink)\n  ('inside', inline._inside)\n  ();\n\n/**\n * Normal Inline Grammar\n */\n\ninline.normal = merge({}, inline);\n\n/**\n * Pedantic Inline Grammar\n */\n\ninline.pedantic = merge({}, inline.normal, {\n  strong: /^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,\n  em: /^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/\n});\n\n/**\n * GFM Inline Grammar\n */\n\ninline.gfm = merge({}, inline.normal, {\n  escape: replace(inline.escape)('])', '~|])')(),\n  url: /^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/,\n  del: /^~~(?=\\S)([\\s\\S]*?\\S)~~/,\n  text: replace(inline.text)\n    (']|', '~]|')\n    ('|', '|https?://|')\n    ()\n});\n\n/**\n * GFM + Line Breaks Inline Grammar\n */\n\ninline.breaks = merge({}, inline.gfm, {\n  br: replace(inline.br)('{2,}', '*')(),\n  text: replace(inline.gfm.text)('{2,}', '*')()\n});\n\n/**\n * Inline Lexer & Compiler\n */\n\nfunction InlineLexer(links, options) {\n  this.options = options || marked.defaults;\n  this.links = links;\n  this.rules = inline.normal;\n  this.renderer = this.options.renderer || new Renderer;\n  this.renderer.options = this.options;\n\n  if (!this.links) {\n    throw new\n      Error('Tokens array requires a `links` property.');\n  }\n\n  if (this.options.gfm) {\n    if (this.options.breaks) {\n      this.rules = inline.breaks;\n    } else {\n      this.rules = inline.gfm;\n    }\n  } else if (this.options.pedantic) {\n    this.rules = inline.pedantic;\n  }\n}\n\n/**\n * Expose Inline Rules\n */\n\nInlineLexer.rules = inline;\n\n/**\n * Static Lexing/Compiling Method\n */\n\nInlineLexer.output = function(src, links, options) {\n  var inline = new InlineLexer(links, options);\n  return inline.output(src);\n};\n\n/**\n * Lexing/Compiling\n */\n\nInlineLexer.prototype.output = function(src) {\n  var out = ''\n    , link\n    , text\n    , href\n    , cap;\n\n  while (src) {\n    // escape\n    if (cap = this.rules.escape.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += cap[1];\n      continue;\n    }\n\n    // autolink\n    if (cap = this.rules.autolink.exec(src)) {\n      src = src.substring(cap[0].length);\n      if (cap[2] === '@') {\n        text = cap[1].charAt(6) === ':'\n          ? this.mangle(cap[1].substring(7))\n          : this.mangle(cap[1]);\n        href = this.mangle('mailto:') + text;\n      } else {\n        text = escape(cap[1]);\n        href = text;\n      }\n      out += this.renderer.link(href, null, text);\n      continue;\n    }\n\n    // url (gfm)\n    if (!this.inLink && (cap = this.rules.url.exec(src))) {\n      src = src.substring(cap[0].length);\n      text = escape(cap[1]);\n      href = text;\n      out += this.renderer.link(href, null, text);\n      continue;\n    }\n\n    // tag\n    if (cap = this.rules.tag.exec(src)) {\n      if (!this.inLink && /^<a /i.test(cap[0])) {\n        this.inLink = true;\n      } else if (this.inLink && /^<\\/a>/i.test(cap[0])) {\n        this.inLink = false;\n      }\n      src = src.substring(cap[0].length);\n      out += this.options.sanitize\n        ? this.options.sanitizer\n          ? this.options.sanitizer(cap[0])\n          : escape(cap[0])\n        : cap[0]\n      continue;\n    }\n\n    // link\n    if (cap = this.rules.link.exec(src)) {\n      src = src.substring(cap[0].length);\n      this.inLink = true;\n      out += this.outputLink(cap, {\n        href: cap[2],\n        title: cap[3]\n      });\n      this.inLink = false;\n      continue;\n    }\n\n    // reflink, nolink\n    if ((cap = this.rules.reflink.exec(src))\n        || (cap = this.rules.nolink.exec(src))) {\n      src = src.substring(cap[0].length);\n      link = (cap[2] || cap[1]).replace(/\\s+/g, ' ');\n      link = this.links[link.toLowerCase()];\n      if (!link || !link.href) {\n        out += cap[0].charAt(0);\n        src = cap[0].substring(1) + src;\n        continue;\n      }\n      this.inLink = true;\n      out += this.outputLink(cap, link);\n      this.inLink = false;\n      continue;\n    }\n\n    // strong\n    if (cap = this.rules.strong.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.strong(this.output(cap[2] || cap[1]));\n      continue;\n    }\n\n    // em\n    if (cap = this.rules.em.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.em(this.output(cap[2] || cap[1]));\n      continue;\n    }\n\n    // code\n    if (cap = this.rules.code.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.codespan(escape(cap[2], true));\n      continue;\n    }\n\n    // br\n    if (cap = this.rules.br.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.br();\n      continue;\n    }\n\n    // del (gfm)\n    if (cap = this.rules.del.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.del(this.output(cap[1]));\n      continue;\n    }\n\n    // text\n    if (cap = this.rules.text.exec(src)) {\n      src = src.substring(cap[0].length);\n      out += this.renderer.text(escape(this.smartypants(cap[0])));\n      continue;\n    }\n\n    if (src) {\n      throw new\n        Error('Infinite loop on byte: ' + src.charCodeAt(0));\n    }\n  }\n\n  return out;\n};\n\n/**\n * Compile Link\n */\n\nInlineLexer.prototype.outputLink = function(cap, link) {\n  var href = escape(link.href)\n    , title = link.title ? escape(link.title) : null;\n\n  return cap[0].charAt(0) !== '!'\n    ? this.renderer.link(href, title, this.output(cap[1]))\n    : this.renderer.image(href, title, escape(cap[1]));\n};\n\n/**\n * Smartypants Transformations\n */\n\nInlineLexer.prototype.smartypants = function(text) {\n  if (!this.options.smartypants) return text;\n  return text\n    // em-dashes\n    .replace(/---/g, '\\u2014')\n    // en-dashes\n    .replace(/--/g, '\\u2013')\n    // opening singles\n    .replace(/(^|[-\\u2014/(\\[{\"\\s])'/g, '$1\\u2018')\n    // closing singles & apostrophes\n    .replace(/'/g, '\\u2019')\n    // opening doubles\n    .replace(/(^|[-\\u2014/(\\[{\\u2018\\s])\"/g, '$1\\u201c')\n    // closing doubles\n    .replace(/\"/g, '\\u201d')\n    // ellipses\n    .replace(/\\.{3}/g, '\\u2026');\n};\n\n/**\n * Mangle Links\n */\n\nInlineLexer.prototype.mangle = function(text) {\n  if (!this.options.mangle) return text;\n  var out = ''\n    , l = text.length\n    , i = 0\n    , ch;\n\n  for (; i < l; i++) {\n    ch = text.charCodeAt(i);\n    if (Math.random() > 0.5) {\n      ch = 'x' + ch.toString(16);\n    }\n    out += '&#' + ch + ';';\n  }\n\n  return out;\n};\n\n/**\n * Renderer\n */\n\nfunction Renderer(options) {\n  this.options = options || {};\n}\n\nRenderer.prototype.code = function(code, lang, escaped) {\n  if (this.options.highlight) {\n    var out = this.options.highlight(code, lang);\n    if (out != null && out !== code) {\n      escaped = true;\n      code = out;\n    }\n  }\n\n  if (!lang) {\n    return '<pre><code>'\n      + (escaped ? code : escape(code, true))\n      + '\\n</code></pre>';\n  }\n\n  return '<pre><code class=\"'\n    + this.options.langPrefix\n    + escape(lang, true)\n    + '\">'\n    + (escaped ? code : escape(code, true))\n    + '\\n</code></pre>\\n';\n};\n\nRenderer.prototype.blockquote = function(quote) {\n  return '<blockquote>\\n' + quote + '</blockquote>\\n';\n};\n\nRenderer.prototype.html = function(html) {\n  return html;\n};\n\nRenderer.prototype.heading = function(text, level, raw) {\n  return '<h'\n    + level\n    + ' id=\"'\n    + this.options.headerPrefix\n    + raw.toLowerCase().replace(/[^\\w]+/g, '-')\n    + '\">'\n    + text\n    + '</h'\n    + level\n    + '>\\n';\n};\n\nRenderer.prototype.hr = function() {\n  return this.options.xhtml ? '<hr/>\\n' : '<hr>\\n';\n};\n\nRenderer.prototype.list = function(body, ordered) {\n  var type = ordered ? 'ol' : 'ul';\n  return '<' + type + '>\\n' + body + '</' + type + '>\\n';\n};\n\nRenderer.prototype.listitem = function(text) {\n  return '<li>' + text + '</li>\\n';\n};\n\nRenderer.prototype.paragraph = function(text) {\n  return '<p>' + text + '</p>\\n';\n};\n\nRenderer.prototype.table = function(header, body) {\n  return '<table>\\n'\n    + '<thead>\\n'\n    + header\n    + '</thead>\\n'\n    + '<tbody>\\n'\n    + body\n    + '</tbody>\\n'\n    + '</table>\\n';\n};\n\nRenderer.prototype.tablerow = function(content) {\n  return '<tr>\\n' + content + '</tr>\\n';\n};\n\nRenderer.prototype.tablecell = function(content, flags) {\n  var type = flags.header ? 'th' : 'td';\n  var tag = flags.align\n    ? '<' + type + ' style=\"text-align:' + flags.align + '\">'\n    : '<' + type + '>';\n  return tag + content + '</' + type + '>\\n';\n};\n\n// span level renderer\nRenderer.prototype.strong = function(text) {\n  return '<strong>' + text + '</strong>';\n};\n\nRenderer.prototype.em = function(text) {\n  return '<em>' + text + '</em>';\n};\n\nRenderer.prototype.codespan = function(text) {\n  return '<code>' + text + '</code>';\n};\n\nRenderer.prototype.br = function() {\n  return this.options.xhtml ? '<br/>' : '<br>';\n};\n\nRenderer.prototype.del = function(text) {\n  return '<del>' + text + '</del>';\n};\n\nRenderer.prototype.link = function(href, title, text) {\n  if (this.options.sanitize) {\n    try {\n      var prot = decodeURIComponent(unescape(href))\n        .replace(/[^\\w:]/g, '')\n        .toLowerCase();\n    } catch (e) {\n      return '';\n    }\n    if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {\n      return '';\n    }\n  }\n  var out = '<a href=\"' + href + '\"';\n  if (title) {\n    out += ' title=\"' + title + '\"';\n  }\n  out += '>' + text + '</a>';\n  return out;\n};\n\nRenderer.prototype.image = function(href, title, text) {\n  var out = '<img src=\"' + href + '\" alt=\"' + text + '\"';\n  if (title) {\n    out += ' title=\"' + title + '\"';\n  }\n  out += this.options.xhtml ? '/>' : '>';\n  return out;\n};\n\nRenderer.prototype.text = function(text) {\n  return text;\n};\n\n/**\n * Parsing & Compiling\n */\n\nfunction Parser(options) {\n  this.tokens = [];\n  this.token = null;\n  this.options = options || marked.defaults;\n  this.options.renderer = this.options.renderer || new Renderer;\n  this.renderer = this.options.renderer;\n  this.renderer.options = this.options;\n}\n\n/**\n * Static Parse Method\n */\n\nParser.parse = function(src, options, renderer) {\n  var parser = new Parser(options, renderer);\n  return parser.parse(src);\n};\n\n/**\n * Parse Loop\n */\n\nParser.prototype.parse = function(src) {\n  this.inline = new InlineLexer(src.links, this.options, this.renderer);\n  this.tokens = src.reverse();\n\n  var out = '';\n  while (this.next()) {\n    out += this.tok();\n  }\n\n  return out;\n};\n\n/**\n * Next Token\n */\n\nParser.prototype.next = function() {\n  return this.token = this.tokens.pop();\n};\n\n/**\n * Preview Next Token\n */\n\nParser.prototype.peek = function() {\n  return this.tokens[this.tokens.length - 1] || 0;\n};\n\n/**\n * Parse Text Tokens\n */\n\nParser.prototype.parseText = function() {\n  var body = this.token.text;\n\n  while (this.peek().type === 'text') {\n    body += '\\n' + this.next().text;\n  }\n\n  return this.inline.output(body);\n};\n\n/**\n * Parse Current Token\n */\n\nParser.prototype.tok = function() {\n  switch (this.token.type) {\n    case 'space': {\n      return '';\n    }\n    case 'hr': {\n      return this.renderer.hr();\n    }\n    case 'heading': {\n      return this.renderer.heading(\n        this.inline.output(this.token.text),\n        this.token.depth,\n        this.token.text);\n    }\n    case 'code': {\n      return this.renderer.code(this.token.text,\n        this.token.lang,\n        this.token.escaped);\n    }\n    case 'table': {\n      var header = ''\n        , body = ''\n        , i\n        , row\n        , cell\n        , flags\n        , j;\n\n      // header\n      cell = '';\n      for (i = 0; i < this.token.header.length; i++) {\n        flags = { header: true, align: this.token.align[i] };\n        cell += this.renderer.tablecell(\n          this.inline.output(this.token.header[i]),\n          { header: true, align: this.token.align[i] }\n        );\n      }\n      header += this.renderer.tablerow(cell);\n\n      for (i = 0; i < this.token.cells.length; i++) {\n        row = this.token.cells[i];\n\n        cell = '';\n        for (j = 0; j < row.length; j++) {\n          cell += this.renderer.tablecell(\n            this.inline.output(row[j]),\n            { header: false, align: this.token.align[j] }\n          );\n        }\n\n        body += this.renderer.tablerow(cell);\n      }\n      return this.renderer.table(header, body);\n    }\n    case 'blockquote_start': {\n      var body = '';\n\n      while (this.next().type !== 'blockquote_end') {\n        body += this.tok();\n      }\n\n      return this.renderer.blockquote(body);\n    }\n    case 'list_start': {\n      var body = ''\n        , ordered = this.token.ordered;\n\n      while (this.next().type !== 'list_end') {\n        body += this.tok();\n      }\n\n      return this.renderer.list(body, ordered);\n    }\n    case 'list_item_start': {\n      var body = '';\n\n      while (this.next().type !== 'list_item_end') {\n        body += this.token.type === 'text'\n          ? this.parseText()\n          : this.tok();\n      }\n\n      return this.renderer.listitem(body);\n    }\n    case 'loose_item_start': {\n      var body = '';\n\n      while (this.next().type !== 'list_item_end') {\n        body += this.tok();\n      }\n\n      return this.renderer.listitem(body);\n    }\n    case 'html': {\n      var html = !this.token.pre && !this.options.pedantic\n        ? this.inline.output(this.token.text)\n        : this.token.text;\n      return this.renderer.html(html);\n    }\n    case 'paragraph': {\n      return this.renderer.paragraph(this.inline.output(this.token.text));\n    }\n    case 'text': {\n      return this.renderer.paragraph(this.parseText());\n    }\n  }\n};\n\n/**\n * Helpers\n */\n\nfunction escape(html, encode) {\n  return html\n    .replace(!encode ? /&(?!#?\\w+;)/g : /&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;')\n    .replace(/'/g, '&#39;');\n}\n\nfunction unescape(html) {\n  return html.replace(/&([#\\w]+);/g, function(_, n) {\n    n = n.toLowerCase();\n    if (n === 'colon') return ':';\n    if (n.charAt(0) === '#') {\n      return n.charAt(1) === 'x'\n        ? String.fromCharCode(parseInt(n.substring(2), 16))\n        : String.fromCharCode(+n.substring(1));\n    }\n    return '';\n  });\n}\n\nfunction replace(regex, opt) {\n  regex = regex.source;\n  opt = opt || '';\n  return function self(name, val) {\n    if (!name) return new RegExp(regex, opt);\n    val = val.source || val;\n    val = val.replace(/(^|[^\\[])\\^/g, '$1');\n    regex = regex.replace(name, val);\n    return self;\n  };\n}\n\nfunction noop() {}\nnoop.exec = noop;\n\nfunction merge(obj) {\n  var i = 1\n    , target\n    , key;\n\n  for (; i < arguments.length; i++) {\n    target = arguments[i];\n    for (key in target) {\n      if (Object.prototype.hasOwnProperty.call(target, key)) {\n        obj[key] = target[key];\n      }\n    }\n  }\n\n  return obj;\n}\n\n\n/**\n * Marked\n */\n\nfunction marked(src, opt, callback) {\n  if (callback || typeof opt === 'function') {\n    if (!callback) {\n      callback = opt;\n      opt = null;\n    }\n\n    opt = merge({}, marked.defaults, opt || {});\n\n    var highlight = opt.highlight\n      , tokens\n      , pending\n      , i = 0;\n\n    try {\n      tokens = Lexer.lex(src, opt)\n    } catch (e) {\n      return callback(e);\n    }\n\n    pending = tokens.length;\n\n    var done = function(err) {\n      if (err) {\n        opt.highlight = highlight;\n        return callback(err);\n      }\n\n      var out;\n\n      try {\n        out = Parser.parse(tokens, opt);\n      } catch (e) {\n        err = e;\n      }\n\n      opt.highlight = highlight;\n\n      return err\n        ? callback(err)\n        : callback(null, out);\n    };\n\n    if (!highlight || highlight.length < 3) {\n      return done();\n    }\n\n    delete opt.highlight;\n\n    if (!pending) return done();\n\n    for (; i < tokens.length; i++) {\n      (function(token) {\n        if (token.type !== 'code') {\n          return --pending || done();\n        }\n        return highlight(token.text, token.lang, function(err, code) {\n          if (err) return done(err);\n          if (code == null || code === token.text) {\n            return --pending || done();\n          }\n          token.text = code;\n          token.escaped = true;\n          --pending || done();\n        });\n      })(tokens[i]);\n    }\n\n    return;\n  }\n  try {\n    if (opt) opt = merge({}, marked.defaults, opt);\n    return Parser.parse(Lexer.lex(src, opt), opt);\n  } catch (e) {\n    e.message += '\\nPlease report this to https://github.com/chjj/marked.';\n    if ((opt || marked.defaults).silent) {\n      return '<p>An error occured:</p><pre>'\n        + escape(e.message + '', true)\n        + '</pre>';\n    }\n    throw e;\n  }\n}\n\n/**\n * Options\n */\n\nmarked.options =\nmarked.setOptions = function(opt) {\n  merge(marked.defaults, opt);\n  return marked;\n};\n\nmarked.defaults = {\n  gfm: true,\n  tables: true,\n  breaks: false,\n  pedantic: false,\n  sanitize: false,\n  sanitizer: null,\n  mangle: true,\n  smartLists: false,\n  silent: false,\n  highlight: null,\n  langPrefix: 'lang-',\n  smartypants: false,\n  headerPrefix: '',\n  renderer: new Renderer,\n  xhtml: false\n};\n\n/**\n * Expose\n */\n\nmarked.Parser = Parser;\nmarked.parser = Parser.parse;\n\nmarked.Renderer = Renderer;\n\nmarked.Lexer = Lexer;\nmarked.lexer = Lexer.lex;\n\nmarked.InlineLexer = InlineLexer;\nmarked.inlineLexer = InlineLexer.output;\n\nmarked.parse = marked;\n\nif (typeof module !== 'undefined' && typeof exports === 'object') {\n  module.exports = marked;\n} else if (typeof define === 'function' && define.amd) {\n  define(function() { return marked; });\n} else {\n  this.marked = marked;\n}\n\n}).call(function() {\n  return this || (typeof window !== 'undefined' ? window : global);\n}());\n\nvar csrfToken = $('meta[name=\"csrf-token\"]').attr('content'),\n    routeName = $('meta[name=\"csrf-token\"]').attr('content'),\n    textAreas = $('textarea');\n\n/* Global Settings */\nwindow.addEventListener('load', function () {\n  FastClick.attach(document.body);\n}, false);\n\n/* Set Ajax request header */\n/* Document can be found at http://laravel.com/docs/5.1/routing#csrf-x-csrf-token */\n$.ajaxSetup({\n  headers: {\n    'X-CSRF-TOKEN': csrfToken\n  }\n});\n\n/* Layouts Related */\n\nif (textAreas.length) {\n  textAreas.tabby({tabString:'    '});\n\n  /* Auto expand textarea size */\n  autosize(textAreas);\n\n  textAreas.on(\"focus\", function(e) {\n    // Show preview pane when a textarea is in focus\n    $(this).siblings(\"div.preview__forum\").first().show();\n  });\n\n  textAreas.on(\"keyup\", function(e) {\n    // Register 'keyup' event handler\n    var self = $(this),\n      content = self.val(),\n      previewEl = self.siblings(\"div.preview__forum\").first();\n    // Compile textarea content\n    var compiled = marked(content, {\n      renderer: new marked.Renderer(),\n      gfm: true,\n      tables: true,\n      breaks: true,\n      pedantic: false,\n      sanitize: true,\n      smartLists: true,\n      smartypants: false\n    });\n    // Fill preview container with compiled content\n    previewEl.html(compiled);\n    // Add syntax highlight on the preview content\n    previewEl.find('pre code').each(function(i, block) {\n      hljs.highlightBlock(block)\n    });\n  }).trigger(\"keyup\");\n}\n\n/* Activate syntax highlight. *\n /* This will affect code blocks right after the page renders */\nhljs.initHighlightingOnLoad();\n\n/* At the time of page loading, remove any element having flash-message class in 5 secs */\nif ($(\".flash-message\")) {\n  $(\".flash-message\").delay(5000).fadeOut();\n}\n\n/* Center image in the html which was compiled from markdown */\n$(\".container__forum article>p>img, .container__documents article>p>img\").closest(\"p\").addClass(\"text-center\");\n\n/* Generate flash message from javascript */\nfunction flash(type, msg, delay) {\n  var el = $(\"div.js-flash-message\");\n\n  if (el) {\n    el.remove();\n  }\n\n  $(\"<div></div>\", {\n    \"class\": \"alert alert-\" + type + \" alert-dismissible js-flash-message\",\n    \"html\": '<button type=\"button\" class=\"close\" data-dismiss=\"alert\">'\n    + '<span aria-hidden=\"true\">&times;</span>'\n    + '<span class=\"sr-only\">Close</span></button>' + msg\n  }).appendTo($(\".container\").first());\n\n  $(\"div.js-flash-message\").fadeIn(\"fast\").delay(delay || 5000).fadeOut(\"fast\");\n}\n\n/* Reload page */\nfunction reload(interval) {\n  setTimeout(function () {\n    window.location.reload(true);\n  }, interval || 5000);\n}\n//# sourceMappingURL=app.js.map\n"
  },
  {
    "path": "public/build/js/app-6c3ef62a70.js",
    "content": "function flash(e,t,n){var i=$(\"div.js-flash-message\");i&&i.remove(),$(\"<div></div>\",{\"class\":\"alert alert-\"+e+\" alert-dismissible js-flash-message\",html:'<button type=\"button\" class=\"close\" data-dismiss=\"alert\"><span aria-hidden=\"true\">&times;</span><span class=\"sr-only\">Close</span></button>'+t}).appendTo($(\".container\").first()),$(\"div.js-flash-message\").fadeIn(\"fast\").delay(n||5e3).fadeOut(\"fast\")}function reload(e){setTimeout(function(){window.location.reload(!0)},e||5e3)}if(function(e,t){\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(e,t){function n(e){var t=\"length\"in e&&e.length,n=J.type(e);return\"function\"===n||J.isWindow(e)?!1:1===e.nodeType&&t?!0:\"array\"===n||0===t||\"number\"==typeof t&&t>0&&t-1 in e}function i(e,t,n){if(J.isFunction(t))return J.grep(e,function(e,i){return!!t.call(e,i,e)!==n});if(t.nodeType)return J.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(se.test(t))return J.filter(t,e,n);t=J.filter(t,e)}return J.grep(e,function(e){return V.call(t,e)>=0!==n})}function r(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function a(e){var t=ge[e]={};return J.each(e.match(me)||[],function(e,n){t[n]=!0}),t}function o(){X.removeEventListener(\"DOMContentLoaded\",o,!1),e.removeEventListener(\"load\",o,!1),J.ready()}function s(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=J.expando+s.uid++}function l(e,t,n){var i;if(void 0===n&&1===e.nodeType)if(i=\"data-\"+t.replace(Ce,\"-$1\").toLowerCase(),n=e.getAttribute(i),\"string\"==typeof n){try{n=\"true\"===n?!0:\"false\"===n?!1:\"null\"===n?null:+n+\"\"===n?+n:ve.test(n)?J.parseJSON(n):n}catch(r){}be.set(e,t,n)}else n=void 0;return n}function c(){return!0}function d(){return!1}function u(){try{return X.activeElement}catch(e){}}function p(e,t){return J.nodeName(e,\"table\")&&J.nodeName(11!==t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function m(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function g(e){var t=Re.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function h(e,t){for(var n=0,i=e.length;i>n;n++)_e.set(e[n],\"globalEval\",!t||_e.get(t[n],\"globalEval\"))}function f(e,t){var n,i,r,a,o,s,l,c;if(1===t.nodeType){if(_e.hasData(e)&&(a=_e.access(e),o=_e.set(t,a),c=a.events)){delete o.handle,o.events={};for(r in c)for(n=0,i=c[r].length;i>n;n++)J.event.add(t,r,c[r][n])}be.hasData(e)&&(s=be.access(e),l=J.extend({},s),be.set(t,l))}}function _(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&J.nodeName(e,t)?J.merge([e],n):n}function b(e,t){var n=t.nodeName.toLowerCase();\"input\"===n&&Ee.test(e.type)?t.checked=e.checked:(\"input\"===n||\"textarea\"===n)&&(t.defaultValue=e.defaultValue)}function v(t,n){var i,r=J(n.createElement(t)).appendTo(n.body),a=e.getDefaultComputedStyle&&(i=e.getDefaultComputedStyle(r[0]))?i.display:J.css(r[0],\"display\");return r.detach(),a}function C(e){var t=X,n=Be[e];return n||(n=v(e,t),\"none\"!==n&&n||(Fe=(Fe||J(\"<iframe frameborder='0' width='0' height='0'/>\")).appendTo(t.documentElement),t=Fe[0].contentDocument,t.write(),t.close(),n=v(e,t),Fe.detach()),Be[e]=n),n}function I(e,t,n){var i,r,a,o,s=e.style;return n=n||ze(e),n&&(o=n.getPropertyValue(t)||n[t]),n&&(\"\"!==o||J.contains(e.ownerDocument,e)||(o=J.style(e,t)),qe.test(o)&&We.test(t)&&(i=s.width,r=s.minWidth,a=s.maxWidth,s.minWidth=s.maxWidth=s.width=o,o=n.width,s.width=i,s.minWidth=r,s.maxWidth=a)),void 0!==o?o+\"\":o}function y(e,t){return{get:function(){return e()?void delete this.get:(this.get=t).apply(this,arguments)}}}function S(e,t){if(t in e)return t;for(var n=t[0].toUpperCase()+t.slice(1),i=t,r=Qe.length;r--;)if(t=Qe[r]+n,t in e)return t;return i}function E(e,t,n){var i=He.exec(t);return i?Math.max(0,i[1]-(n||0))+(i[2]||\"px\"):t}function x(e,t,n,i,r){for(var a=n===(i?\"border\":\"content\")?4:\"width\"===t?1:0,o=0;4>a;a+=2)\"margin\"===n&&(o+=J.css(e,n+ye[a],!0,r)),i?(\"content\"===n&&(o-=J.css(e,\"padding\"+ye[a],!0,r)),\"margin\"!==n&&(o-=J.css(e,\"border\"+ye[a]+\"Width\",!0,r))):(o+=J.css(e,\"padding\"+ye[a],!0,r),\"padding\"!==n&&(o+=J.css(e,\"border\"+ye[a]+\"Width\",!0,r)));return o}function T(e,t,n){var i=!0,r=\"width\"===t?e.offsetWidth:e.offsetHeight,a=ze(e),o=\"border-box\"===J.css(e,\"boxSizing\",!1,a);if(0>=r||null==r){if(r=I(e,t,a),(0>r||null==r)&&(r=e.style[t]),qe.test(r))return r;i=o&&(Z.boxSizingReliable()||r===e.style[t]),r=parseFloat(r)||0}return r+x(e,t,n||(o?\"border\":\"content\"),i,a)+\"px\"}function w(e,t){for(var n,i,r,a=[],o=0,s=e.length;s>o;o++)i=e[o],i.style&&(a[o]=_e.get(i,\"olddisplay\"),n=i.style.display,t?(a[o]||\"none\"!==n||(i.style.display=\"\"),\"\"===i.style.display&&Se(i)&&(a[o]=_e.access(i,\"olddisplay\",C(i.nodeName)))):(r=Se(i),\"none\"===n&&r||_e.set(i,\"olddisplay\",r?n:J.css(i,\"display\"))));for(o=0;s>o;o++)i=e[o],i.style&&(t&&\"none\"!==i.style.display&&\"\"!==i.style.display||(i.style.display=t?a[o]||\"\":\"none\"));return e}function A(e,t,n,i,r){return new A.prototype.init(e,t,n,i,r)}function P(){return setTimeout(function(){Ze=void 0}),Ze=J.now()}function D(e,t){var n,i=0,r={height:e};for(t=t?1:0;4>i;i+=2-t)n=ye[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}function G(e,t,n){for(var i,r=(nt[t]||[]).concat(nt[\"*\"]),a=0,o=r.length;o>a;a++)if(i=r[a].call(n,t,e))return i}function M(e,t,n){var i,r,a,o,s,l,c,d,u=this,p={},m=e.style,g=e.nodeType&&Se(e),h=_e.get(e,\"fxshow\");n.queue||(s=J._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,J.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[m.overflow,m.overflowX,m.overflowY],c=J.css(e,\"display\"),d=\"none\"===c?_e.get(e,\"olddisplay\")||C(e.nodeName):c,\"inline\"===d&&\"none\"===J.css(e,\"float\")&&(m.display=\"inline-block\")),n.overflow&&(m.overflow=\"hidden\",u.always(function(){m.overflow=n.overflow[0],m.overflowX=n.overflow[1],m.overflowY=n.overflow[2]}));for(i in t)if(r=t[i],Ye.exec(r)){if(delete t[i],a=a||\"toggle\"===r,r===(g?\"hide\":\"show\")){if(\"show\"!==r||!h||void 0===h[i])continue;g=!0}p[i]=h&&h[i]||J.style(e,i)}else c=void 0;if(J.isEmptyObject(p))\"inline\"===(\"none\"===c?C(e.nodeName):c)&&(m.display=c);else{h?\"hidden\"in h&&(g=h.hidden):h=_e.access(e,\"fxshow\",{}),a&&(h.hidden=!g),g?J(e).show():u.done(function(){J(e).hide()}),u.done(function(){var t;_e.remove(e,\"fxshow\");for(t in p)J.style(e,t,p[t])});for(i in p)o=G(g?h[i]:0,i,u),i in h||(h[i]=o.start,g&&(o.end=o.start,o.start=\"width\"===i||\"height\"===i?1:0))}}function N(e,t){var n,i,r,a,o;for(n in e)if(i=J.camelCase(n),r=t[i],a=e[n],J.isArray(a)&&(r=a[1],a=e[n]=a[0]),n!==i&&(e[i]=a,delete e[n]),o=J.cssHooks[i],o&&\"expand\"in o){a=o.expand(a),delete e[i];for(n in a)n in e||(e[n]=a[n],t[n]=r)}else t[i]=r}function L(e,t,n){var i,r,a=0,o=tt.length,s=J.Deferred().always(function(){delete l.elem}),l=function(){if(r)return!1;for(var t=Ze||P(),n=Math.max(0,c.startTime+c.duration-t),i=n/c.duration||0,a=1-i,o=0,l=c.tweens.length;l>o;o++)c.tweens[o].run(a);return s.notifyWith(e,[c,a,n]),1>a&&l?n:(s.resolveWith(e,[c]),!1)},c=s.promise({elem:e,props:J.extend({},t),opts:J.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Ze||P(),duration:n.duration,tweens:[],createTween:function(t,n){var i=J.Tween(e,c.opts,t,n,c.opts.specialEasing[t]||c.opts.easing);return c.tweens.push(i),i},stop:function(t){var n=0,i=t?c.tweens.length:0;if(r)return this;for(r=!0;i>n;n++)c.tweens[n].run(1);return t?s.resolveWith(e,[c,t]):s.rejectWith(e,[c,t]),this}}),d=c.props;for(N(d,c.opts.specialEasing);o>a;a++)if(i=tt[a].call(c,e,d,c.opts))return i;return J.map(d,G,c),J.isFunction(c.opts.start)&&c.opts.start.call(e,c),J.fx.timer(J.extend(l,{elem:e,anim:c,queue:c.opts.queue})),c.progress(c.opts.progress).done(c.opts.done,c.opts.complete).fail(c.opts.fail).always(c.opts.always)}function k(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var i,r=0,a=t.toLowerCase().match(me)||[];if(J.isFunction(n))for(;i=a[r++];)\"+\"===i[0]?(i=i.slice(1)||\"*\",(e[i]=e[i]||[]).unshift(n)):(e[i]=e[i]||[]).push(n)}}function R(e,t,n,i){function r(s){var l;return a[s]=!0,J.each(e[s]||[],function(e,s){var c=s(t,n,i);return\"string\"!=typeof c||o||a[c]?o?!(l=c):void 0:(t.dataTypes.unshift(c),r(c),!1)}),l}var a={},o=e===vt;return r(t.dataTypes[0])||!a[\"*\"]&&r(\"*\")}function O(e,t){var n,i,r=J.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((r[n]?e:i||(i={}))[n]=t[n]);return i&&J.extend(!0,e,i),e}function U(e,t,n){for(var i,r,a,o,s=e.contents,l=e.dataTypes;\"*\"===l[0];)l.shift(),void 0===i&&(i=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(i)for(r in s)if(s[r]&&s[r].test(i)){l.unshift(r);break}if(l[0]in n)a=l[0];else{for(r in n){if(!l[0]||e.converters[r+\" \"+l[0]]){a=r;break}o||(o=r)}a=a||o}return a?(a!==l[0]&&l.unshift(a),n[a]):void 0}function F(e,t,n,i){var r,a,o,s,l,c={},d=e.dataTypes.slice();if(d[1])for(o in e.converters)c[o.toLowerCase()]=e.converters[o];for(a=d.shift();a;)if(e.responseFields[a]&&(n[e.responseFields[a]]=t),!l&&i&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=a,a=d.shift())if(\"*\"===a)a=l;else if(\"*\"!==l&&l!==a){if(o=c[l+\" \"+a]||c[\"* \"+a],!o)for(r in c)if(s=r.split(\" \"),s[1]===a&&(o=c[l+\" \"+s[0]]||c[\"* \"+s[0]])){o===!0?o=c[r]:c[r]!==!0&&(a=s[0],d.unshift(s[1]));break}if(o!==!0)if(o&&e[\"throws\"])t=o(t);else try{t=o(t)}catch(u){return{state:\"parsererror\",error:o?u:\"No conversion from \"+l+\" to \"+a}}}return{state:\"success\",data:t}}function B(e,t,n,i){var r;if(J.isArray(t))J.each(t,function(t,r){n||Et.test(e)?i(e,r):B(e+\"[\"+(\"object\"==typeof r?t:\"\")+\"]\",r,n,i)});else if(n||\"object\"!==J.type(t))i(e,t);else for(r in t)B(e+\"[\"+r+\"]\",t[r],n,i)}function W(e){return J.isWindow(e)?e:9===e.nodeType&&e.defaultView}var q=[],z=q.slice,$=q.concat,H=q.push,V=q.indexOf,j={},K=j.toString,Q=j.hasOwnProperty,Z={},X=e.document,Y=\"2.1.4\",J=function(e,t){return new J.fn.init(e,t)},ee=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,te=/^-ms-/,ne=/-([\\da-z])/gi,ie=function(e,t){return t.toUpperCase()};J.fn=J.prototype={jquery:Y,constructor:J,selector:\"\",length:0,toArray:function(){return z.call(this)},get:function(e){return null!=e?0>e?this[e+this.length]:this[e]:z.call(this)},pushStack:function(e){var t=J.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return J.each(this,e,t)},map:function(e){return this.pushStack(J.map(this,function(t,n){return e.call(t,n,t)}))},slice:function(){return this.pushStack(z.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:H,sort:q.sort,splice:q.splice},J.extend=J.fn.extend=function(){var e,t,n,i,r,a,o=arguments[0]||{},s=1,l=arguments.length,c=!1;for(\"boolean\"==typeof o&&(c=o,o=arguments[s]||{},s++),\"object\"==typeof o||J.isFunction(o)||(o={}),s===l&&(o=this,s--);l>s;s++)if(null!=(e=arguments[s]))for(t in e)n=o[t],i=e[t],o!==i&&(c&&i&&(J.isPlainObject(i)||(r=J.isArray(i)))?(r?(r=!1,a=n&&J.isArray(n)?n:[]):a=n&&J.isPlainObject(n)?n:{},o[t]=J.extend(c,a,i)):void 0!==i&&(o[t]=i));return o},J.extend({expando:\"jQuery\"+(Y+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isFunction:function(e){return\"function\"===J.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!J.isArray(e)&&e-parseFloat(e)+1>=0},isPlainObject:function(e){return\"object\"!==J.type(e)||e.nodeType||J.isWindow(e)?!1:e.constructor&&!Q.call(e.constructor.prototype,\"isPrototypeOf\")?!1:!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?j[K.call(e)]||\"object\":typeof e},globalEval:function(e){var t,n=eval;e=J.trim(e),e&&(1===e.indexOf(\"use strict\")?(t=X.createElement(\"script\"),t.text=e,X.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(te,\"ms-\").replace(ne,ie)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,i){var r,a=0,o=e.length,s=n(e);if(i){if(s)for(;o>a&&(r=t.apply(e[a],i),r!==!1);a++);else for(a in e)if(r=t.apply(e[a],i),r===!1)break}else if(s)for(;o>a&&(r=t.call(e[a],a,e[a]),r!==!1);a++);else for(a in e)if(r=t.call(e[a],a,e[a]),r===!1)break;return e},trim:function(e){return null==e?\"\":(e+\"\").replace(ee,\"\")},makeArray:function(e,t){var i=t||[];return null!=e&&(n(Object(e))?J.merge(i,\"string\"==typeof e?[e]:e):H.call(i,e)),i},inArray:function(e,t,n){return null==t?-1:V.call(t,e,n)},merge:function(e,t){for(var n=+t.length,i=0,r=e.length;n>i;i++)e[r++]=t[i];return e.length=r,e},grep:function(e,t,n){for(var i,r=[],a=0,o=e.length,s=!n;o>a;a++)i=!t(e[a],a),i!==s&&r.push(e[a]);return r},map:function(e,t,i){var r,a=0,o=e.length,s=n(e),l=[];if(s)for(;o>a;a++)r=t(e[a],a,i),null!=r&&l.push(r);else for(a in e)r=t(e[a],a,i),null!=r&&l.push(r);return $.apply([],l)},guid:1,proxy:function(e,t){var n,i,r;return\"string\"==typeof t&&(n=e[t],t=e,e=n),J.isFunction(e)?(i=z.call(arguments,2),r=function(){return e.apply(t||this,i.concat(z.call(arguments)))},r.guid=e.guid=e.guid||J.guid++,r):void 0},now:Date.now,support:Z}),J.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(e,t){j[\"[object \"+t+\"]\"]=t.toLowerCase()});var re=function(e){function t(e,t,n,i){var r,a,o,s,l,c,u,m,g,h;if((t?t.ownerDocument||t:B)!==M&&G(t),t=t||M,n=n||[],s=t.nodeType,\"string\"!=typeof e||!e||1!==s&&9!==s&&11!==s)return n;if(!i&&L){if(11!==s&&(r=be.exec(e)))if(o=r[1]){if(9===s){if(a=t.getElementById(o),!a||!a.parentNode)return n;if(a.id===o)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(o))&&U(t,a)&&a.id===o)return n.push(a),n}else{if(r[2])return Y.apply(n,t.getElementsByTagName(e)),n;if((o=r[3])&&I.getElementsByClassName)return Y.apply(n,t.getElementsByClassName(o)),n}if(I.qsa&&(!k||!k.test(e))){if(m=u=F,g=t,h=1!==s&&e,1===s&&\"object\"!==t.nodeName.toLowerCase()){for(c=x(e),(u=t.getAttribute(\"id\"))?m=u.replace(Ce,\"\\\\$&\"):t.setAttribute(\"id\",m),m=\"[id='\"+m+\"'] \",l=c.length;l--;)c[l]=m+p(c[l]);g=ve.test(e)&&d(t.parentNode)||t,h=c.join(\",\")}if(h)try{return Y.apply(n,g.querySelectorAll(h)),n}catch(f){}finally{u||t.removeAttribute(\"id\")}}}return w(e.replace(le,\"$1\"),t,n,i)}function n(){function e(n,i){return t.push(n+\" \")>y.cacheLength&&delete e[t.shift()],e[n+\" \"]=i}var t=[];return e}function i(e){return e[F]=!0,e}function r(e){var t=M.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function a(e,t){for(var n=e.split(\"|\"),i=e.length;i--;)y.attrHandle[n[i]]=t}function o(e,t){var n=t&&e,i=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(i)return i;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function l(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function c(e){return i(function(t){return t=+t,i(function(n,i){for(var r,a=e([],n.length,t),o=a.length;o--;)n[r=a[o]]&&(n[r]=!(i[r]=n[r]))})})}function d(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}function u(){}function p(e){for(var t=0,n=e.length,i=\"\";n>t;t++)i+=e[t].value;return i}function m(e,t,n){var i=t.dir,r=n&&\"parentNode\"===i,a=q++;return t.first?function(t,n,a){for(;t=t[i];)if(1===t.nodeType||r)return e(t,n,a)}:function(t,n,o){var s,l,c=[W,a];if(o){for(;t=t[i];)if((1===t.nodeType||r)&&e(t,n,o))return!0}else for(;t=t[i];)if(1===t.nodeType||r){if(l=t[F]||(t[F]={}),(s=l[i])&&s[0]===W&&s[1]===a)return c[2]=s[2];if(l[i]=c,c[2]=e(t,n,o))return!0}}}function g(e){return e.length>1?function(t,n,i){for(var r=e.length;r--;)if(!e[r](t,n,i))return!1;return!0}:e[0]}function h(e,n,i){for(var r=0,a=n.length;a>r;r++)t(e,n[r],i);return i}function f(e,t,n,i,r){for(var a,o=[],s=0,l=e.length,c=null!=t;l>s;s++)(a=e[s])&&(!n||n(a,i,r))&&(o.push(a),c&&t.push(s));return o}function _(e,t,n,r,a,o){return r&&!r[F]&&(r=_(r)),a&&!a[F]&&(a=_(a,o)),i(function(i,o,s,l){var c,d,u,p=[],m=[],g=o.length,_=i||h(t||\"*\",s.nodeType?[s]:s,[]),b=!e||!i&&t?_:f(_,p,e,s,l),v=n?a||(i?e:g||r)?[]:o:b;if(n&&n(b,v,s,l),r)for(c=f(v,m),r(c,[],s,l),d=c.length;d--;)(u=c[d])&&(v[m[d]]=!(b[m[d]]=u));if(i){if(a||e){if(a){for(c=[],d=v.length;d--;)(u=v[d])&&c.push(b[d]=u);a(null,v=[],c,l)}for(d=v.length;d--;)(u=v[d])&&(c=a?ee(i,u):p[d])>-1&&(i[c]=!(o[c]=u))}}else v=f(v===o?v.splice(g,v.length):v),a?a(null,o,v,l):Y.apply(o,v)})}function b(e){for(var t,n,i,r=e.length,a=y.relative[e[0].type],o=a||y.relative[\" \"],s=a?1:0,l=m(function(e){return e===t},o,!0),c=m(function(e){return ee(t,e)>-1},o,!0),d=[function(e,n,i){var r=!a&&(i||n!==A)||((t=n).nodeType?l(e,n,i):c(e,n,i));return t=null,r}];r>s;s++)if(n=y.relative[e[s].type])d=[m(g(d),n)];else{if(n=y.filter[e[s].type].apply(null,e[s].matches),n[F]){for(i=++s;r>i&&!y.relative[e[i].type];i++);return _(s>1&&g(d),s>1&&p(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace(le,\"$1\"),n,i>s&&b(e.slice(s,i)),r>i&&b(e=e.slice(i)),r>i&&p(e))}d.push(n)}return g(d)}function v(e,n){var r=n.length>0,a=e.length>0,o=function(i,o,s,l,c){var d,u,p,m=0,g=\"0\",h=i&&[],_=[],b=A,v=i||a&&y.find.TAG(\"*\",c),C=W+=null==b?1:Math.random()||.1,I=v.length;for(c&&(A=o!==M&&o);g!==I&&null!=(d=v[g]);g++){if(a&&d){for(u=0;p=e[u++];)if(p(d,o,s)){l.push(d);break}c&&(W=C)}r&&((d=!p&&d)&&m--,i&&h.push(d))}if(m+=g,r&&g!==m){for(u=0;p=n[u++];)p(h,_,o,s);if(i){if(m>0)for(;g--;)h[g]||_[g]||(_[g]=Z.call(l));_=f(_)}Y.apply(l,_),c&&!i&&_.length>0&&m+n.length>1&&t.uniqueSort(l)}return c&&(W=C,A=b),h};return r?i(o):o}var C,I,y,S,E,x,T,w,A,P,D,G,M,N,L,k,R,O,U,F=\"sizzle\"+1*new Date,B=e.document,W=0,q=0,z=n(),$=n(),H=n(),V=function(e,t){return e===t&&(D=!0),0},j=1<<31,K={}.hasOwnProperty,Q=[],Z=Q.pop,X=Q.push,Y=Q.push,J=Q.slice,ee=function(e,t){for(var n=0,i=e.length;i>n;n++)if(e[n]===t)return n;return-1},te=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",ne=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",ie=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",re=ie.replace(\"w\",\"w#\"),ae=\"\\\\[\"+ne+\"*(\"+ie+\")(?:\"+ne+\"*([*^$|!~]?=)\"+ne+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+re+\"))|)\"+ne+\"*\\\\]\",oe=\":(\"+ie+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+ae+\")*)|.*)\\\\)|)\",se=new RegExp(ne+\"+\",\"g\"),le=new RegExp(\"^\"+ne+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+ne+\"+$\",\"g\"),ce=new RegExp(\"^\"+ne+\"*,\"+ne+\"*\"),de=new RegExp(\"^\"+ne+\"*([>+~]|\"+ne+\")\"+ne+\"*\"),ue=new RegExp(\"=\"+ne+\"*([^\\\\]'\\\"]*?)\"+ne+\"*\\\\]\",\"g\"),pe=new RegExp(oe),me=new RegExp(\"^\"+re+\"$\"),ge={ID:new RegExp(\"^#(\"+ie+\")\"),CLASS:new RegExp(\"^\\\\.(\"+ie+\")\"),TAG:new RegExp(\"^(\"+ie.replace(\"w\",\"w*\")+\")\"),ATTR:new RegExp(\"^\"+ae),PSEUDO:new RegExp(\"^\"+oe),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+ne+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+ne+\"*(?:([+-]|)\"+ne+\"*(\\\\d+)|))\"+ne+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+te+\")$\",\"i\"),needsContext:new RegExp(\"^\"+ne+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+ne+\"*((?:-\\\\d)?\\\\d*)\"+ne+\"*\\\\)|)(?=[^-]|$)\",\"i\")},he=/^(?:input|select|textarea|button)$/i,fe=/^h\\d$/i,_e=/^[^{]+\\{\\s*\\[native \\w/,be=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ve=/[+~]/,Ce=/'|\\\\/g,Ie=new RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+ne+\"?|(\"+ne+\")|.)\",\"ig\"),ye=function(e,t,n){var i=\"0x\"+t-65536;return i!==i||n?t:0>i?String.fromCharCode(i+65536):String.fromCharCode(i>>10|55296,1023&i|56320)},Se=function(){G()};try{Y.apply(Q=J.call(B.childNodes),B.childNodes),Q[B.childNodes.length].nodeType}catch(Ee){Y={apply:Q.length?function(e,t){X.apply(e,J.call(t))}:function(e,t){for(var n=e.length,i=0;e[n++]=t[i++];);e.length=n-1}}}I=t.support={},E=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?\"HTML\"!==t.nodeName:!1},G=t.setDocument=function(e){var t,n,i=e?e.ownerDocument||e:B;return i!==M&&9===i.nodeType&&i.documentElement?(M=i,N=i.documentElement,n=i.defaultView,n&&n!==n.top&&(n.addEventListener?n.addEventListener(\"unload\",Se,!1):n.attachEvent&&n.attachEvent(\"onunload\",Se)),L=!E(i),I.attributes=r(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),I.getElementsByTagName=r(function(e){return e.appendChild(i.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),I.getElementsByClassName=_e.test(i.getElementsByClassName),I.getById=r(function(e){return N.appendChild(e).id=F,!i.getElementsByName||!i.getElementsByName(F).length}),I.getById?(y.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&L){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},y.filter.ID=function(e){var t=e.replace(Ie,ye);return function(e){return e.getAttribute(\"id\")===t}}):(delete y.find.ID,y.filter.ID=function(e){var t=e.replace(Ie,ye);return function(e){var n=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return n&&n.value===t}}),y.find.TAG=I.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):I.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,i=[],r=0,a=t.getElementsByTagName(e);if(\"*\"===e){for(;n=a[r++];)1===n.nodeType&&i.push(n);return i}return a},y.find.CLASS=I.getElementsByClassName&&function(e,t){return L?t.getElementsByClassName(e):void 0},R=[],k=[],(I.qsa=_e.test(i.querySelectorAll))&&(r(function(e){N.appendChild(e).innerHTML=\"<a id='\"+F+\"'></a><select id='\"+F+\"-\\f]' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&k.push(\"[*^$]=\"+ne+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||k.push(\"\\\\[\"+ne+\"*(?:value|\"+te+\")\"),e.querySelectorAll(\"[id~=\"+F+\"-]\").length||k.push(\"~=\"),e.querySelectorAll(\":checked\").length||k.push(\":checked\"),e.querySelectorAll(\"a#\"+F+\"+*\").length||k.push(\".#.+[+~]\")}),r(function(e){var t=i.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&k.push(\"name\"+ne+\"*[*^$|!~]?=\"),e.querySelectorAll(\":enabled\").length||k.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),k.push(\",.*:\")})),(I.matchesSelector=_e.test(O=N.matches||N.webkitMatchesSelector||N.mozMatchesSelector||N.oMatchesSelector||N.msMatchesSelector))&&r(function(e){I.disconnectedMatch=O.call(e,\"div\"),O.call(e,\"[s!='']:x\"),R.push(\"!=\",oe)}),k=k.length&&new RegExp(k.join(\"|\")),R=R.length&&new RegExp(R.join(\"|\")),t=_e.test(N.compareDocumentPosition),U=t||_e.test(N.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,i=t&&t.parentNode;return e===i||!(!i||1!==i.nodeType||!(n.contains?n.contains(i):e.compareDocumentPosition&&16&e.compareDocumentPosition(i)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},V=t?function(e,t){if(e===t)return D=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!I.sortDetached&&t.compareDocumentPosition(e)===n?e===i||e.ownerDocument===B&&U(B,e)?-1:t===i||t.ownerDocument===B&&U(B,t)?1:P?ee(P,e)-ee(P,t):0:4&n?-1:1)}:function(e,t){if(e===t)return D=!0,0;var n,r=0,a=e.parentNode,s=t.parentNode,l=[e],c=[t];if(!a||!s)return e===i?-1:t===i?1:a?-1:s?1:P?ee(P,e)-ee(P,t):0;if(a===s)return o(e,t);for(n=e;n=n.parentNode;)l.unshift(n);for(n=t;n=n.parentNode;)c.unshift(n);for(;l[r]===c[r];)r++;return r?o(l[r],c[r]):l[r]===B?-1:c[r]===B?1:0},i):M},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==M&&G(e),n=n.replace(ue,\"='$1']\"),I.matchesSelector&&L&&(!R||!R.test(n))&&(!k||!k.test(n)))try{var i=O.call(e,n);if(i||I.disconnectedMatch||e.document&&11!==e.document.nodeType)return i}catch(r){}return t(n,M,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==M&&G(e),U(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==M&&G(e);var n=y.attrHandle[t.toLowerCase()],i=n&&K.call(y.attrHandle,t.toLowerCase())?n(e,t,!L):void 0;return void 0!==i?i:I.attributes||!L?e.getAttribute(t):(i=e.getAttributeNode(t))&&i.specified?i.value:null},t.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},t.uniqueSort=function(e){var t,n=[],i=0,r=0;if(D=!I.detectDuplicates,P=!I.sortStable&&e.slice(0),e.sort(V),D){for(;t=e[r++];)t===e[r]&&(i=n.push(r));for(;i--;)e.splice(n[i],1)}return P=null,e},S=t.getText=function(e){var t,n=\"\",i=0,r=e.nodeType;if(r){if(1===r||9===r||11===r){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=S(e)}else if(3===r||4===r)return e.nodeValue}else for(;t=e[i++];)n+=S(t);return n},y=t.selectors={cacheLength:50,createPseudo:i,match:ge,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Ie,ye),e[3]=(e[3]||e[4]||e[5]||\"\").replace(Ie,ye),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return ge.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&pe.test(n)&&(t=x(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Ie,ye).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=z[e+\" \"];return t||(t=new RegExp(\"(^|\"+ne+\")\"+e+\"(\"+ne+\"|$)\"))&&z(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,n,i){return function(r){var a=t.attr(r,e);return null==a?\"!=\"===n:n?(a+=\"\",\"=\"===n?a===i:\"!=\"===n?a!==i:\"^=\"===n?i&&0===a.indexOf(i):\"*=\"===n?i&&a.indexOf(i)>-1:\"$=\"===n?i&&a.slice(-i.length)===i:\"~=\"===n?(\" \"+a.replace(se,\" \")+\" \").indexOf(i)>-1:\"|=\"===n?a===i||a.slice(0,i.length+1)===i+\"-\":!1):!0}},CHILD:function(e,t,n,i,r){var a=\"nth\"!==e.slice(0,3),o=\"last\"!==e.slice(-4),s=\"of-type\"===t;return 1===i&&0===r?function(e){return!!e.parentNode}:function(t,n,l){var c,d,u,p,m,g,h=a!==o?\"nextSibling\":\"previousSibling\",f=t.parentNode,_=s&&t.nodeName.toLowerCase(),b=!l&&!s;if(f){if(a){for(;h;){for(u=t;u=u[h];)if(s?u.nodeName.toLowerCase()===_:1===u.nodeType)return!1;g=h=\"only\"===e&&!g&&\"nextSibling\"}return!0}if(g=[o?f.firstChild:f.lastChild],o&&b){for(d=f[F]||(f[F]={}),c=d[e]||[],m=c[0]===W&&c[1],p=c[0]===W&&c[2],u=m&&f.childNodes[m];u=++m&&u&&u[h]||(p=m=0)||g.pop();)if(1===u.nodeType&&++p&&u===t){d[e]=[W,m,p];break}}else if(b&&(c=(t[F]||(t[F]={}))[e])&&c[0]===W)p=c[1];else for(;(u=++m&&u&&u[h]||(p=m=0)||g.pop())&&((s?u.nodeName.toLowerCase()!==_:1!==u.nodeType)||!++p||(b&&((u[F]||(u[F]={}))[e]=[W,p]),u!==t)););return p-=r,p===i||p%i===0&&p/i>=0}}},PSEUDO:function(e,n){var r,a=y.pseudos[e]||y.setFilters[e.toLowerCase()]||t.error(\"unsupported pseudo: \"+e);return a[F]?a(n):a.length>1?(r=[e,e,\"\",n],y.setFilters.hasOwnProperty(e.toLowerCase())?i(function(e,t){for(var i,r=a(e,n),o=r.length;o--;)i=ee(e,r[o]),e[i]=!(t[i]=r[o])}):function(e){return a(e,0,r)}):a}},pseudos:{not:i(function(e){var t=[],n=[],r=T(e.replace(le,\"$1\"));return r[F]?i(function(e,t,n,i){for(var a,o=r(e,null,i,[]),s=e.length;s--;)(a=o[s])&&(e[s]=!(t[s]=a))}):function(e,i,a){return t[0]=e,r(t,null,a,n),t[0]=null,!n.pop()}}),has:i(function(e){return function(n){return t(e,n).length>0}}),contains:i(function(e){return e=e.replace(Ie,ye),function(t){return(t.textContent||t.innerText||S(t)).indexOf(e)>-1}}),lang:i(function(e){return me.test(e||\"\")||t.error(\"unsupported lang: \"+e),e=e.replace(Ie,ye).toLowerCase(),function(t){var n;do if(n=L?t.lang:t.getAttribute(\"xml:lang\")||t.getAttribute(\"lang\"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+\"-\");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===N},focus:function(e){return e===M.activeElement&&(!M.hasFocus||M.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&!!e.checked||\"option\"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!y.pseudos.empty(e)},header:function(e){return fe.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&\"button\"===e.type||\"button\"===t},text:function(e){var t;return\"input\"===e.nodeName.toLowerCase()&&\"text\"===e.type&&(null==(t=e.getAttribute(\"type\"))||\"text\"===t.toLowerCase())},first:c(function(){return[0]}),last:c(function(e,t){return[t-1]}),eq:c(function(e,t,n){return[0>n?n+t:n]}),even:c(function(e,t){for(var n=0;t>n;n+=2)e.push(n);return e}),odd:c(function(e,t){for(var n=1;t>n;n+=2)e.push(n);return e}),lt:c(function(e,t,n){for(var i=0>n?n+t:n;--i>=0;)e.push(i);return e}),gt:c(function(e,t,n){for(var i=0>n?n+t:n;++i<t;)e.push(i);return e})}},y.pseudos.nth=y.pseudos.eq;for(C in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})y.pseudos[C]=s(C);for(C in{submit:!0,reset:!0})y.pseudos[C]=l(C);return u.prototype=y.filters=y.pseudos,y.setFilters=new u,x=t.tokenize=function(e,n){var i,r,a,o,s,l,c,d=$[e+\" \"];if(d)return n?0:d.slice(0);for(s=e,l=[],c=y.preFilter;s;){(!i||(r=ce.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(a=[])),i=!1,(r=de.exec(s))&&(i=r.shift(),a.push({value:i,type:r[0].replace(le,\" \")}),s=s.slice(i.length));for(o in y.filter)!(r=ge[o].exec(s))||c[o]&&!(r=c[o](r))||(i=r.shift(),a.push({value:i,type:o,matches:r}),s=s.slice(i.length));if(!i)break}return n?s.length:s?t.error(e):$(e,l).slice(0)},T=t.compile=function(e,t){var n,i=[],r=[],a=H[e+\" \"];if(!a){for(t||(t=x(e)),n=t.length;n--;)a=b(t[n]),a[F]?i.push(a):r.push(a);a=H(e,v(r,i)),a.selector=e}return a},w=t.select=function(e,t,n,i){var r,a,o,s,l,c=\"function\"==typeof e&&e,u=!i&&x(e=c.selector||e);if(n=n||[],1===u.length){if(a=u[0]=u[0].slice(0),a.length>2&&\"ID\"===(o=a[0]).type&&I.getById&&9===t.nodeType&&L&&y.relative[a[1].type]){if(t=(y.find.ID(o.matches[0].replace(Ie,ye),t)||[])[0],!t)return n;c&&(t=t.parentNode),e=e.slice(a.shift().value.length)}for(r=ge.needsContext.test(e)?0:a.length;r--&&(o=a[r],!y.relative[s=o.type]);)if((l=y.find[s])&&(i=l(o.matches[0].replace(Ie,ye),ve.test(a[0].type)&&d(t.parentNode)||t))){if(a.splice(r,1),e=i.length&&p(a),!e)return Y.apply(n,i),n;break}}return(c||T(e,u))(i,t,!L,n,ve.test(e)&&d(t.parentNode)||t),n},I.sortStable=F.split(\"\").sort(V).join(\"\")===F,I.detectDuplicates=!!D,G(),I.sortDetached=r(function(e){return 1&e.compareDocumentPosition(M.createElement(\"div\"))}),r(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||a(\"type|href|height|width\",function(e,t,n){return n?void 0:e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),I.attributes&&r(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||a(\"value\",function(e,t,n){return n||\"input\"!==e.nodeName.toLowerCase()?void 0:e.defaultValue}),r(function(e){return null==e.getAttribute(\"disabled\")})||a(te,function(e,t,n){var i;return n?void 0:e[t]===!0?t.toLowerCase():(i=e.getAttributeNode(t))&&i.specified?i.value:null;\n}),t}(e);J.find=re,J.expr=re.selectors,J.expr[\":\"]=J.expr.pseudos,J.unique=re.uniqueSort,J.text=re.getText,J.isXMLDoc=re.isXML,J.contains=re.contains;var ae=J.expr.match.needsContext,oe=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,se=/^.[^:#\\[\\.,]*$/;J.filter=function(e,t,n){var i=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===i.nodeType?J.find.matchesSelector(i,e)?[i]:[]:J.find.matches(e,J.grep(t,function(e){return 1===e.nodeType}))},J.fn.extend({find:function(e){var t,n=this.length,i=[],r=this;if(\"string\"!=typeof e)return this.pushStack(J(e).filter(function(){for(t=0;n>t;t++)if(J.contains(r[t],this))return!0}));for(t=0;n>t;t++)J.find(e,r[t],i);return i=this.pushStack(n>1?J.unique(i):i),i.selector=this.selector?this.selector+\" \"+e:e,i},filter:function(e){return this.pushStack(i(this,e||[],!1))},not:function(e){return this.pushStack(i(this,e||[],!0))},is:function(e){return!!i(this,\"string\"==typeof e&&ae.test(e)?J(e):e||[],!1).length}});var le,ce=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,de=J.fn.init=function(e,t){var n,i;if(!e)return this;if(\"string\"==typeof e){if(n=\"<\"===e[0]&&\">\"===e[e.length-1]&&e.length>=3?[null,e,null]:ce.exec(e),!n||!n[1]&&t)return!t||t.jquery?(t||le).find(e):this.constructor(t).find(e);if(n[1]){if(t=t instanceof J?t[0]:t,J.merge(this,J.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:X,!0)),oe.test(n[1])&&J.isPlainObject(t))for(n in t)J.isFunction(this[n])?this[n](t[n]):this.attr(n,t[n]);return this}return i=X.getElementById(n[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=X,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):J.isFunction(e)?\"undefined\"!=typeof le.ready?le.ready(e):e(J):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),J.makeArray(e,this))};de.prototype=J.fn,le=J(X);var ue=/^(?:parents|prev(?:Until|All))/,pe={children:!0,contents:!0,next:!0,prev:!0};J.extend({dir:function(e,t,n){for(var i=[],r=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(r&&J(e).is(n))break;i.push(e)}return i},sibling:function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}}),J.fn.extend({has:function(e){var t=J(e,this),n=t.length;return this.filter(function(){for(var e=0;n>e;e++)if(J.contains(this,t[e]))return!0})},closest:function(e,t){for(var n,i=0,r=this.length,a=[],o=ae.test(e)||\"string\"!=typeof e?J(e,t||this.context):0;r>i;i++)for(n=this[i];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(o?o.index(n)>-1:1===n.nodeType&&J.find.matchesSelector(n,e))){a.push(n);break}return this.pushStack(a.length>1?J.unique(a):a)},index:function(e){return e?\"string\"==typeof e?V.call(J(e),this[0]):V.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(J.unique(J.merge(this.get(),J(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),J.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return J.dir(e,\"parentNode\")},parentsUntil:function(e,t,n){return J.dir(e,\"parentNode\",n)},next:function(e){return r(e,\"nextSibling\")},prev:function(e){return r(e,\"previousSibling\")},nextAll:function(e){return J.dir(e,\"nextSibling\")},prevAll:function(e){return J.dir(e,\"previousSibling\")},nextUntil:function(e,t,n){return J.dir(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return J.dir(e,\"previousSibling\",n)},siblings:function(e){return J.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return J.sibling(e.firstChild)},contents:function(e){return e.contentDocument||J.merge([],e.childNodes)}},function(e,t){J.fn[e]=function(n,i){var r=J.map(this,t,n);return\"Until\"!==e.slice(-5)&&(i=n),i&&\"string\"==typeof i&&(r=J.filter(i,r)),this.length>1&&(pe[e]||J.unique(r),ue.test(e)&&r.reverse()),this.pushStack(r)}});var me=/\\S+/g,ge={};J.Callbacks=function(e){e=\"string\"==typeof e?ge[e]||a(e):J.extend({},e);var t,n,i,r,o,s,l=[],c=!e.once&&[],d=function(a){for(t=e.memory&&a,n=!0,s=r||0,r=0,o=l.length,i=!0;l&&o>s;s++)if(l[s].apply(a[0],a[1])===!1&&e.stopOnFalse){t=!1;break}i=!1,l&&(c?c.length&&d(c.shift()):t?l=[]:u.disable())},u={add:function(){if(l){var n=l.length;!function a(t){J.each(t,function(t,n){var i=J.type(n);\"function\"===i?e.unique&&u.has(n)||l.push(n):n&&n.length&&\"string\"!==i&&a(n)})}(arguments),i?o=l.length:t&&(r=n,d(t))}return this},remove:function(){return l&&J.each(arguments,function(e,t){for(var n;(n=J.inArray(t,l,n))>-1;)l.splice(n,1),i&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?J.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=c=t=void 0,this},disabled:function(){return!l},lock:function(){return c=void 0,t||u.disable(),this},locked:function(){return!c},fireWith:function(e,t){return!l||n&&!c||(t=t||[],t=[e,t.slice?t.slice():t],i?c.push(t):d(t)),this},fire:function(){return u.fireWith(this,arguments),this},fired:function(){return!!n}};return u},J.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",J.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",J.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",J.Callbacks(\"memory\")]],n=\"pending\",i={state:function(){return n},always:function(){return r.done(arguments).fail(arguments),this},then:function(){var e=arguments;return J.Deferred(function(n){J.each(t,function(t,a){var o=J.isFunction(e[t])&&e[t];r[a[1]](function(){var e=o&&o.apply(this,arguments);e&&J.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a[0]+\"With\"](this===i?n.promise():this,o?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?J.extend(e,i):i}},r={};return i.pipe=i.then,J.each(t,function(e,a){var o=a[2],s=a[3];i[a[1]]=o.add,s&&o.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),r[a[0]]=function(){return r[a[0]+\"With\"](this===r?i:this,arguments),this},r[a[0]+\"With\"]=o.fireWith}),i.promise(r),e&&e.call(r,r),r},when:function(e){var t,n,i,r=0,a=z.call(arguments),o=a.length,s=1!==o||e&&J.isFunction(e.promise)?o:0,l=1===s?e:J.Deferred(),c=function(e,n,i){return function(r){n[e]=this,i[e]=arguments.length>1?z.call(arguments):r,i===t?l.notifyWith(n,i):--s||l.resolveWith(n,i)}};if(o>1)for(t=new Array(o),n=new Array(o),i=new Array(o);o>r;r++)a[r]&&J.isFunction(a[r].promise)?a[r].promise().done(c(r,i,a)).fail(l.reject).progress(c(r,n,t)):--s;return s||l.resolveWith(i,a),l.promise()}});var he;J.fn.ready=function(e){return J.ready.promise().done(e),this},J.extend({isReady:!1,readyWait:1,holdReady:function(e){e?J.readyWait++:J.ready(!0)},ready:function(e){(e===!0?--J.readyWait:J.isReady)||(J.isReady=!0,e!==!0&&--J.readyWait>0||(he.resolveWith(X,[J]),J.fn.triggerHandler&&(J(X).triggerHandler(\"ready\"),J(X).off(\"ready\"))))}}),J.ready.promise=function(t){return he||(he=J.Deferred(),\"complete\"===X.readyState?setTimeout(J.ready):(X.addEventListener(\"DOMContentLoaded\",o,!1),e.addEventListener(\"load\",o,!1))),he.promise(t)},J.ready.promise();var fe=J.access=function(e,t,n,i,r,a,o){var s=0,l=e.length,c=null==n;if(\"object\"===J.type(n)){r=!0;for(s in n)J.access(e,t,s,n[s],!0,a,o)}else if(void 0!==i&&(r=!0,J.isFunction(i)||(o=!0),c&&(o?(t.call(e,i),t=null):(c=t,t=function(e,t,n){return c.call(J(e),n)})),t))for(;l>s;s++)t(e[s],n,o?i:i.call(e[s],s,t(e[s],n)));return r?e:c?t.call(e):l?t(e[0],n):a};J.acceptData=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType},s.uid=1,s.accepts=J.acceptData,s.prototype={key:function(e){if(!s.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=s.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(i){t[this.expando]=n,J.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var i,r=this.key(e),a=this.cache[r];if(\"string\"==typeof t)a[t]=n;else if(J.isEmptyObject(a))J.extend(this.cache[r],t);else for(i in t)a[i]=t[i];return a},get:function(e,t){var n=this.cache[this.key(e)];return void 0===t?n:n[t]},access:function(e,t,n){var i;return void 0===t||t&&\"string\"==typeof t&&void 0===n?(i=this.get(e,t),void 0!==i?i:this.get(e,J.camelCase(t))):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,i,r,a=this.key(e),o=this.cache[a];if(void 0===t)this.cache[a]={};else{J.isArray(t)?i=t.concat(t.map(J.camelCase)):(r=J.camelCase(t),t in o?i=[t,r]:(i=r,i=i in o?[i]:i.match(me)||[])),n=i.length;for(;n--;)delete o[i[n]]}},hasData:function(e){return!J.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}};var _e=new s,be=new s,ve=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,Ce=/([A-Z])/g;J.extend({hasData:function(e){return be.hasData(e)||_e.hasData(e)},data:function(e,t,n){return be.access(e,t,n)},removeData:function(e,t){be.remove(e,t)},_data:function(e,t,n){return _e.access(e,t,n)},_removeData:function(e,t){_e.remove(e,t)}}),J.fn.extend({data:function(e,t){var n,i,r,a=this[0],o=a&&a.attributes;if(void 0===e){if(this.length&&(r=be.get(a),1===a.nodeType&&!_e.get(a,\"hasDataAttrs\"))){for(n=o.length;n--;)o[n]&&(i=o[n].name,0===i.indexOf(\"data-\")&&(i=J.camelCase(i.slice(5)),l(a,i,r[i])));_e.set(a,\"hasDataAttrs\",!0)}return r}return\"object\"==typeof e?this.each(function(){be.set(this,e)}):fe(this,function(t){var n,i=J.camelCase(e);if(a&&void 0===t){if(n=be.get(a,e),void 0!==n)return n;if(n=be.get(a,i),void 0!==n)return n;if(n=l(a,i,void 0),void 0!==n)return n}else this.each(function(){var n=be.get(this,i);be.set(this,i,t),-1!==e.indexOf(\"-\")&&void 0!==n&&be.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){be.remove(this,e)})}}),J.extend({queue:function(e,t,n){var i;return e?(t=(t||\"fx\")+\"queue\",i=_e.get(e,t),n&&(!i||J.isArray(n)?i=_e.access(e,t,J.makeArray(n)):i.push(n)),i||[]):void 0},dequeue:function(e,t){t=t||\"fx\";var n=J.queue(e,t),i=n.length,r=n.shift(),a=J._queueHooks(e,t),o=function(){J.dequeue(e,t)};\"inprogress\"===r&&(r=n.shift(),i--),r&&(\"fx\"===t&&n.unshift(\"inprogress\"),delete a.stop,r.call(e,o,a)),!i&&a&&a.empty.fire()},_queueHooks:function(e,t){var n=t+\"queueHooks\";return _e.get(e,n)||_e.access(e,n,{empty:J.Callbacks(\"once memory\").add(function(){_e.remove(e,[t+\"queue\",n])})})}}),J.fn.extend({queue:function(e,t){var n=2;return\"string\"!=typeof e&&(t=e,e=\"fx\",n--),arguments.length<n?J.queue(this[0],e):void 0===t?this:this.each(function(){var n=J.queue(this,e,t);J._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==n[0]&&J.dequeue(this,e)})},dequeue:function(e){return this.each(function(){J.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,i=1,r=J.Deferred(),a=this,o=this.length,s=function(){--i||r.resolveWith(a,[a])};for(\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";o--;)n=_e.get(a[o],e+\"queueHooks\"),n&&n.empty&&(i++,n.empty.add(s));return s(),r.promise(t)}});var Ie=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,ye=[\"Top\",\"Right\",\"Bottom\",\"Left\"],Se=function(e,t){return e=t||e,\"none\"===J.css(e,\"display\")||!J.contains(e.ownerDocument,e)},Ee=/^(?:checkbox|radio)$/i;!function(){var e=X.createDocumentFragment(),t=e.appendChild(X.createElement(\"div\")),n=X.createElement(\"input\");n.setAttribute(\"type\",\"radio\"),n.setAttribute(\"checked\",\"checked\"),n.setAttribute(\"name\",\"t\"),t.appendChild(n),Z.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML=\"<textarea>x</textarea>\",Z.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var xe=\"undefined\";Z.focusinBubbles=\"onfocusin\"in e;var Te=/^key/,we=/^(?:mouse|pointer|contextmenu)|click/,Ae=/^(?:focusinfocus|focusoutblur)$/,Pe=/^([^.]*)(?:\\.(.+)|)$/;J.event={global:{},add:function(e,t,n,i,r){var a,o,s,l,c,d,u,p,m,g,h,f=_e.get(e);if(f)for(n.handler&&(a=n,n=a.handler,r=a.selector),n.guid||(n.guid=J.guid++),(l=f.events)||(l=f.events={}),(o=f.handle)||(o=f.handle=function(t){return typeof J!==xe&&J.event.triggered!==t.type?J.event.dispatch.apply(e,arguments):void 0}),t=(t||\"\").match(me)||[\"\"],c=t.length;c--;)s=Pe.exec(t[c])||[],m=h=s[1],g=(s[2]||\"\").split(\".\").sort(),m&&(u=J.event.special[m]||{},m=(r?u.delegateType:u.bindType)||m,u=J.event.special[m]||{},d=J.extend({type:m,origType:h,data:i,handler:n,guid:n.guid,selector:r,needsContext:r&&J.expr.match.needsContext.test(r),namespace:g.join(\".\")},a),(p=l[m])||(p=l[m]=[],p.delegateCount=0,u.setup&&u.setup.call(e,i,g,o)!==!1||e.addEventListener&&e.addEventListener(m,o,!1)),u.add&&(u.add.call(e,d),d.handler.guid||(d.handler.guid=n.guid)),r?p.splice(p.delegateCount++,0,d):p.push(d),J.event.global[m]=!0)},remove:function(e,t,n,i,r){var a,o,s,l,c,d,u,p,m,g,h,f=_e.hasData(e)&&_e.get(e);if(f&&(l=f.events)){for(t=(t||\"\").match(me)||[\"\"],c=t.length;c--;)if(s=Pe.exec(t[c])||[],m=h=s[1],g=(s[2]||\"\").split(\".\").sort(),m){for(u=J.event.special[m]||{},m=(i?u.delegateType:u.bindType)||m,p=l[m]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+g.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),o=a=p.length;a--;)d=p[a],!r&&h!==d.origType||n&&n.guid!==d.guid||s&&!s.test(d.namespace)||i&&i!==d.selector&&(\"**\"!==i||!d.selector)||(p.splice(a,1),d.selector&&p.delegateCount--,u.remove&&u.remove.call(e,d));o&&!p.length&&(u.teardown&&u.teardown.call(e,g,f.handle)!==!1||J.removeEvent(e,m,f.handle),delete l[m])}else for(m in l)J.event.remove(e,m+t[c],n,i,!0);J.isEmptyObject(l)&&(delete f.handle,_e.remove(e,\"events\"))}},trigger:function(t,n,i,r){var a,o,s,l,c,d,u,p=[i||X],m=Q.call(t,\"type\")?t.type:t,g=Q.call(t,\"namespace\")?t.namespace.split(\".\"):[];if(o=s=i=i||X,3!==i.nodeType&&8!==i.nodeType&&!Ae.test(m+J.event.triggered)&&(m.indexOf(\".\")>=0&&(g=m.split(\".\"),m=g.shift(),g.sort()),c=m.indexOf(\":\")<0&&\"on\"+m,t=t[J.expando]?t:new J.Event(m,\"object\"==typeof t&&t),t.isTrigger=r?2:3,t.namespace=g.join(\".\"),t.namespace_re=t.namespace?new RegExp(\"(^|\\\\.)\"+g.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,t.result=void 0,t.target||(t.target=i),n=null==n?[t]:J.makeArray(n,[t]),u=J.event.special[m]||{},r||!u.trigger||u.trigger.apply(i,n)!==!1)){if(!r&&!u.noBubble&&!J.isWindow(i)){for(l=u.delegateType||m,Ae.test(l+m)||(o=o.parentNode);o;o=o.parentNode)p.push(o),s=o;s===(i.ownerDocument||X)&&p.push(s.defaultView||s.parentWindow||e)}for(a=0;(o=p[a++])&&!t.isPropagationStopped();)t.type=a>1?l:u.bindType||m,d=(_e.get(o,\"events\")||{})[t.type]&&_e.get(o,\"handle\"),d&&d.apply(o,n),d=c&&o[c],d&&d.apply&&J.acceptData(o)&&(t.result=d.apply(o,n),t.result===!1&&t.preventDefault());return t.type=m,r||t.isDefaultPrevented()||u._default&&u._default.apply(p.pop(),n)!==!1||!J.acceptData(i)||c&&J.isFunction(i[m])&&!J.isWindow(i)&&(s=i[c],s&&(i[c]=null),J.event.triggered=m,i[m](),J.event.triggered=void 0,s&&(i[c]=s)),t.result}},dispatch:function(e){e=J.event.fix(e);var t,n,i,r,a,o=[],s=z.call(arguments),l=(_e.get(this,\"events\")||{})[e.type]||[],c=J.event.special[e.type]||{};if(s[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){for(o=J.event.handlers.call(this,e,l),t=0;(r=o[t++])&&!e.isPropagationStopped();)for(e.currentTarget=r.elem,n=0;(a=r.handlers[n++])&&!e.isImmediatePropagationStopped();)(!e.namespace_re||e.namespace_re.test(a.namespace))&&(e.handleObj=a,e.data=a.data,i=((J.event.special[a.origType]||{}).handle||a.handler).apply(r.elem,s),void 0!==i&&(e.result=i)===!1&&(e.preventDefault(),e.stopPropagation()));return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,i,r,a,o=[],s=t.delegateCount,l=e.target;if(s&&l.nodeType&&(!e.button||\"click\"!==e.type))for(;l!==this;l=l.parentNode||this)if(l.disabled!==!0||\"click\"!==e.type){for(i=[],n=0;s>n;n++)a=t[n],r=a.selector+\" \",void 0===i[r]&&(i[r]=a.needsContext?J(r,this).index(l)>=0:J.find(r,this,null,[l]).length),i[r]&&i.push(a);i.length&&o.push({elem:l,handlers:i})}return s<t.length&&o.push({elem:this,handlers:t.slice(s)}),o},props:\"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:\"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(e,t){var n,i,r,a=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||X,i=n.documentElement,r=n.body,e.pageX=t.clientX+(i&&i.scrollLeft||r&&r.scrollLeft||0)-(i&&i.clientLeft||r&&r.clientLeft||0),e.pageY=t.clientY+(i&&i.scrollTop||r&&r.scrollTop||0)-(i&&i.clientTop||r&&r.clientTop||0)),e.which||void 0===a||(e.which=1&a?1:2&a?3:4&a?2:0),e}},fix:function(e){if(e[J.expando])return e;var t,n,i,r=e.type,a=e,o=this.fixHooks[r];for(o||(this.fixHooks[r]=o=we.test(r)?this.mouseHooks:Te.test(r)?this.keyHooks:{}),i=o.props?this.props.concat(o.props):this.props,e=new J.Event(a),t=i.length;t--;)n=i[t],e[n]=a[n];return e.target||(e.target=X),3===e.target.nodeType&&(e.target=e.target.parentNode),o.filter?o.filter(e,a):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==u()&&this.focus?(this.focus(),!1):void 0},delegateType:\"focusin\"},blur:{trigger:function(){return this===u()&&this.blur?(this.blur(),!1):void 0},delegateType:\"focusout\"},click:{trigger:function(){return\"checkbox\"===this.type&&this.click&&J.nodeName(this,\"input\")?(this.click(),!1):void 0},_default:function(e){return J.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,i){var r=J.extend(new J.Event,n,{type:e,isSimulated:!0,originalEvent:{}});i?J.event.trigger(r,null,t):J.event.dispatch.call(t,r),r.isDefaultPrevented()&&n.preventDefault()}},J.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},J.Event=function(e,t){return this instanceof J.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&e.returnValue===!1?c:d):this.type=e,t&&J.extend(this,t),this.timeStamp=e&&e.timeStamp||J.now(),void(this[J.expando]=!0)):new J.Event(e,t)},J.Event.prototype={isDefaultPrevented:d,isPropagationStopped:d,isImmediatePropagationStopped:d,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=c,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=c,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=c,e&&e.stopImmediatePropagation&&e.stopImmediatePropagation(),this.stopPropagation()}},J.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,t){J.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,i=this,r=e.relatedTarget,a=e.handleObj;return(!r||r!==i&&!J.contains(i,r))&&(e.type=a.origType,n=a.handler.apply(this,arguments),e.type=t),n}}}),Z.focusinBubbles||J.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=function(e){J.event.simulate(t,e.target,J.event.fix(e),!0)};J.event.special[t]={setup:function(){var i=this.ownerDocument||this,r=_e.access(i,t);r||i.addEventListener(e,n,!0),_e.access(i,t,(r||0)+1)},teardown:function(){var i=this.ownerDocument||this,r=_e.access(i,t)-1;r?_e.access(i,t,r):(i.removeEventListener(e,n,!0),_e.remove(i,t))}}}),J.fn.extend({on:function(e,t,n,i,r){var a,o;if(\"object\"==typeof e){\"string\"!=typeof t&&(n=n||t,t=void 0);for(o in e)this.on(o,t,n,e[o],r);return this}if(null==n&&null==i?(i=t,n=t=void 0):null==i&&(\"string\"==typeof t?(i=n,n=void 0):(i=n,n=t,t=void 0)),i===!1)i=d;else if(!i)return this;return 1===r&&(a=i,i=function(e){return J().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=J.guid++)),this.each(function(){J.event.add(this,e,i,n,t)})},one:function(e,t,n,i){return this.on(e,t,n,i,1)},off:function(e,t,n){var i,r;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,J(e.delegateTarget).off(i.namespace?i.origType+\".\"+i.namespace:i.origType,i.selector,i.handler),this;if(\"object\"==typeof e){for(r in e)this.off(r,t,e[r]);return this}return(t===!1||\"function\"==typeof t)&&(n=t,t=void 0),n===!1&&(n=d),this.each(function(){J.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){J.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?J.event.trigger(e,t,n,!0):void 0}});var De=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,Ge=/<([\\w:]+)/,Me=/<|&#?\\w+;/,Ne=/<(?:script|style|link)/i,Le=/checked\\s*(?:[^=]|=\\s*.checked.)/i,ke=/^$|\\/(?:java|ecma)script/i,Re=/^true\\/(.*)/,Oe=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,Ue={option:[1,\"<select multiple='multiple'>\",\"</select>\"],thead:[1,\"<table>\",\"</table>\"],col:[2,\"<table><colgroup>\",\"</colgroup></table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:[0,\"\",\"\"]};Ue.optgroup=Ue.option,Ue.tbody=Ue.tfoot=Ue.colgroup=Ue.caption=Ue.thead,Ue.th=Ue.td,J.extend({clone:function(e,t,n){var i,r,a,o,s=e.cloneNode(!0),l=J.contains(e.ownerDocument,e);if(!(Z.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||J.isXMLDoc(e)))for(o=_(s),a=_(e),i=0,r=a.length;r>i;i++)b(a[i],o[i]);if(t)if(n)for(a=a||_(e),o=o||_(s),i=0,r=a.length;r>i;i++)f(a[i],o[i]);else f(e,s);return o=_(s,\"script\"),o.length>0&&h(o,!l&&_(e,\"script\")),s},buildFragment:function(e,t,n,i){for(var r,a,o,s,l,c,d=t.createDocumentFragment(),u=[],p=0,m=e.length;m>p;p++)if(r=e[p],r||0===r)if(\"object\"===J.type(r))J.merge(u,r.nodeType?[r]:r);else if(Me.test(r)){for(a=a||d.appendChild(t.createElement(\"div\")),o=(Ge.exec(r)||[\"\",\"\"])[1].toLowerCase(),s=Ue[o]||Ue._default,a.innerHTML=s[1]+r.replace(De,\"<$1></$2>\")+s[2],c=s[0];c--;)a=a.lastChild;J.merge(u,a.childNodes),a=d.firstChild,a.textContent=\"\"}else u.push(t.createTextNode(r));for(d.textContent=\"\",p=0;r=u[p++];)if((!i||-1===J.inArray(r,i))&&(l=J.contains(r.ownerDocument,r),a=_(d.appendChild(r),\"script\"),l&&h(a),n))for(c=0;r=a[c++];)ke.test(r.type||\"\")&&n.push(r);return d},cleanData:function(e){for(var t,n,i,r,a=J.event.special,o=0;void 0!==(n=e[o]);o++){if(J.acceptData(n)&&(r=n[_e.expando],r&&(t=_e.cache[r]))){if(t.events)for(i in t.events)a[i]?J.event.remove(n,i):J.removeEvent(n,i,t.handle);_e.cache[r]&&delete _e.cache[r]}delete be.cache[n[be.expando]]}}}),J.fn.extend({text:function(e){return fe(this,function(e){return void 0===e?J.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=e)})},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=p(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=p(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){for(var n,i=e?J.filter(e,this):this,r=0;null!=(n=i[r]);r++)t||1!==n.nodeType||J.cleanData(_(n)),n.parentNode&&(t&&J.contains(n.ownerDocument,n)&&h(_(n,\"script\")),n.parentNode.removeChild(n));return this},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(J.cleanData(_(e,!1)),e.textContent=\"\");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return J.clone(this,e,t)})},html:function(e){return fe(this,function(e){var t=this[0]||{},n=0,i=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if(\"string\"==typeof e&&!Ne.test(e)&&!Ue[(Ge.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=e.replace(De,\"<$1></$2>\");try{for(;i>n;n++)t=this[n]||{},1===t.nodeType&&(J.cleanData(_(t,!1)),t.innerHTML=e);t=0}catch(r){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=arguments[0];return this.domManip(arguments,function(t){e=this.parentNode,J.cleanData(_(this)),e&&e.replaceChild(t,this)}),e&&(e.length||e.nodeType)?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t){e=$.apply([],e);var n,i,r,a,o,s,l=0,c=this.length,d=this,u=c-1,p=e[0],h=J.isFunction(p);if(h||c>1&&\"string\"==typeof p&&!Z.checkClone&&Le.test(p))return this.each(function(n){var i=d.eq(n);h&&(e[0]=p.call(this,n,i.html())),i.domManip(e,t)});if(c&&(n=J.buildFragment(e,this[0].ownerDocument,!1,this),i=n.firstChild,1===n.childNodes.length&&(n=i),i)){for(r=J.map(_(n,\"script\"),m),a=r.length;c>l;l++)o=n,l!==u&&(o=J.clone(o,!0,!0),a&&J.merge(r,_(o,\"script\"))),t.call(this[l],o,l);if(a)for(s=r[r.length-1].ownerDocument,J.map(r,g),l=0;a>l;l++)o=r[l],ke.test(o.type||\"\")&&!_e.access(o,\"globalEval\")&&J.contains(s,o)&&(o.src?J._evalUrl&&J._evalUrl(o.src):J.globalEval(o.textContent.replace(Oe,\"\")))}return this}}),J.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){J.fn[e]=function(e){for(var n,i=[],r=J(e),a=r.length-1,o=0;a>=o;o++)n=o===a?this:this.clone(!0),J(r[o])[t](n),H.apply(i,n.get());return this.pushStack(i)}});var Fe,Be={},We=/^margin/,qe=new RegExp(\"^(\"+Ie+\")(?!px)[a-z%]+$\",\"i\"),ze=function(t){return t.ownerDocument.defaultView.opener?t.ownerDocument.defaultView.getComputedStyle(t,null):e.getComputedStyle(t,null)};!function(){function t(){o.style.cssText=\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute\",o.innerHTML=\"\",r.appendChild(a);var t=e.getComputedStyle(o,null);n=\"1%\"!==t.top,i=\"4px\"===t.width,r.removeChild(a)}var n,i,r=X.documentElement,a=X.createElement(\"div\"),o=X.createElement(\"div\");o.style&&(o.style.backgroundClip=\"content-box\",o.cloneNode(!0).style.backgroundClip=\"\",Z.clearCloneStyle=\"content-box\"===o.style.backgroundClip,a.style.cssText=\"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute\",a.appendChild(o),e.getComputedStyle&&J.extend(Z,{pixelPosition:function(){return t(),n},boxSizingReliable:function(){return null==i&&t(),i},reliableMarginRight:function(){var t,n=o.appendChild(X.createElement(\"div\"));return n.style.cssText=o.style.cssText=\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0\",n.style.marginRight=n.style.width=\"0\",o.style.width=\"1px\",r.appendChild(a),t=!parseFloat(e.getComputedStyle(n,null).marginRight),r.removeChild(a),o.removeChild(n),t}}))}(),J.swap=function(e,t,n,i){var r,a,o={};for(a in t)o[a]=e.style[a],e.style[a]=t[a];r=n.apply(e,i||[]);for(a in t)e.style[a]=o[a];return r};var $e=/^(none|table(?!-c[ea]).+)/,He=new RegExp(\"^(\"+Ie+\")(.*)$\",\"i\"),Ve=new RegExp(\"^([+-])=(\"+Ie+\")\",\"i\"),je={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Ke={letterSpacing:\"0\",fontWeight:\"400\"},Qe=[\"Webkit\",\"O\",\"Moz\",\"ms\"];J.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=I(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":\"cssFloat\"},style:function(e,t,n,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var r,a,o,s=J.camelCase(t),l=e.style;return t=J.cssProps[s]||(J.cssProps[s]=S(l,s)),o=J.cssHooks[t]||J.cssHooks[s],void 0===n?o&&\"get\"in o&&void 0!==(r=o.get(e,!1,i))?r:l[t]:(a=typeof n,\"string\"===a&&(r=Ve.exec(n))&&(n=(r[1]+1)*r[2]+parseFloat(J.css(e,t)),a=\"number\"),null!=n&&n===n&&(\"number\"!==a||J.cssNumber[s]||(n+=\"px\"),Z.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(l[t]=\"inherit\"),o&&\"set\"in o&&void 0===(n=o.set(e,n,i))||(l[t]=n)),void 0)}},css:function(e,t,n,i){var r,a,o,s=J.camelCase(t);return t=J.cssProps[s]||(J.cssProps[s]=S(e.style,s)),o=J.cssHooks[t]||J.cssHooks[s],o&&\"get\"in o&&(r=o.get(e,!0,n)),void 0===r&&(r=I(e,t,i)),\"normal\"===r&&t in Ke&&(r=Ke[t]),\"\"===n||n?(a=parseFloat(r),n===!0||J.isNumeric(a)?a||0:r):r}}),J.each([\"height\",\"width\"],function(e,t){J.cssHooks[t]={get:function(e,n,i){return n?$e.test(J.css(e,\"display\"))&&0===e.offsetWidth?J.swap(e,je,function(){return T(e,t,i)}):T(e,t,i):void 0},set:function(e,n,i){var r=i&&ze(e);return E(e,n,i?x(e,t,i,\"border-box\"===J.css(e,\"boxSizing\",!1,r),r):0)}}}),J.cssHooks.marginRight=y(Z.reliableMarginRight,function(e,t){return t?J.swap(e,{display:\"inline-block\"},I,[e,\"marginRight\"]):void 0}),J.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){J.cssHooks[e+t]={expand:function(n){for(var i=0,r={},a=\"string\"==typeof n?n.split(\" \"):[n];4>i;i++)r[e+ye[i]+t]=a[i]||a[i-2]||a[0];return r}},We.test(e)||(J.cssHooks[e+t].set=E)}),J.fn.extend({css:function(e,t){return fe(this,function(e,t,n){var i,r,a={},o=0;if(J.isArray(t)){for(i=ze(e),r=t.length;r>o;o++)a[t[o]]=J.css(e,t[o],!1,i);return a}return void 0!==n?J.style(e,t,n):J.css(e,t)},e,t,arguments.length>1)},show:function(){return w(this,!0)},hide:function(){return w(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){Se(this)?J(this).show():J(this).hide()})}}),J.Tween=A,A.prototype={constructor:A,init:function(e,t,n,i,r,a){this.elem=e,this.prop=n,this.easing=r||\"swing\",this.options=t,this.start=this.now=this.cur(),this.end=i,this.unit=a||(J.cssNumber[n]?\"\":\"px\")},cur:function(){var e=A.propHooks[this.prop];return e&&e.get?e.get(this):A.propHooks._default.get(this)},run:function(e){var t,n=A.propHooks[this.prop];return this.options.duration?this.pos=t=J.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):A.propHooks._default.set(this),this}},A.prototype.init.prototype=A.prototype,A.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=J.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0):e.elem[e.prop]},set:function(e){J.fx.step[e.prop]?J.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[J.cssProps[e.prop]]||J.cssHooks[e.prop])?J.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},A.propHooks.scrollTop=A.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},J.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},J.fx=A.prototype.init,J.fx.step={};var Ze,Xe,Ye=/^(?:toggle|show|hide)$/,Je=new RegExp(\"^(?:([+-])=|)(\"+Ie+\")([a-z%]*)$\",\"i\"),et=/queueHooks$/,tt=[M],nt={\"*\":[function(e,t){var n=this.createTween(e,t),i=n.cur(),r=Je.exec(t),a=r&&r[3]||(J.cssNumber[e]?\"\":\"px\"),o=(J.cssNumber[e]||\"px\"!==a&&+i)&&Je.exec(J.css(n.elem,e)),s=1,l=20;if(o&&o[3]!==a){a=a||o[3],r=r||[],o=+i||1;do s=s||\".5\",o/=s,J.style(n.elem,e,o+a);while(s!==(s=n.cur()/i)&&1!==s&&--l)}return r&&(o=n.start=+o||+i||0,n.unit=a,n.end=r[1]?o+(r[1]+1)*r[2]:+r[2]),n}]};J.Animation=J.extend(L,{tweener:function(e,t){J.isFunction(e)?(t=e,e=[\"*\"]):e=e.split(\" \");for(var n,i=0,r=e.length;r>i;i++)n=e[i],nt[n]=nt[n]||[],nt[n].unshift(t)},prefilter:function(e,t){t?tt.unshift(e):tt.push(e)}}),J.speed=function(e,t,n){var i=e&&\"object\"==typeof e?J.extend({},e):{complete:n||!n&&t||J.isFunction(e)&&e,duration:e,easing:n&&t||t&&!J.isFunction(t)&&t};return i.duration=J.fx.off?0:\"number\"==typeof i.duration?i.duration:i.duration in J.fx.speeds?J.fx.speeds[i.duration]:J.fx.speeds._default,(null==i.queue||i.queue===!0)&&(i.queue=\"fx\"),i.old=i.complete,i.complete=function(){J.isFunction(i.old)&&i.old.call(this),i.queue&&J.dequeue(this,i.queue)},i},J.fn.extend({fadeTo:function(e,t,n,i){return this.filter(Se).css(\"opacity\",0).show().end().animate({opacity:t},e,n,i)},animate:function(e,t,n,i){var r=J.isEmptyObject(e),a=J.speed(t,n,i),o=function(){var t=L(this,J.extend({},e),a);(r||_e.get(this,\"finish\"))&&t.stop(!0)};return o.finish=o,r||a.queue===!1?this.each(o):this.queue(a.queue,o)},stop:function(e,t,n){var i=function(e){var t=e.stop;delete e.stop,t(n)};return\"string\"!=typeof e&&(n=t,t=e,e=void 0),t&&e!==!1&&this.queue(e||\"fx\",[]),\nthis.each(function(){var t=!0,r=null!=e&&e+\"queueHooks\",a=J.timers,o=_e.get(this);if(r)o[r]&&o[r].stop&&i(o[r]);else for(r in o)o[r]&&o[r].stop&&et.test(r)&&i(o[r]);for(r=a.length;r--;)a[r].elem!==this||null!=e&&a[r].queue!==e||(a[r].anim.stop(n),t=!1,a.splice(r,1));(t||!n)&&J.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=_e.get(this),i=n[e+\"queue\"],r=n[e+\"queueHooks\"],a=J.timers,o=i?i.length:0;for(n.finish=!0,J.queue(this,e,[]),r&&r.stop&&r.stop.call(this,!0),t=a.length;t--;)a[t].elem===this&&a[t].queue===e&&(a[t].anim.stop(!0),a.splice(t,1));for(t=0;o>t;t++)i[t]&&i[t].finish&&i[t].finish.call(this);delete n.finish})}}),J.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=J.fn[t];J.fn[t]=function(e,i,r){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(D(t,!0),e,i,r)}}),J.each({slideDown:D(\"show\"),slideUp:D(\"hide\"),slideToggle:D(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){J.fn[e]=function(e,n,i){return this.animate(t,e,n,i)}}),J.timers=[],J.fx.tick=function(){var e,t=0,n=J.timers;for(Ze=J.now();t<n.length;t++)e=n[t],e()||n[t]!==e||n.splice(t--,1);n.length||J.fx.stop(),Ze=void 0},J.fx.timer=function(e){J.timers.push(e),e()?J.fx.start():J.timers.pop()},J.fx.interval=13,J.fx.start=function(){Xe||(Xe=setInterval(J.fx.tick,J.fx.interval))},J.fx.stop=function(){clearInterval(Xe),Xe=null},J.fx.speeds={slow:600,fast:200,_default:400},J.fn.delay=function(e,t){return e=J.fx?J.fx.speeds[e]||e:e,t=t||\"fx\",this.queue(t,function(t,n){var i=setTimeout(t,e);n.stop=function(){clearTimeout(i)}})},function(){var e=X.createElement(\"input\"),t=X.createElement(\"select\"),n=t.appendChild(X.createElement(\"option\"));e.type=\"checkbox\",Z.checkOn=\"\"!==e.value,Z.optSelected=n.selected,t.disabled=!0,Z.optDisabled=!n.disabled,e=X.createElement(\"input\"),e.value=\"t\",e.type=\"radio\",Z.radioValue=\"t\"===e.value}();var it,rt,at=J.expr.attrHandle;J.fn.extend({attr:function(e,t){return fe(this,J.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){J.removeAttr(this,e)})}}),J.extend({attr:function(e,t,n){var i,r,a=e.nodeType;if(e&&3!==a&&8!==a&&2!==a)return typeof e.getAttribute===xe?J.prop(e,t,n):(1===a&&J.isXMLDoc(e)||(t=t.toLowerCase(),i=J.attrHooks[t]||(J.expr.match.bool.test(t)?rt:it)),void 0===n?i&&\"get\"in i&&null!==(r=i.get(e,t))?r:(r=J.find.attr(e,t),null==r?void 0:r):null!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):void J.removeAttr(e,t))},removeAttr:function(e,t){var n,i,r=0,a=t&&t.match(me);if(a&&1===e.nodeType)for(;n=a[r++];)i=J.propFix[n]||n,J.expr.match.bool.test(n)&&(e[i]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!Z.radioValue&&\"radio\"===t&&J.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}}}),rt={set:function(e,t,n){return t===!1?J.removeAttr(e,n):e.setAttribute(n,n),n}},J.each(J.expr.match.bool.source.match(/\\w+/g),function(e,t){var n=at[t]||J.find.attr;at[t]=function(e,t,i){var r,a;return i||(a=at[t],at[t]=r,r=null!=n(e,t,i)?t.toLowerCase():null,at[t]=a),r}});var ot=/^(?:input|select|textarea|button)$/i;J.fn.extend({prop:function(e,t){return fe(this,J.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[J.propFix[e]||e]})}}),J.extend({propFix:{\"for\":\"htmlFor\",\"class\":\"className\"},prop:function(e,t,n){var i,r,a,o=e.nodeType;if(e&&3!==o&&8!==o&&2!==o)return a=1!==o||!J.isXMLDoc(e),a&&(t=J.propFix[t]||t,r=J.propHooks[t]),void 0!==n?r&&\"set\"in r&&void 0!==(i=r.set(e,n,t))?i:e[t]=n:r&&\"get\"in r&&null!==(i=r.get(e,t))?i:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute(\"tabindex\")||ot.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),Z.optSelected||(J.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),J.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){J.propFix[this.toLowerCase()]=this});var st=/[\\t\\r\\n\\f]/g;J.fn.extend({addClass:function(e){var t,n,i,r,a,o,s=\"string\"==typeof e&&e,l=0,c=this.length;if(J.isFunction(e))return this.each(function(t){J(this).addClass(e.call(this,t,this.className))});if(s)for(t=(e||\"\").match(me)||[];c>l;l++)if(n=this[l],i=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(st,\" \"):\" \")){for(a=0;r=t[a++];)i.indexOf(\" \"+r+\" \")<0&&(i+=r+\" \");o=J.trim(i),n.className!==o&&(n.className=o)}return this},removeClass:function(e){var t,n,i,r,a,o,s=0===arguments.length||\"string\"==typeof e&&e,l=0,c=this.length;if(J.isFunction(e))return this.each(function(t){J(this).removeClass(e.call(this,t,this.className))});if(s)for(t=(e||\"\").match(me)||[];c>l;l++)if(n=this[l],i=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(st,\" \"):\"\")){for(a=0;r=t[a++];)for(;i.indexOf(\" \"+r+\" \")>=0;)i=i.replace(\" \"+r+\" \",\" \");o=e?J.trim(i):\"\",n.className!==o&&(n.className=o)}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):J.isFunction(e)?this.each(function(n){J(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(\"string\"===n)for(var t,i=0,r=J(this),a=e.match(me)||[];t=a[i++];)r.hasClass(t)?r.removeClass(t):r.addClass(t);else(n===xe||\"boolean\"===n)&&(this.className&&_e.set(this,\"__className__\",this.className),this.className=this.className||e===!1?\"\":_e.get(this,\"__className__\")||\"\")})},hasClass:function(e){for(var t=\" \"+e+\" \",n=0,i=this.length;i>n;n++)if(1===this[n].nodeType&&(\" \"+this[n].className+\" \").replace(st,\" \").indexOf(t)>=0)return!0;return!1}});var lt=/\\r/g;J.fn.extend({val:function(e){var t,n,i,r=this[0];{if(arguments.length)return i=J.isFunction(e),this.each(function(n){var r;1===this.nodeType&&(r=i?e.call(this,n,J(this).val()):e,null==r?r=\"\":\"number\"==typeof r?r+=\"\":J.isArray(r)&&(r=J.map(r,function(e){return null==e?\"\":e+\"\"})),t=J.valHooks[this.type]||J.valHooks[this.nodeName.toLowerCase()],t&&\"set\"in t&&void 0!==t.set(this,r,\"value\")||(this.value=r))});if(r)return t=J.valHooks[r.type]||J.valHooks[r.nodeName.toLowerCase()],t&&\"get\"in t&&void 0!==(n=t.get(r,\"value\"))?n:(n=r.value,\"string\"==typeof n?n.replace(lt,\"\"):null==n?\"\":n)}}}),J.extend({valHooks:{option:{get:function(e){var t=J.find.attr(e,\"value\");return null!=t?t:J.trim(J.text(e))}},select:{get:function(e){for(var t,n,i=e.options,r=e.selectedIndex,a=\"select-one\"===e.type||0>r,o=a?null:[],s=a?r+1:i.length,l=0>r?s:a?r:0;s>l;l++)if(n=i[l],(n.selected||l===r)&&(Z.optDisabled?!n.disabled:null===n.getAttribute(\"disabled\"))&&(!n.parentNode.disabled||!J.nodeName(n.parentNode,\"optgroup\"))){if(t=J(n).val(),a)return t;o.push(t)}return o},set:function(e,t){for(var n,i,r=e.options,a=J.makeArray(t),o=r.length;o--;)i=r[o],(i.selected=J.inArray(i.value,a)>=0)&&(n=!0);return n||(e.selectedIndex=-1),a}}}}),J.each([\"radio\",\"checkbox\"],function(){J.valHooks[this]={set:function(e,t){return J.isArray(t)?e.checked=J.inArray(J(e).val(),t)>=0:void 0}},Z.checkOn||(J.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})}),J.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(e,t){J.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),J.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,i){return this.on(t,e,n,i)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)}});var ct=J.now(),dt=/\\?/;J.parseJSON=function(e){return JSON.parse(e+\"\")},J.parseXML=function(e){var t,n;if(!e||\"string\"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,\"text/xml\")}catch(i){t=void 0}return(!t||t.getElementsByTagName(\"parsererror\").length)&&J.error(\"Invalid XML: \"+e),t};var ut=/#.*$/,pt=/([?&])_=[^&]*/,mt=/^(.*?):[ \\t]*([^\\r\\n]*)$/gm,gt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ht=/^(?:GET|HEAD)$/,ft=/^\\/\\//,_t=/^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,bt={},vt={},Ct=\"*/\".concat(\"*\"),It=e.location.href,yt=_t.exec(It.toLowerCase())||[];J.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:It,type:\"GET\",isLocal:gt.test(yt[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Ct,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":J.parseJSON,\"text xml\":J.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?O(O(e,J.ajaxSettings),t):O(J.ajaxSettings,e)},ajaxPrefilter:k(bt),ajaxTransport:k(vt),ajax:function(e,t){function n(e,t,n,o){var l,d,_,b,C,y=t;2!==v&&(v=2,s&&clearTimeout(s),i=void 0,a=o||\"\",I.readyState=e>0?4:0,l=e>=200&&300>e||304===e,n&&(b=U(u,I,n)),b=F(u,b,I,l),l?(u.ifModified&&(C=I.getResponseHeader(\"Last-Modified\"),C&&(J.lastModified[r]=C),C=I.getResponseHeader(\"etag\"),C&&(J.etag[r]=C)),204===e||\"HEAD\"===u.type?y=\"nocontent\":304===e?y=\"notmodified\":(y=b.state,d=b.data,_=b.error,l=!_)):(_=y,(e||!y)&&(y=\"error\",0>e&&(e=0))),I.status=e,I.statusText=(t||y)+\"\",l?g.resolveWith(p,[d,y,I]):g.rejectWith(p,[I,y,_]),I.statusCode(f),f=void 0,c&&m.trigger(l?\"ajaxSuccess\":\"ajaxError\",[I,u,l?d:_]),h.fireWith(p,[I,y]),c&&(m.trigger(\"ajaxComplete\",[I,u]),--J.active||J.event.trigger(\"ajaxStop\")))}\"object\"==typeof e&&(t=e,e=void 0),t=t||{};var i,r,a,o,s,l,c,d,u=J.ajaxSetup({},t),p=u.context||u,m=u.context&&(p.nodeType||p.jquery)?J(p):J.event,g=J.Deferred(),h=J.Callbacks(\"once memory\"),f=u.statusCode||{},_={},b={},v=0,C=\"canceled\",I={readyState:0,getResponseHeader:function(e){var t;if(2===v){if(!o)for(o={};t=mt.exec(a);)o[t[1].toLowerCase()]=t[2];t=o[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===v?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return v||(e=b[n]=b[n]||e,_[e]=t),this},overrideMimeType:function(e){return v||(u.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>v)for(t in e)f[t]=[f[t],e[t]];else I.always(e[I.status]);return this},abort:function(e){var t=e||C;return i&&i.abort(t),n(0,t),this}};if(g.promise(I).complete=h.add,I.success=I.done,I.error=I.fail,u.url=((e||u.url||It)+\"\").replace(ut,\"\").replace(ft,yt[1]+\"//\"),u.type=t.method||t.type||u.method||u.type,u.dataTypes=J.trim(u.dataType||\"*\").toLowerCase().match(me)||[\"\"],null==u.crossDomain&&(l=_t.exec(u.url.toLowerCase()),u.crossDomain=!(!l||l[1]===yt[1]&&l[2]===yt[2]&&(l[3]||(\"http:\"===l[1]?\"80\":\"443\"))===(yt[3]||(\"http:\"===yt[1]?\"80\":\"443\")))),u.data&&u.processData&&\"string\"!=typeof u.data&&(u.data=J.param(u.data,u.traditional)),R(bt,u,t,I),2===v)return I;c=J.event&&u.global,c&&0===J.active++&&J.event.trigger(\"ajaxStart\"),u.type=u.type.toUpperCase(),u.hasContent=!ht.test(u.type),r=u.url,u.hasContent||(u.data&&(r=u.url+=(dt.test(r)?\"&\":\"?\")+u.data,delete u.data),u.cache===!1&&(u.url=pt.test(r)?r.replace(pt,\"$1_=\"+ct++):r+(dt.test(r)?\"&\":\"?\")+\"_=\"+ct++)),u.ifModified&&(J.lastModified[r]&&I.setRequestHeader(\"If-Modified-Since\",J.lastModified[r]),J.etag[r]&&I.setRequestHeader(\"If-None-Match\",J.etag[r])),(u.data&&u.hasContent&&u.contentType!==!1||t.contentType)&&I.setRequestHeader(\"Content-Type\",u.contentType),I.setRequestHeader(\"Accept\",u.dataTypes[0]&&u.accepts[u.dataTypes[0]]?u.accepts[u.dataTypes[0]]+(\"*\"!==u.dataTypes[0]?\", \"+Ct+\"; q=0.01\":\"\"):u.accepts[\"*\"]);for(d in u.headers)I.setRequestHeader(d,u.headers[d]);if(u.beforeSend&&(u.beforeSend.call(p,I,u)===!1||2===v))return I.abort();C=\"abort\";for(d in{success:1,error:1,complete:1})I[d](u[d]);if(i=R(vt,u,t,I)){I.readyState=1,c&&m.trigger(\"ajaxSend\",[I,u]),u.async&&u.timeout>0&&(s=setTimeout(function(){I.abort(\"timeout\")},u.timeout));try{v=1,i.send(_,n)}catch(y){if(!(2>v))throw y;n(-1,y)}}else n(-1,\"No Transport\");return I},getJSON:function(e,t,n){return J.get(e,t,n,\"json\")},getScript:function(e,t){return J.get(e,void 0,t,\"script\")}}),J.each([\"get\",\"post\"],function(e,t){J[t]=function(e,n,i,r){return J.isFunction(n)&&(r=r||i,i=n,n=void 0),J.ajax({url:e,type:t,dataType:r,data:n,success:i})}}),J._evalUrl=function(e){return J.ajax({url:e,type:\"GET\",dataType:\"script\",async:!1,global:!1,\"throws\":!0})},J.fn.extend({wrapAll:function(e){var t;return J.isFunction(e)?this.each(function(t){J(this).wrapAll(e.call(this,t))}):(this[0]&&(t=J(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return J.isFunction(e)?this.each(function(t){J(this).wrapInner(e.call(this,t))}):this.each(function(){var t=J(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=J.isFunction(e);return this.each(function(n){J(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){J.nodeName(this,\"body\")||J(this).replaceWith(this.childNodes)}).end()}}),J.expr.filters.hidden=function(e){return e.offsetWidth<=0&&e.offsetHeight<=0},J.expr.filters.visible=function(e){return!J.expr.filters.hidden(e)};var St=/%20/g,Et=/\\[\\]$/,xt=/\\r?\\n/g,Tt=/^(?:submit|button|image|reset|file)$/i,wt=/^(?:input|select|textarea|keygen)/i;J.param=function(e,t){var n,i=[],r=function(e,t){t=J.isFunction(t)?t():null==t?\"\":t,i[i.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(void 0===t&&(t=J.ajaxSettings&&J.ajaxSettings.traditional),J.isArray(e)||e.jquery&&!J.isPlainObject(e))J.each(e,function(){r(this.name,this.value)});else for(n in e)B(n,e[n],t,r);return i.join(\"&\").replace(St,\"+\")},J.fn.extend({serialize:function(){return J.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=J.prop(this,\"elements\");return e?J.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!J(this).is(\":disabled\")&&wt.test(this.nodeName)&&!Tt.test(e)&&(this.checked||!Ee.test(e))}).map(function(e,t){var n=J(this).val();return null==n?null:J.isArray(n)?J.map(n,function(e){return{name:t.name,value:e.replace(xt,\"\\r\\n\")}}):{name:t.name,value:n.replace(xt,\"\\r\\n\")}}).get()}}),J.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(e){}};var At=0,Pt={},Dt={0:200,1223:204},Gt=J.ajaxSettings.xhr();e.attachEvent&&e.attachEvent(\"onunload\",function(){for(var e in Pt)Pt[e]()}),Z.cors=!!Gt&&\"withCredentials\"in Gt,Z.ajax=Gt=!!Gt,J.ajaxTransport(function(e){var t;return Z.cors||Gt&&!e.crossDomain?{send:function(n,i){var r,a=e.xhr(),o=++At;if(a.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(r in e.xhrFields)a[r]=e.xhrFields[r];e.mimeType&&a.overrideMimeType&&a.overrideMimeType(e.mimeType),e.crossDomain||n[\"X-Requested-With\"]||(n[\"X-Requested-With\"]=\"XMLHttpRequest\");for(r in n)a.setRequestHeader(r,n[r]);t=function(e){return function(){t&&(delete Pt[o],t=a.onload=a.onerror=null,\"abort\"===e?a.abort():\"error\"===e?i(a.status,a.statusText):i(Dt[a.status]||a.status,a.statusText,\"string\"==typeof a.responseText?{text:a.responseText}:void 0,a.getAllResponseHeaders()))}},a.onload=t(),a.onerror=t(\"error\"),t=Pt[o]=t(\"abort\");try{a.send(e.hasContent&&e.data||null)}catch(s){if(t)throw s}},abort:function(){t&&t()}}:void 0}),J.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/(?:java|ecma)script/},converters:{\"text script\":function(e){return J.globalEval(e),e}}}),J.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\")}),J.ajaxTransport(\"script\",function(e){if(e.crossDomain){var t,n;return{send:function(i,r){t=J(\"<script>\").prop({async:!0,charset:e.scriptCharset,src:e.url}).on(\"load error\",n=function(e){t.remove(),n=null,e&&r(\"error\"===e.type?404:200,e.type)}),X.head.appendChild(t[0])},abort:function(){n&&n()}}}});var Mt=[],Nt=/(=)\\?(?=&|$)|\\?\\?/;J.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Mt.pop()||J.expando+\"_\"+ct++;return this[e]=!0,e}}),J.ajaxPrefilter(\"json jsonp\",function(t,n,i){var r,a,o,s=t.jsonp!==!1&&(Nt.test(t.url)?\"url\":\"string\"==typeof t.data&&!(t.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Nt.test(t.data)&&\"data\");return s||\"jsonp\"===t.dataTypes[0]?(r=t.jsonpCallback=J.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,s?t[s]=t[s].replace(Nt,\"$1\"+r):t.jsonp!==!1&&(t.url+=(dt.test(t.url)?\"&\":\"?\")+t.jsonp+\"=\"+r),t.converters[\"script json\"]=function(){return o||J.error(r+\" was not called\"),o[0]},t.dataTypes[0]=\"json\",a=e[r],e[r]=function(){o=arguments},i.always(function(){e[r]=a,t[r]&&(t.jsonpCallback=n.jsonpCallback,Mt.push(r)),o&&J.isFunction(a)&&a(o[0]),o=a=void 0}),\"script\"):void 0}),J.parseHTML=function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||X;var i=oe.exec(e),r=!n&&[];return i?[t.createElement(i[1])]:(i=J.buildFragment([e],t,r),r&&r.length&&J(r).remove(),J.merge([],i.childNodes))};var Lt=J.fn.load;J.fn.load=function(e,t,n){if(\"string\"!=typeof e&&Lt)return Lt.apply(this,arguments);var i,r,a,o=this,s=e.indexOf(\" \");return s>=0&&(i=J.trim(e.slice(s)),e=e.slice(0,s)),J.isFunction(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(r=\"POST\"),o.length>0&&J.ajax({url:e,type:r,dataType:\"html\",data:t}).done(function(e){a=arguments,o.html(i?J(\"<div>\").append(J.parseHTML(e)).find(i):e)}).complete(n&&function(e,t){o.each(n,a||[e.responseText,t,e])}),this},J.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){J.fn[t]=function(e){return this.on(t,e)}}),J.expr.filters.animated=function(e){return J.grep(J.timers,function(t){return e===t.elem}).length};var kt=e.document.documentElement;J.offset={setOffset:function(e,t,n){var i,r,a,o,s,l,c,d=J.css(e,\"position\"),u=J(e),p={};\"static\"===d&&(e.style.position=\"relative\"),s=u.offset(),a=J.css(e,\"top\"),l=J.css(e,\"left\"),c=(\"absolute\"===d||\"fixed\"===d)&&(a+l).indexOf(\"auto\")>-1,c?(i=u.position(),o=i.top,r=i.left):(o=parseFloat(a)||0,r=parseFloat(l)||0),J.isFunction(t)&&(t=t.call(e,n,s)),null!=t.top&&(p.top=t.top-s.top+o),null!=t.left&&(p.left=t.left-s.left+r),\"using\"in t?t.using.call(e,p):u.css(p)}},J.fn.extend({offset:function(e){if(arguments.length)return void 0===e?this:this.each(function(t){J.offset.setOffset(this,e,t)});var t,n,i=this[0],r={top:0,left:0},a=i&&i.ownerDocument;if(a)return t=a.documentElement,J.contains(t,i)?(typeof i.getBoundingClientRect!==xe&&(r=i.getBoundingClientRect()),n=W(a),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}):r},position:function(){if(this[0]){var e,t,n=this[0],i={top:0,left:0};return\"fixed\"===J.css(n,\"position\")?t=n.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),J.nodeName(e[0],\"html\")||(i=e.offset()),i.top+=J.css(e[0],\"borderTopWidth\",!0),i.left+=J.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-i.top-J.css(n,\"marginTop\",!0),left:t.left-i.left-J.css(n,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent||kt;e&&!J.nodeName(e,\"html\")&&\"static\"===J.css(e,\"position\");)e=e.offsetParent;return e||kt})}}),J.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,n){var i=\"pageYOffset\"===n;J.fn[t]=function(r){return fe(this,function(t,r,a){var o=W(t);return void 0===a?o?o[n]:t[r]:void(o?o.scrollTo(i?e.pageXOffset:a,i?a:e.pageYOffset):t[r]=a)},t,r,arguments.length,null)}}),J.each([\"top\",\"left\"],function(e,t){J.cssHooks[t]=y(Z.pixelPosition,function(e,n){return n?(n=I(e,t),qe.test(n)?J(e).position()[t]+\"px\":n):void 0})}),J.each({Height:\"height\",Width:\"width\"},function(e,t){J.each({padding:\"inner\"+e,content:t,\"\":\"outer\"+e},function(n,i){J.fn[i]=function(i,r){var a=arguments.length&&(n||\"boolean\"!=typeof i),o=n||(i===!0||r===!0?\"margin\":\"border\");return fe(this,function(t,n,i){var r;return J.isWindow(t)?t.document.documentElement[\"client\"+e]:9===t.nodeType?(r=t.documentElement,Math.max(t.body[\"scroll\"+e],r[\"scroll\"+e],t.body[\"offset\"+e],r[\"offset\"+e],r[\"client\"+e])):void 0===i?J.css(t,n,o):J.style(t,n,i,o)},t,a?i:void 0,a,null)}})}),J.fn.size=function(){return this.length},J.fn.andSelf=J.fn.addBack,\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return J});var Rt=e.jQuery,Ot=e.$;return J.noConflict=function(t){return e.$===J&&(e.$=Ot),t&&e.jQuery===J&&(e.jQuery=Rt),J},typeof t===xe&&(e.jQuery=e.$=J),J}),\"undefined\"==typeof jQuery)throw new Error(\"Bootstrap's JavaScript requires jQuery\");+function(e){\"use strict\";var t=e.fn.jquery.split(\" \")[0].split(\".\");if(t[0]<2&&t[1]<9||1==t[0]&&9==t[1]&&t[2]<1)throw new Error(\"Bootstrap's JavaScript requires jQuery version 1.9.1 or higher\")}(jQuery),+function(e){\"use strict\";function t(){var e=document.createElement(\"bootstrap\"),t={WebkitTransition:\"webkitTransitionEnd\",MozTransition:\"transitionend\",OTransition:\"oTransitionEnd otransitionend\",transition:\"transitionend\"};for(var n in t)if(void 0!==e.style[n])return{end:t[n]};return!1}e.fn.emulateTransitionEnd=function(t){var n=!1,i=this;e(this).one(\"bsTransitionEnd\",function(){n=!0});var r=function(){n||e(i).trigger(e.support.transition.end)};return setTimeout(r,t),this},e(function(){e.support.transition=t(),e.support.transition&&(e.event.special.bsTransitionEnd={bindType:e.support.transition.end,delegateType:e.support.transition.end,handle:function(t){return e(t.target).is(this)?t.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(e){\"use strict\";function t(t){return this.each(function(){var n=e(this),r=n.data(\"bs.alert\");r||n.data(\"bs.alert\",r=new i(this)),\"string\"==typeof t&&r[t].call(n)})}var n='[data-dismiss=\"alert\"]',i=function(t){e(t).on(\"click\",n,this.close)};i.VERSION=\"3.3.5\",i.TRANSITION_DURATION=150,i.prototype.close=function(t){function n(){o.detach().trigger(\"closed.bs.alert\").remove()}var r=e(this),a=r.attr(\"data-target\");a||(a=r.attr(\"href\"),a=a&&a.replace(/.*(?=#[^\\s]*$)/,\"\"));var o=e(a);t&&t.preventDefault(),o.length||(o=r.closest(\".alert\")),o.trigger(t=e.Event(\"close.bs.alert\")),t.isDefaultPrevented()||(o.removeClass(\"in\"),e.support.transition&&o.hasClass(\"fade\")?o.one(\"bsTransitionEnd\",n).emulateTransitionEnd(i.TRANSITION_DURATION):n())};var r=e.fn.alert;e.fn.alert=t,e.fn.alert.Constructor=i,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on(\"click.bs.alert.data-api\",n,i.prototype.close)}(jQuery),+function(e){\"use strict\";function t(t){return this.each(function(){var i=e(this),r=i.data(\"bs.button\"),a=\"object\"==typeof t&&t;r||i.data(\"bs.button\",r=new n(this,a)),\"toggle\"==t?r.toggle():t&&r.setState(t)})}var n=function(t,i){this.$element=e(t),this.options=e.extend({},n.DEFAULTS,i),this.isLoading=!1};n.VERSION=\"3.3.5\",n.DEFAULTS={loadingText:\"loading...\"},n.prototype.setState=function(t){var n=\"disabled\",i=this.$element,r=i.is(\"input\")?\"val\":\"html\",a=i.data();t+=\"Text\",null==a.resetText&&i.data(\"resetText\",i[r]()),setTimeout(e.proxy(function(){i[r](null==a[t]?this.options[t]:a[t]),\"loadingText\"==t?(this.isLoading=!0,i.addClass(n).attr(n,n)):this.isLoading&&(this.isLoading=!1,i.removeClass(n).removeAttr(n))},this),0)},n.prototype.toggle=function(){var e=!0,t=this.$element.closest('[data-toggle=\"buttons\"]');if(t.length){var n=this.$element.find(\"input\");\"radio\"==n.prop(\"type\")?(n.prop(\"checked\")&&(e=!1),t.find(\".active\").removeClass(\"active\"),this.$element.addClass(\"active\")):\"checkbox\"==n.prop(\"type\")&&(n.prop(\"checked\")!==this.$element.hasClass(\"active\")&&(e=!1),this.$element.toggleClass(\"active\")),n.prop(\"checked\",this.$element.hasClass(\"active\")),e&&n.trigger(\"change\")}else this.$element.attr(\"aria-pressed\",!this.$element.hasClass(\"active\")),this.$element.toggleClass(\"active\")};var i=e.fn.button;e.fn.button=t,e.fn.button.Constructor=n,e.fn.button.noConflict=function(){return e.fn.button=i,this},e(document).on(\"click.bs.button.data-api\",'[data-toggle^=\"button\"]',function(n){var i=e(n.target);i.hasClass(\"btn\")||(i=i.closest(\".btn\")),t.call(i,\"toggle\"),e(n.target).is('input[type=\"radio\"]')||e(n.target).is('input[type=\"checkbox\"]')||n.preventDefault()}).on(\"focus.bs.button.data-api blur.bs.button.data-api\",'[data-toggle^=\"button\"]',function(t){e(t.target).closest(\".btn\").toggleClass(\"focus\",/^focus(in)?$/.test(t.type))})}(jQuery),+function(e){\"use strict\";function t(t){return this.each(function(){var i=e(this),r=i.data(\"bs.carousel\"),a=e.extend({},n.DEFAULTS,i.data(),\"object\"==typeof t&&t),o=\"string\"==typeof t?t:a.slide;r||i.data(\"bs.carousel\",r=new n(this,a)),\"number\"==typeof t?r.to(t):o?r[o]():a.interval&&r.pause().cycle()})}var n=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(\".carousel-indicators\"),this.options=n,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on(\"keydown.bs.carousel\",e.proxy(this.keydown,this)),\"hover\"==this.options.pause&&!(\"ontouchstart\"in document.documentElement)&&this.$element.on(\"mouseenter.bs.carousel\",e.proxy(this.pause,this)).on(\"mouseleave.bs.carousel\",e.proxy(this.cycle,this))};n.VERSION=\"3.3.5\",n.TRANSITION_DURATION=600,n.DEFAULTS={interval:5e3,pause:\"hover\",wrap:!0,keyboard:!0},n.prototype.keydown=function(e){if(!/input|textarea/i.test(e.target.tagName)){switch(e.which){case 37:this.prev();break;case 39:this.next();break;default:return}e.preventDefault()}},n.prototype.cycle=function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},n.prototype.getItemIndex=function(e){return this.$items=e.parent().children(\".item\"),this.$items.index(e||this.$active)},n.prototype.getItemForDirection=function(e,t){var n=this.getItemIndex(t),i=\"prev\"==e&&0===n||\"next\"==e&&n==this.$items.length-1;if(i&&!this.options.wrap)return t;var r=\"prev\"==e?-1:1,a=(n+r)%this.$items.length;return this.$items.eq(a)},n.prototype.to=function(e){var t=this,n=this.getItemIndex(this.$active=this.$element.find(\".item.active\"));return e>this.$items.length-1||0>e?void 0:this.sliding?this.$element.one(\"slid.bs.carousel\",function(){t.to(e)}):n==e?this.pause().cycle():this.slide(e>n?\"next\":\"prev\",this.$items.eq(e))},n.prototype.pause=function(t){return t||(this.paused=!0),this.$element.find(\".next, .prev\").length&&e.support.transition&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},n.prototype.next=function(){return this.sliding?void 0:this.slide(\"next\")},n.prototype.prev=function(){return this.sliding?void 0:this.slide(\"prev\")},n.prototype.slide=function(t,i){var r=this.$element.find(\".item.active\"),a=i||this.getItemForDirection(t,r),o=this.interval,s=\"next\"==t?\"left\":\"right\",l=this;if(a.hasClass(\"active\"))return this.sliding=!1;var c=a[0],d=e.Event(\"slide.bs.carousel\",{relatedTarget:c,direction:s});if(this.$element.trigger(d),!d.isDefaultPrevented()){if(this.sliding=!0,o&&this.pause(),this.$indicators.length){this.$indicators.find(\".active\").removeClass(\"active\");var u=e(this.$indicators.children()[this.getItemIndex(a)]);u&&u.addClass(\"active\")}var p=e.Event(\"slid.bs.carousel\",{relatedTarget:c,direction:s});return e.support.transition&&this.$element.hasClass(\"slide\")?(a.addClass(t),a[0].offsetWidth,r.addClass(s),a.addClass(s),r.one(\"bsTransitionEnd\",function(){a.removeClass([t,s].join(\" \")).addClass(\"active\"),r.removeClass([\"active\",s].join(\" \")),l.sliding=!1,setTimeout(function(){l.$element.trigger(p)},0)}).emulateTransitionEnd(n.TRANSITION_DURATION)):(r.removeClass(\"active\"),a.addClass(\"active\"),this.sliding=!1,this.$element.trigger(p)),o&&this.cycle(),this}};var i=e.fn.carousel;e.fn.carousel=t,e.fn.carousel.Constructor=n,e.fn.carousel.noConflict=function(){return e.fn.carousel=i,this};var r=function(n){var i,r=e(this),a=e(r.attr(\"data-target\")||(i=r.attr(\"href\"))&&i.replace(/.*(?=#[^\\s]+$)/,\"\"));if(a.hasClass(\"carousel\")){var o=e.extend({},a.data(),r.data()),s=r.attr(\"data-slide-to\");s&&(o.interval=!1),t.call(a,o),s&&a.data(\"bs.carousel\").to(s),n.preventDefault()}};e(document).on(\"click.bs.carousel.data-api\",\"[data-slide]\",r).on(\"click.bs.carousel.data-api\",\"[data-slide-to]\",r),e(window).on(\"load\",function(){e('[data-ride=\"carousel\"]').each(function(){var n=e(this);t.call(n,n.data())})})}(jQuery),+function(e){\"use strict\";function t(t){var n,i=t.attr(\"data-target\")||(n=t.attr(\"href\"))&&n.replace(/.*(?=#[^\\s]+$)/,\"\");return e(i)}function n(t){return this.each(function(){var n=e(this),r=n.data(\"bs.collapse\"),a=e.extend({},i.DEFAULTS,n.data(),\"object\"==typeof t&&t);!r&&a.toggle&&/show|hide/.test(t)&&(a.toggle=!1),r||n.data(\"bs.collapse\",r=new i(this,a)),\"string\"==typeof t&&r[t]()})}var i=function(t,n){this.$element=e(t),this.options=e.extend({},i.DEFAULTS,n),this.$trigger=e('[data-toggle=\"collapse\"][href=\"#'+t.id+'\"],[data-toggle=\"collapse\"][data-target=\"#'+t.id+'\"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};i.VERSION=\"3.3.5\",i.TRANSITION_DURATION=350,i.DEFAULTS={toggle:!0},i.prototype.dimension=function(){var e=this.$element.hasClass(\"width\");return e?\"width\":\"height\"},i.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass(\"in\")){var t,r=this.$parent&&this.$parent.children(\".panel\").children(\".in, .collapsing\");if(!(r&&r.length&&(t=r.data(\"bs.collapse\"),t&&t.transitioning))){var a=e.Event(\"show.bs.collapse\");if(this.$element.trigger(a),!a.isDefaultPrevented()){r&&r.length&&(n.call(r,\"hide\"),t||r.data(\"bs.collapse\",null));var o=this.dimension();this.$element.removeClass(\"collapse\").addClass(\"collapsing\")[o](0).attr(\"aria-expanded\",!0),this.$trigger.removeClass(\"collapsed\").attr(\"aria-expanded\",!0),this.transitioning=1;var s=function(){this.$element.removeClass(\"collapsing\").addClass(\"collapse in\")[o](\"\"),this.transitioning=0,this.$element.trigger(\"shown.bs.collapse\")};if(!e.support.transition)return s.call(this);var l=e.camelCase([\"scroll\",o].join(\"-\"));this.$element.one(\"bsTransitionEnd\",e.proxy(s,this)).emulateTransitionEnd(i.TRANSITION_DURATION)[o](this.$element[0][l])}}}},i.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass(\"in\")){var t=e.Event(\"hide.bs.collapse\");if(this.$element.trigger(t),!t.isDefaultPrevented()){var n=this.dimension();this.$element[n](this.$element[n]())[0].offsetHeight,this.$element.addClass(\"collapsing\").removeClass(\"collapse in\").attr(\"aria-expanded\",!1),this.$trigger.addClass(\"collapsed\").attr(\"aria-expanded\",!1),this.transitioning=1;var r=function(){this.transitioning=0,this.$element.removeClass(\"collapsing\").addClass(\"collapse\").trigger(\"hidden.bs.collapse\")};return e.support.transition?void this.$element[n](0).one(\"bsTransitionEnd\",e.proxy(r,this)).emulateTransitionEnd(i.TRANSITION_DURATION):r.call(this)}}},i.prototype.toggle=function(){this[this.$element.hasClass(\"in\")?\"hide\":\"show\"]()},i.prototype.getParent=function(){return e(this.options.parent).find('[data-toggle=\"collapse\"][data-parent=\"'+this.options.parent+'\"]').each(e.proxy(function(n,i){var r=e(i);this.addAriaAndCollapsedClass(t(r),r)},this)).end()},i.prototype.addAriaAndCollapsedClass=function(e,t){var n=e.hasClass(\"in\");e.attr(\"aria-expanded\",n),t.toggleClass(\"collapsed\",!n).attr(\"aria-expanded\",n)};var r=e.fn.collapse;e.fn.collapse=n,e.fn.collapse.Constructor=i,e.fn.collapse.noConflict=function(){return e.fn.collapse=r,this},e(document).on(\"click.bs.collapse.data-api\",'[data-toggle=\"collapse\"]',function(i){var r=e(this);r.attr(\"data-target\")||i.preventDefault();var a=t(r),o=a.data(\"bs.collapse\"),s=o?\"toggle\":r.data();n.call(a,s)})}(jQuery),+function(e){\"use strict\";function t(t){\nvar n=t.attr(\"data-target\");n||(n=t.attr(\"href\"),n=n&&/#[A-Za-z]/.test(n)&&n.replace(/.*(?=#[^\\s]*$)/,\"\"));var i=n&&e(n);return i&&i.length?i:t.parent()}function n(n){n&&3===n.which||(e(r).remove(),e(a).each(function(){var i=e(this),r=t(i),a={relatedTarget:this};r.hasClass(\"open\")&&(n&&\"click\"==n.type&&/input|textarea/i.test(n.target.tagName)&&e.contains(r[0],n.target)||(r.trigger(n=e.Event(\"hide.bs.dropdown\",a)),n.isDefaultPrevented()||(i.attr(\"aria-expanded\",\"false\"),r.removeClass(\"open\").trigger(\"hidden.bs.dropdown\",a))))}))}function i(t){return this.each(function(){var n=e(this),i=n.data(\"bs.dropdown\");i||n.data(\"bs.dropdown\",i=new o(this)),\"string\"==typeof t&&i[t].call(n)})}var r=\".dropdown-backdrop\",a='[data-toggle=\"dropdown\"]',o=function(t){e(t).on(\"click.bs.dropdown\",this.toggle)};o.VERSION=\"3.3.5\",o.prototype.toggle=function(i){var r=e(this);if(!r.is(\".disabled, :disabled\")){var a=t(r),o=a.hasClass(\"open\");if(n(),!o){\"ontouchstart\"in document.documentElement&&!a.closest(\".navbar-nav\").length&&e(document.createElement(\"div\")).addClass(\"dropdown-backdrop\").insertAfter(e(this)).on(\"click\",n);var s={relatedTarget:this};if(a.trigger(i=e.Event(\"show.bs.dropdown\",s)),i.isDefaultPrevented())return;r.trigger(\"focus\").attr(\"aria-expanded\",\"true\"),a.toggleClass(\"open\").trigger(\"shown.bs.dropdown\",s)}return!1}},o.prototype.keydown=function(n){if(/(38|40|27|32)/.test(n.which)&&!/input|textarea/i.test(n.target.tagName)){var i=e(this);if(n.preventDefault(),n.stopPropagation(),!i.is(\".disabled, :disabled\")){var r=t(i),o=r.hasClass(\"open\");if(!o&&27!=n.which||o&&27==n.which)return 27==n.which&&r.find(a).trigger(\"focus\"),i.trigger(\"click\");var s=\" li:not(.disabled):visible a\",l=r.find(\".dropdown-menu\"+s);if(l.length){var c=l.index(n.target);38==n.which&&c>0&&c--,40==n.which&&c<l.length-1&&c++,~c||(c=0),l.eq(c).trigger(\"focus\")}}}};var s=e.fn.dropdown;e.fn.dropdown=i,e.fn.dropdown.Constructor=o,e.fn.dropdown.noConflict=function(){return e.fn.dropdown=s,this},e(document).on(\"click.bs.dropdown.data-api\",n).on(\"click.bs.dropdown.data-api\",\".dropdown form\",function(e){e.stopPropagation()}).on(\"click.bs.dropdown.data-api\",a,o.prototype.toggle).on(\"keydown.bs.dropdown.data-api\",a,o.prototype.keydown).on(\"keydown.bs.dropdown.data-api\",\".dropdown-menu\",o.prototype.keydown)}(jQuery),+function(e){\"use strict\";function t(t,i){return this.each(function(){var r=e(this),a=r.data(\"bs.modal\"),o=e.extend({},n.DEFAULTS,r.data(),\"object\"==typeof t&&t);a||r.data(\"bs.modal\",a=new n(this,o)),\"string\"==typeof t?a[t](i):o.show&&a.show(i)})}var n=function(t,n){this.options=n,this.$body=e(document.body),this.$element=e(t),this.$dialog=this.$element.find(\".modal-dialog\"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(\".modal-content\").load(this.options.remote,e.proxy(function(){this.$element.trigger(\"loaded.bs.modal\")},this))};n.VERSION=\"3.3.5\",n.TRANSITION_DURATION=300,n.BACKDROP_TRANSITION_DURATION=150,n.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},n.prototype.toggle=function(e){return this.isShown?this.hide():this.show(e)},n.prototype.show=function(t){var i=this,r=e.Event(\"show.bs.modal\",{relatedTarget:t});this.$element.trigger(r),this.isShown||r.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass(\"modal-open\"),this.escape(),this.resize(),this.$element.on(\"click.dismiss.bs.modal\",'[data-dismiss=\"modal\"]',e.proxy(this.hide,this)),this.$dialog.on(\"mousedown.dismiss.bs.modal\",function(){i.$element.one(\"mouseup.dismiss.bs.modal\",function(t){e(t.target).is(i.$element)&&(i.ignoreBackdropClick=!0)})}),this.backdrop(function(){var r=e.support.transition&&i.$element.hasClass(\"fade\");i.$element.parent().length||i.$element.appendTo(i.$body),i.$element.show().scrollTop(0),i.adjustDialog(),r&&i.$element[0].offsetWidth,i.$element.addClass(\"in\"),i.enforceFocus();var a=e.Event(\"shown.bs.modal\",{relatedTarget:t});r?i.$dialog.one(\"bsTransitionEnd\",function(){i.$element.trigger(\"focus\").trigger(a)}).emulateTransitionEnd(n.TRANSITION_DURATION):i.$element.trigger(\"focus\").trigger(a)}))},n.prototype.hide=function(t){t&&t.preventDefault(),t=e.Event(\"hide.bs.modal\"),this.$element.trigger(t),this.isShown&&!t.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),e(document).off(\"focusin.bs.modal\"),this.$element.removeClass(\"in\").off(\"click.dismiss.bs.modal\").off(\"mouseup.dismiss.bs.modal\"),this.$dialog.off(\"mousedown.dismiss.bs.modal\"),e.support.transition&&this.$element.hasClass(\"fade\")?this.$element.one(\"bsTransitionEnd\",e.proxy(this.hideModal,this)).emulateTransitionEnd(n.TRANSITION_DURATION):this.hideModal())},n.prototype.enforceFocus=function(){e(document).off(\"focusin.bs.modal\").on(\"focusin.bs.modal\",e.proxy(function(e){this.$element[0]===e.target||this.$element.has(e.target).length||this.$element.trigger(\"focus\")},this))},n.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on(\"keydown.dismiss.bs.modal\",e.proxy(function(e){27==e.which&&this.hide()},this)):this.isShown||this.$element.off(\"keydown.dismiss.bs.modal\")},n.prototype.resize=function(){this.isShown?e(window).on(\"resize.bs.modal\",e.proxy(this.handleUpdate,this)):e(window).off(\"resize.bs.modal\")},n.prototype.hideModal=function(){var e=this;this.$element.hide(),this.backdrop(function(){e.$body.removeClass(\"modal-open\"),e.resetAdjustments(),e.resetScrollbar(),e.$element.trigger(\"hidden.bs.modal\")})},n.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},n.prototype.backdrop=function(t){var i=this,r=this.$element.hasClass(\"fade\")?\"fade\":\"\";if(this.isShown&&this.options.backdrop){var a=e.support.transition&&r;if(this.$backdrop=e(document.createElement(\"div\")).addClass(\"modal-backdrop \"+r).appendTo(this.$body),this.$element.on(\"click.dismiss.bs.modal\",e.proxy(function(e){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(e.target===e.currentTarget&&(\"static\"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),a&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass(\"in\"),!t)return;a?this.$backdrop.one(\"bsTransitionEnd\",t).emulateTransitionEnd(n.BACKDROP_TRANSITION_DURATION):t()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass(\"in\");var o=function(){i.removeBackdrop(),t&&t()};e.support.transition&&this.$element.hasClass(\"fade\")?this.$backdrop.one(\"bsTransitionEnd\",o).emulateTransitionEnd(n.BACKDROP_TRANSITION_DURATION):o()}else t&&t()},n.prototype.handleUpdate=function(){this.adjustDialog()},n.prototype.adjustDialog=function(){var e=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&e?this.scrollbarWidth:\"\",paddingRight:this.bodyIsOverflowing&&!e?this.scrollbarWidth:\"\"})},n.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:\"\",paddingRight:\"\"})},n.prototype.checkScrollbar=function(){var e=window.innerWidth;if(!e){var t=document.documentElement.getBoundingClientRect();e=t.right-Math.abs(t.left)}this.bodyIsOverflowing=document.body.clientWidth<e,this.scrollbarWidth=this.measureScrollbar()},n.prototype.setScrollbar=function(){var e=parseInt(this.$body.css(\"padding-right\")||0,10);this.originalBodyPad=document.body.style.paddingRight||\"\",this.bodyIsOverflowing&&this.$body.css(\"padding-right\",e+this.scrollbarWidth)},n.prototype.resetScrollbar=function(){this.$body.css(\"padding-right\",this.originalBodyPad)},n.prototype.measureScrollbar=function(){var e=document.createElement(\"div\");e.className=\"modal-scrollbar-measure\",this.$body.append(e);var t=e.offsetWidth-e.clientWidth;return this.$body[0].removeChild(e),t};var i=e.fn.modal;e.fn.modal=t,e.fn.modal.Constructor=n,e.fn.modal.noConflict=function(){return e.fn.modal=i,this},e(document).on(\"click.bs.modal.data-api\",'[data-toggle=\"modal\"]',function(n){var i=e(this),r=i.attr(\"href\"),a=e(i.attr(\"data-target\")||r&&r.replace(/.*(?=#[^\\s]+$)/,\"\")),o=a.data(\"bs.modal\")?\"toggle\":e.extend({remote:!/#/.test(r)&&r},a.data(),i.data());i.is(\"a\")&&n.preventDefault(),a.one(\"show.bs.modal\",function(e){e.isDefaultPrevented()||a.one(\"hidden.bs.modal\",function(){i.is(\":visible\")&&i.trigger(\"focus\")})}),t.call(a,o,this)})}(jQuery),+function(e){\"use strict\";function t(t){return this.each(function(){var i=e(this),r=i.data(\"bs.tooltip\"),a=\"object\"==typeof t&&t;(r||!/destroy|hide/.test(t))&&(r||i.data(\"bs.tooltip\",r=new n(this,a)),\"string\"==typeof t&&r[t]())})}var n=function(e,t){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init(\"tooltip\",e,t)};n.VERSION=\"3.3.5\",n.TRANSITION_DURATION=150,n.DEFAULTS={animation:!0,placement:\"top\",selector:!1,template:'<div class=\"tooltip\" role=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>',trigger:\"hover focus\",title:\"\",delay:0,html:!1,container:!1,viewport:{selector:\"body\",padding:0}},n.prototype.init=function(t,n,i){if(this.enabled=!0,this.type=t,this.$element=e(n),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&e(e.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error(\"`selector` option must be specified when initializing \"+this.type+\" on the window.document object!\");for(var r=this.options.trigger.split(\" \"),a=r.length;a--;){var o=r[a];if(\"click\"==o)this.$element.on(\"click.\"+this.type,this.options.selector,e.proxy(this.toggle,this));else if(\"manual\"!=o){var s=\"hover\"==o?\"mouseenter\":\"focusin\",l=\"hover\"==o?\"mouseleave\":\"focusout\";this.$element.on(s+\".\"+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(l+\".\"+this.type,this.options.selector,e.proxy(this.leave,this))}}this.options.selector?this._options=e.extend({},this.options,{trigger:\"manual\",selector:\"\"}):this.fixTitle()},n.prototype.getDefaults=function(){return n.DEFAULTS},n.prototype.getOptions=function(t){return t=e.extend({},this.getDefaults(),this.$element.data(),t),t.delay&&\"number\"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t},n.prototype.getDelegateOptions=function(){var t={},n=this.getDefaults();return this._options&&e.each(this._options,function(e,i){n[e]!=i&&(t[e]=i)}),t},n.prototype.enter=function(t){var n=t instanceof this.constructor?t:e(t.currentTarget).data(\"bs.\"+this.type);return n||(n=new this.constructor(t.currentTarget,this.getDelegateOptions()),e(t.currentTarget).data(\"bs.\"+this.type,n)),t instanceof e.Event&&(n.inState[\"focusin\"==t.type?\"focus\":\"hover\"]=!0),n.tip().hasClass(\"in\")||\"in\"==n.hoverState?void(n.hoverState=\"in\"):(clearTimeout(n.timeout),n.hoverState=\"in\",n.options.delay&&n.options.delay.show?void(n.timeout=setTimeout(function(){\"in\"==n.hoverState&&n.show()},n.options.delay.show)):n.show())},n.prototype.isInStateTrue=function(){for(var e in this.inState)if(this.inState[e])return!0;return!1},n.prototype.leave=function(t){var n=t instanceof this.constructor?t:e(t.currentTarget).data(\"bs.\"+this.type);return n||(n=new this.constructor(t.currentTarget,this.getDelegateOptions()),e(t.currentTarget).data(\"bs.\"+this.type,n)),t instanceof e.Event&&(n.inState[\"focusout\"==t.type?\"focus\":\"hover\"]=!1),n.isInStateTrue()?void 0:(clearTimeout(n.timeout),n.hoverState=\"out\",n.options.delay&&n.options.delay.hide?void(n.timeout=setTimeout(function(){\"out\"==n.hoverState&&n.hide()},n.options.delay.hide)):n.hide())},n.prototype.show=function(){var t=e.Event(\"show.bs.\"+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var i=e.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!i)return;var r=this,a=this.tip(),o=this.getUID(this.type);this.setContent(),a.attr(\"id\",o),this.$element.attr(\"aria-describedby\",o),this.options.animation&&a.addClass(\"fade\");var s=\"function\"==typeof this.options.placement?this.options.placement.call(this,a[0],this.$element[0]):this.options.placement,l=/\\s?auto?\\s?/i,c=l.test(s);c&&(s=s.replace(l,\"\")||\"top\"),a.detach().css({top:0,left:0,display:\"block\"}).addClass(s).data(\"bs.\"+this.type,this),this.options.container?a.appendTo(this.options.container):a.insertAfter(this.$element),this.$element.trigger(\"inserted.bs.\"+this.type);var d=this.getPosition(),u=a[0].offsetWidth,p=a[0].offsetHeight;if(c){var m=s,g=this.getPosition(this.$viewport);s=\"bottom\"==s&&d.bottom+p>g.bottom?\"top\":\"top\"==s&&d.top-p<g.top?\"bottom\":\"right\"==s&&d.right+u>g.width?\"left\":\"left\"==s&&d.left-u<g.left?\"right\":s,a.removeClass(m).addClass(s)}var h=this.getCalculatedOffset(s,d,u,p);this.applyPlacement(h,s);var f=function(){var e=r.hoverState;r.$element.trigger(\"shown.bs.\"+r.type),r.hoverState=null,\"out\"==e&&r.leave(r)};e.support.transition&&this.$tip.hasClass(\"fade\")?a.one(\"bsTransitionEnd\",f).emulateTransitionEnd(n.TRANSITION_DURATION):f()}},n.prototype.applyPlacement=function(t,n){var i=this.tip(),r=i[0].offsetWidth,a=i[0].offsetHeight,o=parseInt(i.css(\"margin-top\"),10),s=parseInt(i.css(\"margin-left\"),10);isNaN(o)&&(o=0),isNaN(s)&&(s=0),t.top+=o,t.left+=s,e.offset.setOffset(i[0],e.extend({using:function(e){i.css({top:Math.round(e.top),left:Math.round(e.left)})}},t),0),i.addClass(\"in\");var l=i[0].offsetWidth,c=i[0].offsetHeight;\"top\"==n&&c!=a&&(t.top=t.top+a-c);var d=this.getViewportAdjustedDelta(n,t,l,c);d.left?t.left+=d.left:t.top+=d.top;var u=/top|bottom/.test(n),p=u?2*d.left-r+l:2*d.top-a+c,m=u?\"offsetWidth\":\"offsetHeight\";i.offset(t),this.replaceArrow(p,i[0][m],u)},n.prototype.replaceArrow=function(e,t,n){this.arrow().css(n?\"left\":\"top\",50*(1-e/t)+\"%\").css(n?\"top\":\"left\",\"\")},n.prototype.setContent=function(){var e=this.tip(),t=this.getTitle();e.find(\".tooltip-inner\")[this.options.html?\"html\":\"text\"](t),e.removeClass(\"fade in top bottom left right\")},n.prototype.hide=function(t){function i(){\"in\"!=r.hoverState&&a.detach(),r.$element.removeAttr(\"aria-describedby\").trigger(\"hidden.bs.\"+r.type),t&&t()}var r=this,a=e(this.$tip),o=e.Event(\"hide.bs.\"+this.type);return this.$element.trigger(o),o.isDefaultPrevented()?void 0:(a.removeClass(\"in\"),e.support.transition&&a.hasClass(\"fade\")?a.one(\"bsTransitionEnd\",i).emulateTransitionEnd(n.TRANSITION_DURATION):i(),this.hoverState=null,this)},n.prototype.fixTitle=function(){var e=this.$element;(e.attr(\"title\")||\"string\"!=typeof e.attr(\"data-original-title\"))&&e.attr(\"data-original-title\",e.attr(\"title\")||\"\").attr(\"title\",\"\")},n.prototype.hasContent=function(){return this.getTitle()},n.prototype.getPosition=function(t){t=t||this.$element;var n=t[0],i=\"BODY\"==n.tagName,r=n.getBoundingClientRect();null==r.width&&(r=e.extend({},r,{width:r.right-r.left,height:r.bottom-r.top}));var a=i?{top:0,left:0}:t.offset(),o={scroll:i?document.documentElement.scrollTop||document.body.scrollTop:t.scrollTop()},s=i?{width:e(window).width(),height:e(window).height()}:null;return e.extend({},r,o,s,a)},n.prototype.getCalculatedOffset=function(e,t,n,i){return\"bottom\"==e?{top:t.top+t.height,left:t.left+t.width/2-n/2}:\"top\"==e?{top:t.top-i,left:t.left+t.width/2-n/2}:\"left\"==e?{top:t.top+t.height/2-i/2,left:t.left-n}:{top:t.top+t.height/2-i/2,left:t.left+t.width}},n.prototype.getViewportAdjustedDelta=function(e,t,n,i){var r={top:0,left:0};if(!this.$viewport)return r;var a=this.options.viewport&&this.options.viewport.padding||0,o=this.getPosition(this.$viewport);if(/right|left/.test(e)){var s=t.top-a-o.scroll,l=t.top+a-o.scroll+i;s<o.top?r.top=o.top-s:l>o.top+o.height&&(r.top=o.top+o.height-l)}else{var c=t.left-a,d=t.left+a+n;c<o.left?r.left=o.left-c:d>o.right&&(r.left=o.left+o.width-d)}return r},n.prototype.getTitle=function(){var e,t=this.$element,n=this.options;return e=t.attr(\"data-original-title\")||(\"function\"==typeof n.title?n.title.call(t[0]):n.title)},n.prototype.getUID=function(e){do e+=~~(1e6*Math.random());while(document.getElementById(e));return e},n.prototype.tip=function(){if(!this.$tip&&(this.$tip=e(this.options.template),1!=this.$tip.length))throw new Error(this.type+\" `template` option must consist of exactly 1 top-level element!\");return this.$tip},n.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(\".tooltip-arrow\")},n.prototype.enable=function(){this.enabled=!0},n.prototype.disable=function(){this.enabled=!1},n.prototype.toggleEnabled=function(){this.enabled=!this.enabled},n.prototype.toggle=function(t){var n=this;t&&(n=e(t.currentTarget).data(\"bs.\"+this.type),n||(n=new this.constructor(t.currentTarget,this.getDelegateOptions()),e(t.currentTarget).data(\"bs.\"+this.type,n))),t?(n.inState.click=!n.inState.click,n.isInStateTrue()?n.enter(n):n.leave(n)):n.tip().hasClass(\"in\")?n.leave(n):n.enter(n)},n.prototype.destroy=function(){var e=this;clearTimeout(this.timeout),this.hide(function(){e.$element.off(\".\"+e.type).removeData(\"bs.\"+e.type),e.$tip&&e.$tip.detach(),e.$tip=null,e.$arrow=null,e.$viewport=null})};var i=e.fn.tooltip;e.fn.tooltip=t,e.fn.tooltip.Constructor=n,e.fn.tooltip.noConflict=function(){return e.fn.tooltip=i,this}}(jQuery),+function(e){\"use strict\";function t(t){return this.each(function(){var i=e(this),r=i.data(\"bs.popover\"),a=\"object\"==typeof t&&t;(r||!/destroy|hide/.test(t))&&(r||i.data(\"bs.popover\",r=new n(this,a)),\"string\"==typeof t&&r[t]())})}var n=function(e,t){this.init(\"popover\",e,t)};if(!e.fn.tooltip)throw new Error(\"Popover requires tooltip.js\");n.VERSION=\"3.3.5\",n.DEFAULTS=e.extend({},e.fn.tooltip.Constructor.DEFAULTS,{placement:\"right\",trigger:\"click\",content:\"\",template:'<div class=\"popover\" role=\"tooltip\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'}),n.prototype=e.extend({},e.fn.tooltip.Constructor.prototype),n.prototype.constructor=n,n.prototype.getDefaults=function(){return n.DEFAULTS},n.prototype.setContent=function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(\".popover-title\")[this.options.html?\"html\":\"text\"](t),e.find(\".popover-content\").children().detach().end()[this.options.html?\"string\"==typeof n?\"html\":\"append\":\"text\"](n),e.removeClass(\"fade top bottom left right in\"),e.find(\".popover-title\").html()||e.find(\".popover-title\").hide()},n.prototype.hasContent=function(){return this.getTitle()||this.getContent()},n.prototype.getContent=function(){var e=this.$element,t=this.options;return e.attr(\"data-content\")||(\"function\"==typeof t.content?t.content.call(e[0]):t.content)},n.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(\".arrow\")};var i=e.fn.popover;e.fn.popover=t,e.fn.popover.Constructor=n,e.fn.popover.noConflict=function(){return e.fn.popover=i,this}}(jQuery),+function(e){\"use strict\";function t(n,i){this.$body=e(document.body),this.$scrollElement=e(e(n).is(document.body)?window:n),this.options=e.extend({},t.DEFAULTS,i),this.selector=(this.options.target||\"\")+\" .nav li > a\",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on(\"scroll.bs.scrollspy\",e.proxy(this.process,this)),this.refresh(),this.process()}function n(n){return this.each(function(){var i=e(this),r=i.data(\"bs.scrollspy\"),a=\"object\"==typeof n&&n;r||i.data(\"bs.scrollspy\",r=new t(this,a)),\"string\"==typeof n&&r[n]()})}t.VERSION=\"3.3.5\",t.DEFAULTS={offset:10},t.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},t.prototype.refresh=function(){var t=this,n=\"offset\",i=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),e.isWindow(this.$scrollElement[0])||(n=\"position\",i=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=e(this),r=t.data(\"target\")||t.attr(\"href\"),a=/^#./.test(r)&&e(r);return a&&a.length&&a.is(\":visible\")&&[[a[n]().top+i,r]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},t.prototype.process=function(){var e,t=this.$scrollElement.scrollTop()+this.options.offset,n=this.getScrollHeight(),i=this.options.offset+n-this.$scrollElement.height(),r=this.offsets,a=this.targets,o=this.activeTarget;if(this.scrollHeight!=n&&this.refresh(),t>=i)return o!=(e=a[a.length-1])&&this.activate(e);if(o&&t<r[0])return this.activeTarget=null,this.clear();for(e=r.length;e--;)o!=a[e]&&t>=r[e]&&(void 0===r[e+1]||t<r[e+1])&&this.activate(a[e])},t.prototype.activate=function(t){this.activeTarget=t,this.clear();var n=this.selector+'[data-target=\"'+t+'\"],'+this.selector+'[href=\"'+t+'\"]',i=e(n).parents(\"li\").addClass(\"active\");i.parent(\".dropdown-menu\").length&&(i=i.closest(\"li.dropdown\").addClass(\"active\")),i.trigger(\"activate.bs.scrollspy\")},t.prototype.clear=function(){e(this.selector).parentsUntil(this.options.target,\".active\").removeClass(\"active\")};var i=e.fn.scrollspy;e.fn.scrollspy=n,e.fn.scrollspy.Constructor=t,e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=i,this},e(window).on(\"load.bs.scrollspy.data-api\",function(){e('[data-spy=\"scroll\"]').each(function(){var t=e(this);n.call(t,t.data())})})}(jQuery),+function(e){\"use strict\";function t(t){return this.each(function(){var i=e(this),r=i.data(\"bs.tab\");r||i.data(\"bs.tab\",r=new n(this)),\"string\"==typeof t&&r[t]()})}var n=function(t){this.element=e(t)};n.VERSION=\"3.3.5\",n.TRANSITION_DURATION=150,n.prototype.show=function(){var t=this.element,n=t.closest(\"ul:not(.dropdown-menu)\"),i=t.data(\"target\");if(i||(i=t.attr(\"href\"),i=i&&i.replace(/.*(?=#[^\\s]*$)/,\"\")),!t.parent(\"li\").hasClass(\"active\")){var r=n.find(\".active:last a\"),a=e.Event(\"hide.bs.tab\",{relatedTarget:t[0]}),o=e.Event(\"show.bs.tab\",{relatedTarget:r[0]});if(r.trigger(a),t.trigger(o),!o.isDefaultPrevented()&&!a.isDefaultPrevented()){var s=e(i);this.activate(t.closest(\"li\"),n),this.activate(s,s.parent(),function(){r.trigger({type:\"hidden.bs.tab\",relatedTarget:t[0]}),t.trigger({type:\"shown.bs.tab\",relatedTarget:r[0]})})}}},n.prototype.activate=function(t,i,r){function a(){o.removeClass(\"active\").find(\"> .dropdown-menu > .active\").removeClass(\"active\").end().find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!1),t.addClass(\"active\").find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!0),s?(t[0].offsetWidth,t.addClass(\"in\")):t.removeClass(\"fade\"),t.parent(\".dropdown-menu\").length&&t.closest(\"li.dropdown\").addClass(\"active\").end().find('[data-toggle=\"tab\"]').attr(\"aria-expanded\",!0),r&&r()}var o=i.find(\"> .active\"),s=r&&e.support.transition&&(o.length&&o.hasClass(\"fade\")||!!i.find(\"> .fade\").length);o.length&&s?o.one(\"bsTransitionEnd\",a).emulateTransitionEnd(n.TRANSITION_DURATION):a(),o.removeClass(\"in\")};var i=e.fn.tab;e.fn.tab=t,e.fn.tab.Constructor=n,e.fn.tab.noConflict=function(){return e.fn.tab=i,this};var r=function(n){n.preventDefault(),t.call(e(this),\"show\")};e(document).on(\"click.bs.tab.data-api\",'[data-toggle=\"tab\"]',r).on(\"click.bs.tab.data-api\",'[data-toggle=\"pill\"]',r)}(jQuery),+function(e){\"use strict\";function t(t){return this.each(function(){var i=e(this),r=i.data(\"bs.affix\"),a=\"object\"==typeof t&&t;r||i.data(\"bs.affix\",r=new n(this,a)),\"string\"==typeof t&&r[t]()})}var n=function(t,i){this.options=e.extend({},n.DEFAULTS,i),this.$target=e(this.options.target).on(\"scroll.bs.affix.data-api\",e.proxy(this.checkPosition,this)).on(\"click.bs.affix.data-api\",e.proxy(this.checkPositionWithEventLoop,this)),this.$element=e(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};n.VERSION=\"3.3.5\",n.RESET=\"affix affix-top affix-bottom\",n.DEFAULTS={offset:0,target:window},n.prototype.getState=function(e,t,n,i){var r=this.$target.scrollTop(),a=this.$element.offset(),o=this.$target.height();if(null!=n&&\"top\"==this.affixed)return n>r?\"top\":!1;if(\"bottom\"==this.affixed)return null!=n?r+this.unpin<=a.top?!1:\"bottom\":e-i>=r+o?!1:\"bottom\";var s=null==this.affixed,l=s?r:a.top,c=s?o:t;return null!=n&&n>=r?\"top\":null!=i&&l+c>=e-i?\"bottom\":!1},n.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(n.RESET).addClass(\"affix\");var e=this.$target.scrollTop(),t=this.$element.offset();return this.pinnedOffset=t.top-e},n.prototype.checkPositionWithEventLoop=function(){setTimeout(e.proxy(this.checkPosition,this),1)},n.prototype.checkPosition=function(){if(this.$element.is(\":visible\")){var t=this.$element.height(),i=this.options.offset,r=i.top,a=i.bottom,o=Math.max(e(document).height(),e(document.body).height());\"object\"!=typeof i&&(a=r=i),\"function\"==typeof r&&(r=i.top(this.$element)),\"function\"==typeof a&&(a=i.bottom(this.$element));var s=this.getState(o,t,r,a);if(this.affixed!=s){null!=this.unpin&&this.$element.css(\"top\",\"\");var l=\"affix\"+(s?\"-\"+s:\"\"),c=e.Event(l+\".bs.affix\");if(this.$element.trigger(c),c.isDefaultPrevented())return;this.affixed=s,this.unpin=\"bottom\"==s?this.getPinnedOffset():null,this.$element.removeClass(n.RESET).addClass(l).trigger(l.replace(\"affix\",\"affixed\")+\".bs.affix\")}\"bottom\"==s&&this.$element.offset({top:o-t-a})}};var i=e.fn.affix;e.fn.affix=t,e.fn.affix.Constructor=n,e.fn.affix.noConflict=function(){return e.fn.affix=i,this},e(window).on(\"load\",function(){e('[data-spy=\"affix\"]').each(function(){var n=e(this),i=n.data();i.offset=i.offset||{},null!=i.offsetBottom&&(i.offset.bottom=i.offsetBottom),null!=i.offsetTop&&(i.offset.top=i.offsetTop),t.call(n,i)})})}(jQuery),function(){\"use strict\";function e(t,i){function r(e,t){return function(){return e.apply(t,arguments)}}var a;if(i=i||{},this.trackingClick=!1,this.trackingClickStart=0,this.targetElement=null,this.touchStartX=0,this.touchStartY=0,this.lastTouchIdentifier=0,this.touchBoundary=i.touchBoundary||10,this.layer=t,this.tapDelay=i.tapDelay||200,this.tapTimeout=i.tapTimeout||700,!e.notNeeded(t)){for(var o=[\"onMouse\",\"onClick\",\"onTouchStart\",\"onTouchMove\",\"onTouchEnd\",\"onTouchCancel\"],s=this,l=0,c=o.length;c>l;l++)s[o[l]]=r(s[o[l]],s);n&&(t.addEventListener(\"mouseover\",this.onMouse,!0),t.addEventListener(\"mousedown\",this.onMouse,!0),t.addEventListener(\"mouseup\",this.onMouse,!0)),t.addEventListener(\"click\",this.onClick,!0),t.addEventListener(\"touchstart\",this.onTouchStart,!1),t.addEventListener(\"touchmove\",this.onTouchMove,!1),t.addEventListener(\"touchend\",this.onTouchEnd,!1),t.addEventListener(\"touchcancel\",this.onTouchCancel,!1),Event.prototype.stopImmediatePropagation||(t.removeEventListener=function(e,n,i){var r=Node.prototype.removeEventListener;\"click\"===e?r.call(t,e,n.hijacked||n,i):r.call(t,e,n,i)},t.addEventListener=function(e,n,i){var r=Node.prototype.addEventListener;\"click\"===e?r.call(t,e,n.hijacked||(n.hijacked=function(e){e.propagationStopped||n(e)}),i):r.call(t,e,n,i)}),\"function\"==typeof t.onclick&&(a=t.onclick,t.addEventListener(\"click\",function(e){a(e)},!1),t.onclick=null)}}var t=navigator.userAgent.indexOf(\"Windows Phone\")>=0,n=navigator.userAgent.indexOf(\"Android\")>0&&!t,i=/iP(ad|hone|od)/.test(navigator.userAgent)&&!t,r=i&&/OS 4_\\d(_\\d)?/.test(navigator.userAgent),a=i&&/OS [6-7]_\\d/.test(navigator.userAgent),o=navigator.userAgent.indexOf(\"BB10\")>0;e.prototype.needsClick=function(e){switch(e.nodeName.toLowerCase()){case\"button\":case\"select\":case\"textarea\":if(e.disabled)return!0;break;case\"input\":if(i&&\"file\"===e.type||e.disabled)return!0;break;case\"label\":case\"iframe\":case\"video\":return!0}return/\\bneedsclick\\b/.test(e.className)},e.prototype.needsFocus=function(e){switch(e.nodeName.toLowerCase()){case\"textarea\":return!0;case\"select\":return!n;case\"input\":switch(e.type){case\"button\":case\"checkbox\":case\"file\":case\"image\":case\"radio\":case\"submit\":return!1}return!e.disabled&&!e.readOnly;default:return/\\bneedsfocus\\b/.test(e.className)}},e.prototype.sendClick=function(e,t){var n,i;document.activeElement&&document.activeElement!==e&&document.activeElement.blur(),i=t.changedTouches[0],n=document.createEvent(\"MouseEvents\"),n.initMouseEvent(this.determineEventType(e),!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),n.forwardedTouchEvent=!0,e.dispatchEvent(n)},e.prototype.determineEventType=function(e){return n&&\"select\"===e.tagName.toLowerCase()?\"mousedown\":\"click\"},e.prototype.focus=function(e){var t;i&&e.setSelectionRange&&0!==e.type.indexOf(\"date\")&&\"time\"!==e.type&&\"month\"!==e.type?(t=e.value.length,e.setSelectionRange(t,t)):e.focus()},e.prototype.updateScrollParent=function(e){var t,n;if(t=e.fastClickScrollParent,!t||!t.contains(e)){n=e;do{if(n.scrollHeight>n.offsetHeight){t=n,e.fastClickScrollParent=n;break}n=n.parentElement}while(n)}t&&(t.fastClickLastScrollTop=t.scrollTop)},e.prototype.getTargetElementFromEventTarget=function(e){return e.nodeType===Node.TEXT_NODE?e.parentNode:e},e.prototype.onTouchStart=function(e){var t,n,a;if(e.targetTouches.length>1)return!0;if(t=this.getTargetElementFromEventTarget(e.target),n=e.targetTouches[0],i){if(a=window.getSelection(),a.rangeCount&&!a.isCollapsed)return!0;if(!r){if(n.identifier&&n.identifier===this.lastTouchIdentifier)return e.preventDefault(),!1;this.lastTouchIdentifier=n.identifier,this.updateScrollParent(t)}}return this.trackingClick=!0,this.trackingClickStart=e.timeStamp,this.targetElement=t,this.touchStartX=n.pageX,this.touchStartY=n.pageY,e.timeStamp-this.lastClickTime<this.tapDelay&&e.preventDefault(),!0},e.prototype.touchHasMoved=function(e){var t=e.changedTouches[0],n=this.touchBoundary;return Math.abs(t.pageX-this.touchStartX)>n||Math.abs(t.pageY-this.touchStartY)>n?!0:!1},e.prototype.onTouchMove=function(e){return this.trackingClick?((this.targetElement!==this.getTargetElementFromEventTarget(e.target)||this.touchHasMoved(e))&&(this.trackingClick=!1,this.targetElement=null),!0):!0},e.prototype.findControl=function(e){return void 0!==e.control?e.control:e.htmlFor?document.getElementById(e.htmlFor):e.querySelector(\"button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea\")},e.prototype.onTouchEnd=function(e){var t,o,s,l,c,d=this.targetElement;if(!this.trackingClick)return!0;if(e.timeStamp-this.lastClickTime<this.tapDelay)return this.cancelNextClick=!0,!0;if(e.timeStamp-this.trackingClickStart>this.tapTimeout)return!0;if(this.cancelNextClick=!1,this.lastClickTime=e.timeStamp,o=this.trackingClickStart,this.trackingClick=!1,this.trackingClickStart=0,a&&(c=e.changedTouches[0],d=document.elementFromPoint(c.pageX-window.pageXOffset,c.pageY-window.pageYOffset)||d,d.fastClickScrollParent=this.targetElement.fastClickScrollParent),s=d.tagName.toLowerCase(),\"label\"===s){if(t=this.findControl(d)){if(this.focus(d),n)return!1;d=t}}else if(this.needsFocus(d))return e.timeStamp-o>100||i&&window.top!==window&&\"input\"===s?(this.targetElement=null,!1):(this.focus(d),this.sendClick(d,e),i&&\"select\"===s||(this.targetElement=null,e.preventDefault()),!1);return i&&!r&&(l=d.fastClickScrollParent,l&&l.fastClickLastScrollTop!==l.scrollTop)?!0:(this.needsClick(d)||(e.preventDefault(),this.sendClick(d,e)),!1)},e.prototype.onTouchCancel=function(){this.trackingClick=!1,this.targetElement=null},e.prototype.onMouse=function(e){return this.targetElement?e.forwardedTouchEvent?!0:e.cancelable&&(!this.needsClick(this.targetElement)||this.cancelNextClick)?(e.stopImmediatePropagation?e.stopImmediatePropagation():e.propagationStopped=!0,e.stopPropagation(),e.preventDefault(),!1):!0:!0},e.prototype.onClick=function(e){var t;return this.trackingClick?(this.targetElement=null,this.trackingClick=!1,!0):\"submit\"===e.target.type&&0===e.detail?!0:(t=this.onMouse(e),t||(this.targetElement=null),t)},e.prototype.destroy=function(){var e=this.layer;n&&(e.removeEventListener(\"mouseover\",this.onMouse,!0),e.removeEventListener(\"mousedown\",this.onMouse,!0),e.removeEventListener(\"mouseup\",this.onMouse,!0)),e.removeEventListener(\"click\",this.onClick,!0),e.removeEventListener(\"touchstart\",this.onTouchStart,!1),e.removeEventListener(\"touchmove\",this.onTouchMove,!1),e.removeEventListener(\"touchend\",this.onTouchEnd,!1),e.removeEventListener(\"touchcancel\",this.onTouchCancel,!1)},e.notNeeded=function(e){var t,i,r,a;if(\"undefined\"==typeof window.ontouchstart)return!0;\nif(i=+(/Chrome\\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1]){if(!n)return!0;if(t=document.querySelector(\"meta[name=viewport]\")){if(-1!==t.content.indexOf(\"user-scalable=no\"))return!0;if(i>31&&document.documentElement.scrollWidth<=window.outerWidth)return!0}}if(o&&(r=navigator.userAgent.match(/Version\\/([0-9]*)\\.([0-9]*)/),r[1]>=10&&r[2]>=3&&(t=document.querySelector(\"meta[name=viewport]\")))){if(-1!==t.content.indexOf(\"user-scalable=no\"))return!0;if(document.documentElement.scrollWidth<=window.outerWidth)return!0}return\"none\"===e.style.msTouchAction||\"manipulation\"===e.style.touchAction?!0:(a=+(/Firefox\\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1],a>=27&&(t=document.querySelector(\"meta[name=viewport]\"),t&&(-1!==t.content.indexOf(\"user-scalable=no\")||document.documentElement.scrollWidth<=window.outerWidth))?!0:\"none\"===e.style.touchAction||\"manipulation\"===e.style.touchAction?!0:!1)},e.attach=function(t,n){return new e(t,n)},\"function\"==typeof define&&\"object\"==typeof define.amd&&define.amd?define(function(){return e}):\"undefined\"!=typeof module&&module.exports?(module.exports=e.attach,module.exports.FastClick=e):window.FastClick=e}(),function(e){\"function\"==typeof define&&define.amd?define([\"jquery\"],e):e(\"object\"==typeof exports?require(\"jquery\"):jQuery)}(function(e){var t=function(){if(e&&e.fn&&e.fn.select2&&e.fn.select2.amd)var t=e.fn.select2.amd;var t;return function(){if(!t||!t.requirejs){t?n=t:t={};var e,n,i;!function(t){function r(e,t){return C.call(e,t)}function a(e,t){var n,i,r,a,o,s,l,c,d,u,p,m=t&&t.split(\"/\"),g=b.map,h=g&&g[\"*\"]||{};if(e&&\".\"===e.charAt(0))if(t){for(e=e.split(\"/\"),o=e.length-1,b.nodeIdCompat&&y.test(e[o])&&(e[o]=e[o].replace(y,\"\")),e=m.slice(0,m.length-1).concat(e),d=0;d<e.length;d+=1)if(p=e[d],\".\"===p)e.splice(d,1),d-=1;else if(\"..\"===p){if(1===d&&(\"..\"===e[2]||\"..\"===e[0]))break;d>0&&(e.splice(d-1,2),d-=2)}e=e.join(\"/\")}else 0===e.indexOf(\"./\")&&(e=e.substring(2));if((m||h)&&g){for(n=e.split(\"/\"),d=n.length;d>0;d-=1){if(i=n.slice(0,d).join(\"/\"),m)for(u=m.length;u>0;u-=1)if(r=g[m.slice(0,u).join(\"/\")],r&&(r=r[i])){a=r,s=d;break}if(a)break;!l&&h&&h[i]&&(l=h[i],c=d)}!a&&l&&(a=l,s=c),a&&(n.splice(0,s,a),e=n.join(\"/\"))}return e}function o(e,n){return function(){var i=I.call(arguments,0);return\"string\"!=typeof i[0]&&1===i.length&&i.push(null),m.apply(t,i.concat([e,n]))}}function s(e){return function(t){return a(t,e)}}function l(e){return function(t){f[e]=t}}function c(e){if(r(_,e)){var n=_[e];delete _[e],v[e]=!0,p.apply(t,n)}if(!r(f,e)&&!r(v,e))throw new Error(\"No \"+e);return f[e]}function d(e){var t,n=e?e.indexOf(\"!\"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function u(e){return function(){return b&&b.config&&b.config[e]||{}}}var p,m,g,h,f={},_={},b={},v={},C=Object.prototype.hasOwnProperty,I=[].slice,y=/\\.js$/;g=function(e,t){var n,i=d(e),r=i[0];return e=i[1],r&&(r=a(r,t),n=c(r)),r?e=n&&n.normalize?n.normalize(e,s(t)):a(e,t):(e=a(e,t),i=d(e),r=i[0],e=i[1],r&&(n=c(r))),{f:r?r+\"!\"+e:e,n:e,pr:r,p:n}},h={require:function(e){return o(e)},exports:function(e){var t=f[e];return\"undefined\"!=typeof t?t:f[e]={}},module:function(e){return{id:e,uri:\"\",exports:f[e],config:u(e)}}},p=function(e,n,i,a){var s,d,u,p,m,b,C=[],I=typeof i;if(a=a||e,\"undefined\"===I||\"function\"===I){for(n=!n.length&&i.length?[\"require\",\"exports\",\"module\"]:n,m=0;m<n.length;m+=1)if(p=g(n[m],a),d=p.f,\"require\"===d)C[m]=h.require(e);else if(\"exports\"===d)C[m]=h.exports(e),b=!0;else if(\"module\"===d)s=C[m]=h.module(e);else if(r(f,d)||r(_,d)||r(v,d))C[m]=c(d);else{if(!p.p)throw new Error(e+\" missing \"+d);p.p.load(p.n,o(a,!0),l(d),{}),C[m]=f[d]}u=i?i.apply(f[e],C):void 0,e&&(s&&s.exports!==t&&s.exports!==f[e]?f[e]=s.exports:u===t&&b||(f[e]=u))}else e&&(f[e]=i)},e=n=m=function(e,n,i,r,a){if(\"string\"==typeof e)return h[e]?h[e](n):c(g(e,n).f);if(!e.splice){if(b=e,b.deps&&m(b.deps,b.callback),!n)return;n.splice?(e=n,n=i,i=null):e=t}return n=n||function(){},\"function\"==typeof i&&(i=r,r=a),r?p(t,e,n,i):setTimeout(function(){p(t,e,n,i)},4),m},m.config=function(e){return m(e)},e._defined=f,i=function(e,t,n){if(\"string\"!=typeof e)throw new Error(\"See almond README: incorrect module build, no module name\");t.splice||(n=t,t=[]),r(f,e)||r(_,e)||(_[e]=[e,t,n])},i.amd={jQuery:!0}}(),t.requirejs=e,t.require=n,t.define=i}}(),t.define(\"almond\",function(){}),t.define(\"jquery\",[],function(){var t=e||$;return null==t&&console&&console.error&&console.error(\"Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page.\"),t}),t.define(\"select2/utils\",[\"jquery\"],function(e){function t(e){var t=e.prototype,n=[];for(var i in t){var r=t[i];\"function\"==typeof r&&\"constructor\"!==i&&n.push(i)}return n}var n={};n.Extend=function(e,t){function n(){this.constructor=e}var i={}.hasOwnProperty;for(var r in t)i.call(t,r)&&(e[r]=t[r]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},n.Decorate=function(e,n){function i(){var t=Array.prototype.unshift,i=n.prototype.constructor.length,r=e.prototype.constructor;i>0&&(t.call(arguments,e.prototype.constructor),r=n.prototype.constructor),r.apply(this,arguments)}function r(){this.constructor=i}var a=t(n),o=t(e);n.displayName=e.displayName,i.prototype=new r;for(var s=0;s<o.length;s++){var l=o[s];i.prototype[l]=e.prototype[l]}for(var c=(function(e){var t=function(){};e in i.prototype&&(t=i.prototype[e]);var r=n.prototype[e];return function(){var e=Array.prototype.unshift;return e.call(arguments,t),r.apply(this,arguments)}}),d=0;d<a.length;d++){var u=a[d];i.prototype[u]=c(u)}return i};var i=function(){this.listeners={}};return i.prototype.on=function(e,t){this.listeners=this.listeners||{},e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t]},i.prototype.trigger=function(e){var t=Array.prototype.slice;this.listeners=this.listeners||{},e in this.listeners&&this.invoke(this.listeners[e],t.call(arguments,1)),\"*\"in this.listeners&&this.invoke(this.listeners[\"*\"],arguments)},i.prototype.invoke=function(e,t){for(var n=0,i=e.length;i>n;n++)e[n].apply(this,t)},n.Observable=i,n.generateChars=function(e){for(var t=\"\",n=0;e>n;n++){var i=Math.floor(36*Math.random());t+=i.toString(36)}return t},n.bind=function(e,t){return function(){e.apply(t,arguments)}},n._convertData=function(e){for(var t in e){var n=t.split(\"-\"),i=e;if(1!==n.length){for(var r=0;r<n.length;r++){var a=n[r];a=a.substring(0,1).toLowerCase()+a.substring(1),a in i||(i[a]={}),r==n.length-1&&(i[a]=e[t]),i=i[a]}delete e[t]}}return e},n.hasScroll=function(t,n){var i=e(n),r=n.style.overflowX,a=n.style.overflowY;return r!==a||\"hidden\"!==a&&\"visible\"!==a?\"scroll\"===r||\"scroll\"===a?!0:i.innerHeight()<n.scrollHeight||i.innerWidth()<n.scrollWidth:!1},n.escapeMarkup=function(e){var t={\"\\\\\":\"&#92;\",\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\",\"/\":\"&#47;\"};return\"string\"!=typeof e?e:String(e).replace(/[&<>\"'\\/\\\\]/g,function(e){return t[e]})},n.appendMany=function(t,n){if(\"1.7\"===e.fn.jquery.substr(0,3)){var i=e();e.map(n,function(e){i=i.add(e)}),n=i}t.append(n)},n}),t.define(\"select2/results\",[\"jquery\",\"./utils\"],function(e,t){function n(e,t,i){this.$element=e,this.data=i,this.options=t,n.__super__.constructor.call(this)}return t.Extend(n,t.Observable),n.prototype.render=function(){var t=e('<ul class=\"select2-results__options\" role=\"tree\"></ul>');return this.options.get(\"multiple\")&&t.attr(\"aria-multiselectable\",\"true\"),this.$results=t,t},n.prototype.clear=function(){this.$results.empty()},n.prototype.displayMessage=function(t){var n=this.options.get(\"escapeMarkup\");this.clear(),this.hideLoading();var i=e('<li role=\"treeitem\" aria-live=\"assertive\" class=\"select2-results__option\"></li>'),r=this.options.get(\"translations\").get(t.message);i.append(n(r(t.args))),i[0].className+=\" select2-results__message\",this.$results.append(i)},n.prototype.hideMessages=function(){this.$results.find(\".select2-results__message\").remove()},n.prototype.append=function(e){this.hideLoading();var t=[];if(null==e.results||0===e.results.length)return void(0===this.$results.children().length&&this.trigger(\"results:message\",{message:\"noResults\"}));e.results=this.sort(e.results);for(var n=0;n<e.results.length;n++){var i=e.results[n],r=this.option(i);t.push(r)}this.$results.append(t)},n.prototype.position=function(e,t){var n=t.find(\".select2-results\");n.append(e)},n.prototype.sort=function(e){var t=this.options.get(\"sorter\");return t(e)},n.prototype.setClasses=function(){var t=this;this.data.current(function(n){var i=e.map(n,function(e){return e.id.toString()}),r=t.$results.find(\".select2-results__option[aria-selected]\");r.each(function(){var t=e(this),n=e.data(this,\"data\"),r=\"\"+n.id;null!=n.element&&n.element.selected||null==n.element&&e.inArray(r,i)>-1?t.attr(\"aria-selected\",\"true\"):t.attr(\"aria-selected\",\"false\")});var a=r.filter(\"[aria-selected=true]\");a.length>0?a.first().trigger(\"mouseenter\"):r.first().trigger(\"mouseenter\")})},n.prototype.showLoading=function(e){this.hideLoading();var t=this.options.get(\"translations\").get(\"searching\"),n={disabled:!0,loading:!0,text:t(e)},i=this.option(n);i.className+=\" loading-results\",this.$results.prepend(i)},n.prototype.hideLoading=function(){this.$results.find(\".loading-results\").remove()},n.prototype.option=function(t){var n=document.createElement(\"li\");n.className=\"select2-results__option\";var i={role:\"treeitem\",\"aria-selected\":\"false\"};t.disabled&&(delete i[\"aria-selected\"],i[\"aria-disabled\"]=\"true\"),null==t.id&&delete i[\"aria-selected\"],null!=t._resultId&&(n.id=t._resultId),t.title&&(n.title=t.title),t.children&&(i.role=\"group\",i[\"aria-label\"]=t.text,delete i[\"aria-selected\"]);for(var r in i){var a=i[r];n.setAttribute(r,a)}if(t.children){var o=e(n),s=document.createElement(\"strong\");s.className=\"select2-results__group\";e(s);this.template(t,s);for(var l=[],c=0;c<t.children.length;c++){var d=t.children[c],u=this.option(d);l.push(u)}var p=e(\"<ul></ul>\",{\"class\":\"select2-results__options select2-results__options--nested\"});p.append(l),o.append(s),o.append(p)}else this.template(t,n);return e.data(n,\"data\",t),n},n.prototype.bind=function(t,n){var i=this,r=t.id+\"-results\";this.$results.attr(\"id\",r),t.on(\"results:all\",function(e){i.clear(),i.append(e.data),t.isOpen()&&i.setClasses()}),t.on(\"results:append\",function(e){i.append(e.data),t.isOpen()&&i.setClasses()}),t.on(\"query\",function(e){i.hideMessages(),i.showLoading(e)}),t.on(\"select\",function(){t.isOpen()&&i.setClasses()}),t.on(\"unselect\",function(){t.isOpen()&&i.setClasses()}),t.on(\"open\",function(){i.$results.attr(\"aria-expanded\",\"true\"),i.$results.attr(\"aria-hidden\",\"false\"),i.setClasses(),i.ensureHighlightVisible()}),t.on(\"close\",function(){i.$results.attr(\"aria-expanded\",\"false\"),i.$results.attr(\"aria-hidden\",\"true\"),i.$results.removeAttr(\"aria-activedescendant\")}),t.on(\"results:toggle\",function(){var e=i.getHighlightedResults();0!==e.length&&e.trigger(\"mouseup\")}),t.on(\"results:select\",function(){var e=i.getHighlightedResults();if(0!==e.length){var t=e.data(\"data\");\"true\"==e.attr(\"aria-selected\")?i.trigger(\"close\",{}):i.trigger(\"select\",{data:t})}}),t.on(\"results:previous\",function(){var e=i.getHighlightedResults(),t=i.$results.find(\"[aria-selected]\"),n=t.index(e);if(0!==n){var r=n-1;0===e.length&&(r=0);var a=t.eq(r);a.trigger(\"mouseenter\");var o=i.$results.offset().top,s=a.offset().top,l=i.$results.scrollTop()+(s-o);0===r?i.$results.scrollTop(0):0>s-o&&i.$results.scrollTop(l)}}),t.on(\"results:next\",function(){var e=i.getHighlightedResults(),t=i.$results.find(\"[aria-selected]\"),n=t.index(e),r=n+1;if(!(r>=t.length)){var a=t.eq(r);a.trigger(\"mouseenter\");var o=i.$results.offset().top+i.$results.outerHeight(!1),s=a.offset().top+a.outerHeight(!1),l=i.$results.scrollTop()+s-o;0===r?i.$results.scrollTop(0):s>o&&i.$results.scrollTop(l)}}),t.on(\"results:focus\",function(e){e.element.addClass(\"select2-results__option--highlighted\")}),t.on(\"results:message\",function(e){i.displayMessage(e)}),e.fn.mousewheel&&this.$results.on(\"mousewheel\",function(e){var t=i.$results.scrollTop(),n=i.$results.get(0).scrollHeight-i.$results.scrollTop()+e.deltaY,r=e.deltaY>0&&t-e.deltaY<=0,a=e.deltaY<0&&n<=i.$results.height();r?(i.$results.scrollTop(0),e.preventDefault(),e.stopPropagation()):a&&(i.$results.scrollTop(i.$results.get(0).scrollHeight-i.$results.height()),e.preventDefault(),e.stopPropagation())}),this.$results.on(\"mouseup\",\".select2-results__option[aria-selected]\",function(t){var n=e(this),r=n.data(\"data\");return\"true\"===n.attr(\"aria-selected\")?void(i.options.get(\"multiple\")?i.trigger(\"unselect\",{originalEvent:t,data:r}):i.trigger(\"close\",{})):void i.trigger(\"select\",{originalEvent:t,data:r})}),this.$results.on(\"mouseenter\",\".select2-results__option[aria-selected]\",function(t){var n=e(this).data(\"data\");i.getHighlightedResults().removeClass(\"select2-results__option--highlighted\"),i.trigger(\"results:focus\",{data:n,element:e(this)})})},n.prototype.getHighlightedResults=function(){var e=this.$results.find(\".select2-results__option--highlighted\");return e},n.prototype.destroy=function(){this.$results.remove()},n.prototype.ensureHighlightVisible=function(){var e=this.getHighlightedResults();if(0!==e.length){var t=this.$results.find(\"[aria-selected]\"),n=t.index(e),i=this.$results.offset().top,r=e.offset().top,a=this.$results.scrollTop()+(r-i),o=r-i;a-=2*e.outerHeight(!1),2>=n?this.$results.scrollTop(0):(o>this.$results.outerHeight()||0>o)&&this.$results.scrollTop(a)}},n.prototype.template=function(t,n){var i=this.options.get(\"templateResult\"),r=this.options.get(\"escapeMarkup\"),a=i(t,n);null==a?n.style.display=\"none\":\"string\"==typeof a?n.innerHTML=r(a):e(n).append(a)},n}),t.define(\"select2/keys\",[],function(){var e={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46};return e}),t.define(\"select2/selection/base\",[\"jquery\",\"../utils\",\"../keys\"],function(e,t,n){function i(e,t){this.$element=e,this.options=t,i.__super__.constructor.call(this)}return t.Extend(i,t.Observable),i.prototype.render=function(){var t=e('<span class=\"select2-selection\" role=\"combobox\"  aria-haspopup=\"true\" aria-expanded=\"false\"></span>');return this._tabindex=0,null!=this.$element.data(\"old-tabindex\")?this._tabindex=this.$element.data(\"old-tabindex\"):null!=this.$element.attr(\"tabindex\")&&(this._tabindex=this.$element.attr(\"tabindex\")),t.attr(\"title\",this.$element.attr(\"title\")),t.attr(\"tabindex\",this._tabindex),this.$selection=t,t},i.prototype.bind=function(e,t){var i=this,r=(e.id+\"-container\",e.id+\"-results\");this.container=e,this.$selection.on(\"focus\",function(e){i.trigger(\"focus\",e)}),this.$selection.on(\"blur\",function(e){i._handleBlur(e)}),this.$selection.on(\"keydown\",function(e){i.trigger(\"keypress\",e),e.which===n.SPACE&&e.preventDefault()}),e.on(\"results:focus\",function(e){i.$selection.attr(\"aria-activedescendant\",e.data._resultId)}),e.on(\"selection:update\",function(e){i.update(e.data)}),e.on(\"open\",function(){i.$selection.attr(\"aria-expanded\",\"true\"),i.$selection.attr(\"aria-owns\",r),i._attachCloseHandler(e)}),e.on(\"close\",function(){i.$selection.attr(\"aria-expanded\",\"false\"),i.$selection.removeAttr(\"aria-activedescendant\"),i.$selection.removeAttr(\"aria-owns\"),i.$selection.focus(),i._detachCloseHandler(e)}),e.on(\"enable\",function(){i.$selection.attr(\"tabindex\",i._tabindex)}),e.on(\"disable\",function(){i.$selection.attr(\"tabindex\",\"-1\")})},i.prototype._handleBlur=function(t){var n=this;window.setTimeout(function(){document.activeElement==n.$selection[0]||e.contains(n.$selection[0],document.activeElement)||n.trigger(\"blur\",t)},1)},i.prototype._attachCloseHandler=function(t){e(document.body).on(\"mousedown.select2.\"+t.id,function(t){var n=e(t.target),i=n.closest(\".select2\"),r=e(\".select2.select2-container--open\");r.each(function(){var t=e(this);if(this!=i[0]){var n=t.data(\"element\");n.select2(\"close\")}})})},i.prototype._detachCloseHandler=function(t){e(document.body).off(\"mousedown.select2.\"+t.id)},i.prototype.position=function(e,t){var n=t.find(\".selection\");n.append(e)},i.prototype.destroy=function(){this._detachCloseHandler(this.container)},i.prototype.update=function(e){throw new Error(\"The `update` method must be defined in child classes.\")},i}),t.define(\"select2/selection/single\",[\"jquery\",\"./base\",\"../utils\",\"../keys\"],function(e,t,n,i){function r(){r.__super__.constructor.apply(this,arguments)}return n.Extend(r,t),r.prototype.render=function(){var e=r.__super__.render.call(this);return e.addClass(\"select2-selection--single\"),e.html('<span class=\"select2-selection__rendered\"></span><span class=\"select2-selection__arrow\" role=\"presentation\"><b role=\"presentation\"></b></span>'),e},r.prototype.bind=function(e,t){var n=this;r.__super__.bind.apply(this,arguments);var i=e.id+\"-container\";this.$selection.find(\".select2-selection__rendered\").attr(\"id\",i),this.$selection.attr(\"aria-labelledby\",i),this.$selection.on(\"mousedown\",function(e){1===e.which&&n.trigger(\"toggle\",{originalEvent:e})}),this.$selection.on(\"focus\",function(e){}),this.$selection.on(\"blur\",function(e){}),e.on(\"selection:update\",function(e){n.update(e.data)})},r.prototype.clear=function(){this.$selection.find(\".select2-selection__rendered\").empty()},r.prototype.display=function(e,t){var n=this.options.get(\"templateSelection\"),i=this.options.get(\"escapeMarkup\");return i(n(e,t))},r.prototype.selectionContainer=function(){return e(\"<span></span>\")},r.prototype.update=function(e){if(0===e.length)return void this.clear();var t=e[0],n=this.$selection.find(\".select2-selection__rendered\"),i=this.display(t,n);n.empty().append(i),n.prop(\"title\",t.title||t.text)},r}),t.define(\"select2/selection/multiple\",[\"jquery\",\"./base\",\"../utils\"],function(e,t,n){function i(e,t){i.__super__.constructor.apply(this,arguments)}return n.Extend(i,t),i.prototype.render=function(){var e=i.__super__.render.call(this);return e.addClass(\"select2-selection--multiple\"),e.html('<ul class=\"select2-selection__rendered\"></ul>'),e},i.prototype.bind=function(t,n){var r=this;i.__super__.bind.apply(this,arguments),this.$selection.on(\"click\",function(e){r.trigger(\"toggle\",{originalEvent:e})}),this.$selection.on(\"click\",\".select2-selection__choice__remove\",function(t){if(!r.options.get(\"disabled\")){var n=e(this),i=n.parent(),a=i.data(\"data\");r.trigger(\"unselect\",{originalEvent:t,data:a})}})},i.prototype.clear=function(){this.$selection.find(\".select2-selection__rendered\").empty()},i.prototype.display=function(e,t){var n=this.options.get(\"templateSelection\"),i=this.options.get(\"escapeMarkup\");return i(n(e,t))},i.prototype.selectionContainer=function(){var t=e('<li class=\"select2-selection__choice\"><span class=\"select2-selection__choice__remove\" role=\"presentation\">&times;</span></li>');return t},i.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],i=0;i<e.length;i++){var r=e[i],a=this.selectionContainer(),o=this.display(r,a);a.append(o),a.prop(\"title\",r.title||r.text),a.data(\"data\",r),t.push(a)}var s=this.$selection.find(\".select2-selection__rendered\");n.appendMany(s,t)}},i}),t.define(\"select2/selection/placeholder\",[\"../utils\"],function(e){function t(e,t,n){this.placeholder=this.normalizePlaceholder(n.get(\"placeholder\")),e.call(this,t,n)}return t.prototype.normalizePlaceholder=function(e,t){return\"string\"==typeof t&&(t={id:\"\",text:t}),t},t.prototype.createPlaceholder=function(e,t){var n=this.selectionContainer();return n.html(this.display(t)),n.addClass(\"select2-selection__placeholder\").removeClass(\"select2-selection__choice\"),n},t.prototype.update=function(e,t){var n=1==t.length&&t[0].id!=this.placeholder.id,i=t.length>1;if(i||n)return e.call(this,t);this.clear();var r=this.createPlaceholder(this.placeholder);this.$selection.find(\".select2-selection__rendered\").append(r)},t}),t.define(\"select2/selection/allowClear\",[\"jquery\",\"../keys\"],function(e,t){function n(){}return n.prototype.bind=function(e,t,n){var i=this;e.call(this,t,n),null==this.placeholder&&this.options.get(\"debug\")&&window.console&&console.error&&console.error(\"Select2: The `allowClear` option should be used in combination with the `placeholder` option.\"),this.$selection.on(\"mousedown\",\".select2-selection__clear\",function(e){i._handleClear(e)}),t.on(\"keypress\",function(e){i._handleKeyboardClear(e,t)})},n.prototype._handleClear=function(e,t){if(!this.options.get(\"disabled\")){var n=this.$selection.find(\".select2-selection__clear\");if(0!==n.length){t.stopPropagation();for(var i=n.data(\"data\"),r=0;r<i.length;r++){var a={data:i[r]};if(this.trigger(\"unselect\",a),a.prevented)return}this.$element.val(this.placeholder.id).trigger(\"change\"),this.trigger(\"toggle\",{})}}},n.prototype._handleKeyboardClear=function(e,n,i){i.isOpen()||(n.which==t.DELETE||n.which==t.BACKSPACE)&&this._handleClear(n)},n.prototype.update=function(t,n){if(t.call(this,n),!(this.$selection.find(\".select2-selection__placeholder\").length>0||0===n.length)){var i=e('<span class=\"select2-selection__clear\">&times;</span>');i.data(\"data\",n),this.$selection.find(\".select2-selection__rendered\").prepend(i)}},n}),t.define(\"select2/selection/search\",[\"jquery\",\"../utils\",\"../keys\"],function(e,t,n){function i(e,t,n){e.call(this,t,n)}return i.prototype.render=function(t){var n=e('<li class=\"select2-search select2-search--inline\"><input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" role=\"textbox\" aria-autocomplete=\"list\" /></li>');this.$searchContainer=n,this.$search=n.find(\"input\");var i=t.call(this);return this._transferTabIndex(),i},i.prototype.bind=function(e,t,i){var r=this;e.call(this,t,i),t.on(\"open\",function(){r.$search.trigger(\"focus\")}),t.on(\"close\",function(){r.$search.val(\"\"),r.$search.removeAttr(\"aria-activedescendant\"),r.$search.trigger(\"focus\")}),t.on(\"enable\",function(){r.$search.prop(\"disabled\",!1),r._transferTabIndex()}),t.on(\"disable\",function(){r.$search.prop(\"disabled\",!0)}),t.on(\"focus\",function(e){r.$search.trigger(\"focus\")}),t.on(\"results:focus\",function(e){r.$search.attr(\"aria-activedescendant\",e.id)}),this.$selection.on(\"focusin\",\".select2-search--inline\",function(e){r.trigger(\"focus\",e)}),this.$selection.on(\"focusout\",\".select2-search--inline\",function(e){r._handleBlur(e)}),this.$selection.on(\"keydown\",\".select2-search--inline\",function(e){e.stopPropagation(),r.trigger(\"keypress\",e),r._keyUpPrevented=e.isDefaultPrevented();var t=e.which;if(t===n.BACKSPACE&&\"\"===r.$search.val()){var i=r.$searchContainer.prev(\".select2-selection__choice\");if(i.length>0){var a=i.data(\"data\");r.searchRemoveChoice(a),e.preventDefault()}}});var a=document.documentMode,o=a&&11>=a;this.$selection.on(\"input.searchcheck\",\".select2-search--inline\",function(e){return o?void r.$selection.off(\"input.search input.searchcheck\"):void r.$selection.off(\"keyup.search\")}),this.$selection.on(\"keyup.search input.search\",\".select2-search--inline\",function(e){if(o&&\"input\"===e.type)return void r.$selection.off(\"input.search input.searchcheck\");var t=e.which;t!=n.SHIFT&&t!=n.CTRL&&t!=n.ALT&&t!=n.TAB&&r.handleSearch(e)})},i.prototype._transferTabIndex=function(e){this.$search.attr(\"tabindex\",this.$selection.attr(\"tabindex\")),this.$selection.attr(\"tabindex\",\"-1\")},i.prototype.createPlaceholder=function(e,t){this.$search.attr(\"placeholder\",t.text)},i.prototype.update=function(e,t){var n=this.$search[0]==document.activeElement;this.$search.attr(\"placeholder\",\"\"),e.call(this,t),this.$selection.find(\".select2-selection__rendered\").append(this.$searchContainer),this.resizeSearch(),n&&this.$search.focus()},i.prototype.handleSearch=function(){if(this.resizeSearch(),!this._keyUpPrevented){var e=this.$search.val();this.trigger(\"query\",{term:e})}this._keyUpPrevented=!1},i.prototype.searchRemoveChoice=function(e,t){this.trigger(\"unselect\",{data:t}),this.$search.val(t.text),this.handleSearch()},i.prototype.resizeSearch=function(){this.$search.css(\"width\",\"25px\");var e=\"\";if(\"\"!==this.$search.attr(\"placeholder\"))e=this.$selection.find(\".select2-selection__rendered\").innerWidth();else{var t=this.$search.val().length+1;e=.75*t+\"em\"}this.$search.css(\"width\",e)},i}),t.define(\"select2/selection/eventRelay\",[\"jquery\"],function(e){function t(){}return t.prototype.bind=function(t,n,i){var r=this,a=[\"open\",\"opening\",\"close\",\"closing\",\"select\",\"selecting\",\"unselect\",\"unselecting\"],o=[\"opening\",\"closing\",\"selecting\",\"unselecting\"];t.call(this,n,i),n.on(\"*\",function(t,n){if(-1!==e.inArray(t,a)){n=n||{};var i=e.Event(\"select2:\"+t,{params:n});r.$element.trigger(i),-1!==e.inArray(t,o)&&(n.prevented=i.isDefaultPrevented())}})},t}),t.define(\"select2/translation\",[\"jquery\",\"require\"],function(e,t){function n(e){this.dict=e||{}}return n.prototype.all=function(){return this.dict},n.prototype.get=function(e){return this.dict[e]},n.prototype.extend=function(t){this.dict=e.extend({},t.all(),this.dict)},n._cache={},n.loadPath=function(e){if(!(e in n._cache)){var i=t(e);n._cache[e]=i}return new n(n._cache[e])},n}),t.define(\"select2/diacritics\",[],function(){var e={\"Ⓐ\":\"A\",\"Ａ\":\"A\",\"À\":\"A\",\"Á\":\"A\",\"Â\":\"A\",\"Ầ\":\"A\",\"Ấ\":\"A\",\"Ẫ\":\"A\",\"Ẩ\":\"A\",\"Ã\":\"A\",\"Ā\":\"A\",\"Ă\":\"A\",\"Ằ\":\"A\",\"Ắ\":\"A\",\"Ẵ\":\"A\",\"Ẳ\":\"A\",\"Ȧ\":\"A\",\"Ǡ\":\"A\",\"Ä\":\"A\",\"Ǟ\":\"A\",\"Ả\":\"A\",\"Å\":\"A\",\"Ǻ\":\"A\",\"Ǎ\":\"A\",\"Ȁ\":\"A\",\"Ȃ\":\"A\",\"Ạ\":\"A\",\"Ậ\":\"A\",\"Ặ\":\"A\",\"Ḁ\":\"A\",\"Ą\":\"A\",\"Ⱥ\":\"A\",\"Ɐ\":\"A\",\"Ꜳ\":\"AA\",\"Æ\":\"AE\",\"Ǽ\":\"AE\",\"Ǣ\":\"AE\",\"Ꜵ\":\"AO\",\"Ꜷ\":\"AU\",\"Ꜹ\":\"AV\",\"Ꜻ\":\"AV\",\"Ꜽ\":\"AY\",\"Ⓑ\":\"B\",\"Ｂ\":\"B\",\"Ḃ\":\"B\",\"Ḅ\":\"B\",\"Ḇ\":\"B\",\"Ƀ\":\"B\",\"Ƃ\":\"B\",\"Ɓ\":\"B\",\"Ⓒ\":\"C\",\"Ｃ\":\"C\",\"Ć\":\"C\",\"Ĉ\":\"C\",\"Ċ\":\"C\",\"Č\":\"C\",\"Ç\":\"C\",\"Ḉ\":\"C\",\"Ƈ\":\"C\",\"Ȼ\":\"C\",\"Ꜿ\":\"C\",\"Ⓓ\":\"D\",\"Ｄ\":\"D\",\"Ḋ\":\"D\",\"Ď\":\"D\",\"Ḍ\":\"D\",\"Ḑ\":\"D\",\"Ḓ\":\"D\",\"Ḏ\":\"D\",\"Đ\":\"D\",\"Ƌ\":\"D\",\"Ɗ\":\"D\",\"Ɖ\":\"D\",\"Ꝺ\":\"D\",\"Ǳ\":\"DZ\",\"Ǆ\":\"DZ\",\"ǲ\":\"Dz\",\"ǅ\":\"Dz\",\"Ⓔ\":\"E\",\"Ｅ\":\"E\",\"È\":\"E\",\"É\":\"E\",\"Ê\":\"E\",\"Ề\":\"E\",\"Ế\":\"E\",\"Ễ\":\"E\",\"Ể\":\"E\",\"Ẽ\":\"E\",\"Ē\":\"E\",\"Ḕ\":\"E\",\"Ḗ\":\"E\",\"Ĕ\":\"E\",\"Ė\":\"E\",\"Ë\":\"E\",\"Ẻ\":\"E\",\"Ě\":\"E\",\"Ȅ\":\"E\",\"Ȇ\":\"E\",\"Ẹ\":\"E\",\"Ệ\":\"E\",\"Ȩ\":\"E\",\"Ḝ\":\"E\",\"Ę\":\"E\",\"Ḙ\":\"E\",\"Ḛ\":\"E\",\"Ɛ\":\"E\",\"Ǝ\":\"E\",\"Ⓕ\":\"F\",\"Ｆ\":\"F\",\"Ḟ\":\"F\",\"Ƒ\":\"F\",\"Ꝼ\":\"F\",\"Ⓖ\":\"G\",\"Ｇ\":\"G\",\"Ǵ\":\"G\",\"Ĝ\":\"G\",\"Ḡ\":\"G\",\"Ğ\":\"G\",\"Ġ\":\"G\",\"Ǧ\":\"G\",\"Ģ\":\"G\",\"Ǥ\":\"G\",\"Ɠ\":\"G\",\"Ꞡ\":\"G\",\"Ᵹ\":\"G\",\"Ꝿ\":\"G\",\"Ⓗ\":\"H\",\"Ｈ\":\"H\",\"Ĥ\":\"H\",\"Ḣ\":\"H\",\"Ḧ\":\"H\",\"Ȟ\":\"H\",\"Ḥ\":\"H\",\"Ḩ\":\"H\",\"Ḫ\":\"H\",\"Ħ\":\"H\",\"Ⱨ\":\"H\",\"Ⱶ\":\"H\",\"Ɥ\":\"H\",\"Ⓘ\":\"I\",\"Ｉ\":\"I\",\"Ì\":\"I\",\"Í\":\"I\",\"Î\":\"I\",\"Ĩ\":\"I\",\"Ī\":\"I\",\"Ĭ\":\"I\",\"İ\":\"I\",\"Ï\":\"I\",\"Ḯ\":\"I\",\"Ỉ\":\"I\",\"Ǐ\":\"I\",\"Ȉ\":\"I\",\"Ȋ\":\"I\",\"Ị\":\"I\",\"Į\":\"I\",\"Ḭ\":\"I\",\"Ɨ\":\"I\",\"Ⓙ\":\"J\",\"Ｊ\":\"J\",\"Ĵ\":\"J\",\"Ɉ\":\"J\",\"Ⓚ\":\"K\",\"Ｋ\":\"K\",\"Ḱ\":\"K\",\"Ǩ\":\"K\",\"Ḳ\":\"K\",\"Ķ\":\"K\",\"Ḵ\":\"K\",\"Ƙ\":\"K\",\"Ⱪ\":\"K\",\"Ꝁ\":\"K\",\"Ꝃ\":\"K\",\"Ꝅ\":\"K\",\"Ꞣ\":\"K\",\"Ⓛ\":\"L\",\"Ｌ\":\"L\",\"Ŀ\":\"L\",\"Ĺ\":\"L\",\"Ľ\":\"L\",\"Ḷ\":\"L\",\"Ḹ\":\"L\",\"Ļ\":\"L\",\"Ḽ\":\"L\",\"Ḻ\":\"L\",\"Ł\":\"L\",\"Ƚ\":\"L\",\"Ɫ\":\"L\",\"Ⱡ\":\"L\",\"Ꝉ\":\"L\",\"Ꝇ\":\"L\",\"Ꞁ\":\"L\",\"Ǉ\":\"LJ\",\"ǈ\":\"Lj\",\"Ⓜ\":\"M\",\"Ｍ\":\"M\",\"Ḿ\":\"M\",\"Ṁ\":\"M\",\"Ṃ\":\"M\",\"Ɱ\":\"M\",\"Ɯ\":\"M\",\"Ⓝ\":\"N\",\"Ｎ\":\"N\",\"Ǹ\":\"N\",\"Ń\":\"N\",\"Ñ\":\"N\",\"Ṅ\":\"N\",\"Ň\":\"N\",\"Ṇ\":\"N\",\"Ņ\":\"N\",\"Ṋ\":\"N\",\"Ṉ\":\"N\",\"Ƞ\":\"N\",\"Ɲ\":\"N\",\"Ꞑ\":\"N\",\"Ꞥ\":\"N\",\"Ǌ\":\"NJ\",\"ǋ\":\"Nj\",\"Ⓞ\":\"O\",\"Ｏ\":\"O\",\"Ò\":\"O\",\"Ó\":\"O\",\"Ô\":\"O\",\"Ồ\":\"O\",\"Ố\":\"O\",\"Ỗ\":\"O\",\"Ổ\":\"O\",\"Õ\":\"O\",\"Ṍ\":\"O\",\"Ȭ\":\"O\",\"Ṏ\":\"O\",\"Ō\":\"O\",\"Ṑ\":\"O\",\"Ṓ\":\"O\",\"Ŏ\":\"O\",\"Ȯ\":\"O\",\"Ȱ\":\"O\",\"Ö\":\"O\",\"Ȫ\":\"O\",\"Ỏ\":\"O\",\"Ő\":\"O\",\"Ǒ\":\"O\",\"Ȍ\":\"O\",\"Ȏ\":\"O\",\"Ơ\":\"O\",\"Ờ\":\"O\",\"Ớ\":\"O\",\"Ỡ\":\"O\",\"Ở\":\"O\",\"Ợ\":\"O\",\"Ọ\":\"O\",\"Ộ\":\"O\",\"Ǫ\":\"O\",\"Ǭ\":\"O\",\"Ø\":\"O\",\"Ǿ\":\"O\",\"Ɔ\":\"O\",\"Ɵ\":\"O\",\"Ꝋ\":\"O\",\"Ꝍ\":\"O\",\"Ƣ\":\"OI\",\"Ꝏ\":\"OO\",\"Ȣ\":\"OU\",\"Ⓟ\":\"P\",\"Ｐ\":\"P\",\"Ṕ\":\"P\",\"Ṗ\":\"P\",\"Ƥ\":\"P\",\"Ᵽ\":\"P\",\"Ꝑ\":\"P\",\"Ꝓ\":\"P\",\"Ꝕ\":\"P\",\"Ⓠ\":\"Q\",\"Ｑ\":\"Q\",\"Ꝗ\":\"Q\",\"Ꝙ\":\"Q\",\"Ɋ\":\"Q\",\"Ⓡ\":\"R\",\"Ｒ\":\"R\",\"Ŕ\":\"R\",\"Ṙ\":\"R\",\"Ř\":\"R\",\"Ȑ\":\"R\",\"Ȓ\":\"R\",\"Ṛ\":\"R\",\"Ṝ\":\"R\",\"Ŗ\":\"R\",\"Ṟ\":\"R\",\"Ɍ\":\"R\",\"Ɽ\":\"R\",\"Ꝛ\":\"R\",\"Ꞧ\":\"R\",\"Ꞃ\":\"R\",\"Ⓢ\":\"S\",\"Ｓ\":\"S\",\"ẞ\":\"S\",\"Ś\":\"S\",\"Ṥ\":\"S\",\"Ŝ\":\"S\",\"Ṡ\":\"S\",\"Š\":\"S\",\"Ṧ\":\"S\",\"Ṣ\":\"S\",\"Ṩ\":\"S\",\"Ș\":\"S\",\"Ş\":\"S\",\"Ȿ\":\"S\",\"Ꞩ\":\"S\",\"Ꞅ\":\"S\",\"Ⓣ\":\"T\",\"Ｔ\":\"T\",\"Ṫ\":\"T\",\"Ť\":\"T\",\"Ṭ\":\"T\",\"Ț\":\"T\",\"Ţ\":\"T\",\"Ṱ\":\"T\",\"Ṯ\":\"T\",\"Ŧ\":\"T\",\"Ƭ\":\"T\",\"Ʈ\":\"T\",\"Ⱦ\":\"T\",\"Ꞇ\":\"T\",\"Ꜩ\":\"TZ\",\"Ⓤ\":\"U\",\"Ｕ\":\"U\",\"Ù\":\"U\",\"Ú\":\"U\",\"Û\":\"U\",\"Ũ\":\"U\",\"Ṹ\":\"U\",\"Ū\":\"U\",\"Ṻ\":\"U\",\"Ŭ\":\"U\",\"Ü\":\"U\",\"Ǜ\":\"U\",\"Ǘ\":\"U\",\"Ǖ\":\"U\",\"Ǚ\":\"U\",\"Ủ\":\"U\",\"Ů\":\"U\",\"Ű\":\"U\",\"Ǔ\":\"U\",\"Ȕ\":\"U\",\"Ȗ\":\"U\",\"Ư\":\"U\",\"Ừ\":\"U\",\"Ứ\":\"U\",\"Ữ\":\"U\",\"Ử\":\"U\",\"Ự\":\"U\",\"Ụ\":\"U\",\"Ṳ\":\"U\",\"Ų\":\"U\",\"Ṷ\":\"U\",\"Ṵ\":\"U\",\"Ʉ\":\"U\",\"Ⓥ\":\"V\",\"Ｖ\":\"V\",\"Ṽ\":\"V\",\"Ṿ\":\"V\",\"Ʋ\":\"V\",\"Ꝟ\":\"V\",\"Ʌ\":\"V\",\"Ꝡ\":\"VY\",\"Ⓦ\":\"W\",\"Ｗ\":\"W\",\"Ẁ\":\"W\",\"Ẃ\":\"W\",\"Ŵ\":\"W\",\"Ẇ\":\"W\",\"Ẅ\":\"W\",\"Ẉ\":\"W\",\"Ⱳ\":\"W\",\"Ⓧ\":\"X\",\"Ｘ\":\"X\",\"Ẋ\":\"X\",\"Ẍ\":\"X\",\"Ⓨ\":\"Y\",\"Ｙ\":\"Y\",\"Ỳ\":\"Y\",\"Ý\":\"Y\",\"Ŷ\":\"Y\",\"Ỹ\":\"Y\",\"Ȳ\":\"Y\",\"Ẏ\":\"Y\",\"Ÿ\":\"Y\",\"Ỷ\":\"Y\",\"Ỵ\":\"Y\",\"Ƴ\":\"Y\",\"Ɏ\":\"Y\",\"Ỿ\":\"Y\",\"Ⓩ\":\"Z\",\"Ｚ\":\"Z\",\"Ź\":\"Z\",\"Ẑ\":\"Z\",\"Ż\":\"Z\",\"Ž\":\"Z\",\"Ẓ\":\"Z\",\"Ẕ\":\"Z\",\"Ƶ\":\"Z\",\"Ȥ\":\"Z\",\"Ɀ\":\"Z\",\"Ⱬ\":\"Z\",\"Ꝣ\":\"Z\",\"ⓐ\":\"a\",\"ａ\":\"a\",\"ẚ\":\"a\",\"à\":\"a\",\"á\":\"a\",\"â\":\"a\",\"ầ\":\"a\",\"ấ\":\"a\",\"ẫ\":\"a\",\"ẩ\":\"a\",\"ã\":\"a\",\"ā\":\"a\",\"ă\":\"a\",\"ằ\":\"a\",\"ắ\":\"a\",\"ẵ\":\"a\",\"ẳ\":\"a\",\"ȧ\":\"a\",\"ǡ\":\"a\",\"ä\":\"a\",\"ǟ\":\"a\",\"ả\":\"a\",\"å\":\"a\",\"ǻ\":\"a\",\"ǎ\":\"a\",\"ȁ\":\"a\",\"ȃ\":\"a\",\"ạ\":\"a\",\"ậ\":\"a\",\"ặ\":\"a\",\"ḁ\":\"a\",\"ą\":\"a\",\"ⱥ\":\"a\",\"ɐ\":\"a\",\"ꜳ\":\"aa\",\"æ\":\"ae\",\"ǽ\":\"ae\",\"ǣ\":\"ae\",\"ꜵ\":\"ao\",\"ꜷ\":\"au\",\"ꜹ\":\"av\",\"ꜻ\":\"av\",\"ꜽ\":\"ay\",\"ⓑ\":\"b\",\"ｂ\":\"b\",\"ḃ\":\"b\",\"ḅ\":\"b\",\"ḇ\":\"b\",\"ƀ\":\"b\",\"ƃ\":\"b\",\"ɓ\":\"b\",\"ⓒ\":\"c\",\"ｃ\":\"c\",\"ć\":\"c\",\"ĉ\":\"c\",\"ċ\":\"c\",\"č\":\"c\",\"ç\":\"c\",\"ḉ\":\"c\",\"ƈ\":\"c\",\"ȼ\":\"c\",\"ꜿ\":\"c\",\"ↄ\":\"c\",\"ⓓ\":\"d\",\"ｄ\":\"d\",\"ḋ\":\"d\",\"ď\":\"d\",\"ḍ\":\"d\",\"ḑ\":\"d\",\"ḓ\":\"d\",\"ḏ\":\"d\",\"đ\":\"d\",\"ƌ\":\"d\",\"ɖ\":\"d\",\"ɗ\":\"d\",\"ꝺ\":\"d\",\"ǳ\":\"dz\",\"ǆ\":\"dz\",\"ⓔ\":\"e\",\"ｅ\":\"e\",\"è\":\"e\",\"é\":\"e\",\"ê\":\"e\",\"ề\":\"e\",\"ế\":\"e\",\"ễ\":\"e\",\"ể\":\"e\",\"ẽ\":\"e\",\"ē\":\"e\",\"ḕ\":\"e\",\"ḗ\":\"e\",\"ĕ\":\"e\",\"ė\":\"e\",\"ë\":\"e\",\"ẻ\":\"e\",\"ě\":\"e\",\"ȅ\":\"e\",\"ȇ\":\"e\",\"ẹ\":\"e\",\"ệ\":\"e\",\"ȩ\":\"e\",\"ḝ\":\"e\",\"ę\":\"e\",\"ḙ\":\"e\",\"ḛ\":\"e\",\"ɇ\":\"e\",\"ɛ\":\"e\",\"ǝ\":\"e\",\"ⓕ\":\"f\",\"ｆ\":\"f\",\"ḟ\":\"f\",\"ƒ\":\"f\",\"ꝼ\":\"f\",\"ⓖ\":\"g\",\"ｇ\":\"g\",\"ǵ\":\"g\",\"ĝ\":\"g\",\"ḡ\":\"g\",\"ğ\":\"g\",\"ġ\":\"g\",\"ǧ\":\"g\",\"ģ\":\"g\",\"ǥ\":\"g\",\"ɠ\":\"g\",\"ꞡ\":\"g\",\"ᵹ\":\"g\",\"ꝿ\":\"g\",\"ⓗ\":\"h\",\"ｈ\":\"h\",\"ĥ\":\"h\",\"ḣ\":\"h\",\"ḧ\":\"h\",\"ȟ\":\"h\",\"ḥ\":\"h\",\"ḩ\":\"h\",\"ḫ\":\"h\",\"ẖ\":\"h\",\"ħ\":\"h\",\"ⱨ\":\"h\",\"ⱶ\":\"h\",\"ɥ\":\"h\",\"ƕ\":\"hv\",\"ⓘ\":\"i\",\"ｉ\":\"i\",\"ì\":\"i\",\"í\":\"i\",\"î\":\"i\",\"ĩ\":\"i\",\"ī\":\"i\",\"ĭ\":\"i\",\"ï\":\"i\",\"ḯ\":\"i\",\"ỉ\":\"i\",\"ǐ\":\"i\",\"ȉ\":\"i\",\"ȋ\":\"i\",\"ị\":\"i\",\"į\":\"i\",\"ḭ\":\"i\",\"ɨ\":\"i\",\"ı\":\"i\",\"ⓙ\":\"j\",\"ｊ\":\"j\",\"ĵ\":\"j\",\"ǰ\":\"j\",\"ɉ\":\"j\",\"ⓚ\":\"k\",\"ｋ\":\"k\",\"ḱ\":\"k\",\"ǩ\":\"k\",\"ḳ\":\"k\",\"ķ\":\"k\",\"ḵ\":\"k\",\"ƙ\":\"k\",\"ⱪ\":\"k\",\"ꝁ\":\"k\",\"ꝃ\":\"k\",\"ꝅ\":\"k\",\"ꞣ\":\"k\",\"ⓛ\":\"l\",\"ｌ\":\"l\",\"ŀ\":\"l\",\"ĺ\":\"l\",\"ľ\":\"l\",\"ḷ\":\"l\",\"ḹ\":\"l\",\"ļ\":\"l\",\"ḽ\":\"l\",\"ḻ\":\"l\",\"ſ\":\"l\",\"ł\":\"l\",\"ƚ\":\"l\",\"ɫ\":\"l\",\"ⱡ\":\"l\",\"ꝉ\":\"l\",\"ꞁ\":\"l\",\"ꝇ\":\"l\",\"ǉ\":\"lj\",\"ⓜ\":\"m\",\"ｍ\":\"m\",\"ḿ\":\"m\",\"ṁ\":\"m\",\"ṃ\":\"m\",\"ɱ\":\"m\",\"ɯ\":\"m\",\"ⓝ\":\"n\",\"ｎ\":\"n\",\"ǹ\":\"n\",\"ń\":\"n\",\"ñ\":\"n\",\"ṅ\":\"n\",\"ň\":\"n\",\"ṇ\":\"n\",\"ņ\":\"n\",\"ṋ\":\"n\",\"ṉ\":\"n\",\"ƞ\":\"n\",\"ɲ\":\"n\",\"ŉ\":\"n\",\"ꞑ\":\"n\",\"ꞥ\":\"n\",\"ǌ\":\"nj\",\"ⓞ\":\"o\",\"ｏ\":\"o\",\"ò\":\"o\",\"ó\":\"o\",\"ô\":\"o\",\"ồ\":\"o\",\"ố\":\"o\",\"ỗ\":\"o\",\"ổ\":\"o\",\"õ\":\"o\",\"ṍ\":\"o\",\"ȭ\":\"o\",\"ṏ\":\"o\",\"ō\":\"o\",\"ṑ\":\"o\",\"ṓ\":\"o\",\"ŏ\":\"o\",\"ȯ\":\"o\",\"ȱ\":\"o\",\"ö\":\"o\",\"ȫ\":\"o\",\"ỏ\":\"o\",\"ő\":\"o\",\"ǒ\":\"o\",\"ȍ\":\"o\",\"ȏ\":\"o\",\"ơ\":\"o\",\"ờ\":\"o\",\"ớ\":\"o\",\"ỡ\":\"o\",\"ở\":\"o\",\"ợ\":\"o\",\"ọ\":\"o\",\"ộ\":\"o\",\"ǫ\":\"o\",\"ǭ\":\"o\",\"ø\":\"o\",\"ǿ\":\"o\",\"ɔ\":\"o\",\"ꝋ\":\"o\",\"ꝍ\":\"o\",\"ɵ\":\"o\",\"ƣ\":\"oi\",\"ȣ\":\"ou\",\"ꝏ\":\"oo\",\"ⓟ\":\"p\",\"ｐ\":\"p\",\"ṕ\":\"p\",\"ṗ\":\"p\",\"ƥ\":\"p\",\"ᵽ\":\"p\",\"ꝑ\":\"p\",\"ꝓ\":\"p\",\"ꝕ\":\"p\",\"ⓠ\":\"q\",\"ｑ\":\"q\",\"ɋ\":\"q\",\"ꝗ\":\"q\",\"ꝙ\":\"q\",\"ⓡ\":\"r\",\"ｒ\":\"r\",\"ŕ\":\"r\",\"ṙ\":\"r\",\"ř\":\"r\",\"ȑ\":\"r\",\"ȓ\":\"r\",\"ṛ\":\"r\",\"ṝ\":\"r\",\"ŗ\":\"r\",\"ṟ\":\"r\",\"ɍ\":\"r\",\"ɽ\":\"r\",\"ꝛ\":\"r\",\"ꞧ\":\"r\",\"ꞃ\":\"r\",\"ⓢ\":\"s\",\"ｓ\":\"s\",\"ß\":\"s\",\"ś\":\"s\",\"ṥ\":\"s\",\"ŝ\":\"s\",\"ṡ\":\"s\",\"š\":\"s\",\"ṧ\":\"s\",\"ṣ\":\"s\",\"ṩ\":\"s\",\"ș\":\"s\",\"ş\":\"s\",\"ȿ\":\"s\",\"ꞩ\":\"s\",\"ꞅ\":\"s\",\"ẛ\":\"s\",\"ⓣ\":\"t\",\"ｔ\":\"t\",\"ṫ\":\"t\",\"ẗ\":\"t\",\"ť\":\"t\",\"ṭ\":\"t\",\"ț\":\"t\",\"ţ\":\"t\",\"ṱ\":\"t\",\"ṯ\":\"t\",\"ŧ\":\"t\",\"ƭ\":\"t\",\"ʈ\":\"t\",\"ⱦ\":\"t\",\"ꞇ\":\"t\",\"ꜩ\":\"tz\",\"ⓤ\":\"u\",\"ｕ\":\"u\",\"ù\":\"u\",\"ú\":\"u\",\"û\":\"u\",\"ũ\":\"u\",\"ṹ\":\"u\",\"ū\":\"u\",\"ṻ\":\"u\",\"ŭ\":\"u\",\"ü\":\"u\",\"ǜ\":\"u\",\"ǘ\":\"u\",\"ǖ\":\"u\",\"ǚ\":\"u\",\"ủ\":\"u\",\"ů\":\"u\",\"ű\":\"u\",\"ǔ\":\"u\",\"ȕ\":\"u\",\"ȗ\":\"u\",\"ư\":\"u\",\"ừ\":\"u\",\"ứ\":\"u\",\"ữ\":\"u\",\"ử\":\"u\",\"ự\":\"u\",\"ụ\":\"u\",\"ṳ\":\"u\",\"ų\":\"u\",\"ṷ\":\"u\",\"ṵ\":\"u\",\"ʉ\":\"u\",\"ⓥ\":\"v\",\"ｖ\":\"v\",\"ṽ\":\"v\",\"ṿ\":\"v\",\"ʋ\":\"v\",\"ꝟ\":\"v\",\"ʌ\":\"v\",\"ꝡ\":\"vy\",\"ⓦ\":\"w\",\"ｗ\":\"w\",\"ẁ\":\"w\",\"ẃ\":\"w\",\"ŵ\":\"w\",\"ẇ\":\"w\",\"ẅ\":\"w\",\"ẘ\":\"w\",\"ẉ\":\"w\",\"ⱳ\":\"w\",\"ⓧ\":\"x\",\"ｘ\":\"x\",\"ẋ\":\"x\",\"ẍ\":\"x\",\"ⓨ\":\"y\",\"ｙ\":\"y\",\"ỳ\":\"y\",\"ý\":\"y\",\"ŷ\":\"y\",\"ỹ\":\"y\",\"ȳ\":\"y\",\"ẏ\":\"y\",\"ÿ\":\"y\",\"ỷ\":\"y\",\"ẙ\":\"y\",\"ỵ\":\"y\",\"ƴ\":\"y\",\"ɏ\":\"y\",\"ỿ\":\"y\",\"ⓩ\":\"z\",\"ｚ\":\"z\",\"ź\":\"z\",\"ẑ\":\"z\",\"ż\":\"z\",\"ž\":\"z\",\"ẓ\":\"z\",\"ẕ\":\"z\",\"ƶ\":\"z\",\"ȥ\":\"z\",\"ɀ\":\"z\",\"ⱬ\":\"z\",\"ꝣ\":\"z\",\"Ά\":\"Α\",\"Έ\":\"Ε\",\"Ή\":\"Η\",\"Ί\":\"Ι\",\"Ϊ\":\"Ι\",\"Ό\":\"Ο\",\"Ύ\":\"Υ\",\"Ϋ\":\"Υ\",\"Ώ\":\"Ω\",\"ά\":\"α\",\"έ\":\"ε\",\"ή\":\"η\",\"ί\":\"ι\",\"ϊ\":\"ι\",\"ΐ\":\"ι\",\"ό\":\"ο\",\"ύ\":\"υ\",\"ϋ\":\"υ\",\"ΰ\":\"υ\",\"ω\":\"ω\",\"ς\":\"σ\"};return e}),t.define(\"select2/data/base\",[\"../utils\"],function(e){function t(e,n){t.__super__.constructor.call(this)}return e.Extend(t,e.Observable),t.prototype.current=function(e){throw new Error(\"The `current` method must be defined in child classes.\");\n},t.prototype.query=function(e,t){throw new Error(\"The `query` method must be defined in child classes.\")},t.prototype.bind=function(e,t){},t.prototype.destroy=function(){},t.prototype.generateResultId=function(t,n){var i=t.id+\"-result-\";return i+=e.generateChars(4),i+=null!=n.id?\"-\"+n.id.toString():\"-\"+e.generateChars(4)},t}),t.define(\"select2/data/select\",[\"./base\",\"../utils\",\"jquery\"],function(e,t,n){function i(e,t){this.$element=e,this.options=t,i.__super__.constructor.call(this)}return t.Extend(i,e),i.prototype.current=function(e){var t=[],i=this;this.$element.find(\":selected\").each(function(){var e=n(this),r=i.item(e);t.push(r)}),e(t)},i.prototype.select=function(e){var t=this;if(e.selected=!0,n(e.element).is(\"option\"))return e.element.selected=!0,void this.$element.trigger(\"change\");if(this.$element.prop(\"multiple\"))this.current(function(i){var r=[];e=[e],e.push.apply(e,i);for(var a=0;a<e.length;a++){var o=e[a].id;-1===n.inArray(o,r)&&r.push(o)}t.$element.val(r),t.$element.trigger(\"change\")});else{var i=e.id;this.$element.val(i),this.$element.trigger(\"change\")}},i.prototype.unselect=function(e){var t=this;if(this.$element.prop(\"multiple\"))return e.selected=!1,n(e.element).is(\"option\")?(e.element.selected=!1,void this.$element.trigger(\"change\")):void this.current(function(i){for(var r=[],a=0;a<i.length;a++){var o=i[a].id;o!==e.id&&-1===n.inArray(o,r)&&r.push(o)}t.$element.val(r),t.$element.trigger(\"change\")})},i.prototype.bind=function(e,t){var n=this;this.container=e,e.on(\"select\",function(e){n.select(e.data)}),e.on(\"unselect\",function(e){n.unselect(e.data)})},i.prototype.destroy=function(){this.$element.find(\"*\").each(function(){n.removeData(this,\"data\")})},i.prototype.query=function(e,t){var i=[],r=this,a=this.$element.children();a.each(function(){var t=n(this);if(t.is(\"option\")||t.is(\"optgroup\")){var a=r.item(t),o=r.matches(e,a);null!==o&&i.push(o)}}),t({results:i})},i.prototype.addOptions=function(e){t.appendMany(this.$element,e)},i.prototype.option=function(e){var t;e.children?(t=document.createElement(\"optgroup\"),t.label=e.text):(t=document.createElement(\"option\"),void 0!==t.textContent?t.textContent=e.text:t.innerText=e.text),e.id&&(t.value=e.id),e.disabled&&(t.disabled=!0),e.selected&&(t.selected=!0),e.title&&(t.title=e.title);var i=n(t),r=this._normalizeItem(e);return r.element=t,n.data(t,\"data\",r),i},i.prototype.item=function(e){var t={};if(t=n.data(e[0],\"data\"),null!=t)return t;if(e.is(\"option\"))t={id:e.val(),text:e.text(),disabled:e.prop(\"disabled\"),selected:e.prop(\"selected\"),title:e.prop(\"title\")};else if(e.is(\"optgroup\")){t={text:e.prop(\"label\"),children:[],title:e.prop(\"title\")};for(var i=e.children(\"option\"),r=[],a=0;a<i.length;a++){var o=n(i[a]),s=this.item(o);r.push(s)}t.children=r}return t=this._normalizeItem(t),t.element=e[0],n.data(e[0],\"data\",t),t},i.prototype._normalizeItem=function(e){n.isPlainObject(e)||(e={id:e,text:e}),e=n.extend({},{text:\"\"},e);var t={selected:!1,disabled:!1};return null!=e.id&&(e.id=e.id.toString()),null!=e.text&&(e.text=e.text.toString()),null==e._resultId&&e.id&&null!=this.container&&(e._resultId=this.generateResultId(this.container,e)),n.extend({},t,e)},i.prototype.matches=function(e,t){var n=this.options.get(\"matcher\");return n(e,t)},i}),t.define(\"select2/data/array\",[\"./select\",\"../utils\",\"jquery\"],function(e,t,n){function i(e,t){var n=t.get(\"data\")||[];i.__super__.constructor.call(this,e,t),this.addOptions(this.convertToOptions(n))}return t.Extend(i,e),i.prototype.select=function(e){var t=this.$element.find(\"option\").filter(function(t,n){return n.value==e.id.toString()});0===t.length&&(t=this.option(e),this.addOptions(t)),i.__super__.select.call(this,e)},i.prototype.convertToOptions=function(e){function i(e){return function(){return n(this).val()==e.id}}for(var r=this,a=this.$element.find(\"option\"),o=a.map(function(){return r.item(n(this)).id}).get(),s=[],l=0;l<e.length;l++){var c=this._normalizeItem(e[l]);if(n.inArray(c.id,o)>=0){var d=a.filter(i(c)),u=this.item(d),p=n.extend(!0,{},u,c),m=this.option(p);d.replaceWith(m)}else{var g=this.option(c);if(c.children){var h=this.convertToOptions(c.children);t.appendMany(g,h)}s.push(g)}}return s},i}),t.define(\"select2/data/ajax\",[\"./array\",\"../utils\",\"jquery\"],function(e,t,n){function i(e,t){this.ajaxOptions=this._applyDefaults(t.get(\"ajax\")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),i.__super__.constructor.call(this,e,t)}return t.Extend(i,e),i.prototype._applyDefaults=function(e){var t={data:function(e){return n.extend({},e,{q:e.term})},transport:function(e,t,i){var r=n.ajax(e);return r.then(t),r.fail(i),r}};return n.extend({},t,e,!0)},i.prototype.processResults=function(e){return e},i.prototype.query=function(e,t){function i(){var i=a.transport(a,function(i){var a=r.processResults(i,e);r.options.get(\"debug\")&&window.console&&console.error&&(a&&a.results&&n.isArray(a.results)||console.error(\"Select2: The AJAX results did not return an array in the `results` key of the response.\")),t(a)},function(){});r._request=i}var r=this;null!=this._request&&(n.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var a=n.extend({type:\"GET\"},this.ajaxOptions);\"function\"==typeof a.url&&(a.url=a.url.call(this.$element,e)),\"function\"==typeof a.data&&(a.data=a.data.call(this.$element,e)),this.ajaxOptions.delay&&\"\"!==e.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(i,this.ajaxOptions.delay)):i()},i}),t.define(\"select2/data/tags\",[\"jquery\"],function(e){function t(t,n,i){var r=i.get(\"tags\"),a=i.get(\"createTag\");if(void 0!==a&&(this.createTag=a),t.call(this,n,i),e.isArray(r))for(var o=0;o<r.length;o++){var s=r[o],l=this._normalizeItem(s),c=this.option(l);this.$element.append(c)}}return t.prototype.query=function(e,t,n){function i(e,a){for(var o=e.results,s=0;s<o.length;s++){var l=o[s],c=null!=l.children&&!i({results:l.children},!0),d=l.text===t.term;if(d||c)return a?!1:(e.data=o,void n(e))}if(a)return!0;var u=r.createTag(t);if(null!=u){var p=r.option(u);p.attr(\"data-select2-tag\",!0),r.addOptions([p]),r.insertTag(o,u)}e.results=o,n(e)}var r=this;return this._removeOldTags(),null==t.term||null!=t.page?void e.call(this,t,n):void e.call(this,t,i)},t.prototype.createTag=function(t,n){var i=e.trim(n.term);return\"\"===i?null:{id:i,text:i}},t.prototype.insertTag=function(e,t,n){t.unshift(n)},t.prototype._removeOldTags=function(t){var n=(this._lastTag,this.$element.find(\"option[data-select2-tag]\"));n.each(function(){this.selected||e(this).remove()})},t}),t.define(\"select2/data/tokenizer\",[\"jquery\"],function(e){function t(e,t,n){var i=n.get(\"tokenizer\");void 0!==i&&(this.tokenizer=i),e.call(this,t,n)}return t.prototype.bind=function(e,t,n){e.call(this,t,n),this.$search=t.dropdown.$search||t.selection.$search||n.find(\".select2-search__field\")},t.prototype.query=function(e,t,n){function i(e){r.trigger(\"select\",{data:e})}var r=this;t.term=t.term||\"\";var a=this.tokenizer(t,this.options,i);a.term!==t.term&&(this.$search.length&&(this.$search.val(a.term),this.$search.focus()),t.term=a.term),e.call(this,t,n)},t.prototype.tokenizer=function(t,n,i,r){for(var a=i.get(\"tokenSeparators\")||[],o=n.term,s=0,l=this.createTag||function(e){return{id:e.term,text:e.term}};s<o.length;){var c=o[s];if(-1!==e.inArray(c,a)){var d=o.substr(0,s),u=e.extend({},n,{term:d}),p=l(u);null!=p?(r(p),o=o.substr(s+1)||\"\",s=0):s++}else s++}return{term:o}},t}),t.define(\"select2/data/minimumInputLength\",[],function(){function e(e,t,n){this.minimumInputLength=n.get(\"minimumInputLength\"),e.call(this,t,n)}return e.prototype.query=function(e,t,n){return t.term=t.term||\"\",t.term.length<this.minimumInputLength?void this.trigger(\"results:message\",{message:\"inputTooShort\",args:{minimum:this.minimumInputLength,input:t.term,params:t}}):void e.call(this,t,n)},e}),t.define(\"select2/data/maximumInputLength\",[],function(){function e(e,t,n){this.maximumInputLength=n.get(\"maximumInputLength\"),e.call(this,t,n)}return e.prototype.query=function(e,t,n){return t.term=t.term||\"\",this.maximumInputLength>0&&t.term.length>this.maximumInputLength?void this.trigger(\"results:message\",{message:\"inputTooLong\",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):void e.call(this,t,n)},e}),t.define(\"select2/data/maximumSelectionLength\",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get(\"maximumSelectionLength\"),e.call(this,t,n)}return e.prototype.query=function(e,t,n){var i=this;this.current(function(r){var a=null!=r?r.length:0;return i.maximumSelectionLength>0&&a>=i.maximumSelectionLength?void i.trigger(\"results:message\",{message:\"maximumSelected\",args:{maximum:i.maximumSelectionLength}}):void e.call(i,t,n)})},e}),t.define(\"select2/dropdown\",[\"jquery\",\"./utils\"],function(e,t){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return t.Extend(n,t.Observable),n.prototype.render=function(){var t=e('<span class=\"select2-dropdown\"><span class=\"select2-results\"></span></span>');return t.attr(\"dir\",this.options.get(\"dir\")),this.$dropdown=t,t},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),t.define(\"select2/dropdown/search\",[\"jquery\",\"../utils\"],function(e,t){function n(){}return n.prototype.render=function(t){var n=t.call(this),i=e('<span class=\"select2-search select2-search--dropdown\"><input class=\"select2-search__field\" type=\"search\" tabindex=\"-1\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" role=\"textbox\" /></span>');return this.$searchContainer=i,this.$search=i.find(\"input\"),n.prepend(i),n},n.prototype.bind=function(t,n,i){var r=this;t.call(this,n,i),this.$search.on(\"keydown\",function(e){r.trigger(\"keypress\",e),r._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on(\"input\",function(t){e(this).off(\"keyup\")}),this.$search.on(\"keyup input\",function(e){r.handleSearch(e)}),n.on(\"open\",function(){r.$search.attr(\"tabindex\",0),r.$search.focus(),window.setTimeout(function(){r.$search.focus()},0)}),n.on(\"close\",function(){r.$search.attr(\"tabindex\",-1),r.$search.val(\"\")}),n.on(\"results:all\",function(e){if(null==e.query.term||\"\"===e.query.term){var t=r.showSearch(e);t?r.$searchContainer.removeClass(\"select2-search--hide\"):r.$searchContainer.addClass(\"select2-search--hide\")}})},n.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger(\"query\",{term:t})}this._keyUpPrevented=!1},n.prototype.showSearch=function(e,t){return!0},n}),t.define(\"select2/dropdown/hidePlaceholder\",[],function(){function e(e,t,n,i){this.placeholder=this.normalizePlaceholder(n.get(\"placeholder\")),e.call(this,t,n,i)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return\"string\"==typeof t&&(t={id:\"\",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),i=t.length-1;i>=0;i--){var r=t[i];this.placeholder.id===r.id&&n.splice(i,1)}return n},e}),t.define(\"select2/dropdown/infiniteScroll\",[\"jquery\"],function(e){function t(e,t,n,i){this.lastParams={},e.call(this,t,n,i),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return t.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&this.$results.append(this.$loadingMore)},t.prototype.bind=function(t,n,i){var r=this;t.call(this,n,i),n.on(\"query\",function(e){r.lastParams=e,r.loading=!0}),n.on(\"query:append\",function(e){r.lastParams=e,r.loading=!0}),this.$results.on(\"scroll\",function(){var t=e.contains(document.documentElement,r.$loadingMore[0]);if(!r.loading&&t){var n=r.$results.offset().top+r.$results.outerHeight(!1),i=r.$loadingMore.offset().top+r.$loadingMore.outerHeight(!1);n+50>=i&&r.loadMore()}})},t.prototype.loadMore=function(){this.loading=!0;var t=e.extend({},{page:1},this.lastParams);t.page++,this.trigger(\"query:append\",t)},t.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},t.prototype.createLoadingMore=function(){var t=e('<li class=\"select2-results__option select2-results__option--load-more\"role=\"treeitem\" aria-disabled=\"true\"></li>'),n=this.options.get(\"translations\").get(\"loadingMore\");return t.html(n(this.lastParams)),t},t}),t.define(\"select2/dropdown/attachBody\",[\"jquery\",\"../utils\"],function(e,t){function n(t,n,i){this.$dropdownParent=i.get(\"dropdownParent\")||e(document.body),t.call(this,n,i)}return n.prototype.bind=function(e,t,n){var i=this,r=!1;e.call(this,t,n),t.on(\"open\",function(){i._showDropdown(),i._attachPositioningHandler(t),r||(r=!0,t.on(\"results:all\",function(){i._positionDropdown(),i._resizeDropdown()}),t.on(\"results:append\",function(){i._positionDropdown(),i._resizeDropdown()}))}),t.on(\"close\",function(){i._hideDropdown(),i._detachPositioningHandler(t)}),this.$dropdownContainer.on(\"mousedown\",function(e){e.stopPropagation()})},n.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},n.prototype.position=function(e,t,n){t.attr(\"class\",n.attr(\"class\")),t.removeClass(\"select2\"),t.addClass(\"select2-container--open\"),t.css({position:\"absolute\",top:-999999}),this.$container=n},n.prototype.render=function(t){var n=e(\"<span></span>\"),i=t.call(this);return n.append(i),this.$dropdownContainer=n,n},n.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},n.prototype._attachPositioningHandler=function(n,i){var r=this,a=\"scroll.select2.\"+i.id,o=\"resize.select2.\"+i.id,s=\"orientationchange.select2.\"+i.id,l=this.$container.parents().filter(t.hasScroll);l.each(function(){e(this).data(\"select2-scroll-position\",{x:e(this).scrollLeft(),y:e(this).scrollTop()})}),l.on(a,function(t){var n=e(this).data(\"select2-scroll-position\");e(this).scrollTop(n.y)}),e(window).on(a+\" \"+o+\" \"+s,function(e){r._positionDropdown(),r._resizeDropdown()})},n.prototype._detachPositioningHandler=function(n,i){var r=\"scroll.select2.\"+i.id,a=\"resize.select2.\"+i.id,o=\"orientationchange.select2.\"+i.id,s=this.$container.parents().filter(t.hasScroll);s.off(r),e(window).off(r+\" \"+a+\" \"+o)},n.prototype._positionDropdown=function(){var t=e(window),n=this.$dropdown.hasClass(\"select2-dropdown--above\"),i=this.$dropdown.hasClass(\"select2-dropdown--below\"),r=null,a=(this.$container.position(),this.$container.offset());a.bottom=a.top+this.$container.outerHeight(!1);var o={height:this.$container.outerHeight(!1)};o.top=a.top,o.bottom=a.top+o.height;var s={height:this.$dropdown.outerHeight(!1)},l={top:t.scrollTop(),bottom:t.scrollTop()+t.height()},c=l.top<a.top-s.height,d=l.bottom>a.bottom+s.height,u={left:a.left,top:o.bottom};if(\"static\"!==this.$dropdownParent[0].style.position){var p=this.$dropdownParent.offset();u.top-=p.top,u.left-=p.left}n||i||(r=\"below\"),d||!c||n?!c&&d&&n&&(r=\"below\"):r=\"above\",(\"above\"==r||n&&\"below\"!==r)&&(u.top=o.top-s.height),null!=r&&(this.$dropdown.removeClass(\"select2-dropdown--below select2-dropdown--above\").addClass(\"select2-dropdown--\"+r),this.$container.removeClass(\"select2-container--below select2-container--above\").addClass(\"select2-container--\"+r)),this.$dropdownContainer.css(u)},n.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+\"px\"};this.options.get(\"dropdownAutoWidth\")&&(e.minWidth=e.width,e.width=\"auto\"),this.$dropdown.css(e)},n.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},n}),t.define(\"select2/dropdown/minimumResultsForSearch\",[],function(){function e(t){for(var n=0,i=0;i<t.length;i++){var r=t[i];r.children?n+=e(r.children):n++}return n}function t(e,t,n,i){this.minimumResultsForSearch=n.get(\"minimumResultsForSearch\"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),e.call(this,t,n,i)}return t.prototype.showSearch=function(t,n){return e(n.data.results)<this.minimumResultsForSearch?!1:t.call(this,n)},t}),t.define(\"select2/dropdown/selectOnClose\",[],function(){function e(){}return e.prototype.bind=function(e,t,n){var i=this;e.call(this,t,n),t.on(\"close\",function(){i._handleSelectOnClose()})},e.prototype._handleSelectOnClose=function(){var e=this.getHighlightedResults();if(!(e.length<1)){var t=e.data(\"data\");null!=t.element&&t.element.selected||null==t.element&&t.selected||this.trigger(\"select\",{data:t})}},e}),t.define(\"select2/dropdown/closeOnSelect\",[],function(){function e(){}return e.prototype.bind=function(e,t,n){var i=this;e.call(this,t,n),t.on(\"select\",function(e){i._selectTriggered(e)}),t.on(\"unselect\",function(e){i._selectTriggered(e)})},e.prototype._selectTriggered=function(e,t){var n=t.originalEvent;n&&n.ctrlKey||this.trigger(\"close\",{})},e}),t.define(\"select2/i18n/en\",[],function(){return{errorLoading:function(){return\"The results could not be loaded.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Please delete \"+t+\" character\";return 1!=t&&(n+=\"s\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Please enter \"+t+\" or more characters\";return n},loadingMore:function(){return\"Loading more results…\"},maximumSelected:function(e){var t=\"You can only select \"+e.maximum+\" item\";return 1!=e.maximum&&(t+=\"s\"),t},noResults:function(){return\"No results found\"},searching:function(){return\"Searching…\"}}}),t.define(\"select2/defaults\",[\"jquery\",\"require\",\"./results\",\"./selection/single\",\"./selection/multiple\",\"./selection/placeholder\",\"./selection/allowClear\",\"./selection/search\",\"./selection/eventRelay\",\"./utils\",\"./translation\",\"./diacritics\",\"./data/select\",\"./data/array\",\"./data/ajax\",\"./data/tags\",\"./data/tokenizer\",\"./data/minimumInputLength\",\"./data/maximumInputLength\",\"./data/maximumSelectionLength\",\"./dropdown\",\"./dropdown/search\",\"./dropdown/hidePlaceholder\",\"./dropdown/infiniteScroll\",\"./dropdown/attachBody\",\"./dropdown/minimumResultsForSearch\",\"./dropdown/selectOnClose\",\"./dropdown/closeOnSelect\",\"./i18n/en\"],function(e,t,n,i,r,a,o,s,l,c,d,u,p,m,g,h,f,_,b,v,C,I,y,S,E,x,T,w,A){function P(){this.reset()}P.prototype.apply=function(u){if(u=e.extend({},this.defaults,u),null==u.dataAdapter){if(null!=u.ajax?u.dataAdapter=g:null!=u.data?u.dataAdapter=m:u.dataAdapter=p,u.minimumInputLength>0&&(u.dataAdapter=c.Decorate(u.dataAdapter,_)),u.maximumInputLength>0&&(u.dataAdapter=c.Decorate(u.dataAdapter,b)),u.maximumSelectionLength>0&&(u.dataAdapter=c.Decorate(u.dataAdapter,v)),u.tags&&(u.dataAdapter=c.Decorate(u.dataAdapter,h)),(null!=u.tokenSeparators||null!=u.tokenizer)&&(u.dataAdapter=c.Decorate(u.dataAdapter,f)),null!=u.query){var A=t(u.amdBase+\"compat/query\");u.dataAdapter=c.Decorate(u.dataAdapter,A)}if(null!=u.initSelection){var P=t(u.amdBase+\"compat/initSelection\");u.dataAdapter=c.Decorate(u.dataAdapter,P)}}if(null==u.resultsAdapter&&(u.resultsAdapter=n,null!=u.ajax&&(u.resultsAdapter=c.Decorate(u.resultsAdapter,S)),null!=u.placeholder&&(u.resultsAdapter=c.Decorate(u.resultsAdapter,y)),u.selectOnClose&&(u.resultsAdapter=c.Decorate(u.resultsAdapter,T))),null==u.dropdownAdapter){if(u.multiple)u.dropdownAdapter=C;else{var D=c.Decorate(C,I);u.dropdownAdapter=D}if(0!==u.minimumResultsForSearch&&(u.dropdownAdapter=c.Decorate(u.dropdownAdapter,x)),u.closeOnSelect&&(u.dropdownAdapter=c.Decorate(u.dropdownAdapter,w)),null!=u.dropdownCssClass||null!=u.dropdownCss||null!=u.adaptDropdownCssClass){var G=t(u.amdBase+\"compat/dropdownCss\");u.dropdownAdapter=c.Decorate(u.dropdownAdapter,G)}u.dropdownAdapter=c.Decorate(u.dropdownAdapter,E)}if(null==u.selectionAdapter){if(u.multiple?u.selectionAdapter=r:u.selectionAdapter=i,null!=u.placeholder&&(u.selectionAdapter=c.Decorate(u.selectionAdapter,a)),u.allowClear&&(u.selectionAdapter=c.Decorate(u.selectionAdapter,o)),u.multiple&&(u.selectionAdapter=c.Decorate(u.selectionAdapter,s)),null!=u.containerCssClass||null!=u.containerCss||null!=u.adaptContainerCssClass){var M=t(u.amdBase+\"compat/containerCss\");u.selectionAdapter=c.Decorate(u.selectionAdapter,M)}u.selectionAdapter=c.Decorate(u.selectionAdapter,l)}if(\"string\"==typeof u.language)if(u.language.indexOf(\"-\")>0){var N=u.language.split(\"-\"),L=N[0];u.language=[u.language,L]}else u.language=[u.language];if(e.isArray(u.language)){var k=new d;u.language.push(\"en\");for(var R=u.language,O=0;O<R.length;O++){var U=R[O],F={};try{F=d.loadPath(U)}catch(B){try{U=this.defaults.amdLanguageBase+U,F=d.loadPath(U)}catch(W){u.debug&&window.console&&console.warn&&console.warn('Select2: The language file for \"'+U+'\" could not be automatically loaded. A fallback will be used instead.');continue}}k.extend(F)}u.translations=k}else{var q=d.loadPath(this.defaults.amdLanguageBase+\"en\"),z=new d(u.language);z.extend(q),u.translations=z}return u},P.prototype.reset=function(){function t(e){function t(e){return u[e]||e}return e.replace(/[^\\u0000-\\u007E]/g,t)}function n(i,r){if(\"\"===e.trim(i.term))return r;if(r.children&&r.children.length>0){for(var a=e.extend(!0,{},r),o=r.children.length-1;o>=0;o--){var s=r.children[o],l=n(i,s);null==l&&a.children.splice(o,1)}return a.children.length>0?a:n(i,a)}var c=t(r.text).toUpperCase(),d=t(i.term).toUpperCase();return c.indexOf(d)>-1?r:null}this.defaults={amdBase:\"./\",amdLanguageBase:\"./i18n/\",closeOnSelect:!0,debug:!1,dropdownAutoWidth:!1,escapeMarkup:c.escapeMarkup,language:A,matcher:n,minimumInputLength:0,maximumInputLength:0,maximumSelectionLength:0,minimumResultsForSearch:0,selectOnClose:!1,sorter:function(e){return e},templateResult:function(e){return e.text},templateSelection:function(e){return e.text},theme:\"default\",width:\"resolve\"}},P.prototype.set=function(t,n){var i=e.camelCase(t),r={};r[i]=n;var a=c._convertData(r);e.extend(this.defaults,a)};var D=new P;return D}),t.define(\"select2/options\",[\"require\",\"jquery\",\"./defaults\",\"./utils\"],function(e,t,n,i){function r(t,r){if(this.options=t,null!=r&&this.fromElement(r),this.options=n.apply(this.options),r&&r.is(\"input\")){var a=e(this.get(\"amdBase\")+\"compat/inputData\");this.options.dataAdapter=i.Decorate(this.options.dataAdapter,a)}}return r.prototype.fromElement=function(e){var n=[\"select2\"];null==this.options.multiple&&(this.options.multiple=e.prop(\"multiple\")),null==this.options.disabled&&(this.options.disabled=e.prop(\"disabled\")),null==this.options.language&&(e.prop(\"lang\")?this.options.language=e.prop(\"lang\").toLowerCase():e.closest(\"[lang]\").prop(\"lang\")&&(this.options.language=e.closest(\"[lang]\").prop(\"lang\"))),null==this.options.dir&&(e.prop(\"dir\")?this.options.dir=e.prop(\"dir\"):e.closest(\"[dir]\").prop(\"dir\")?this.options.dir=e.closest(\"[dir]\").prop(\"dir\"):this.options.dir=\"ltr\"),e.prop(\"disabled\",this.options.disabled),e.prop(\"multiple\",this.options.multiple),e.data(\"select2Tags\")&&(this.options.debug&&window.console&&console.warn&&console.warn('Select2: The `data-select2-tags` attribute has been changed to use the `data-data` and `data-tags=\"true\"` attributes and will be removed in future versions of Select2.'),e.data(\"data\",e.data(\"select2Tags\")),e.data(\"tags\",!0)),e.data(\"ajaxUrl\")&&(this.options.debug&&window.console&&console.warn&&console.warn(\"Select2: The `data-ajax-url` attribute has been changed to `data-ajax--url` and support for the old attribute will be removed in future versions of Select2.\"),e.attr(\"ajax--url\",e.data(\"ajaxUrl\")),e.data(\"ajax--url\",e.data(\"ajaxUrl\")));var r={};r=t.fn.jquery&&\"1.\"==t.fn.jquery.substr(0,2)&&e[0].dataset?t.extend(!0,{},e[0].dataset,e.data()):e.data();var a=t.extend(!0,{},r);a=i._convertData(a);for(var o in a)t.inArray(o,n)>-1||(t.isPlainObject(this.options[o])?t.extend(this.options[o],a[o]):this.options[o]=a[o]);return this},r.prototype.get=function(e){return this.options[e]},r.prototype.set=function(e,t){this.options[e]=t},r}),t.define(\"select2/core\",[\"jquery\",\"./options\",\"./utils\",\"./keys\"],function(e,t,n,i){var r=function(e,n){null!=e.data(\"select2\")&&e.data(\"select2\").destroy(),this.$element=e,this.id=this._generateId(e),n=n||{},this.options=new t(n,e),r.__super__.constructor.call(this);var i=e.attr(\"tabindex\")||0;e.data(\"old-tabindex\",i),e.attr(\"tabindex\",\"-1\");var a=this.options.get(\"dataAdapter\");this.dataAdapter=new a(e,this.options);var o=this.render();this._placeContainer(o);var s=this.options.get(\"selectionAdapter\");this.selection=new s(e,this.options),this.$selection=this.selection.render(),this.selection.position(this.$selection,o);var l=this.options.get(\"dropdownAdapter\");this.dropdown=new l(e,this.options),this.$dropdown=this.dropdown.render(),this.dropdown.position(this.$dropdown,o);var c=this.options.get(\"resultsAdapter\");this.results=new c(e,this.options,this.dataAdapter),this.$results=this.results.render(),this.results.position(this.$results,this.$dropdown);var d=this;this._bindAdapters(),this._registerDomEvents(),this._registerDataEvents(),this._registerSelectionEvents(),this._registerDropdownEvents(),this._registerResultsEvents(),this._registerEvents(),this.dataAdapter.current(function(e){d.trigger(\"selection:update\",{data:e})}),e.addClass(\"select2-hidden-accessible\"),e.attr(\"aria-hidden\",\"true\"),this._syncAttributes(),e.data(\"select2\",this)};return n.Extend(r,n.Observable),r.prototype._generateId=function(e){var t=\"\";return t=null!=e.attr(\"id\")?e.attr(\"id\"):null!=e.attr(\"name\")?e.attr(\"name\")+\"-\"+n.generateChars(2):n.generateChars(4),t=\"select2-\"+t},r.prototype._placeContainer=function(e){e.insertAfter(this.$element);var t=this._resolveWidth(this.$element,this.options.get(\"width\"));null!=t&&e.css(\"width\",t)},r.prototype._resolveWidth=function(e,t){var n=/^width:(([-+]?([0-9]*\\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;if(\"resolve\"==t){var i=this._resolveWidth(e,\"style\");return null!=i?i:this._resolveWidth(e,\"element\")}if(\"element\"==t){var r=e.outerWidth(!1);return 0>=r?\"auto\":r+\"px\"}if(\"style\"==t){var a=e.attr(\"style\");if(\"string\"!=typeof a)return null;for(var o=a.split(\";\"),s=0,l=o.length;l>s;s+=1){var c=o[s].replace(/\\s/g,\"\"),d=c.match(n);if(null!==d&&d.length>=1)return d[1]}return null}return t},r.prototype._bindAdapters=function(){this.dataAdapter.bind(this,this.$container),this.selection.bind(this,this.$container),this.dropdown.bind(this,this.$container),this.results.bind(this,this.$container)},r.prototype._registerDomEvents=function(){var t=this;this.$element.on(\"change.select2\",function(){t.dataAdapter.current(function(e){t.trigger(\"selection:update\",{data:e})})}),this._sync=n.bind(this._syncAttributes,this),this.$element[0].attachEvent&&this.$element[0].attachEvent(\"onpropertychange\",this._sync);var i=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver;null!=i?(this._observer=new i(function(n){e.each(n,t._sync)}),this._observer.observe(this.$element[0],{attributes:!0,subtree:!1})):this.$element[0].addEventListener&&this.$element[0].addEventListener(\"DOMAttrModified\",t._sync,!1)},r.prototype._registerDataEvents=function(){var e=this;this.dataAdapter.on(\"*\",function(t,n){e.trigger(t,n)})},r.prototype._registerSelectionEvents=function(){var t=this,n=[\"toggle\",\"focus\"];this.selection.on(\"toggle\",function(){t.toggleDropdown()}),this.selection.on(\"focus\",function(e){t.focus(e)}),this.selection.on(\"*\",function(i,r){-1===e.inArray(i,n)&&t.trigger(i,r)})},r.prototype._registerDropdownEvents=function(){var e=this;this.dropdown.on(\"*\",function(t,n){e.trigger(t,n)})},r.prototype._registerResultsEvents=function(){var e=this;this.results.on(\"*\",function(t,n){e.trigger(t,n)})},r.prototype._registerEvents=function(){var e=this;this.on(\"open\",function(){e.$container.addClass(\"select2-container--open\")}),this.on(\"close\",function(){e.$container.removeClass(\"select2-container--open\")}),this.on(\"enable\",function(){e.$container.removeClass(\"select2-container--disabled\")}),this.on(\"disable\",function(){e.$container.addClass(\"select2-container--disabled\")}),this.on(\"blur\",function(){e.$container.removeClass(\"select2-container--focus\")}),this.on(\"query\",function(t){e.isOpen()||e.trigger(\"open\",{}),this.dataAdapter.query(t,function(n){e.trigger(\"results:all\",{data:n,query:t})})}),this.on(\"query:append\",function(t){this.dataAdapter.query(t,function(n){e.trigger(\"results:append\",{data:n,query:t})})}),this.on(\"keypress\",function(t){var n=t.which;e.isOpen()?n===i.ESC||n===i.TAB||n===i.UP&&t.altKey?(e.close(),t.preventDefault()):n===i.ENTER?(e.trigger(\"results:select\",{}),t.preventDefault()):n===i.SPACE&&t.ctrlKey?(e.trigger(\"results:toggle\",{}),t.preventDefault()):n===i.UP?(e.trigger(\"results:previous\",{}),t.preventDefault()):n===i.DOWN&&(e.trigger(\"results:next\",{}),t.preventDefault()):(n===i.ENTER||n===i.SPACE||n===i.DOWN&&t.altKey)&&(e.open(),t.preventDefault())})},r.prototype._syncAttributes=function(){this.options.set(\"disabled\",this.$element.prop(\"disabled\")),this.options.get(\"disabled\")?(this.isOpen()&&this.close(),this.trigger(\"disable\",{})):this.trigger(\"enable\",{})},r.prototype.trigger=function(e,t){var n=r.__super__.trigger,i={open:\"opening\",close:\"closing\",select:\"selecting\",unselect:\"unselecting\"};if(void 0===t&&(t={}),e in i){var a=i[e],o={prevented:!1,name:e,args:t};if(n.call(this,a,o),o.prevented)return void(t.prevented=!0)}n.call(this,e,t)},r.prototype.toggleDropdown=function(){this.options.get(\"disabled\")||(this.isOpen()?this.close():this.open())},r.prototype.open=function(){this.isOpen()||this.trigger(\"query\",{})},r.prototype.close=function(){this.isOpen()&&this.trigger(\"close\",{})},r.prototype.isOpen=function(){return this.$container.hasClass(\"select2-container--open\")},r.prototype.hasFocus=function(){return this.$container.hasClass(\"select2-container--focus\")},r.prototype.focus=function(e){this.hasFocus()||(this.$container.addClass(\"select2-container--focus\"),this.trigger(\"focus\",{}))},r.prototype.enable=function(e){this.options.get(\"debug\")&&window.console&&console.warn&&console.warn('Select2: The `select2(\"enable\")` method has been deprecated and will be removed in later Select2 versions. Use $element.prop(\"disabled\") instead.'),(null==e||0===e.length)&&(e=[!0]);var t=!e[0];this.$element.prop(\"disabled\",t)},r.prototype.data=function(){this.options.get(\"debug\")&&arguments.length>0&&window.console&&console.warn&&console.warn('Select2: Data can no longer be set using `select2(\"data\")`. You should consider setting the value instead using `$element.val()`.');var e=[];return this.dataAdapter.current(function(t){e=t}),e},r.prototype.val=function(t){if(this.options.get(\"debug\")&&window.console&&console.warn&&console.warn('Select2: The `select2(\"val\")` method has been deprecated and will be removed in later Select2 versions. Use $element.val() instead.'),null==t||0===t.length)return this.$element.val();var n=t[0];e.isArray(n)&&(n=e.map(n,function(e){return e.toString()})),this.$element.val(n).trigger(\"change\")},r.prototype.destroy=function(){this.$container.remove(),this.$element[0].detachEvent&&this.$element[0].detachEvent(\"onpropertychange\",this._sync),null!=this._observer?(this._observer.disconnect(),this._observer=null):this.$element[0].removeEventListener&&this.$element[0].removeEventListener(\"DOMAttrModified\",this._sync,!1),this._sync=null,this.$element.off(\".select2\"),this.$element.attr(\"tabindex\",this.$element.data(\"old-tabindex\")),this.$element.removeClass(\"select2-hidden-accessible\"),this.$element.attr(\"aria-hidden\",\"false\"),this.$element.removeData(\"select2\"),this.dataAdapter.destroy(),this.selection.destroy(),this.dropdown.destroy(),this.results.destroy(),this.dataAdapter=null,this.selection=null,this.dropdown=null,this.results=null},r.prototype.render=function(){var t=e('<span class=\"select2 select2-container\"><span class=\"selection\"></span><span class=\"dropdown-wrapper\" aria-hidden=\"true\"></span></span>');return t.attr(\"dir\",this.options.get(\"dir\")),this.$container=t,this.$container.addClass(\"select2-container--\"+this.options.get(\"theme\")),t.data(\"element\",this.$element),t},r}),t.define(\"jquery-mousewheel\",[\"jquery\"],function(e){return e}),t.define(\"jquery.select2\",[\"jquery\",\"jquery-mousewheel\",\"./select2/core\",\"./select2/defaults\"],function(e,t,n,i){if(null==e.fn.select2){var r=[\"open\",\"close\",\"destroy\"];e.fn.select2=function(t){if(t=t||{},\"object\"==typeof t)return this.each(function(){\nvar i=e.extend(!0,{},t);new n(e(this),i)}),this;if(\"string\"==typeof t){var i;return this.each(function(){var n=e(this).data(\"select2\");null==n&&window.console&&console.error&&console.error(\"The select2('\"+t+\"') method was called on an element that is not using Select2.\");var r=Array.prototype.slice.call(arguments,1);i=n[t].apply(n,r)}),e.inArray(t,r)>-1?this:i}throw new Error(\"Invalid arguments for Select2: \"+t)}}return null==e.fn.select2.defaults&&(e.fn.select2.defaults=i),n}),{define:t.define,require:t.require}}(),n=t.require(\"jquery.select2\");return e.fn.select2.amd=t,n}),function(){var e,t,n,i,r,a,o,s,l=[].slice,c={}.hasOwnProperty,d=function(e,t){function n(){this.constructor=e}for(var i in t)c.call(t,i)&&(e[i]=t[i]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e};o=function(){},t=function(){function e(){}return e.prototype.addEventListener=e.prototype.on,e.prototype.on=function(e,t){return this._callbacks=this._callbacks||{},this._callbacks[e]||(this._callbacks[e]=[]),this._callbacks[e].push(t),this},e.prototype.emit=function(){var e,t,n,i,r,a;if(i=arguments[0],e=2<=arguments.length?l.call(arguments,1):[],this._callbacks=this._callbacks||{},n=this._callbacks[i])for(r=0,a=n.length;a>r;r++)t=n[r],t.apply(this,e);return this},e.prototype.removeListener=e.prototype.off,e.prototype.removeAllListeners=e.prototype.off,e.prototype.removeEventListener=e.prototype.off,e.prototype.off=function(e,t){var n,i,r,a,o;if(!this._callbacks||0===arguments.length)return this._callbacks={},this;if(i=this._callbacks[e],!i)return this;if(1===arguments.length)return delete this._callbacks[e],this;for(r=a=0,o=i.length;o>a;r=++a)if(n=i[r],n===t){i.splice(r,1);break}return this},e}(),e=function(e){function n(e,t){var r,a,o;if(this.element=e,this.version=n.version,this.defaultOptions.previewTemplate=this.defaultOptions.previewTemplate.replace(/\\n*/g,\"\"),this.clickableElements=[],this.listeners=[],this.files=[],\"string\"==typeof this.element&&(this.element=document.querySelector(this.element)),!this.element||null==this.element.nodeType)throw new Error(\"Invalid dropzone element.\");if(this.element.dropzone)throw new Error(\"Dropzone already attached.\");if(n.instances.push(this),this.element.dropzone=this,r=null!=(o=n.optionsForElement(this.element))?o:{},this.options=i({},this.defaultOptions,r,null!=t?t:{}),this.options.forceFallback||!n.isBrowserSupported())return this.options.fallback.call(this);if(null==this.options.url&&(this.options.url=this.element.getAttribute(\"action\")),!this.options.url)throw new Error(\"No URL provided.\");if(this.options.acceptedFiles&&this.options.acceptedMimeTypes)throw new Error(\"You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.\");this.options.acceptedMimeTypes&&(this.options.acceptedFiles=this.options.acceptedMimeTypes,delete this.options.acceptedMimeTypes),this.options.method=this.options.method.toUpperCase(),(a=this.getExistingFallback())&&a.parentNode&&a.parentNode.removeChild(a),this.options.previewsContainer!==!1&&(this.options.previewsContainer?this.previewsContainer=n.getElement(this.options.previewsContainer,\"previewsContainer\"):this.previewsContainer=this.element),this.options.clickable&&(this.options.clickable===!0?this.clickableElements=[this.element]:this.clickableElements=n.getElements(this.options.clickable,\"clickable\")),this.init()}var i,r;return d(n,e),n.prototype.Emitter=t,n.prototype.events=[\"drop\",\"dragstart\",\"dragend\",\"dragenter\",\"dragover\",\"dragleave\",\"addedfile\",\"addedfiles\",\"removedfile\",\"thumbnail\",\"error\",\"errormultiple\",\"processing\",\"processingmultiple\",\"uploadprogress\",\"totaluploadprogress\",\"sending\",\"sendingmultiple\",\"success\",\"successmultiple\",\"canceled\",\"canceledmultiple\",\"complete\",\"completemultiple\",\"reset\",\"maxfilesexceeded\",\"maxfilesreached\",\"queuecomplete\"],n.prototype.defaultOptions={url:null,method:\"post\",withCredentials:!1,parallelUploads:2,uploadMultiple:!1,maxFilesize:256,paramName:\"file\",createImageThumbnails:!0,maxThumbnailFilesize:10,thumbnailWidth:120,thumbnailHeight:120,filesizeBase:1e3,maxFiles:null,params:{},clickable:!0,ignoreHiddenFiles:!0,acceptedFiles:null,acceptedMimeTypes:null,autoProcessQueue:!0,autoQueue:!0,addRemoveLinks:!1,previewsContainer:null,hiddenInputContainer:\"body\",capture:null,dictDefaultMessage:\"Drop files here to upload\",dictFallbackMessage:\"Your browser does not support drag'n'drop file uploads.\",dictFallbackText:\"Please use the fallback form below to upload your files like in the olden days.\",dictFileTooBig:\"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.\",dictInvalidFileType:\"You can't upload files of this type.\",dictResponseError:\"Server responded with {{statusCode}} code.\",dictCancelUpload:\"Cancel upload\",dictCancelUploadConfirmation:\"Are you sure you want to cancel this upload?\",dictRemoveFile:\"Remove file\",dictRemoveFileConfirmation:null,dictMaxFilesExceeded:\"You can not upload any more files.\",accept:function(e,t){return t()},init:function(){return o},forceFallback:!1,fallback:function(){var e,t,i,r,a,o;for(this.element.className=\"\"+this.element.className+\" dz-browser-not-supported\",o=this.element.getElementsByTagName(\"div\"),r=0,a=o.length;a>r;r++)e=o[r],/(^| )dz-message($| )/.test(e.className)&&(t=e,e.className=\"dz-message\");return t||(t=n.createElement('<div class=\"dz-message\"><span></span></div>'),this.element.appendChild(t)),i=t.getElementsByTagName(\"span\")[0],i&&(null!=i.textContent?i.textContent=this.options.dictFallbackMessage:null!=i.innerText&&(i.innerText=this.options.dictFallbackMessage)),this.element.appendChild(this.getFallbackForm())},resize:function(e){var t,n,i;return t={srcX:0,srcY:0,srcWidth:e.width,srcHeight:e.height},n=e.width/e.height,t.optWidth=this.options.thumbnailWidth,t.optHeight=this.options.thumbnailHeight,null==t.optWidth&&null==t.optHeight?(t.optWidth=t.srcWidth,t.optHeight=t.srcHeight):null==t.optWidth?t.optWidth=n*t.optHeight:null==t.optHeight&&(t.optHeight=1/n*t.optWidth),i=t.optWidth/t.optHeight,e.height<t.optHeight||e.width<t.optWidth?(t.trgHeight=t.srcHeight,t.trgWidth=t.srcWidth):n>i?(t.srcHeight=e.height,t.srcWidth=t.srcHeight*i):(t.srcWidth=e.width,t.srcHeight=t.srcWidth/i),t.srcX=(e.width-t.srcWidth)/2,t.srcY=(e.height-t.srcHeight)/2,t},drop:function(e){return this.element.classList.remove(\"dz-drag-hover\")},dragstart:o,dragend:function(e){return this.element.classList.remove(\"dz-drag-hover\")},dragenter:function(e){return this.element.classList.add(\"dz-drag-hover\")},dragover:function(e){return this.element.classList.add(\"dz-drag-hover\")},dragleave:function(e){return this.element.classList.remove(\"dz-drag-hover\")},paste:o,reset:function(){return this.element.classList.remove(\"dz-started\")},addedfile:function(e){var t,i,r,a,o,s,l,c,d,u,p,m,g;if(this.element===this.previewsContainer&&this.element.classList.add(\"dz-started\"),this.previewsContainer){for(e.previewElement=n.createElement(this.options.previewTemplate.trim()),e.previewTemplate=e.previewElement,this.previewsContainer.appendChild(e.previewElement),u=e.previewElement.querySelectorAll(\"[data-dz-name]\"),a=0,l=u.length;l>a;a++)t=u[a],t.textContent=e.name;for(p=e.previewElement.querySelectorAll(\"[data-dz-size]\"),o=0,c=p.length;c>o;o++)t=p[o],t.innerHTML=this.filesize(e.size);for(this.options.addRemoveLinks&&(e._removeLink=n.createElement('<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>'+this.options.dictRemoveFile+\"</a>\"),e.previewElement.appendChild(e._removeLink)),i=function(t){return function(i){return i.preventDefault(),i.stopPropagation(),e.status===n.UPLOADING?n.confirm(t.options.dictCancelUploadConfirmation,function(){return t.removeFile(e)}):t.options.dictRemoveFileConfirmation?n.confirm(t.options.dictRemoveFileConfirmation,function(){return t.removeFile(e)}):t.removeFile(e)}}(this),m=e.previewElement.querySelectorAll(\"[data-dz-remove]\"),g=[],s=0,d=m.length;d>s;s++)r=m[s],g.push(r.addEventListener(\"click\",i));return g}},removedfile:function(e){var t;return e.previewElement&&null!=(t=e.previewElement)&&t.parentNode.removeChild(e.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(e,t){var n,i,r,a;if(e.previewElement){for(e.previewElement.classList.remove(\"dz-file-preview\"),a=e.previewElement.querySelectorAll(\"[data-dz-thumbnail]\"),i=0,r=a.length;r>i;i++)n=a[i],n.alt=e.name,n.src=t;return setTimeout(function(t){return function(){return e.previewElement.classList.add(\"dz-image-preview\")}}(this),1)}},error:function(e,t){var n,i,r,a,o;if(e.previewElement){for(e.previewElement.classList.add(\"dz-error\"),\"String\"!=typeof t&&t.error&&(t=t.error),a=e.previewElement.querySelectorAll(\"[data-dz-errormessage]\"),o=[],i=0,r=a.length;r>i;i++)n=a[i],o.push(n.textContent=t);return o}},errormultiple:o,processing:function(e){return e.previewElement&&(e.previewElement.classList.add(\"dz-processing\"),e._removeLink)?e._removeLink.textContent=this.options.dictCancelUpload:void 0},processingmultiple:o,uploadprogress:function(e,t,n){var i,r,a,o,s;if(e.previewElement){for(o=e.previewElement.querySelectorAll(\"[data-dz-uploadprogress]\"),s=[],r=0,a=o.length;a>r;r++)i=o[r],\"PROGRESS\"===i.nodeName?s.push(i.value=t):s.push(i.style.width=\"\"+t+\"%\");return s}},totaluploadprogress:o,sending:o,sendingmultiple:o,success:function(e){return e.previewElement?e.previewElement.classList.add(\"dz-success\"):void 0},successmultiple:o,canceled:function(e){return this.emit(\"error\",e,\"Upload canceled.\")},canceledmultiple:o,complete:function(e){return e._removeLink&&(e._removeLink.textContent=this.options.dictRemoveFile),e.previewElement?e.previewElement.classList.add(\"dz-complete\"):void 0},completemultiple:o,maxfilesexceeded:o,maxfilesreached:o,queuecomplete:o,addedfiles:o,previewTemplate:'<div class=\"dz-preview dz-file-preview\">\\n  <div class=\"dz-image\"><img data-dz-thumbnail /></div>\\n  <div class=\"dz-details\">\\n    <div class=\"dz-size\"><span data-dz-size></span></div>\\n    <div class=\"dz-filename\"><span data-dz-name></span></div>\\n  </div>\\n  <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\\n  <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\\n  <div class=\"dz-success-mark\">\\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\\n      <title>Check</title>\\n      <defs></defs>\\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\\n        <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\\n      </g>\\n    </svg>\\n  </div>\\n  <div class=\"dz-error-mark\">\\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\\n      <title>Error</title>\\n      <defs></defs>\\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\\n        <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\\n          <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\\n        </g>\\n      </g>\\n    </svg>\\n  </div>\\n</div>'},i=function(){var e,t,n,i,r,a,o;for(i=arguments[0],n=2<=arguments.length?l.call(arguments,1):[],a=0,o=n.length;o>a;a++){t=n[a];for(e in t)r=t[e],i[e]=r}return i},n.prototype.getAcceptedFiles=function(){var e,t,n,i,r;for(i=this.files,r=[],t=0,n=i.length;n>t;t++)e=i[t],e.accepted&&r.push(e);return r},n.prototype.getRejectedFiles=function(){var e,t,n,i,r;for(i=this.files,r=[],t=0,n=i.length;n>t;t++)e=i[t],e.accepted||r.push(e);return r},n.prototype.getFilesWithStatus=function(e){var t,n,i,r,a;for(r=this.files,a=[],n=0,i=r.length;i>n;n++)t=r[n],t.status===e&&a.push(t);return a},n.prototype.getQueuedFiles=function(){return this.getFilesWithStatus(n.QUEUED)},n.prototype.getUploadingFiles=function(){return this.getFilesWithStatus(n.UPLOADING)},n.prototype.getAddedFiles=function(){return this.getFilesWithStatus(n.ADDED)},n.prototype.getActiveFiles=function(){var e,t,i,r,a;for(r=this.files,a=[],t=0,i=r.length;i>t;t++)e=r[t],(e.status===n.UPLOADING||e.status===n.QUEUED)&&a.push(e);return a},n.prototype.init=function(){var e,t,i,r,a,o,s;for(\"form\"===this.element.tagName&&this.element.setAttribute(\"enctype\",\"multipart/form-data\"),this.element.classList.contains(\"dropzone\")&&!this.element.querySelector(\".dz-message\")&&this.element.appendChild(n.createElement('<div class=\"dz-default dz-message\"><span>'+this.options.dictDefaultMessage+\"</span></div>\")),this.clickableElements.length&&(i=function(e){return function(){return e.hiddenFileInput&&e.hiddenFileInput.parentNode.removeChild(e.hiddenFileInput),e.hiddenFileInput=document.createElement(\"input\"),e.hiddenFileInput.setAttribute(\"type\",\"file\"),(null==e.options.maxFiles||e.options.maxFiles>1)&&e.hiddenFileInput.setAttribute(\"multiple\",\"multiple\"),e.hiddenFileInput.className=\"dz-hidden-input\",null!=e.options.acceptedFiles&&e.hiddenFileInput.setAttribute(\"accept\",e.options.acceptedFiles),null!=e.options.capture&&e.hiddenFileInput.setAttribute(\"capture\",e.options.capture),e.hiddenFileInput.style.visibility=\"hidden\",e.hiddenFileInput.style.position=\"absolute\",e.hiddenFileInput.style.top=\"0\",e.hiddenFileInput.style.left=\"0\",e.hiddenFileInput.style.height=\"0\",e.hiddenFileInput.style.width=\"0\",document.querySelector(e.options.hiddenInputContainer).appendChild(e.hiddenFileInput),e.hiddenFileInput.addEventListener(\"change\",function(){var t,n,r,a;if(n=e.hiddenFileInput.files,n.length)for(r=0,a=n.length;a>r;r++)t=n[r],e.addFile(t);return e.emit(\"addedfiles\",n),i()})}}(this))(),this.URL=null!=(o=window.URL)?o:window.webkitURL,s=this.events,r=0,a=s.length;a>r;r++)e=s[r],this.on(e,this.options[e]);return this.on(\"uploadprogress\",function(e){return function(){return e.updateTotalUploadProgress()}}(this)),this.on(\"removedfile\",function(e){return function(){return e.updateTotalUploadProgress()}}(this)),this.on(\"canceled\",function(e){return function(t){return e.emit(\"complete\",t)}}(this)),this.on(\"complete\",function(e){return function(t){return 0===e.getAddedFiles().length&&0===e.getUploadingFiles().length&&0===e.getQueuedFiles().length?setTimeout(function(){return e.emit(\"queuecomplete\")},0):void 0}}(this)),t=function(e){return e.stopPropagation(),e.preventDefault?e.preventDefault():e.returnValue=!1},this.listeners=[{element:this.element,events:{dragstart:function(e){return function(t){return e.emit(\"dragstart\",t)}}(this),dragenter:function(e){return function(n){return t(n),e.emit(\"dragenter\",n)}}(this),dragover:function(e){return function(n){var i;try{i=n.dataTransfer.effectAllowed}catch(r){}return n.dataTransfer.dropEffect=\"move\"===i||\"linkMove\"===i?\"move\":\"copy\",t(n),e.emit(\"dragover\",n)}}(this),dragleave:function(e){return function(t){return e.emit(\"dragleave\",t)}}(this),drop:function(e){return function(n){return t(n),e.drop(n)}}(this),dragend:function(e){return function(t){return e.emit(\"dragend\",t)}}(this)}}],this.clickableElements.forEach(function(e){return function(t){return e.listeners.push({element:t,events:{click:function(i){return(t!==e.element||i.target===e.element||n.elementInside(i.target,e.element.querySelector(\".dz-message\")))&&e.hiddenFileInput.click(),!0}}})}}(this)),this.enable(),this.options.init.call(this)},n.prototype.destroy=function(){var e;return this.disable(),this.removeAllFiles(!0),(null!=(e=this.hiddenFileInput)?e.parentNode:void 0)&&(this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput),this.hiddenFileInput=null),delete this.element.dropzone,n.instances.splice(n.instances.indexOf(this),1)},n.prototype.updateTotalUploadProgress=function(){var e,t,n,i,r,a,o,s;if(i=0,n=0,e=this.getActiveFiles(),e.length){for(s=this.getActiveFiles(),a=0,o=s.length;o>a;a++)t=s[a],i+=t.upload.bytesSent,n+=t.upload.total;r=100*i/n}else r=100;return this.emit(\"totaluploadprogress\",r,n,i)},n.prototype._getParamName=function(e){return\"function\"==typeof this.options.paramName?this.options.paramName(e):\"\"+this.options.paramName+(this.options.uploadMultiple?\"[\"+e+\"]\":\"\")},n.prototype.getFallbackForm=function(){var e,t,i,r;return(e=this.getExistingFallback())?e:(i='<div class=\"dz-fallback\">',this.options.dictFallbackText&&(i+=\"<p>\"+this.options.dictFallbackText+\"</p>\"),i+='<input type=\"file\" name=\"'+this._getParamName(0)+'\" '+(this.options.uploadMultiple?'multiple=\"multiple\"':void 0)+' /><input type=\"submit\" value=\"Upload!\"></div>',t=n.createElement(i),\"FORM\"!==this.element.tagName?(r=n.createElement('<form action=\"'+this.options.url+'\" enctype=\"multipart/form-data\" method=\"'+this.options.method+'\"></form>'),r.appendChild(t)):(this.element.setAttribute(\"enctype\",\"multipart/form-data\"),this.element.setAttribute(\"method\",this.options.method)),null!=r?r:t)},n.prototype.getExistingFallback=function(){var e,t,n,i,r,a;for(t=function(e){var t,n,i;for(n=0,i=e.length;i>n;n++)if(t=e[n],/(^| )fallback($| )/.test(t.className))return t},a=[\"div\",\"form\"],i=0,r=a.length;r>i;i++)if(n=a[i],e=t(this.element.getElementsByTagName(n)))return e},n.prototype.setupEventListeners=function(){var e,t,n,i,r,a,o;for(a=this.listeners,o=[],i=0,r=a.length;r>i;i++)e=a[i],o.push(function(){var i,r;i=e.events,r=[];for(t in i)n=i[t],r.push(e.element.addEventListener(t,n,!1));return r}());return o},n.prototype.removeEventListeners=function(){var e,t,n,i,r,a,o;for(a=this.listeners,o=[],i=0,r=a.length;r>i;i++)e=a[i],o.push(function(){var i,r;i=e.events,r=[];for(t in i)n=i[t],r.push(e.element.removeEventListener(t,n,!1));return r}());return o},n.prototype.disable=function(){var e,t,n,i,r;for(this.clickableElements.forEach(function(e){return e.classList.remove(\"dz-clickable\")}),this.removeEventListeners(),i=this.files,r=[],t=0,n=i.length;n>t;t++)e=i[t],r.push(this.cancelUpload(e));return r},n.prototype.enable=function(){return this.clickableElements.forEach(function(e){return e.classList.add(\"dz-clickable\")}),this.setupEventListeners()},n.prototype.filesize=function(e){var t,n,i,r,a,o,s,l;if(i=0,r=\"b\",e>0){for(o=[\"TB\",\"GB\",\"MB\",\"KB\",\"b\"],n=s=0,l=o.length;l>s;n=++s)if(a=o[n],t=Math.pow(this.options.filesizeBase,4-n)/10,e>=t){i=e/Math.pow(this.options.filesizeBase,4-n),r=a;break}i=Math.round(10*i)/10}return\"<strong>\"+i+\"</strong> \"+r},n.prototype._updateMaxFilesReachedClass=function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit(\"maxfilesreached\",this.files),this.element.classList.add(\"dz-max-files-reached\")):this.element.classList.remove(\"dz-max-files-reached\")},n.prototype.drop=function(e){var t,n;e.dataTransfer&&(this.emit(\"drop\",e),t=e.dataTransfer.files,this.emit(\"addedfiles\",t),t.length&&(n=e.dataTransfer.items,n&&n.length&&null!=n[0].webkitGetAsEntry?this._addFilesFromItems(n):this.handleFiles(t)))},n.prototype.paste=function(e){var t,n;if(null!=(null!=e&&null!=(n=e.clipboardData)?n.items:void 0))return this.emit(\"paste\",e),t=e.clipboardData.items,t.length?this._addFilesFromItems(t):void 0},n.prototype.handleFiles=function(e){var t,n,i,r;for(r=[],n=0,i=e.length;i>n;n++)t=e[n],r.push(this.addFile(t));return r},n.prototype._addFilesFromItems=function(e){var t,n,i,r,a;for(a=[],i=0,r=e.length;r>i;i++)n=e[i],null!=n.webkitGetAsEntry&&(t=n.webkitGetAsEntry())?t.isFile?a.push(this.addFile(n.getAsFile())):t.isDirectory?a.push(this._addFilesFromDirectory(t,t.name)):a.push(void 0):null!=n.getAsFile&&(null==n.kind||\"file\"===n.kind)?a.push(this.addFile(n.getAsFile())):a.push(void 0);return a},n.prototype._addFilesFromDirectory=function(e,t){var n,i;return n=e.createReader(),i=function(e){return function(n){var i,r,a;for(r=0,a=n.length;a>r;r++)i=n[r],i.isFile?i.file(function(n){return e.options.ignoreHiddenFiles&&\".\"===n.name.substring(0,1)?void 0:(n.fullPath=\"\"+t+\"/\"+n.name,e.addFile(n))}):i.isDirectory&&e._addFilesFromDirectory(i,\"\"+t+\"/\"+i.name)}}(this),n.readEntries(i,function(e){return\"undefined\"!=typeof console&&null!==console&&\"function\"==typeof console.log?console.log(e):void 0})},n.prototype.accept=function(e,t){return e.size>1024*this.options.maxFilesize*1024?t(this.options.dictFileTooBig.replace(\"{{filesize}}\",Math.round(e.size/1024/10.24)/100).replace(\"{{maxFilesize}}\",this.options.maxFilesize)):n.isValidFile(e,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(t(this.options.dictMaxFilesExceeded.replace(\"{{maxFiles}}\",this.options.maxFiles)),this.emit(\"maxfilesexceeded\",e)):this.options.accept.call(this,e,t):t(this.options.dictInvalidFileType)},n.prototype.addFile=function(e){return e.upload={progress:0,total:e.size,bytesSent:0},this.files.push(e),e.status=n.ADDED,this.emit(\"addedfile\",e),this._enqueueThumbnail(e),this.accept(e,function(t){return function(n){return n?(e.accepted=!1,t._errorProcessing([e],n)):(e.accepted=!0,t.options.autoQueue&&t.enqueueFile(e)),t._updateMaxFilesReachedClass()}}(this))},n.prototype.enqueueFiles=function(e){var t,n,i;for(n=0,i=e.length;i>n;n++)t=e[n],this.enqueueFile(t);return null},n.prototype.enqueueFile=function(e){if(e.status!==n.ADDED||e.accepted!==!0)throw new Error(\"This file can't be queued because it has already been processed or was rejected.\");return e.status=n.QUEUED,this.options.autoProcessQueue?setTimeout(function(e){return function(){return e.processQueue()}}(this),0):void 0},n.prototype._thumbnailQueue=[],n.prototype._processingThumbnail=!1,n.prototype._enqueueThumbnail=function(e){return this.options.createImageThumbnails&&e.type.match(/image.*/)&&e.size<=1024*this.options.maxThumbnailFilesize*1024?(this._thumbnailQueue.push(e),setTimeout(function(e){return function(){return e._processThumbnailQueue()}}(this),0)):void 0},n.prototype._processThumbnailQueue=function(){return this._processingThumbnail||0===this._thumbnailQueue.length?void 0:(this._processingThumbnail=!0,this.createThumbnail(this._thumbnailQueue.shift(),function(e){return function(){return e._processingThumbnail=!1,e._processThumbnailQueue()}}(this)))},n.prototype.removeFile=function(e){return e.status===n.UPLOADING&&this.cancelUpload(e),this.files=s(this.files,e),this.emit(\"removedfile\",e),0===this.files.length?this.emit(\"reset\"):void 0},n.prototype.removeAllFiles=function(e){var t,i,r,a;for(null==e&&(e=!1),a=this.files.slice(),i=0,r=a.length;r>i;i++)t=a[i],(t.status!==n.UPLOADING||e)&&this.removeFile(t);return null},n.prototype.createThumbnail=function(e,t){var n;return n=new FileReader,n.onload=function(i){return function(){return\"image/svg+xml\"===e.type?(i.emit(\"thumbnail\",e,n.result),void(null!=t&&t())):i.createThumbnailFromUrl(e,n.result,t)}}(this),n.readAsDataURL(e)},n.prototype.createThumbnailFromUrl=function(e,t,n,i){var r;return r=document.createElement(\"img\"),i&&(r.crossOrigin=i),r.onload=function(t){return function(){var i,o,s,l,c,d,u,p;return e.width=r.width,e.height=r.height,s=t.options.resize.call(t,e),null==s.trgWidth&&(s.trgWidth=s.optWidth),null==s.trgHeight&&(s.trgHeight=s.optHeight),i=document.createElement(\"canvas\"),o=i.getContext(\"2d\"),i.width=s.trgWidth,i.height=s.trgHeight,a(o,r,null!=(c=s.srcX)?c:0,null!=(d=s.srcY)?d:0,s.srcWidth,s.srcHeight,null!=(u=s.trgX)?u:0,null!=(p=s.trgY)?p:0,s.trgWidth,s.trgHeight),l=i.toDataURL(\"image/png\"),t.emit(\"thumbnail\",e,l),null!=n?n():void 0}}(this),null!=n&&(r.onerror=n),r.src=t},n.prototype.processQueue=function(){var e,t,n,i;if(t=this.options.parallelUploads,n=this.getUploadingFiles().length,e=n,!(n>=t)&&(i=this.getQueuedFiles(),i.length>0)){if(this.options.uploadMultiple)return this.processFiles(i.slice(0,t-n));for(;t>e;){if(!i.length)return;this.processFile(i.shift()),e++}}},n.prototype.processFile=function(e){return this.processFiles([e])},n.prototype.processFiles=function(e){var t,i,r;for(i=0,r=e.length;r>i;i++)t=e[i],t.processing=!0,t.status=n.UPLOADING,this.emit(\"processing\",t);return this.options.uploadMultiple&&this.emit(\"processingmultiple\",e),this.uploadFiles(e)},n.prototype._getFilesWithXhr=function(e){var t,n;return n=function(){var n,i,r,a;for(r=this.files,a=[],n=0,i=r.length;i>n;n++)t=r[n],t.xhr===e&&a.push(t);return a}.call(this)},n.prototype.cancelUpload=function(e){var t,i,r,a,o,s,l;if(e.status===n.UPLOADING){for(i=this._getFilesWithXhr(e.xhr),r=0,o=i.length;o>r;r++)t=i[r],t.status=n.CANCELED;for(e.xhr.abort(),a=0,s=i.length;s>a;a++)t=i[a],this.emit(\"canceled\",t);this.options.uploadMultiple&&this.emit(\"canceledmultiple\",i)}else((l=e.status)===n.ADDED||l===n.QUEUED)&&(e.status=n.CANCELED,this.emit(\"canceled\",e),this.options.uploadMultiple&&this.emit(\"canceledmultiple\",[e]));return this.options.autoProcessQueue?this.processQueue():void 0},r=function(){var e,t;return t=arguments[0],e=2<=arguments.length?l.call(arguments,1):[],\"function\"==typeof t?t.apply(this,e):t},n.prototype.uploadFile=function(e){return this.uploadFiles([e])},n.prototype.uploadFiles=function(e){var t,a,o,s,l,c,d,u,p,m,g,h,f,_,b,v,C,I,y,S,E,x,T,w,A,P,D,G,M,N,L,k,R,O;for(y=new XMLHttpRequest,S=0,w=e.length;w>S;S++)t=e[S],t.xhr=y;h=r(this.options.method,e),C=r(this.options.url,e),y.open(h,C,!0),y.withCredentials=!!this.options.withCredentials,b=null,o=function(n){return function(){var i,r,a;for(a=[],i=0,r=e.length;r>i;i++)t=e[i],a.push(n._errorProcessing(e,b||n.options.dictResponseError.replace(\"{{statusCode}}\",y.status),y));return a}}(this),v=function(n){return function(i){var r,a,o,s,l,c,d,u,p;if(null!=i)for(a=100*i.loaded/i.total,o=0,c=e.length;c>o;o++)t=e[o],t.upload={progress:a,total:i.total,bytesSent:i.loaded};else{for(r=!0,a=100,s=0,d=e.length;d>s;s++)t=e[s],(100!==t.upload.progress||t.upload.bytesSent!==t.upload.total)&&(r=!1),t.upload.progress=a,t.upload.bytesSent=t.upload.total;if(r)return}for(p=[],l=0,u=e.length;u>l;l++)t=e[l],p.push(n.emit(\"uploadprogress\",t,a,t.upload.bytesSent));return p}}(this),y.onload=function(t){return function(i){var r;if(e[0].status!==n.CANCELED&&4===y.readyState){if(b=y.responseText,y.getResponseHeader(\"content-type\")&&~y.getResponseHeader(\"content-type\").indexOf(\"application/json\"))try{b=JSON.parse(b)}catch(a){i=a,b=\"Invalid JSON response from server.\"}return v(),200<=(r=y.status)&&300>r?t._finished(e,b,i):o()}}}(this),y.onerror=function(t){return function(){return e[0].status!==n.CANCELED?o():void 0}}(this),_=null!=(M=y.upload)?M:y,_.onprogress=v,c={Accept:\"application/json\",\"Cache-Control\":\"no-cache\",\"X-Requested-With\":\"XMLHttpRequest\"},this.options.headers&&i(c,this.options.headers);for(s in c)l=c[s],l&&y.setRequestHeader(s,l);if(a=new FormData,this.options.params){N=this.options.params;for(g in N)I=N[g],a.append(g,I)}for(E=0,A=e.length;A>E;E++)t=e[E],this.emit(\"sending\",t,y,a);if(this.options.uploadMultiple&&this.emit(\"sendingmultiple\",e,y,a),\"FORM\"===this.element.tagName)for(L=this.element.querySelectorAll(\"input, textarea, select, button\"),x=0,P=L.length;P>x;x++)if(u=L[x],p=u.getAttribute(\"name\"),m=u.getAttribute(\"type\"),\"SELECT\"===u.tagName&&u.hasAttribute(\"multiple\"))for(k=u.options,T=0,D=k.length;D>T;T++)f=k[T],f.selected&&a.append(p,f.value);else(!m||\"checkbox\"!==(R=m.toLowerCase())&&\"radio\"!==R||u.checked)&&a.append(p,u.value);for(d=G=0,O=e.length-1;O>=0?O>=G:G>=O;d=O>=0?++G:--G)a.append(this._getParamName(d),e[d],e[d].name);return this.submitRequest(y,a,e)},n.prototype.submitRequest=function(e,t,n){return e.send(t)},n.prototype._finished=function(e,t,i){var r,a,o;for(a=0,o=e.length;o>a;a++)r=e[a],r.status=n.SUCCESS,this.emit(\"success\",r,t,i),this.emit(\"complete\",r);return this.options.uploadMultiple&&(this.emit(\"successmultiple\",e,t,i),this.emit(\"completemultiple\",e)),this.options.autoProcessQueue?this.processQueue():void 0},n.prototype._errorProcessing=function(e,t,i){var r,a,o;for(a=0,o=e.length;o>a;a++)r=e[a],r.status=n.ERROR,this.emit(\"error\",r,t,i),this.emit(\"complete\",r);return this.options.uploadMultiple&&(this.emit(\"errormultiple\",e,t,i),this.emit(\"completemultiple\",e)),this.options.autoProcessQueue?this.processQueue():void 0},n}(t),e.version=\"4.2.0\",e.options={},e.optionsForElement=function(t){return t.getAttribute(\"id\")?e.options[n(t.getAttribute(\"id\"))]:void 0},e.instances=[],e.forElement=function(e){if(\"string\"==typeof e&&(e=document.querySelector(e)),null==(null!=e?e.dropzone:void 0))throw new Error(\"No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.\");return e.dropzone},e.autoDiscover=!0,e.discover=function(){var t,n,i,r,a,o;for(document.querySelectorAll?i=document.querySelectorAll(\".dropzone\"):(i=[],t=function(e){var t,n,r,a;for(a=[],n=0,r=e.length;r>n;n++)t=e[n],/(^| )dropzone($| )/.test(t.className)?a.push(i.push(t)):a.push(void 0);return a},t(document.getElementsByTagName(\"div\")),t(document.getElementsByTagName(\"form\"))),o=[],r=0,a=i.length;a>r;r++)n=i[r],e.optionsForElement(n)!==!1?o.push(new e(n)):o.push(void 0);return o},e.blacklistedBrowsers=[/opera.*Macintosh.*version\\/12/i],e.isBrowserSupported=function(){var t,n,i,r,a;if(t=!0,window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector)if(\"classList\"in document.createElement(\"a\"))for(a=e.blacklistedBrowsers,i=0,r=a.length;r>i;i++)n=a[i],n.test(navigator.userAgent)&&(t=!1);else t=!1;else t=!1;return t},s=function(e,t){var n,i,r,a;for(a=[],i=0,r=e.length;r>i;i++)n=e[i],n!==t&&a.push(n);return a},n=function(e){return e.replace(/[\\-_](\\w)/g,function(e){return e.charAt(1).toUpperCase()})},e.createElement=function(e){var t;return t=document.createElement(\"div\"),t.innerHTML=e,t.childNodes[0]},e.elementInside=function(e,t){if(e===t)return!0;for(;e=e.parentNode;)if(e===t)return!0;return!1},e.getElement=function(e,t){var n;if(\"string\"==typeof e?n=document.querySelector(e):null!=e.nodeType&&(n=e),null==n)throw new Error(\"Invalid `\"+t+\"` option provided. Please provide a CSS selector or a plain HTML element.\");return n},e.getElements=function(e,t){var n,i,r,a,o,s,l,c;if(e instanceof Array){r=[];try{for(a=0,s=e.length;s>a;a++)i=e[a],r.push(this.getElement(i,t))}catch(d){n=d,r=null}}else if(\"string\"==typeof e)for(r=[],c=document.querySelectorAll(e),o=0,l=c.length;l>o;o++)i=c[o],r.push(i);else null!=e.nodeType&&(r=[e]);if(null==r||!r.length)throw new Error(\"Invalid `\"+t+\"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.\");\nreturn r},e.confirm=function(e,t,n){return window.confirm(e)?t():null!=n?n():void 0},e.isValidFile=function(e,t){var n,i,r,a,o;if(!t)return!0;for(t=t.split(\",\"),i=e.type,n=i.replace(/\\/.*$/,\"\"),a=0,o=t.length;o>a;a++)if(r=t[a],r=r.trim(),\".\"===r.charAt(0)){if(-1!==e.name.toLowerCase().indexOf(r.toLowerCase(),e.name.length-r.length))return!0}else if(/\\/\\*$/.test(r)){if(n===r.replace(/\\/.*$/,\"\"))return!0}else if(i===r)return!0;return!1},\"undefined\"!=typeof jQuery&&null!==jQuery&&(jQuery.fn.dropzone=function(t){return this.each(function(){return new e(this,t)})}),\"undefined\"!=typeof module&&null!==module?module.exports=e:window.Dropzone=e,e.ADDED=\"added\",e.QUEUED=\"queued\",e.ACCEPTED=e.QUEUED,e.UPLOADING=\"uploading\",e.PROCESSING=e.UPLOADING,e.CANCELED=\"canceled\",e.ERROR=\"error\",e.SUCCESS=\"success\",r=function(e){var t,n,i,r,a,o,s,l,c,d;for(s=e.naturalWidth,o=e.naturalHeight,n=document.createElement(\"canvas\"),n.width=1,n.height=o,i=n.getContext(\"2d\"),i.drawImage(e,0,0),r=i.getImageData(0,0,1,o).data,d=0,a=o,l=o;l>d;)t=r[4*(l-1)+3],0===t?a=l:d=l,l=a+d>>1;return c=l/o,0===c?1:c},a=function(e,t,n,i,a,o,s,l,c,d){var u;return u=r(t),e.drawImage(t,n,i,a,o,s,l,c,d/u)},i=function(e,t){var n,i,r,a,o,s,l,c,d;if(r=!1,d=!0,i=e.document,c=i.documentElement,n=i.addEventListener?\"addEventListener\":\"attachEvent\",l=i.addEventListener?\"removeEventListener\":\"detachEvent\",s=i.addEventListener?\"\":\"on\",a=function(n){return\"readystatechange\"!==n.type||\"complete\"===i.readyState?((\"load\"===n.type?e:i)[l](s+n.type,a,!1),!r&&(r=!0)?t.call(e,n.type||n):void 0):void 0},o=function(){var e;try{c.doScroll(\"left\")}catch(t){return e=t,void setTimeout(o,50)}return a(\"poll\")},\"complete\"!==i.readyState){if(i.createEventObject&&c.doScroll){try{d=!e.frameElement}catch(u){}d&&o()}return i[n](s+\"DOMContentLoaded\",a,!1),i[n](s+\"readystatechange\",a,!1),e[n](s+\"load\",a,!1)}},e._autoDiscoverFunction=function(){return e.autoDiscover?e.discover():void 0},i(window,e._autoDiscoverFunction)}.call(this),function(e){function t(e,t,r){var a=e.scrollTop;e.setSelectionRange?n(e,t,r):document.selection&&i(e,t,r),e.scrollTop=a}function n(e,t,n){var i=e.selectionStart,r=e.selectionEnd;if(i===r)t?i-n.tabString===e.value.substring(i-n.tabString.length,i)?(e.value=e.value.substring(0,i-n.tabString.length)+e.value.substring(i),e.focus(),e.setSelectionRange(i-n.tabString.length,i-n.tabString.length)):i-n.tabString===e.value.substring(i,i+n.tabString.length)&&(e.value=e.value.substring(0,i)+e.value.substring(i+n.tabString.length),e.focus(),e.setSelectionRange(i,i)):(e.value=e.value.substring(0,i)+n.tabString+e.value.substring(i),e.focus(),e.setSelectionRange(i+n.tabString.length,i+n.tabString.length));else{for(;i<e.value.length&&e.value.charAt(i).match(/[ \\t]/);)i++;var a=e.value.split(\"\\n\"),o=[],s=0,l=0,c=0;for(c in a)l=s+a[c].length,o.push({start:s,end:l,selected:i>=s&&l>i||l>=r&&r>s||s>i&&r>l}),s=l+1;var d=0;for(c in o)if(o[c].selected){var u=o[c].start+d;t&&n.tabString===e.value.substring(u,u+n.tabString.length)?(e.value=e.value.substring(0,u)+e.value.substring(u+n.tabString.length),d-=n.tabString.length):t||(e.value=e.value.substring(0,u)+n.tabString+e.value.substring(u),d+=n.tabString.length)}e.focus();var p=i+(d>0?n.tabString.length:0>d?-n.tabString.length:0),m=r+d;e.setSelectionRange(p,m)}}function i(t,n,i){var r=document.selection.createRange();if(t===r.parentElement())if(\"\"===r.text)if(n){var a=r.getBookmark();r.moveStart(\"character\",-i.tabString.length),i.tabString===r.text?r.text=\"\":(r.moveToBookmark(a),r.moveEnd(\"character\",i.tabString.length),i.tabString===r.text&&(r.text=\"\")),r.collapse(!0),r.select()}else r.text=i.tabString,r.collapse(!1),r.select();else{var o=r.text,s=o.length,l=o.split(\"\\r\\n\"),c=document.body.createTextRange();c.moveToElementText(t),c.setEndPoint(\"EndToStart\",r);var d=c.text,u=d.split(\"\\r\\n\"),p=d.length,m=document.body.createTextRange();m.moveToElementText(t),m.setEndPoint(\"StartToEnd\",r);var g=m.text,h=document.body.createTextRange();h.moveToElementText(t),h.setEndPoint(\"StartToEnd\",c);var f=h.text,_=e(t).html();e(\"#r3\").text(p+\" + \"+s+\" + \"+g.length+\" = \"+_.length),p+f.length<_.length?(u.push(\"\"),p+=2,n&&i.tabString===l[0].substring(0,i.tabString.length)?l[0]=l[0].substring(i.tabString.length):n||(l[0]=i.tabString+l[0])):n&&i.tabString===u[u.length-1].substring(0,i.tabString.length)?u[u.length-1]=u[u.length-1].substring(i.tabString.length):n||(u[u.length-1]=i.tabString+u[u.length-1]);for(var b=1;b<l.length;b++)n&&i.tabString===l[b].substring(0,i.tabString.length)?l[b]=l[b].substring(i.tabString.length):n||(l[b]=i.tabString+l[b]);1===u.length&&0===p&&(n&&i.tabString===l[0].substring(0,i.tabString.length)?l[0]=l[0].substring(i.tabString.length):n||(l[0]=i.tabString+l[0])),p+s+g.length<_.length&&(l.push(\"\"),s+=2),c.text=u.join(\"\\r\\n\"),r.text=l.join(\"\\r\\n\");var v=document.body.createTextRange();v.moveToElementText(t),p>0?v.setEndPoint(\"StartToEnd\",c):v.setEndPoint(\"StartToStart\",c),v.setEndPoint(\"EndToEnd\",r),v.select()}}e.fn.tabby=function(n){var i=e.extend({},e.fn.tabby.defaults,n),r=e.fn.tabby.pressed;return this.each(function(){var n=e(this),a=e.meta?e.extend({},i,n.data()):i;n.bind(\"keydown\",function(n){var i=e.fn.tabby.catch_kc(n);return 16===i&&(r.shft=!0),17===i&&(r.ctrl=!0,setTimeout(function(){e.fn.tabby.pressed.ctrl=!1},1e3)),18===i&&(r.alt=!0,setTimeout(function(){e.fn.tabby.pressed.alt=!1},1e3)),9!==i||r.ctrl||r.alt?void 0:(n.preventDefault(),r.last=i,setTimeout(function(){e.fn.tabby.pressed.last=null},0),t(e(n.target).get(0),r.shft,a),!1)}).bind(\"keyup\",function(t){16===e.fn.tabby.catch_kc(t)&&(r.shft=!1)}).bind(\"blur\",function(t){9===r.last&&e(t.target).one(\"focus\",function(){r.last=null}).get(0).focus()})})},e.fn.tabby.catch_kc=function(e){return e.keyCode?e.keyCode:e.charCode?e.charCode:e.which},e.fn.tabby.pressed={shft:!1,ctrl:!1,alt:!1,last:null},e.fn.tabby.defaults={tabString:String.fromCharCode(9)}}(jQuery),function(e,t){if(\"function\"==typeof define&&define.amd)define([\"exports\",\"module\"],t);else if(\"undefined\"!=typeof exports&&\"undefined\"!=typeof module)t(exports,module);else{var n={exports:{}};t(n.exports,n),e.autosize=n.exports}}(this,function(e,t){\"use strict\";function n(e){function t(){var t=window.getComputedStyle(e,null);p=t.overflowY,\"vertical\"===t.resize?e.style.resize=\"none\":\"both\"===t.resize&&(e.style.resize=\"horizontal\"),u=\"content-box\"===t.boxSizing?-(parseFloat(t.paddingTop)+parseFloat(t.paddingBottom)):parseFloat(t.borderTopWidth)+parseFloat(t.borderBottomWidth),isNaN(u)&&(u=0),r()}function n(t){var n=e.style.width;e.style.width=\"0px\",e.offsetWidth,e.style.width=n,p=t,d&&(e.style.overflowY=t),i()}function i(){var t=window.pageYOffset,n=document.body.scrollTop,i=e.style.height;e.style.height=\"auto\";var r=e.scrollHeight+u;return 0===e.scrollHeight?void(e.style.height=i):(e.style.height=r+\"px\",m=e.clientWidth,document.documentElement.scrollTop=t,void(document.body.scrollTop=n))}function r(){var t=e.style.height;i();var r=window.getComputedStyle(e,null);if(r.height!==e.style.height?\"visible\"!==p&&n(\"visible\"):\"hidden\"!==p&&n(\"hidden\"),t!==e.style.height){var a=document.createEvent(\"Event\");a.initEvent(\"autosize:resized\",!0,!1),e.dispatchEvent(a)}}var o=void 0===arguments[1]?{}:arguments[1],s=o.setOverflowX,l=void 0===s?!0:s,c=o.setOverflowY,d=void 0===c?!0:c;if(e&&e.nodeName&&\"TEXTAREA\"===e.nodeName&&!a.has(e)){var u=null,p=null,m=e.clientWidth,g=function(){e.clientWidth!==m&&r()},h=function(t){window.removeEventListener(\"resize\",g,!1),e.removeEventListener(\"input\",r,!1),e.removeEventListener(\"keyup\",r,!1),e.removeEventListener(\"autosize:destroy\",h,!1),e.removeEventListener(\"autosize:update\",r,!1),a[\"delete\"](e),Object.keys(t).forEach(function(n){e.style[n]=t[n]})}.bind(e,{height:e.style.height,resize:e.style.resize,overflowY:e.style.overflowY,overflowX:e.style.overflowX,wordWrap:e.style.wordWrap});e.addEventListener(\"autosize:destroy\",h,!1),\"onpropertychange\"in e&&\"oninput\"in e&&e.addEventListener(\"keyup\",r,!1),window.addEventListener(\"resize\",g,!1),e.addEventListener(\"input\",r,!1),e.addEventListener(\"autosize:update\",r,!1),a.add(e),l&&(e.style.overflowX=\"hidden\",e.style.wordWrap=\"break-word\"),t()}}function i(e){if(e&&e.nodeName&&\"TEXTAREA\"===e.nodeName){var t=document.createEvent(\"Event\");t.initEvent(\"autosize:destroy\",!0,!1),e.dispatchEvent(t)}}function r(e){if(e&&e.nodeName&&\"TEXTAREA\"===e.nodeName){var t=document.createEvent(\"Event\");t.initEvent(\"autosize:update\",!0,!1),e.dispatchEvent(t)}}var a=\"function\"==typeof Set?new Set:function(){var e=[];return{has:function(t){return Boolean(e.indexOf(t)>-1)},add:function(t){e.push(t)},\"delete\":function(t){e.splice(e.indexOf(t),1)}}}(),o=null;\"undefined\"==typeof window||\"function\"!=typeof window.getComputedStyle?(o=function(e){return e},o.destroy=function(e){return e},o.update=function(e){return e}):(o=function(e,t){return e&&Array.prototype.forEach.call(e.length?e:[e],function(e){return n(e,t)}),e},o.destroy=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],i),e},o.update=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],r),e}),t.exports=o}),function(e){\"undefined\"!=typeof exports?e(exports):(window.hljs=e({}),\"function\"==typeof define&&define.amd&&define(\"hljs\",[],function(){return window.hljs}))}(function(e){function t(e){return e.replace(/&/gm,\"&amp;\").replace(/</gm,\"&lt;\").replace(/>/gm,\"&gt;\")}function n(e){return e.nodeName.toLowerCase()}function i(e,t){var n=e&&e.exec(t);return n&&0==n.index}function r(e){return/^(no-?highlight|plain|text)$/i.test(e)}function a(e){var t,n,i,a=e.className+\" \";if(a+=e.parentNode?e.parentNode.className:\"\",n=/\\blang(?:uage)?-([\\w-]+)\\b/i.exec(a))return C(n[1])?n[1]:\"no-highlight\";for(a=a.split(/\\s+/),t=0,i=a.length;i>t;t++)if(C(a[t])||r(a[t]))return a[t]}function o(e,t){var n,i={};for(n in e)i[n]=e[n];if(t)for(n in t)i[n]=t[n];return i}function s(e){var t=[];return function i(e,r){for(var a=e.firstChild;a;a=a.nextSibling)3==a.nodeType?r+=a.nodeValue.length:1==a.nodeType&&(t.push({event:\"start\",offset:r,node:a}),r=i(a,r),n(a).match(/br|hr|img|input/)||t.push({event:\"stop\",offset:r,node:a}));return r}(e,0),t}function l(e,i,r){function a(){return e.length&&i.length?e[0].offset!=i[0].offset?e[0].offset<i[0].offset?e:i:\"start\"==i[0].event?e:i:e.length?e:i}function o(e){function i(e){return\" \"+e.nodeName+'=\"'+t(e.value)+'\"'}d+=\"<\"+n(e)+Array.prototype.map.call(e.attributes,i).join(\"\")+\">\"}function s(e){d+=\"</\"+n(e)+\">\"}function l(e){(\"start\"==e.event?o:s)(e.node)}for(var c=0,d=\"\",u=[];e.length||i.length;){var p=a();if(d+=t(r.substr(c,p[0].offset-c)),c=p[0].offset,p==e){u.reverse().forEach(s);do l(p.splice(0,1)[0]),p=a();while(p==e&&p.length&&p[0].offset==c);u.reverse().forEach(o)}else\"start\"==p[0].event?u.push(p[0].node):u.pop(),l(p.splice(0,1)[0])}return d+t(r.substr(c))}function c(e){function t(e){return e&&e.source||e}function n(n,i){return new RegExp(t(n),\"m\"+(e.case_insensitive?\"i\":\"\")+(i?\"g\":\"\"))}function i(r,a){if(!r.compiled){if(r.compiled=!0,r.keywords=r.keywords||r.beginKeywords,r.keywords){var s={},l=function(t,n){e.case_insensitive&&(n=n.toLowerCase()),n.split(\" \").forEach(function(e){var n=e.split(\"|\");s[n[0]]=[t,n[1]?Number(n[1]):1]})};\"string\"==typeof r.keywords?l(\"keyword\",r.keywords):Object.keys(r.keywords).forEach(function(e){l(e,r.keywords[e])}),r.keywords=s}r.lexemesRe=n(r.lexemes||/\\b\\w+\\b/,!0),a&&(r.beginKeywords&&(r.begin=\"\\\\b(\"+r.beginKeywords.split(\" \").join(\"|\")+\")\\\\b\"),r.begin||(r.begin=/\\B|\\b/),r.beginRe=n(r.begin),r.end||r.endsWithParent||(r.end=/\\B|\\b/),r.end&&(r.endRe=n(r.end)),r.terminator_end=t(r.end)||\"\",r.endsWithParent&&a.terminator_end&&(r.terminator_end+=(r.end?\"|\":\"\")+a.terminator_end)),r.illegal&&(r.illegalRe=n(r.illegal)),void 0===r.relevance&&(r.relevance=1),r.contains||(r.contains=[]);var c=[];r.contains.forEach(function(e){e.variants?e.variants.forEach(function(t){c.push(o(e,t))}):c.push(\"self\"==e?r:e)}),r.contains=c,r.contains.forEach(function(e){i(e,r)}),r.starts&&i(r.starts,a);var d=r.contains.map(function(e){return e.beginKeywords?\"\\\\.?(\"+e.begin+\")\\\\.?\":e.begin}).concat([r.terminator_end,r.illegal]).map(t).filter(Boolean);r.terminators=d.length?n(d.join(\"|\"),!0):{exec:function(){return null}}}}i(e)}function d(e,n,r,a){function o(e,t){for(var n=0;n<t.contains.length;n++)if(i(t.contains[n].beginRe,e))return t.contains[n]}function s(e,t){if(i(e.endRe,t)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.endsWithParent?s(e.parent,t):void 0}function l(e,t){return!r&&i(t.illegalRe,e)}function p(e,t){var n=v.case_insensitive?t[0].toLowerCase():t[0];return e.keywords.hasOwnProperty(n)&&e.keywords[n]}function m(e,t,n,i){var r=i?\"\":I.classPrefix,a='<span class=\"'+r,o=n?\"\":\"</span>\";return a+=e+'\">',a+t+o}function g(){if(!E.keywords)return t(w);var e=\"\",n=0;E.lexemesRe.lastIndex=0;for(var i=E.lexemesRe.exec(w);i;){e+=t(w.substr(n,i.index-n));var r=p(E,i);r?(A+=r[1],e+=m(r[0],t(i[0]))):e+=t(i[0]),n=E.lexemesRe.lastIndex,i=E.lexemesRe.exec(w)}return e+t(w.substr(n))}function h(){var e=\"string\"==typeof E.subLanguage;if(e&&!y[E.subLanguage])return t(w);var n=e?d(E.subLanguage,w,!0,x[E.subLanguage]):u(w,E.subLanguage.length?E.subLanguage:void 0);return E.relevance>0&&(A+=n.relevance),e&&(x[E.subLanguage]=n.top),m(n.language,n.value,!1,!0)}function f(){return void 0!==E.subLanguage?h():g()}function _(e,n){var i=e.className?m(e.className,\"\",!0):\"\";e.returnBegin?(T+=i,w=\"\"):e.excludeBegin?(T+=t(n)+i,w=\"\"):(T+=i,w=n),E=Object.create(e,{parent:{value:E}})}function b(e,n){if(w+=e,void 0===n)return T+=f(),0;var i=o(n,E);if(i)return T+=f(),_(i,n),i.returnBegin?0:n.length;var r=s(E,n);if(r){var a=E;a.returnEnd||a.excludeEnd||(w+=n),T+=f();do E.className&&(T+=\"</span>\"),A+=E.relevance,E=E.parent;while(E!=r.parent);return a.excludeEnd&&(T+=t(n)),w=\"\",r.starts&&_(r.starts,\"\"),a.returnEnd?0:n.length}if(l(n,E))throw new Error('Illegal lexeme \"'+n+'\" for mode \"'+(E.className||\"<unnamed>\")+'\"');return w+=n,n.length||1}var v=C(e);if(!v)throw new Error('Unknown language: \"'+e+'\"');c(v);var S,E=a||v,x={},T=\"\";for(S=E;S!=v;S=S.parent)S.className&&(T=m(S.className,\"\",!0)+T);var w=\"\",A=0;try{for(var P,D,G=0;;){if(E.terminators.lastIndex=G,P=E.terminators.exec(n),!P)break;D=b(n.substr(G,P.index-G),P[0]),G=P.index+D}for(b(n.substr(G)),S=E;S.parent;S=S.parent)S.className&&(T+=\"</span>\");return{relevance:A,value:T,language:e,top:E}}catch(M){if(-1!=M.message.indexOf(\"Illegal\"))return{relevance:0,value:t(n)};throw M}}function u(e,n){n=n||I.languages||Object.keys(y);var i={relevance:0,value:t(e)},r=i;return n.forEach(function(t){if(C(t)){var n=d(t,e,!1);n.language=t,n.relevance>r.relevance&&(r=n),n.relevance>i.relevance&&(r=i,i=n)}}),r.language&&(i.second_best=r),i}function p(e){return I.tabReplace&&(e=e.replace(/^((<[^>]+>|\\t)+)/gm,function(e,t){return t.replace(/\\t/g,I.tabReplace)})),I.useBR&&(e=e.replace(/\\n/g,\"<br>\")),e}function m(e,t,n){var i=t?S[t]:n,r=[e.trim()];return e.match(/\\bhljs\\b/)||r.push(\"hljs\"),-1===e.indexOf(i)&&r.push(i),r.join(\" \").trim()}function g(e){var t=a(e);if(!r(t)){var n;I.useBR?(n=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\"),n.innerHTML=e.innerHTML.replace(/\\n/g,\"\").replace(/<br[ \\/]*>/g,\"\\n\")):n=e;var i=n.textContent,o=t?d(t,i,!0):u(i),c=s(n);if(c.length){var g=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\");g.innerHTML=o.value,o.value=l(c,s(g),i)}o.value=p(o.value),e.innerHTML=o.value,e.className=m(e.className,t,o.language),e.result={language:o.language,re:o.relevance},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.relevance})}}function h(e){I=o(I,e)}function f(){if(!f.called){f.called=!0;var e=document.querySelectorAll(\"pre code\");Array.prototype.forEach.call(e,g)}}function _(){addEventListener(\"DOMContentLoaded\",f,!1),addEventListener(\"load\",f,!1)}function b(t,n){var i=y[t]=n(e);i.aliases&&i.aliases.forEach(function(e){S[e]=t})}function v(){return Object.keys(y)}function C(e){return e=(e||\"\").toLowerCase(),y[e]||y[S[e]]}var I={classPrefix:\"hljs-\",tabReplace:null,useBR:!1,languages:void 0},y={},S={};return e.highlight=d,e.highlightAuto=u,e.fixMarkup=p,e.highlightBlock=g,e.configure=h,e.initHighlighting=f,e.initHighlightingOnLoad=_,e.registerLanguage=b,e.listLanguages=v,e.getLanguage=C,e.inherit=o,e.IDENT_RE=\"[a-zA-Z]\\\\w*\",e.UNDERSCORE_IDENT_RE=\"[a-zA-Z_]\\\\w*\",e.NUMBER_RE=\"\\\\b\\\\d+(\\\\.\\\\d+)?\",e.C_NUMBER_RE=\"(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)\",e.BINARY_NUMBER_RE=\"\\\\b(0b[01]+)\",e.RE_STARTERS_RE=\"!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~\",e.BACKSLASH_ESCAPE={begin:\"\\\\\\\\[\\\\s\\\\S]\",relevance:0},e.APOS_STRING_MODE={className:\"string\",begin:\"'\",end:\"'\",illegal:\"\\\\n\",contains:[e.BACKSLASH_ESCAPE]},e.QUOTE_STRING_MODE={className:\"string\",begin:'\"',end:'\"',illegal:\"\\\\n\",contains:[e.BACKSLASH_ESCAPE]},e.PHRASAL_WORDS_MODE={begin:/\\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\\b/},e.COMMENT=function(t,n,i){var r=e.inherit({className:\"comment\",begin:t,end:n,contains:[]},i||{});return r.contains.push(e.PHRASAL_WORDS_MODE),r.contains.push({className:\"doctag\",begin:\"(?:TODO|FIXME|NOTE|BUG|XXX):\",relevance:0}),r},e.C_LINE_COMMENT_MODE=e.COMMENT(\"//\",\"$\"),e.C_BLOCK_COMMENT_MODE=e.COMMENT(\"/\\\\*\",\"\\\\*/\"),e.HASH_COMMENT_MODE=e.COMMENT(\"#\",\"$\"),e.NUMBER_MODE={className:\"number\",begin:e.NUMBER_RE,relevance:0},e.C_NUMBER_MODE={className:\"number\",begin:e.C_NUMBER_RE,relevance:0},e.BINARY_NUMBER_MODE={className:\"number\",begin:e.BINARY_NUMBER_RE,relevance:0},e.CSS_NUMBER_MODE={className:\"number\",begin:e.NUMBER_RE+\"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?\",relevance:0},e.REGEXP_MODE={className:\"regexp\",begin:/\\//,end:/\\/[gimuy]*/,illegal:/\\n/,contains:[e.BACKSLASH_ESCAPE,{begin:/\\[/,end:/\\]/,relevance:0,contains:[e.BACKSLASH_ESCAPE]}]},e.TITLE_MODE={className:\"title\",begin:e.IDENT_RE,relevance:0},e.UNDERSCORE_TITLE_MODE={className:\"title\",begin:e.UNDERSCORE_IDENT_RE,relevance:0},e.registerLanguage(\"1c\",function(e){var t=\"[a-zA-Zа-яА-Я][a-zA-Z0-9_а-яА-Я]*\",n=\"возврат дата для если и или иначе иначеесли исключение конецесли конецпопытки конецпроцедуры конецфункции конеццикла константа не перейти перем перечисление по пока попытка прервать продолжить процедура строка тогда фс функция цикл число экспорт\",i=\"ansitooem oemtoansi ввестивидсубконто ввестидату ввестизначение ввестиперечисление ввестипериод ввестиплансчетов ввестистроку ввестичисло вопрос восстановитьзначение врег выбранныйплансчетов вызватьисключение датагод датамесяц датачисло добавитьмесяц завершитьработусистемы заголовоксистемы записьжурналарегистрации запуститьприложение зафиксироватьтранзакцию значениевстроку значениевстрокувнутр значениевфайл значениеизстроки значениеизстрокивнутр значениеизфайла имякомпьютера имяпользователя каталогвременныхфайлов каталогиб каталогпользователя каталогпрограммы кодсимв командасистемы конгода конецпериодаби конецрассчитанногопериодаби конецстандартногоинтервала конквартала конмесяца коннедели лев лог лог10 макс максимальноеколичествосубконто мин монопольныйрежим названиеинтерфейса названиенабораправ назначитьвид назначитьсчет найти найтипомеченныенаудаление найтиссылки началопериодаби началостандартногоинтервала начатьтранзакцию начгода начквартала начмесяца начнедели номерднягода номерднянедели номернеделигода нрег обработкаожидания окр описаниеошибки основнойжурналрасчетов основнойплансчетов основнойязык открытьформу открытьформумодально отменитьтранзакцию очиститьокносообщений периодстр полноеимяпользователя получитьвремята получитьдатута получитьдокументта получитьзначенияотбора получитьпозициюта получитьпустоезначение получитьта прав праводоступа предупреждение префиксавтонумерации пустаястрока пустоезначение рабочаядаттьпустоезначение рабочаядата разделительстраниц разделительстрок разм разобратьпозициюдокумента рассчитатьрегистрына рассчитатьрегистрыпо сигнал симв символтабуляции создатьобъект сокрл сокрлп сокрп сообщить состояние сохранитьзначение сред статусвозврата стрдлина стрзаменить стрколичествострок стрполучитьстроку  стрчисловхождений сформироватьпозициюдокумента счетпокоду текущаядата текущеевремя типзначения типзначениястр удалитьобъекты установитьтана установитьтапо фиксшаблон формат цел шаблон\",r={className:\"dquote\",begin:'\"\"'},a={className:\"string\",begin:'\"',end:'\"|$',contains:[r]},o={className:\"string\",begin:\"\\\\|\",end:'\"|$',contains:[r]};return{case_insensitive:!0,lexemes:t,keywords:{keyword:n,built_in:i},contains:[e.C_LINE_COMMENT_MODE,e.NUMBER_MODE,a,o,{className:\"function\",begin:\"(процедура|функция)\",end:\"$\",lexemes:t,keywords:\"процедура функция\",contains:[e.inherit(e.TITLE_MODE,{begin:t}),{className:\"tail\",endsWithParent:!0,contains:[{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",lexemes:t,keywords:\"знач\",contains:[a,o]},{className:\"export\",begin:\"экспорт\",endsWithParent:!0,lexemes:t,keywords:\"экспорт\",contains:[e.C_LINE_COMMENT_MODE]}]},e.C_LINE_COMMENT_MODE]},{className:\"preprocessor\",begin:\"#\",end:\"$\"},{className:\"date\",begin:\"'\\\\d{2}\\\\.\\\\d{2}\\\\.(\\\\d{2}|\\\\d{4})'\"}]}}),e.registerLanguage(\"accesslog\",function(e){return{contains:[{className:\"number\",begin:\"\\\\b\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}(:\\\\d{1,5})?\\\\b\"},{className:\"number\",begin:\"\\\\b\\\\d+\\\\b\",relevance:0},{className:\"string\",begin:'\"(GET|POST|HEAD|PUT|DELETE|CONNECT|OPTIONS|PATCH|TRACE)',end:'\"',keywords:\"GET POST HEAD PUT DELETE CONNECT OPTIONS PATCH TRACE\",illegal:\"\\\\n\",relevance:10},{className:\"string\",begin:/\\[/,end:/\\]/,illegal:\"\\\\n\"},{className:\"string\",begin:'\"',end:'\"',illegal:\"\\\\n\"}]}}),e.registerLanguage(\"actionscript\",function(e){var t=\"[a-zA-Z_$][a-zA-Z0-9_$]*\",n=\"([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)\",i={className:\"rest_arg\",begin:\"[.]{3}\",end:t,relevance:10};return{aliases:[\"as\"],keywords:{keyword:\"as break case catch class const continue default delete do dynamic each else extends final finally for function get if implements import in include instanceof interface internal is namespace native new override package private protected public return set static super switch this throw try typeof use var void while with\",literal:\"true false null undefined\"},contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.C_NUMBER_MODE,{className:\"package\",beginKeywords:\"package\",end:\"{\",contains:[e.TITLE_MODE]},{className:\"class\",beginKeywords:\"class interface\",end:\"{\",excludeEnd:!0,contains:[{beginKeywords:\"extends implements\"},e.TITLE_MODE]},{className:\"preprocessor\",beginKeywords:\"import include\",end:\";\"},{className:\"function\",beginKeywords:\"function\",end:\"[{;]\",excludeEnd:!0,illegal:\"\\\\S\",contains:[e.TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i]},{className:\"type\",begin:\":\",end:n,relevance:10}]}],illegal:/#/}}),e.registerLanguage(\"apache\",function(e){var t={className:\"number\",begin:\"[\\\\$%]\\\\d+\"};return{aliases:[\"apacheconf\"],case_insensitive:!0,contains:[e.HASH_COMMENT_MODE,{className:\"tag\",begin:\"</?\",end:\">\"},{className:\"keyword\",begin:/\\w+/,relevance:0,keywords:{common:\"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername\"},starts:{end:/$/,relevance:0,keywords:{literal:\"on off all\"},contains:[{className:\"sqbracket\",begin:\"\\\\s\\\\[\",end:\"\\\\]$\"},{className:\"cbracket\",begin:\"[\\\\$%]\\\\{\",end:\"\\\\}\",contains:[\"self\",t]},t,e.QUOTE_STRING_MODE]}}],illegal:/\\S/}}),e.registerLanguage(\"applescript\",function(e){var t=e.inherit(e.QUOTE_STRING_MODE,{illegal:\"\"}),n={className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:[\"self\",e.C_NUMBER_MODE,t]},i=e.COMMENT(\"--\",\"$\"),r=e.COMMENT(\"\\\\(\\\\*\",\"\\\\*\\\\)\",{contains:[\"self\",i]}),a=[i,r,e.HASH_COMMENT_MODE];return{aliases:[\"osascript\"],keywords:{keyword:\"about above after against and around as at back before beginning behind below beneath beside between but by considering contain contains continue copy div does eighth else end equal equals error every exit fifth first for fourth from front get given global if ignoring in into is it its last local me middle mod my ninth not of on onto or over prop property put ref reference repeat returning script second set seventh since sixth some tell tenth that the|0 then third through thru timeout times to transaction try until where while whose with without\",constant:\"AppleScript false linefeed return pi quote result space tab true\",type:\"alias application boolean class constant date file integer list number real record string text\",command:\"activate beep count delay launch log offset read round run say summarize write\",property:\"character characters contents day frontmost id item length month name paragraph paragraphs rest reverse running time version weekday word words year\"},contains:[t,e.C_NUMBER_MODE,{className:\"type\",begin:\"\\\\bPOSIX file\\\\b\"},{className:\"command\",begin:\"\\\\b(clipboard info|the clipboard|info for|list (disks|folder)|mount volume|path to|(close|open for) access|(get|set) eof|current date|do shell script|get volume settings|random number|set volume|system attribute|system info|time to GMT|(load|run|store) script|scripting components|ASCII (character|number)|localized string|choose (application|color|file|file name|folder|from list|remote application|URL)|display (alert|dialog))\\\\b|^\\\\s*return\\\\b\"},{className:\"constant\",begin:\"\\\\b(text item delimiters|current application|missing value)\\\\b\"},{className:\"keyword\",begin:\"\\\\b(apart from|aside from|instead of|out of|greater than|isn't|(doesn't|does not) (equal|come before|come after|contain)|(greater|less) than( or equal)?|(starts?|ends|begins?) with|contained by|comes (before|after)|a (ref|reference))\\\\b\"},{className:\"property\",begin:\"\\\\b(POSIX path|(date|time) string|quoted form)\\\\b\"},{className:\"function_start\",beginKeywords:\"on\",illegal:\"[${=;\\\\n]\",contains:[e.UNDERSCORE_TITLE_MODE,n]}].concat(a),illegal:\"//|->|=>|\\\\[\\\\[\"}}),e.registerLanguage(\"armasm\",function(e){return{case_insensitive:!0,aliases:[\"arm\"],lexemes:\"\\\\.?\"+e.IDENT_RE,keywords:{literal:\"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 pc lr sp ip sl sb fp a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 \",preprocessor:\".2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .arm .thumb .code16 .code32 .force_thumb .thumb_func .ltorg ALIAS ALIGN ARM AREA ASSERT ATTR CN CODE CODE16 CODE32 COMMON CP DATA DCB DCD DCDU DCDO DCFD DCFDU DCI DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT EXPORTAS EXTERN FIELD FILL FUNCTION GBLA GBLL GBLS GET GLOBAL IF IMPORT INCBIN INCLUDE INFO KEEP LCLA LCLL LCLS LTORG MACRO MAP MEND MEXIT NOFP OPT PRESERVE8 PROC QN READONLY RELOC REQUIRE REQUIRE8 RLIST FN ROUT SETA SETL SETS SN SPACE SUBT THUMB THUMBX TTL WHILE WEND \",built_in:\"{PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @ \"},contains:[{className:\"keyword\",begin:\"\\\\b(adc|(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|wfe|wfi|yield)(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?[sptrx]?\",end:\"\\\\s\"},e.COMMENT(\"[;@]\",\"$\",{relevance:0}),e.C_BLOCK_COMMENT_MODE,e.QUOTE_STRING_MODE,{className:\"string\",begin:\"'\",end:\"[^\\\\\\\\]'\",relevance:0},{className:\"title\",begin:\"\\\\|\",end:\"\\\\|\",illegal:\"\\\\n\",relevance:0},{className:\"number\",variants:[{begin:\"[#$=]?0x[0-9a-f]+\"},{begin:\"[#$=]?0b[01]+\"},{begin:\"[#$=]\\\\d+\"},{begin:\"\\\\b\\\\d+\"}],relevance:0},{className:\"label\",variants:[{begin:\"^[a-z_\\\\.\\\\$][a-z0-9_\\\\.\\\\$]+\"},{begin:\"^\\\\s*[a-z_\\\\.\\\\$][a-z0-9_\\\\.\\\\$]+:\"},{begin:\"[=#]\\\\w+\"}],relevance:0}]}}),e.registerLanguage(\"xml\",function(e){var t=\"[A-Za-z0-9\\\\._:-]+\",n={begin:/<\\?(php)?(?!\\w)/,end:/\\?>/,subLanguage:\"php\"},i={endsWithParent:!0,illegal:/</,relevance:0,contains:[n,{className:\"attribute\",begin:t,relevance:0},{begin:\"=\",relevance:0,contains:[{className:\"value\",contains:[n],variants:[{begin:/\"/,end:/\"/},{begin:/'/,end:/'/},{begin:/[^\\s\\/>]+/}]}]}]};return{aliases:[\"html\",\"xhtml\",\"rss\",\"atom\",\"xsl\",\"plist\"],case_insensitive:!0,contains:[{className:\"doctype\",begin:\"<!DOCTYPE\",end:\">\",relevance:10,contains:[{begin:\"\\\\[\",end:\"\\\\]\"}]},e.COMMENT(\"<!--\",\"-->\",{relevance:10}),{className:\"cdata\",begin:\"<\\\\!\\\\[CDATA\\\\[\",end:\"\\\\]\\\\]>\",relevance:10},{className:\"tag\",begin:\"<style(?=\\\\s|>|$)\",end:\">\",keywords:{title:\"style\"},contains:[i],starts:{end:\"</style>\",returnEnd:!0,subLanguage:\"css\"}},{className:\"tag\",begin:\"<script(?=\\\\s|>|$)\",end:\">\",keywords:{title:\"script\"},contains:[i],starts:{end:\"</script>\",returnEnd:!0,subLanguage:[\"actionscript\",\"javascript\",\"handlebars\"]}},n,{className:\"pi\",begin:/<\\?\\w+/,end:/\\?>/,relevance:10},{className:\"tag\",begin:\"</?\",end:\"/?>\",contains:[{className:\"title\",begin:/[^ \\/><\\n\\t]+/,relevance:0},i]}]}}),e.registerLanguage(\"asciidoc\",function(e){return{aliases:[\"adoc\"],contains:[e.COMMENT(\"^/{4,}\\\\n\",\"\\\\n/{4,}$\",{relevance:10}),e.COMMENT(\"^//\",\"$\",{relevance:0}),{className:\"title\",begin:\"^\\\\.\\\\w.*$\"},{begin:\"^[=\\\\*]{4,}\\\\n\",end:\"\\\\n^[=\\\\*]{4,}$\",relevance:10},{className:\"header\",begin:\"^(={1,5}) .+?( \\\\1)?$\",relevance:10},{className:\"header\",begin:\"^[^\\\\[\\\\]\\\\n]+?\\\\n[=\\\\-~\\\\^\\\\+]{2,}$\",relevance:10},{className:\"attribute\",begin:\"^:.+?:\",end:\"\\\\s\",excludeEnd:!0,relevance:10},{className:\"attribute\",begin:\"^\\\\[.+?\\\\]$\",relevance:0},{className:\"blockquote\",begin:\"^_{4,}\\\\n\",end:\"\\\\n_{4,}$\",relevance:10},{className:\"code\",begin:\"^[\\\\-\\\\.]{4,}\\\\n\",end:\"\\\\n[\\\\-\\\\.]{4,}$\",relevance:10},{begin:\"^\\\\+{4,}\\\\n\",end:\"\\\\n\\\\+{4,}$\",contains:[{begin:\"<\",end:\">\",subLanguage:\"xml\",relevance:0}],relevance:10},{className:\"bullet\",begin:\"^(\\\\*+|\\\\-+|\\\\.+|[^\\\\n]+?::)\\\\s+\"},{className:\"label\",begin:\"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\\\s+\",relevance:10},{className:\"strong\",begin:\"\\\\B\\\\*(?![\\\\*\\\\s])\",end:\"(\\\\n{2}|\\\\*)\",contains:[{begin:\"\\\\\\\\*\\\\w\",relevance:0}]},{className:\"emphasis\",begin:\"\\\\B'(?!['\\\\s])\",end:\"(\\\\n{2}|')\",contains:[{begin:\"\\\\\\\\'\\\\w\",relevance:0}],relevance:0},{className:\"emphasis\",begin:\"_(?![_\\\\s])\",end:\"(\\\\n{2}|_)\",relevance:0},{className:\"smartquote\",variants:[{begin:\"``.+?''\"},{begin:\"`.+?'\"}]},{className:\"code\",begin:\"(`.+?`|\\\\+.+?\\\\+)\",relevance:0},{className:\"code\",begin:\"^[ \\\\t]\",end:\"$\",relevance:0},{className:\"horizontal_rule\",begin:\"^'{3,}[ \\\\t]*$\",relevance:10},{begin:\"(link:)?(http|https|ftp|file|irc|image:?):\\\\S+\\\\[.*?\\\\]\",returnBegin:!0,contains:[{begin:\"(link|image:?):\",relevance:0},{className:\"link_url\",begin:\"\\\\w\",end:\"[^\\\\[]+\",relevance:0},{className:\"link_label\",begin:\"\\\\[\",end:\"\\\\]\",excludeBegin:!0,excludeEnd:!0,relevance:0}],relevance:10}]}}),e.registerLanguage(\"aspectj\",function(e){\nvar t=\"false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else extends implements break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws privileged aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization staticinitialization withincode target within execution getWithinTypeName handler thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents warning error soft precedence thisAspectInstance\",n=\"get set args call\";return{keywords:t,illegal:/<\\/|#/,contains:[e.COMMENT(\"/\\\\*\\\\*\",\"\\\\*/\",{relevance:0,contains:[{className:\"doctag\",begin:\"@[A-Za-z]+\"}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:\"aspect\",beginKeywords:\"aspect\",end:/[{;=]/,excludeEnd:!0,illegal:/[:;\"\\[\\]]/,contains:[{beginKeywords:\"extends implements pertypewithin perthis pertarget percflowbelow percflow issingleton\"},e.UNDERSCORE_TITLE_MODE,{begin:/\\([^\\)]*/,end:/[)]+/,keywords:t+\" \"+n,excludeEnd:!1}]},{className:\"class\",beginKeywords:\"class interface\",end:/[{;=]/,excludeEnd:!0,relevance:0,keywords:\"class interface\",illegal:/[:\"\\[\\]]/,contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:\"pointcut after before around throwing returning\",end:/[)]/,excludeEnd:!1,illegal:/[\"\\[\\]]/,contains:[{begin:e.UNDERSCORE_IDENT_RE+\"\\\\s*\\\\(\",returnBegin:!0,contains:[e.UNDERSCORE_TITLE_MODE]}]},{begin:/[:]/,returnBegin:!0,end:/[{;]/,relevance:0,excludeEnd:!1,keywords:t,illegal:/[\"\\[\\]]/,contains:[{begin:e.UNDERSCORE_IDENT_RE+\"\\\\s*\\\\(\",keywords:t+\" \"+n},e.QUOTE_STRING_MODE]},{beginKeywords:\"new throw\",relevance:0},{className:\"function\",begin:/\\w+ +\\w+(\\.)?\\w+\\s*\\([^\\)]*\\)\\s*((throws)[\\w\\s,]+)?[\\{;]/,returnBegin:!0,end:/[{;=]/,keywords:t,excludeEnd:!0,contains:[{begin:e.UNDERSCORE_IDENT_RE+\"\\\\s*\\\\(\",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:\"params\",begin:/\\(/,end:/\\)/,relevance:0,keywords:t,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},e.C_NUMBER_MODE,{className:\"annotation\",begin:\"@[A-Za-z]+\"}]}}),e.registerLanguage(\"autohotkey\",function(e){var t={className:\"escape\",begin:\"`[\\\\s\\\\S]\"},n=e.COMMENT(\";\",\"$\",{relevance:0}),i=[{className:\"built_in\",begin:\"A_[a-zA-Z0-9]+\"},{className:\"built_in\",beginKeywords:\"ComSpec Clipboard ClipboardAll ErrorLevel\"}];return{case_insensitive:!0,keywords:{keyword:\"Break Continue Else Gosub If Loop Return While\",literal:\"A true false NOT AND OR\"},contains:i.concat([t,e.inherit(e.QUOTE_STRING_MODE,{contains:[t]}),n,{className:\"number\",begin:e.NUMBER_RE,relevance:0},{className:\"var_expand\",begin:\"%\",end:\"%\",illegal:\"\\\\n\",contains:[t]},{className:\"label\",contains:[t],variants:[{begin:'^[^\\\\n\";]+::(?!=)'},{begin:'^[^\\\\n\";]+:(?!=)',relevance:0}]},{begin:\",\\\\s*,\",relevance:10}])}}),e.registerLanguage(\"autoit\",function(e){var t=\"ByRef Case Const ContinueCase ContinueLoop Default Dim Do Else ElseIf EndFunc EndIf EndSelect EndSwitch EndWith Enum Exit ExitLoop For Func Global If In Local Next ReDim Return Select Static Step Switch Then To Until Volatile WEnd While With\",n=\"True False And Null Not Or\",i=\"Abs ACos AdlibRegister AdlibUnRegister Asc AscW ASin Assign ATan AutoItSetOption AutoItWinGetTitle AutoItWinSetTitle Beep Binary BinaryLen BinaryMid BinaryToString BitAND BitNOT BitOR BitRotate BitShift BitXOR BlockInput Break Call CDTray Ceiling Chr ChrW ClipGet ClipPut ConsoleRead ConsoleWrite ConsoleWriteError ControlClick ControlCommand ControlDisable ControlEnable ControlFocus ControlGetFocus ControlGetHandle ControlGetPos ControlGetText ControlHide ControlListView ControlMove ControlSend ControlSetText ControlShow ControlTreeView Cos Dec DirCopy DirCreate DirGetSize DirMove DirRemove DllCall DllCallAddress DllCallbackFree DllCallbackGetPtr DllCallbackRegister DllClose DllOpen DllStructCreate DllStructGetData DllStructGetPtr DllStructGetSize DllStructSetData DriveGetDrive DriveGetFileSystem DriveGetLabel DriveGetSerial DriveGetType DriveMapAdd DriveMapDel DriveMapGet DriveSetLabel DriveSpaceFree DriveSpaceTotal DriveStatus EnvGet EnvSet EnvUpdate Eval Execute Exp FileChangeDir FileClose FileCopy FileCreateNTFSLink FileCreateShortcut FileDelete FileExists FileFindFirstFile FileFindNextFile FileFlush FileGetAttrib FileGetEncoding FileGetLongName FileGetPos FileGetShortcut FileGetShortName FileGetSize FileGetTime FileGetVersion FileInstall FileMove FileOpen FileOpenDialog FileRead FileReadLine FileReadToArray FileRecycle FileRecycleEmpty FileSaveDialog FileSelectFolder FileSetAttrib FileSetEnd FileSetPos FileSetTime FileWrite FileWriteLine Floor FtpSetProxy FuncName GUICreate GUICtrlCreateAvi GUICtrlCreateButton GUICtrlCreateCheckbox GUICtrlCreateCombo GUICtrlCreateContextMenu GUICtrlCreateDate GUICtrlCreateDummy GUICtrlCreateEdit GUICtrlCreateGraphic GUICtrlCreateGroup GUICtrlCreateIcon GUICtrlCreateInput GUICtrlCreateLabel GUICtrlCreateList GUICtrlCreateListView GUICtrlCreateListViewItem GUICtrlCreateMenu GUICtrlCreateMenuItem GUICtrlCreateMonthCal GUICtrlCreateObj GUICtrlCreatePic GUICtrlCreateProgress GUICtrlCreateRadio GUICtrlCreateSlider GUICtrlCreateTab GUICtrlCreateTabItem GUICtrlCreateTreeView GUICtrlCreateTreeViewItem GUICtrlCreateUpdown GUICtrlDelete GUICtrlGetHandle GUICtrlGetState GUICtrlRead GUICtrlRecvMsg GUICtrlRegisterListViewSort GUICtrlSendMsg GUICtrlSendToDummy GUICtrlSetBkColor GUICtrlSetColor GUICtrlSetCursor GUICtrlSetData GUICtrlSetDefBkColor GUICtrlSetDefColor GUICtrlSetFont GUICtrlSetGraphic GUICtrlSetImage GUICtrlSetLimit GUICtrlSetOnEvent GUICtrlSetPos GUICtrlSetResizing GUICtrlSetState GUICtrlSetStyle GUICtrlSetTip GUIDelete GUIGetCursorInfo GUIGetMsg GUIGetStyle GUIRegisterMsg GUISetAccelerators GUISetBkColor GUISetCoord GUISetCursor GUISetFont GUISetHelp GUISetIcon GUISetOnEvent GUISetState GUISetStyle GUIStartGroup GUISwitch Hex HotKeySet HttpSetProxy HttpSetUserAgent HWnd InetClose InetGet InetGetInfo InetGetSize InetRead IniDelete IniRead IniReadSection IniReadSectionNames IniRenameSection IniWrite IniWriteSection InputBox Int IsAdmin IsArray IsBinary IsBool IsDeclared IsDllStruct IsFloat IsFunc IsHWnd IsInt IsKeyword IsNumber IsObj IsPtr IsString Log MemGetStats Mod MouseClick MouseClickDrag MouseDown MouseGetCursor MouseGetPos MouseMove MouseUp MouseWheel MsgBox Number ObjCreate ObjCreateInterface ObjEvent ObjGet ObjName OnAutoItExitRegister OnAutoItExitUnRegister Opt Ping PixelChecksum PixelGetColor PixelSearch ProcessClose ProcessExists ProcessGetStats ProcessList ProcessSetPriority ProcessWait ProcessWaitClose ProgressOff ProgressOn ProgressSet Ptr Random RegDelete RegEnumKey RegEnumVal RegRead RegWrite Round Run RunAs RunAsWait RunWait Send SendKeepActive SetError SetExtended ShellExecute ShellExecuteWait Shutdown Sin Sleep SoundPlay SoundSetWaveVolume SplashImageOn SplashOff SplashTextOn Sqrt SRandom StatusbarGetText StderrRead StdinWrite StdioClose StdoutRead String StringAddCR StringCompare StringFormat StringFromASCIIArray StringInStr StringIsAlNum StringIsAlpha StringIsASCII StringIsDigit StringIsFloat StringIsInt StringIsLower StringIsSpace StringIsUpper StringIsXDigit StringLeft StringLen StringLower StringMid StringRegExp StringRegExpReplace StringReplace StringReverse StringRight StringSplit StringStripCR StringStripWS StringToASCIIArray StringToBinary StringTrimLeft StringTrimRight StringUpper Tan TCPAccept TCPCloseSocket TCPConnect TCPListen TCPNameToIP TCPRecv TCPSend TCPShutdown TCPStartup TimerDiff TimerInit ToolTip TrayCreateItem TrayCreateMenu TrayGetMsg TrayItemDelete TrayItemGetHandle TrayItemGetState TrayItemGetText TrayItemSetOnEvent TrayItemSetState TrayItemSetText TraySetClick TraySetIcon TraySetOnEvent TraySetPauseIcon TraySetState TraySetToolTip TrayTip UBound UDPBind UDPCloseSocket UDPOpen UDPRecv UDPSend UDPShutdown UDPStartup VarGetType WinActivate WinActive WinClose WinExists WinFlash WinGetCaretPos WinGetClassList WinGetClientSize WinGetHandle WinGetPos WinGetProcess WinGetState WinGetText WinGetTitle WinKill WinList WinMenuSelectItem WinMinimizeAll WinMinimizeAllUndo WinMove WinSetOnTop WinSetState WinSetTitle WinSetTrans WinWait WinWaitActive WinWaitClose WinWaitNotActive Array1DToHistogram ArrayAdd ArrayBinarySearch ArrayColDelete ArrayColInsert ArrayCombinations ArrayConcatenate ArrayDelete ArrayDisplay ArrayExtract ArrayFindAll ArrayInsert ArrayMax ArrayMaxIndex ArrayMin ArrayMinIndex ArrayPermute ArrayPop ArrayPush ArrayReverse ArraySearch ArrayShuffle ArraySort ArraySwap ArrayToClip ArrayToString ArrayTranspose ArrayTrim ArrayUnique Assert ChooseColor ChooseFont ClipBoard_ChangeChain ClipBoard_Close ClipBoard_CountFormats ClipBoard_Empty ClipBoard_EnumFormats ClipBoard_FormatStr ClipBoard_GetData ClipBoard_GetDataEx ClipBoard_GetFormatName ClipBoard_GetOpenWindow ClipBoard_GetOwner ClipBoard_GetPriorityFormat ClipBoard_GetSequenceNumber ClipBoard_GetViewer ClipBoard_IsFormatAvailable ClipBoard_Open ClipBoard_RegisterFormat ClipBoard_SetData ClipBoard_SetDataEx ClipBoard_SetViewer ClipPutFile ColorConvertHSLtoRGB ColorConvertRGBtoHSL ColorGetBlue ColorGetCOLORREF ColorGetGreen ColorGetRed ColorGetRGB ColorSetCOLORREF ColorSetRGB Crypt_DecryptData Crypt_DecryptFile Crypt_DeriveKey Crypt_DestroyKey Crypt_EncryptData Crypt_EncryptFile Crypt_GenRandom Crypt_HashData Crypt_HashFile Crypt_Shutdown Crypt_Startup DateAdd DateDayOfWeek DateDaysInMonth DateDiff DateIsLeapYear DateIsValid DateTimeFormat DateTimeSplit DateToDayOfWeek DateToDayOfWeekISO DateToDayValue DateToMonth Date_Time_CompareFileTime Date_Time_DOSDateTimeToArray Date_Time_DOSDateTimeToFileTime Date_Time_DOSDateTimeToStr Date_Time_DOSDateToArray Date_Time_DOSDateToStr Date_Time_DOSTimeToArray Date_Time_DOSTimeToStr Date_Time_EncodeFileTime Date_Time_EncodeSystemTime Date_Time_FileTimeToArray Date_Time_FileTimeToDOSDateTime Date_Time_FileTimeToLocalFileTime Date_Time_FileTimeToStr Date_Time_FileTimeToSystemTime Date_Time_GetFileTime Date_Time_GetLocalTime Date_Time_GetSystemTime Date_Time_GetSystemTimeAdjustment Date_Time_GetSystemTimeAsFileTime Date_Time_GetSystemTimes Date_Time_GetTickCount Date_Time_GetTimeZoneInformation Date_Time_LocalFileTimeToFileTime Date_Time_SetFileTime Date_Time_SetLocalTime Date_Time_SetSystemTime Date_Time_SetSystemTimeAdjustment Date_Time_SetTimeZoneInformation Date_Time_SystemTimeToArray Date_Time_SystemTimeToDateStr Date_Time_SystemTimeToDateTimeStr Date_Time_SystemTimeToFileTime Date_Time_SystemTimeToTimeStr Date_Time_SystemTimeToTzSpecificLocalTime Date_Time_TzSpecificLocalTimeToSystemTime DayValueToDate DebugBugReportEnv DebugCOMError DebugOut DebugReport DebugReportEx DebugReportVar DebugSetup Degree EventLog__Backup EventLog__Clear EventLog__Close EventLog__Count EventLog__DeregisterSource EventLog__Full EventLog__Notify EventLog__Oldest EventLog__Open EventLog__OpenBackup EventLog__Read EventLog__RegisterSource EventLog__Report Excel_BookAttach Excel_BookClose Excel_BookList Excel_BookNew Excel_BookOpen Excel_BookOpenText Excel_BookSave Excel_BookSaveAs Excel_Close Excel_ColumnToLetter Excel_ColumnToNumber Excel_ConvertFormula Excel_Export Excel_FilterGet Excel_FilterSet Excel_Open Excel_PictureAdd Excel_Print Excel_RangeCopyPaste Excel_RangeDelete Excel_RangeFind Excel_RangeInsert Excel_RangeLinkAddRemove Excel_RangeRead Excel_RangeReplace Excel_RangeSort Excel_RangeValidate Excel_RangeWrite Excel_SheetAdd Excel_SheetCopyMove Excel_SheetDelete Excel_SheetList FileCountLines FileCreate FileListToArray FileListToArrayRec FilePrint FileReadToArray FileWriteFromArray FileWriteLog FileWriteToLine FTP_Close FTP_Command FTP_Connect FTP_DecodeInternetStatus FTP_DirCreate FTP_DirDelete FTP_DirGetCurrent FTP_DirPutContents FTP_DirSetCurrent FTP_FileClose FTP_FileDelete FTP_FileGet FTP_FileGetSize FTP_FileOpen FTP_FilePut FTP_FileRead FTP_FileRename FTP_FileTimeLoHiToStr FTP_FindFileClose FTP_FindFileFirst FTP_FindFileNext FTP_GetLastResponseInfo FTP_ListToArray FTP_ListToArray2D FTP_ListToArrayEx FTP_Open FTP_ProgressDownload FTP_ProgressUpload FTP_SetStatusCallback GDIPlus_ArrowCapCreate GDIPlus_ArrowCapDispose GDIPlus_ArrowCapGetFillState GDIPlus_ArrowCapGetHeight GDIPlus_ArrowCapGetMiddleInset GDIPlus_ArrowCapGetWidth GDIPlus_ArrowCapSetFillState GDIPlus_ArrowCapSetHeight GDIPlus_ArrowCapSetMiddleInset GDIPlus_ArrowCapSetWidth GDIPlus_BitmapApplyEffect GDIPlus_BitmapApplyEffectEx GDIPlus_BitmapCloneArea GDIPlus_BitmapConvertFormat GDIPlus_BitmapCreateApplyEffect GDIPlus_BitmapCreateApplyEffectEx GDIPlus_BitmapCreateDIBFromBitmap GDIPlus_BitmapCreateFromFile GDIPlus_BitmapCreateFromGraphics GDIPlus_BitmapCreateFromHBITMAP GDIPlus_BitmapCreateFromHICON GDIPlus_BitmapCreateFromHICON32 GDIPlus_BitmapCreateFromMemory GDIPlus_BitmapCreateFromResource GDIPlus_BitmapCreateFromScan0 GDIPlus_BitmapCreateFromStream GDIPlus_BitmapCreateHBITMAPFromBitmap GDIPlus_BitmapDispose GDIPlus_BitmapGetHistogram GDIPlus_BitmapGetHistogramEx GDIPlus_BitmapGetHistogramSize GDIPlus_BitmapGetPixel GDIPlus_BitmapLockBits GDIPlus_BitmapSetPixel GDIPlus_BitmapUnlockBits GDIPlus_BrushClone GDIPlus_BrushCreateSolid GDIPlus_BrushDispose GDIPlus_BrushGetSolidColor GDIPlus_BrushGetType GDIPlus_BrushSetSolidColor GDIPlus_ColorMatrixCreate GDIPlus_ColorMatrixCreateGrayScale GDIPlus_ColorMatrixCreateNegative GDIPlus_ColorMatrixCreateSaturation GDIPlus_ColorMatrixCreateScale GDIPlus_ColorMatrixCreateTranslate GDIPlus_CustomLineCapClone GDIPlus_CustomLineCapCreate GDIPlus_CustomLineCapDispose GDIPlus_CustomLineCapGetStrokeCaps GDIPlus_CustomLineCapSetStrokeCaps GDIPlus_Decoders GDIPlus_DecodersGetCount GDIPlus_DecodersGetSize GDIPlus_DrawImageFX GDIPlus_DrawImageFXEx GDIPlus_DrawImagePoints GDIPlus_EffectCreate GDIPlus_EffectCreateBlur GDIPlus_EffectCreateBrightnessContrast GDIPlus_EffectCreateColorBalance GDIPlus_EffectCreateColorCurve GDIPlus_EffectCreateColorLUT GDIPlus_EffectCreateColorMatrix GDIPlus_EffectCreateHueSaturationLightness GDIPlus_EffectCreateLevels GDIPlus_EffectCreateRedEyeCorrection GDIPlus_EffectCreateSharpen GDIPlus_EffectCreateTint GDIPlus_EffectDispose GDIPlus_EffectGetParameters GDIPlus_EffectSetParameters GDIPlus_Encoders GDIPlus_EncodersGetCLSID GDIPlus_EncodersGetCount GDIPlus_EncodersGetParamList GDIPlus_EncodersGetParamListSize GDIPlus_EncodersGetSize GDIPlus_FontCreate GDIPlus_FontDispose GDIPlus_FontFamilyCreate GDIPlus_FontFamilyCreateFromCollection GDIPlus_FontFamilyDispose GDIPlus_FontFamilyGetCellAscent GDIPlus_FontFamilyGetCellDescent GDIPlus_FontFamilyGetEmHeight GDIPlus_FontFamilyGetLineSpacing GDIPlus_FontGetHeight GDIPlus_FontPrivateAddFont GDIPlus_FontPrivateAddMemoryFont GDIPlus_FontPrivateCollectionDispose GDIPlus_FontPrivateCreateCollection GDIPlus_GraphicsClear GDIPlus_GraphicsCreateFromHDC GDIPlus_GraphicsCreateFromHWND GDIPlus_GraphicsDispose GDIPlus_GraphicsDrawArc GDIPlus_GraphicsDrawBezier GDIPlus_GraphicsDrawClosedCurve GDIPlus_GraphicsDrawClosedCurve2 GDIPlus_GraphicsDrawCurve GDIPlus_GraphicsDrawCurve2 GDIPlus_GraphicsDrawEllipse GDIPlus_GraphicsDrawImage GDIPlus_GraphicsDrawImagePointsRect GDIPlus_GraphicsDrawImageRect GDIPlus_GraphicsDrawImageRectRect GDIPlus_GraphicsDrawLine GDIPlus_GraphicsDrawPath GDIPlus_GraphicsDrawPie GDIPlus_GraphicsDrawPolygon GDIPlus_GraphicsDrawRect GDIPlus_GraphicsDrawString GDIPlus_GraphicsDrawStringEx GDIPlus_GraphicsFillClosedCurve GDIPlus_GraphicsFillClosedCurve2 GDIPlus_GraphicsFillEllipse GDIPlus_GraphicsFillPath GDIPlus_GraphicsFillPie GDIPlus_GraphicsFillPolygon GDIPlus_GraphicsFillRect GDIPlus_GraphicsFillRegion GDIPlus_GraphicsGetCompositingMode GDIPlus_GraphicsGetCompositingQuality GDIPlus_GraphicsGetDC GDIPlus_GraphicsGetInterpolationMode GDIPlus_GraphicsGetSmoothingMode GDIPlus_GraphicsGetTransform GDIPlus_GraphicsMeasureCharacterRanges GDIPlus_GraphicsMeasureString GDIPlus_GraphicsReleaseDC GDIPlus_GraphicsResetClip GDIPlus_GraphicsResetTransform GDIPlus_GraphicsRestore GDIPlus_GraphicsRotateTransform GDIPlus_GraphicsSave GDIPlus_GraphicsScaleTransform GDIPlus_GraphicsSetClipPath GDIPlus_GraphicsSetClipRect GDIPlus_GraphicsSetClipRegion GDIPlus_GraphicsSetCompositingMode GDIPlus_GraphicsSetCompositingQuality GDIPlus_GraphicsSetInterpolationMode GDIPlus_GraphicsSetPixelOffsetMode GDIPlus_GraphicsSetSmoothingMode GDIPlus_GraphicsSetTextRenderingHint GDIPlus_GraphicsSetTransform GDIPlus_GraphicsTransformPoints GDIPlus_GraphicsTranslateTransform GDIPlus_HatchBrushCreate GDIPlus_HICONCreateFromBitmap GDIPlus_ImageAttributesCreate GDIPlus_ImageAttributesDispose GDIPlus_ImageAttributesSetColorKeys GDIPlus_ImageAttributesSetColorMatrix GDIPlus_ImageDispose GDIPlus_ImageGetDimension GDIPlus_ImageGetFlags GDIPlus_ImageGetGraphicsContext GDIPlus_ImageGetHeight GDIPlus_ImageGetHorizontalResolution GDIPlus_ImageGetPixelFormat GDIPlus_ImageGetRawFormat GDIPlus_ImageGetThumbnail GDIPlus_ImageGetType GDIPlus_ImageGetVerticalResolution GDIPlus_ImageGetWidth GDIPlus_ImageLoadFromFile GDIPlus_ImageLoadFromStream GDIPlus_ImageResize GDIPlus_ImageRotateFlip GDIPlus_ImageSaveToFile GDIPlus_ImageSaveToFileEx GDIPlus_ImageSaveToStream GDIPlus_ImageScale GDIPlus_LineBrushCreate GDIPlus_LineBrushCreateFromRect GDIPlus_LineBrushCreateFromRectWithAngle GDIPlus_LineBrushGetColors GDIPlus_LineBrushGetRect GDIPlus_LineBrushMultiplyTransform GDIPlus_LineBrushResetTransform GDIPlus_LineBrushSetBlend GDIPlus_LineBrushSetColors GDIPlus_LineBrushSetGammaCorrection GDIPlus_LineBrushSetLinearBlend GDIPlus_LineBrushSetPresetBlend GDIPlus_LineBrushSetSigmaBlend GDIPlus_LineBrushSetTransform GDIPlus_MatrixClone GDIPlus_MatrixCreate GDIPlus_MatrixDispose GDIPlus_MatrixGetElements GDIPlus_MatrixInvert GDIPlus_MatrixMultiply GDIPlus_MatrixRotate GDIPlus_MatrixScale GDIPlus_MatrixSetElements GDIPlus_MatrixShear GDIPlus_MatrixTransformPoints GDIPlus_MatrixTranslate GDIPlus_PaletteInitialize GDIPlus_ParamAdd GDIPlus_ParamInit GDIPlus_ParamSize GDIPlus_PathAddArc GDIPlus_PathAddBezier GDIPlus_PathAddClosedCurve GDIPlus_PathAddClosedCurve2 GDIPlus_PathAddCurve GDIPlus_PathAddCurve2 GDIPlus_PathAddCurve3 GDIPlus_PathAddEllipse GDIPlus_PathAddLine GDIPlus_PathAddLine2 GDIPlus_PathAddPath GDIPlus_PathAddPie GDIPlus_PathAddPolygon GDIPlus_PathAddRectangle GDIPlus_PathAddString GDIPlus_PathBrushCreate GDIPlus_PathBrushCreateFromPath GDIPlus_PathBrushGetCenterPoint GDIPlus_PathBrushGetFocusScales GDIPlus_PathBrushGetPointCount GDIPlus_PathBrushGetRect GDIPlus_PathBrushGetWrapMode GDIPlus_PathBrushMultiplyTransform GDIPlus_PathBrushResetTransform GDIPlus_PathBrushSetBlend GDIPlus_PathBrushSetCenterColor GDIPlus_PathBrushSetCenterPoint GDIPlus_PathBrushSetFocusScales GDIPlus_PathBrushSetGammaCorrection GDIPlus_PathBrushSetLinearBlend GDIPlus_PathBrushSetPresetBlend GDIPlus_PathBrushSetSigmaBlend GDIPlus_PathBrushSetSurroundColor GDIPlus_PathBrushSetSurroundColorsWithCount GDIPlus_PathBrushSetTransform GDIPlus_PathBrushSetWrapMode GDIPlus_PathClone GDIPlus_PathCloseFigure GDIPlus_PathCreate GDIPlus_PathCreate2 GDIPlus_PathDispose GDIPlus_PathFlatten GDIPlus_PathGetData GDIPlus_PathGetFillMode GDIPlus_PathGetLastPoint GDIPlus_PathGetPointCount GDIPlus_PathGetPoints GDIPlus_PathGetWorldBounds GDIPlus_PathIsOutlineVisiblePoint GDIPlus_PathIsVisiblePoint GDIPlus_PathIterCreate GDIPlus_PathIterDispose GDIPlus_PathIterGetSubpathCount GDIPlus_PathIterNextMarkerPath GDIPlus_PathIterNextSubpathPath GDIPlus_PathIterRewind GDIPlus_PathReset GDIPlus_PathReverse GDIPlus_PathSetFillMode GDIPlus_PathSetMarker GDIPlus_PathStartFigure GDIPlus_PathTransform GDIPlus_PathWarp GDIPlus_PathWiden GDIPlus_PathWindingModeOutline GDIPlus_PenCreate GDIPlus_PenCreate2 GDIPlus_PenDispose GDIPlus_PenGetAlignment GDIPlus_PenGetColor GDIPlus_PenGetCustomEndCap GDIPlus_PenGetDashCap GDIPlus_PenGetDashStyle GDIPlus_PenGetEndCap GDIPlus_PenGetMiterLimit GDIPlus_PenGetWidth GDIPlus_PenSetAlignment GDIPlus_PenSetColor GDIPlus_PenSetCustomEndCap GDIPlus_PenSetDashCap GDIPlus_PenSetDashStyle GDIPlus_PenSetEndCap GDIPlus_PenSetLineCap GDIPlus_PenSetLineJoin GDIPlus_PenSetMiterLimit GDIPlus_PenSetStartCap GDIPlus_PenSetWidth GDIPlus_RectFCreate GDIPlus_RegionClone GDIPlus_RegionCombinePath GDIPlus_RegionCombineRect GDIPlus_RegionCombineRegion GDIPlus_RegionCreate GDIPlus_RegionCreateFromPath GDIPlus_RegionCreateFromRect GDIPlus_RegionDispose GDIPlus_RegionGetBounds GDIPlus_RegionGetHRgn GDIPlus_RegionTransform GDIPlus_RegionTranslate GDIPlus_Shutdown GDIPlus_Startup GDIPlus_StringFormatCreate GDIPlus_StringFormatDispose GDIPlus_StringFormatGetMeasurableCharacterRangeCount GDIPlus_StringFormatSetAlign GDIPlus_StringFormatSetLineAlign GDIPlus_StringFormatSetMeasurableCharacterRanges GDIPlus_TextureCreate GDIPlus_TextureCreate2 GDIPlus_TextureCreateIA GetIP GUICtrlAVI_Close GUICtrlAVI_Create GUICtrlAVI_Destroy GUICtrlAVI_IsPlaying GUICtrlAVI_Open GUICtrlAVI_OpenEx GUICtrlAVI_Play GUICtrlAVI_Seek GUICtrlAVI_Show GUICtrlAVI_Stop GUICtrlButton_Click GUICtrlButton_Create GUICtrlButton_Destroy GUICtrlButton_Enable GUICtrlButton_GetCheck GUICtrlButton_GetFocus GUICtrlButton_GetIdealSize GUICtrlButton_GetImage GUICtrlButton_GetImageList GUICtrlButton_GetNote GUICtrlButton_GetNoteLength GUICtrlButton_GetSplitInfo GUICtrlButton_GetState GUICtrlButton_GetText GUICtrlButton_GetTextMargin GUICtrlButton_SetCheck GUICtrlButton_SetDontClick GUICtrlButton_SetFocus GUICtrlButton_SetImage GUICtrlButton_SetImageList GUICtrlButton_SetNote GUICtrlButton_SetShield GUICtrlButton_SetSize GUICtrlButton_SetSplitInfo GUICtrlButton_SetState GUICtrlButton_SetStyle GUICtrlButton_SetText GUICtrlButton_SetTextMargin GUICtrlButton_Show GUICtrlComboBoxEx_AddDir GUICtrlComboBoxEx_AddString GUICtrlComboBoxEx_BeginUpdate GUICtrlComboBoxEx_Create GUICtrlComboBoxEx_CreateSolidBitMap GUICtrlComboBoxEx_DeleteString GUICtrlComboBoxEx_Destroy GUICtrlComboBoxEx_EndUpdate GUICtrlComboBoxEx_FindStringExact GUICtrlComboBoxEx_GetComboBoxInfo GUICtrlComboBoxEx_GetComboControl GUICtrlComboBoxEx_GetCount GUICtrlComboBoxEx_GetCurSel GUICtrlComboBoxEx_GetDroppedControlRect GUICtrlComboBoxEx_GetDroppedControlRectEx GUICtrlComboBoxEx_GetDroppedState GUICtrlComboBoxEx_GetDroppedWidth GUICtrlComboBoxEx_GetEditControl GUICtrlComboBoxEx_GetEditSel GUICtrlComboBoxEx_GetEditText GUICtrlComboBoxEx_GetExtendedStyle GUICtrlComboBoxEx_GetExtendedUI GUICtrlComboBoxEx_GetImageList GUICtrlComboBoxEx_GetItem GUICtrlComboBoxEx_GetItemEx GUICtrlComboBoxEx_GetItemHeight GUICtrlComboBoxEx_GetItemImage GUICtrlComboBoxEx_GetItemIndent GUICtrlComboBoxEx_GetItemOverlayImage GUICtrlComboBoxEx_GetItemParam GUICtrlComboBoxEx_GetItemSelectedImage GUICtrlComboBoxEx_GetItemText GUICtrlComboBoxEx_GetItemTextLen GUICtrlComboBoxEx_GetList GUICtrlComboBoxEx_GetListArray GUICtrlComboBoxEx_GetLocale GUICtrlComboBoxEx_GetLocaleCountry GUICtrlComboBoxEx_GetLocaleLang GUICtrlComboBoxEx_GetLocalePrimLang GUICtrlComboBoxEx_GetLocaleSubLang GUICtrlComboBoxEx_GetMinVisible GUICtrlComboBoxEx_GetTopIndex GUICtrlComboBoxEx_GetUnicode GUICtrlComboBoxEx_InitStorage GUICtrlComboBoxEx_InsertString GUICtrlComboBoxEx_LimitText GUICtrlComboBoxEx_ReplaceEditSel GUICtrlComboBoxEx_ResetContent GUICtrlComboBoxEx_SetCurSel GUICtrlComboBoxEx_SetDroppedWidth GUICtrlComboBoxEx_SetEditSel GUICtrlComboBoxEx_SetEditText GUICtrlComboBoxEx_SetExtendedStyle GUICtrlComboBoxEx_SetExtendedUI GUICtrlComboBoxEx_SetImageList GUICtrlComboBoxEx_SetItem GUICtrlComboBoxEx_SetItemEx GUICtrlComboBoxEx_SetItemHeight GUICtrlComboBoxEx_SetItemImage GUICtrlComboBoxEx_SetItemIndent GUICtrlComboBoxEx_SetItemOverlayImage GUICtrlComboBoxEx_SetItemParam GUICtrlComboBoxEx_SetItemSelectedImage GUICtrlComboBoxEx_SetMinVisible GUICtrlComboBoxEx_SetTopIndex GUICtrlComboBoxEx_SetUnicode GUICtrlComboBoxEx_ShowDropDown GUICtrlComboBox_AddDir GUICtrlComboBox_AddString GUICtrlComboBox_AutoComplete GUICtrlComboBox_BeginUpdate GUICtrlComboBox_Create GUICtrlComboBox_DeleteString GUICtrlComboBox_Destroy GUICtrlComboBox_EndUpdate GUICtrlComboBox_FindString GUICtrlComboBox_FindStringExact GUICtrlComboBox_GetComboBoxInfo GUICtrlComboBox_GetCount GUICtrlComboBox_GetCueBanner GUICtrlComboBox_GetCurSel GUICtrlComboBox_GetDroppedControlRect GUICtrlComboBox_GetDroppedControlRectEx GUICtrlComboBox_GetDroppedState GUICtrlComboBox_GetDroppedWidth GUICtrlComboBox_GetEditSel GUICtrlComboBox_GetEditText GUICtrlComboBox_GetExtendedUI GUICtrlComboBox_GetHorizontalExtent GUICtrlComboBox_GetItemHeight GUICtrlComboBox_GetLBText GUICtrlComboBox_GetLBTextLen GUICtrlComboBox_GetList GUICtrlComboBox_GetListArray GUICtrlComboBox_GetLocale GUICtrlComboBox_GetLocaleCountry GUICtrlComboBox_GetLocaleLang GUICtrlComboBox_GetLocalePrimLang GUICtrlComboBox_GetLocaleSubLang GUICtrlComboBox_GetMinVisible GUICtrlComboBox_GetTopIndex GUICtrlComboBox_InitStorage GUICtrlComboBox_InsertString GUICtrlComboBox_LimitText GUICtrlComboBox_ReplaceEditSel GUICtrlComboBox_ResetContent GUICtrlComboBox_SelectString GUICtrlComboBox_SetCueBanner GUICtrlComboBox_SetCurSel GUICtrlComboBox_SetDroppedWidth GUICtrlComboBox_SetEditSel GUICtrlComboBox_SetEditText GUICtrlComboBox_SetExtendedUI GUICtrlComboBox_SetHorizontalExtent GUICtrlComboBox_SetItemHeight GUICtrlComboBox_SetMinVisible GUICtrlComboBox_SetTopIndex GUICtrlComboBox_ShowDropDown GUICtrlDTP_Create GUICtrlDTP_Destroy GUICtrlDTP_GetMCColor GUICtrlDTP_GetMCFont GUICtrlDTP_GetMonthCal GUICtrlDTP_GetRange GUICtrlDTP_GetRangeEx GUICtrlDTP_GetSystemTime GUICtrlDTP_GetSystemTimeEx GUICtrlDTP_SetFormat GUICtrlDTP_SetMCColor GUICtrlDTP_SetMCFont GUICtrlDTP_SetRange GUICtrlDTP_SetRangeEx GUICtrlDTP_SetSystemTime GUICtrlDTP_SetSystemTimeEx GUICtrlEdit_AppendText GUICtrlEdit_BeginUpdate GUICtrlEdit_CanUndo GUICtrlEdit_CharFromPos GUICtrlEdit_Create GUICtrlEdit_Destroy GUICtrlEdit_EmptyUndoBuffer GUICtrlEdit_EndUpdate GUICtrlEdit_Find GUICtrlEdit_FmtLines GUICtrlEdit_GetCueBanner GUICtrlEdit_GetFirstVisibleLine GUICtrlEdit_GetLimitText GUICtrlEdit_GetLine GUICtrlEdit_GetLineCount GUICtrlEdit_GetMargins GUICtrlEdit_GetModify GUICtrlEdit_GetPasswordChar GUICtrlEdit_GetRECT GUICtrlEdit_GetRECTEx GUICtrlEdit_GetSel GUICtrlEdit_GetText GUICtrlEdit_GetTextLen GUICtrlEdit_HideBalloonTip GUICtrlEdit_InsertText GUICtrlEdit_LineFromChar GUICtrlEdit_LineIndex GUICtrlEdit_LineLength GUICtrlEdit_LineScroll GUICtrlEdit_PosFromChar GUICtrlEdit_ReplaceSel GUICtrlEdit_Scroll GUICtrlEdit_SetCueBanner GUICtrlEdit_SetLimitText GUICtrlEdit_SetMargins GUICtrlEdit_SetModify GUICtrlEdit_SetPasswordChar GUICtrlEdit_SetReadOnly GUICtrlEdit_SetRECT GUICtrlEdit_SetRECTEx GUICtrlEdit_SetRECTNP GUICtrlEdit_SetRectNPEx GUICtrlEdit_SetSel GUICtrlEdit_SetTabStops GUICtrlEdit_SetText GUICtrlEdit_ShowBalloonTip GUICtrlEdit_Undo GUICtrlHeader_AddItem GUICtrlHeader_ClearFilter GUICtrlHeader_ClearFilterAll GUICtrlHeader_Create GUICtrlHeader_CreateDragImage GUICtrlHeader_DeleteItem GUICtrlHeader_Destroy GUICtrlHeader_EditFilter GUICtrlHeader_GetBitmapMargin GUICtrlHeader_GetImageList GUICtrlHeader_GetItem GUICtrlHeader_GetItemAlign GUICtrlHeader_GetItemBitmap GUICtrlHeader_GetItemCount GUICtrlHeader_GetItemDisplay GUICtrlHeader_GetItemFlags GUICtrlHeader_GetItemFormat GUICtrlHeader_GetItemImage GUICtrlHeader_GetItemOrder GUICtrlHeader_GetItemParam GUICtrlHeader_GetItemRect GUICtrlHeader_GetItemRectEx GUICtrlHeader_GetItemText GUICtrlHeader_GetItemWidth GUICtrlHeader_GetOrderArray GUICtrlHeader_GetUnicodeFormat GUICtrlHeader_HitTest GUICtrlHeader_InsertItem GUICtrlHeader_Layout GUICtrlHeader_OrderToIndex GUICtrlHeader_SetBitmapMargin GUICtrlHeader_SetFilterChangeTimeout GUICtrlHeader_SetHotDivider GUICtrlHeader_SetImageList GUICtrlHeader_SetItem GUICtrlHeader_SetItemAlign GUICtrlHeader_SetItemBitmap GUICtrlHeader_SetItemDisplay GUICtrlHeader_SetItemFlags GUICtrlHeader_SetItemFormat GUICtrlHeader_SetItemImage GUICtrlHeader_SetItemOrder GUICtrlHeader_SetItemParam GUICtrlHeader_SetItemText GUICtrlHeader_SetItemWidth GUICtrlHeader_SetOrderArray GUICtrlHeader_SetUnicodeFormat GUICtrlIpAddress_ClearAddress GUICtrlIpAddress_Create GUICtrlIpAddress_Destroy GUICtrlIpAddress_Get GUICtrlIpAddress_GetArray GUICtrlIpAddress_GetEx GUICtrlIpAddress_IsBlank GUICtrlIpAddress_Set GUICtrlIpAddress_SetArray GUICtrlIpAddress_SetEx GUICtrlIpAddress_SetFocus GUICtrlIpAddress_SetFont GUICtrlIpAddress_SetRange GUICtrlIpAddress_ShowHide GUICtrlListBox_AddFile GUICtrlListBox_AddString GUICtrlListBox_BeginUpdate GUICtrlListBox_ClickItem GUICtrlListBox_Create GUICtrlListBox_DeleteString GUICtrlListBox_Destroy GUICtrlListBox_Dir GUICtrlListBox_EndUpdate GUICtrlListBox_FindInText GUICtrlListBox_FindString GUICtrlListBox_GetAnchorIndex GUICtrlListBox_GetCaretIndex GUICtrlListBox_GetCount GUICtrlListBox_GetCurSel GUICtrlListBox_GetHorizontalExtent GUICtrlListBox_GetItemData GUICtrlListBox_GetItemHeight GUICtrlListBox_GetItemRect GUICtrlListBox_GetItemRectEx GUICtrlListBox_GetListBoxInfo GUICtrlListBox_GetLocale GUICtrlListBox_GetLocaleCountry GUICtrlListBox_GetLocaleLang GUICtrlListBox_GetLocalePrimLang GUICtrlListBox_GetLocaleSubLang GUICtrlListBox_GetSel GUICtrlListBox_GetSelCount GUICtrlListBox_GetSelItems GUICtrlListBox_GetSelItemsText GUICtrlListBox_GetText GUICtrlListBox_GetTextLen GUICtrlListBox_GetTopIndex GUICtrlListBox_InitStorage GUICtrlListBox_InsertString GUICtrlListBox_ItemFromPoint GUICtrlListBox_ReplaceString GUICtrlListBox_ResetContent GUICtrlListBox_SelectString GUICtrlListBox_SelItemRange GUICtrlListBox_SelItemRangeEx GUICtrlListBox_SetAnchorIndex GUICtrlListBox_SetCaretIndex GUICtrlListBox_SetColumnWidth GUICtrlListBox_SetCurSel GUICtrlListBox_SetHorizontalExtent GUICtrlListBox_SetItemData GUICtrlListBox_SetItemHeight GUICtrlListBox_SetLocale GUICtrlListBox_SetSel GUICtrlListBox_SetTabStops GUICtrlListBox_SetTopIndex GUICtrlListBox_Sort GUICtrlListBox_SwapString GUICtrlListBox_UpdateHScroll GUICtrlListView_AddArray GUICtrlListView_AddColumn GUICtrlListView_AddItem GUICtrlListView_AddSubItem GUICtrlListView_ApproximateViewHeight GUICtrlListView_ApproximateViewRect GUICtrlListView_ApproximateViewWidth GUICtrlListView_Arrange GUICtrlListView_BeginUpdate GUICtrlListView_CancelEditLabel GUICtrlListView_ClickItem GUICtrlListView_CopyItems GUICtrlListView_Create GUICtrlListView_CreateDragImage GUICtrlListView_CreateSolidBitMap GUICtrlListView_DeleteAllItems GUICtrlListView_DeleteColumn GUICtrlListView_DeleteItem GUICtrlListView_DeleteItemsSelected GUICtrlListView_Destroy GUICtrlListView_DrawDragImage GUICtrlListView_EditLabel GUICtrlListView_EnableGroupView GUICtrlListView_EndUpdate GUICtrlListView_EnsureVisible GUICtrlListView_FindInText GUICtrlListView_FindItem GUICtrlListView_FindNearest GUICtrlListView_FindParam GUICtrlListView_FindText GUICtrlListView_GetBkColor GUICtrlListView_GetBkImage GUICtrlListView_GetCallbackMask GUICtrlListView_GetColumn GUICtrlListView_GetColumnCount GUICtrlListView_GetColumnOrder GUICtrlListView_GetColumnOrderArray GUICtrlListView_GetColumnWidth GUICtrlListView_GetCounterPage GUICtrlListView_GetEditControl GUICtrlListView_GetExtendedListViewStyle GUICtrlListView_GetFocusedGroup GUICtrlListView_GetGroupCount GUICtrlListView_GetGroupInfo GUICtrlListView_GetGroupInfoByIndex GUICtrlListView_GetGroupRect GUICtrlListView_GetGroupViewEnabled GUICtrlListView_GetHeader GUICtrlListView_GetHotCursor GUICtrlListView_GetHotItem GUICtrlListView_GetHoverTime GUICtrlListView_GetImageList GUICtrlListView_GetISearchString GUICtrlListView_GetItem GUICtrlListView_GetItemChecked GUICtrlListView_GetItemCount GUICtrlListView_GetItemCut GUICtrlListView_GetItemDropHilited GUICtrlListView_GetItemEx GUICtrlListView_GetItemFocused GUICtrlListView_GetItemGroupID GUICtrlListView_GetItemImage GUICtrlListView_GetItemIndent GUICtrlListView_GetItemParam GUICtrlListView_GetItemPosition GUICtrlListView_GetItemPositionX GUICtrlListView_GetItemPositionY GUICtrlListView_GetItemRect GUICtrlListView_GetItemRectEx GUICtrlListView_GetItemSelected GUICtrlListView_GetItemSpacing GUICtrlListView_GetItemSpacingX GUICtrlListView_GetItemSpacingY GUICtrlListView_GetItemState GUICtrlListView_GetItemStateImage GUICtrlListView_GetItemText GUICtrlListView_GetItemTextArray GUICtrlListView_GetItemTextString GUICtrlListView_GetNextItem GUICtrlListView_GetNumberOfWorkAreas GUICtrlListView_GetOrigin GUICtrlListView_GetOriginX GUICtrlListView_GetOriginY GUICtrlListView_GetOutlineColor GUICtrlListView_GetSelectedColumn GUICtrlListView_GetSelectedCount GUICtrlListView_GetSelectedIndices GUICtrlListView_GetSelectionMark GUICtrlListView_GetStringWidth GUICtrlListView_GetSubItemRect GUICtrlListView_GetTextBkColor GUICtrlListView_GetTextColor GUICtrlListView_GetToolTips GUICtrlListView_GetTopIndex GUICtrlListView_GetUnicodeFormat GUICtrlListView_GetView GUICtrlListView_GetViewDetails GUICtrlListView_GetViewLarge GUICtrlListView_GetViewList GUICtrlListView_GetViewRect GUICtrlListView_GetViewSmall GUICtrlListView_GetViewTile GUICtrlListView_HideColumn GUICtrlListView_HitTest GUICtrlListView_InsertColumn GUICtrlListView_InsertGroup GUICtrlListView_InsertItem GUICtrlListView_JustifyColumn GUICtrlListView_MapIDToIndex GUICtrlListView_MapIndexToID GUICtrlListView_RedrawItems GUICtrlListView_RegisterSortCallBack GUICtrlListView_RemoveAllGroups GUICtrlListView_RemoveGroup GUICtrlListView_Scroll GUICtrlListView_SetBkColor GUICtrlListView_SetBkImage GUICtrlListView_SetCallBackMask GUICtrlListView_SetColumn GUICtrlListView_SetColumnOrder GUICtrlListView_SetColumnOrderArray GUICtrlListView_SetColumnWidth GUICtrlListView_SetExtendedListViewStyle GUICtrlListView_SetGroupInfo GUICtrlListView_SetHotItem GUICtrlListView_SetHoverTime GUICtrlListView_SetIconSpacing GUICtrlListView_SetImageList GUICtrlListView_SetItem GUICtrlListView_SetItemChecked GUICtrlListView_SetItemCount GUICtrlListView_SetItemCut GUICtrlListView_SetItemDropHilited GUICtrlListView_SetItemEx GUICtrlListView_SetItemFocused GUICtrlListView_SetItemGroupID GUICtrlListView_SetItemImage GUICtrlListView_SetItemIndent GUICtrlListView_SetItemParam GUICtrlListView_SetItemPosition GUICtrlListView_SetItemPosition32 GUICtrlListView_SetItemSelected GUICtrlListView_SetItemState GUICtrlListView_SetItemStateImage GUICtrlListView_SetItemText GUICtrlListView_SetOutlineColor GUICtrlListView_SetSelectedColumn GUICtrlListView_SetSelectionMark GUICtrlListView_SetTextBkColor GUICtrlListView_SetTextColor GUICtrlListView_SetToolTips GUICtrlListView_SetUnicodeFormat GUICtrlListView_SetView GUICtrlListView_SetWorkAreas GUICtrlListView_SimpleSort GUICtrlListView_SortItems GUICtrlListView_SubItemHitTest GUICtrlListView_UnRegisterSortCallBack GUICtrlMenu_AddMenuItem GUICtrlMenu_AppendMenu GUICtrlMenu_CalculatePopupWindowPosition GUICtrlMenu_CheckMenuItem GUICtrlMenu_CheckRadioItem GUICtrlMenu_CreateMenu GUICtrlMenu_CreatePopup GUICtrlMenu_DeleteMenu GUICtrlMenu_DestroyMenu GUICtrlMenu_DrawMenuBar GUICtrlMenu_EnableMenuItem GUICtrlMenu_FindItem GUICtrlMenu_FindParent GUICtrlMenu_GetItemBmp GUICtrlMenu_GetItemBmpChecked GUICtrlMenu_GetItemBmpUnchecked GUICtrlMenu_GetItemChecked GUICtrlMenu_GetItemCount GUICtrlMenu_GetItemData GUICtrlMenu_GetItemDefault GUICtrlMenu_GetItemDisabled GUICtrlMenu_GetItemEnabled GUICtrlMenu_GetItemGrayed GUICtrlMenu_GetItemHighlighted GUICtrlMenu_GetItemID GUICtrlMenu_GetItemInfo GUICtrlMenu_GetItemRect GUICtrlMenu_GetItemRectEx GUICtrlMenu_GetItemState GUICtrlMenu_GetItemStateEx GUICtrlMenu_GetItemSubMenu GUICtrlMenu_GetItemText GUICtrlMenu_GetItemType GUICtrlMenu_GetMenu GUICtrlMenu_GetMenuBackground GUICtrlMenu_GetMenuBarInfo GUICtrlMenu_GetMenuContextHelpID GUICtrlMenu_GetMenuData GUICtrlMenu_GetMenuDefaultItem GUICtrlMenu_GetMenuHeight GUICtrlMenu_GetMenuInfo GUICtrlMenu_GetMenuStyle GUICtrlMenu_GetSystemMenu GUICtrlMenu_InsertMenuItem GUICtrlMenu_InsertMenuItemEx GUICtrlMenu_IsMenu GUICtrlMenu_LoadMenu GUICtrlMenu_MapAccelerator GUICtrlMenu_MenuItemFromPoint GUICtrlMenu_RemoveMenu GUICtrlMenu_SetItemBitmaps GUICtrlMenu_SetItemBmp GUICtrlMenu_SetItemBmpChecked GUICtrlMenu_SetItemBmpUnchecked GUICtrlMenu_SetItemChecked GUICtrlMenu_SetItemData GUICtrlMenu_SetItemDefault GUICtrlMenu_SetItemDisabled GUICtrlMenu_SetItemEnabled GUICtrlMenu_SetItemGrayed GUICtrlMenu_SetItemHighlighted GUICtrlMenu_SetItemID GUICtrlMenu_SetItemInfo GUICtrlMenu_SetItemState GUICtrlMenu_SetItemSubMenu GUICtrlMenu_SetItemText GUICtrlMenu_SetItemType GUICtrlMenu_SetMenu GUICtrlMenu_SetMenuBackground GUICtrlMenu_SetMenuContextHelpID GUICtrlMenu_SetMenuData GUICtrlMenu_SetMenuDefaultItem GUICtrlMenu_SetMenuHeight GUICtrlMenu_SetMenuInfo GUICtrlMenu_SetMenuStyle GUICtrlMenu_TrackPopupMenu GUICtrlMonthCal_Create GUICtrlMonthCal_Destroy GUICtrlMonthCal_GetCalendarBorder GUICtrlMonthCal_GetCalendarCount GUICtrlMonthCal_GetColor GUICtrlMonthCal_GetColorArray GUICtrlMonthCal_GetCurSel GUICtrlMonthCal_GetCurSelStr GUICtrlMonthCal_GetFirstDOW GUICtrlMonthCal_GetFirstDOWStr GUICtrlMonthCal_GetMaxSelCount GUICtrlMonthCal_GetMaxTodayWidth GUICtrlMonthCal_GetMinReqHeight GUICtrlMonthCal_GetMinReqRect GUICtrlMonthCal_GetMinReqRectArray GUICtrlMonthCal_GetMinReqWidth GUICtrlMonthCal_GetMonthDelta GUICtrlMonthCal_GetMonthRange GUICtrlMonthCal_GetMonthRangeMax GUICtrlMonthCal_GetMonthRangeMaxStr GUICtrlMonthCal_GetMonthRangeMin GUICtrlMonthCal_GetMonthRangeMinStr GUICtrlMonthCal_GetMonthRangeSpan GUICtrlMonthCal_GetRange GUICtrlMonthCal_GetRangeMax GUICtrlMonthCal_GetRangeMaxStr GUICtrlMonthCal_GetRangeMin GUICtrlMonthCal_GetRangeMinStr GUICtrlMonthCal_GetSelRange GUICtrlMonthCal_GetSelRangeMax GUICtrlMonthCal_GetSelRangeMaxStr GUICtrlMonthCal_GetSelRangeMin GUICtrlMonthCal_GetSelRangeMinStr GUICtrlMonthCal_GetToday GUICtrlMonthCal_GetTodayStr GUICtrlMonthCal_GetUnicodeFormat GUICtrlMonthCal_HitTest GUICtrlMonthCal_SetCalendarBorder GUICtrlMonthCal_SetColor GUICtrlMonthCal_SetCurSel GUICtrlMonthCal_SetDayState GUICtrlMonthCal_SetFirstDOW GUICtrlMonthCal_SetMaxSelCount GUICtrlMonthCal_SetMonthDelta GUICtrlMonthCal_SetRange GUICtrlMonthCal_SetSelRange GUICtrlMonthCal_SetToday GUICtrlMonthCal_SetUnicodeFormat GUICtrlRebar_AddBand GUICtrlRebar_AddToolBarBand GUICtrlRebar_BeginDrag GUICtrlRebar_Create GUICtrlRebar_DeleteBand GUICtrlRebar_Destroy GUICtrlRebar_DragMove GUICtrlRebar_EndDrag GUICtrlRebar_GetBandBackColor GUICtrlRebar_GetBandBorders GUICtrlRebar_GetBandBordersEx GUICtrlRebar_GetBandChildHandle GUICtrlRebar_GetBandChildSize GUICtrlRebar_GetBandCount GUICtrlRebar_GetBandForeColor GUICtrlRebar_GetBandHeaderSize GUICtrlRebar_GetBandID GUICtrlRebar_GetBandIdealSize GUICtrlRebar_GetBandLength GUICtrlRebar_GetBandLParam GUICtrlRebar_GetBandMargins GUICtrlRebar_GetBandMarginsEx GUICtrlRebar_GetBandRect GUICtrlRebar_GetBandRectEx GUICtrlRebar_GetBandStyle GUICtrlRebar_GetBandStyleBreak GUICtrlRebar_GetBandStyleChildEdge GUICtrlRebar_GetBandStyleFixedBMP GUICtrlRebar_GetBandStyleFixedSize GUICtrlRebar_GetBandStyleGripperAlways GUICtrlRebar_GetBandStyleHidden GUICtrlRebar_GetBandStyleHideTitle GUICtrlRebar_GetBandStyleNoGripper GUICtrlRebar_GetBandStyleTopAlign GUICtrlRebar_GetBandStyleUseChevron GUICtrlRebar_GetBandStyleVariableHeight GUICtrlRebar_GetBandText GUICtrlRebar_GetBarHeight GUICtrlRebar_GetBarInfo GUICtrlRebar_GetBKColor GUICtrlRebar_GetColorScheme GUICtrlRebar_GetRowCount GUICtrlRebar_GetRowHeight GUICtrlRebar_GetTextColor GUICtrlRebar_GetToolTips GUICtrlRebar_GetUnicodeFormat GUICtrlRebar_HitTest GUICtrlRebar_IDToIndex GUICtrlRebar_MaximizeBand GUICtrlRebar_MinimizeBand GUICtrlRebar_MoveBand GUICtrlRebar_SetBandBackColor GUICtrlRebar_SetBandForeColor GUICtrlRebar_SetBandHeaderSize GUICtrlRebar_SetBandID GUICtrlRebar_SetBandIdealSize GUICtrlRebar_SetBandLength GUICtrlRebar_SetBandLParam GUICtrlRebar_SetBandStyle GUICtrlRebar_SetBandStyleBreak GUICtrlRebar_SetBandStyleChildEdge GUICtrlRebar_SetBandStyleFixedBMP GUICtrlRebar_SetBandStyleFixedSize GUICtrlRebar_SetBandStyleGripperAlways GUICtrlRebar_SetBandStyleHidden GUICtrlRebar_SetBandStyleHideTitle GUICtrlRebar_SetBandStyleNoGripper GUICtrlRebar_SetBandStyleTopAlign GUICtrlRebar_SetBandStyleUseChevron GUICtrlRebar_SetBandStyleVariableHeight GUICtrlRebar_SetBandText GUICtrlRebar_SetBarInfo GUICtrlRebar_SetBKColor GUICtrlRebar_SetColorScheme GUICtrlRebar_SetTextColor GUICtrlRebar_SetToolTips GUICtrlRebar_SetUnicodeFormat GUICtrlRebar_ShowBand GUICtrlRichEdit_AppendText GUICtrlRichEdit_AutoDetectURL GUICtrlRichEdit_CanPaste GUICtrlRichEdit_CanPasteSpecial GUICtrlRichEdit_CanRedo GUICtrlRichEdit_CanUndo GUICtrlRichEdit_ChangeFontSize GUICtrlRichEdit_Copy GUICtrlRichEdit_Create GUICtrlRichEdit_Cut GUICtrlRichEdit_Deselect GUICtrlRichEdit_Destroy GUICtrlRichEdit_EmptyUndoBuffer GUICtrlRichEdit_FindText GUICtrlRichEdit_FindTextInRange GUICtrlRichEdit_GetBkColor GUICtrlRichEdit_GetCharAttributes GUICtrlRichEdit_GetCharBkColor GUICtrlRichEdit_GetCharColor GUICtrlRichEdit_GetCharPosFromXY GUICtrlRichEdit_GetCharPosOfNextWord GUICtrlRichEdit_GetCharPosOfPreviousWord GUICtrlRichEdit_GetCharWordBreakInfo GUICtrlRichEdit_GetFirstCharPosOnLine GUICtrlRichEdit_GetFont GUICtrlRichEdit_GetLineCount GUICtrlRichEdit_GetLineLength GUICtrlRichEdit_GetLineNumberFromCharPos GUICtrlRichEdit_GetNextRedo GUICtrlRichEdit_GetNextUndo GUICtrlRichEdit_GetNumberOfFirstVisibleLine GUICtrlRichEdit_GetParaAlignment GUICtrlRichEdit_GetParaAttributes GUICtrlRichEdit_GetParaBorder GUICtrlRichEdit_GetParaIndents GUICtrlRichEdit_GetParaNumbering GUICtrlRichEdit_GetParaShading GUICtrlRichEdit_GetParaSpacing GUICtrlRichEdit_GetParaTabStops GUICtrlRichEdit_GetPasswordChar GUICtrlRichEdit_GetRECT GUICtrlRichEdit_GetScrollPos GUICtrlRichEdit_GetSel GUICtrlRichEdit_GetSelAA GUICtrlRichEdit_GetSelText GUICtrlRichEdit_GetSpaceUnit GUICtrlRichEdit_GetText GUICtrlRichEdit_GetTextInLine GUICtrlRichEdit_GetTextInRange GUICtrlRichEdit_GetTextLength GUICtrlRichEdit_GetVersion GUICtrlRichEdit_GetXYFromCharPos GUICtrlRichEdit_GetZoom GUICtrlRichEdit_GotoCharPos GUICtrlRichEdit_HideSelection GUICtrlRichEdit_InsertText GUICtrlRichEdit_IsModified GUICtrlRichEdit_IsTextSelected GUICtrlRichEdit_Paste GUICtrlRichEdit_PasteSpecial GUICtrlRichEdit_PauseRedraw GUICtrlRichEdit_Redo GUICtrlRichEdit_ReplaceText GUICtrlRichEdit_ResumeRedraw GUICtrlRichEdit_ScrollLineOrPage GUICtrlRichEdit_ScrollLines GUICtrlRichEdit_ScrollToCaret GUICtrlRichEdit_SetBkColor GUICtrlRichEdit_SetCharAttributes GUICtrlRichEdit_SetCharBkColor GUICtrlRichEdit_SetCharColor GUICtrlRichEdit_SetEventMask GUICtrlRichEdit_SetFont GUICtrlRichEdit_SetLimitOnText GUICtrlRichEdit_SetModified GUICtrlRichEdit_SetParaAlignment GUICtrlRichEdit_SetParaAttributes GUICtrlRichEdit_SetParaBorder GUICtrlRichEdit_SetParaIndents GUICtrlRichEdit_SetParaNumbering GUICtrlRichEdit_SetParaShading GUICtrlRichEdit_SetParaSpacing GUICtrlRichEdit_SetParaTabStops GUICtrlRichEdit_SetPasswordChar GUICtrlRichEdit_SetReadOnly GUICtrlRichEdit_SetRECT GUICtrlRichEdit_SetScrollPos GUICtrlRichEdit_SetSel GUICtrlRichEdit_SetSpaceUnit GUICtrlRichEdit_SetTabStops GUICtrlRichEdit_SetText GUICtrlRichEdit_SetUndoLimit GUICtrlRichEdit_SetZoom GUICtrlRichEdit_StreamFromFile GUICtrlRichEdit_StreamFromVar GUICtrlRichEdit_StreamToFile GUICtrlRichEdit_StreamToVar GUICtrlRichEdit_Undo GUICtrlSlider_ClearSel GUICtrlSlider_ClearTics GUICtrlSlider_Create GUICtrlSlider_Destroy GUICtrlSlider_GetBuddy GUICtrlSlider_GetChannelRect GUICtrlSlider_GetChannelRectEx GUICtrlSlider_GetLineSize GUICtrlSlider_GetLogicalTics GUICtrlSlider_GetNumTics GUICtrlSlider_GetPageSize GUICtrlSlider_GetPos GUICtrlSlider_GetRange GUICtrlSlider_GetRangeMax GUICtrlSlider_GetRangeMin GUICtrlSlider_GetSel GUICtrlSlider_GetSelEnd GUICtrlSlider_GetSelStart GUICtrlSlider_GetThumbLength GUICtrlSlider_GetThumbRect GUICtrlSlider_GetThumbRectEx GUICtrlSlider_GetTic GUICtrlSlider_GetTicPos GUICtrlSlider_GetToolTips GUICtrlSlider_GetUnicodeFormat GUICtrlSlider_SetBuddy GUICtrlSlider_SetLineSize GUICtrlSlider_SetPageSize GUICtrlSlider_SetPos GUICtrlSlider_SetRange GUICtrlSlider_SetRangeMax GUICtrlSlider_SetRangeMin GUICtrlSlider_SetSel GUICtrlSlider_SetSelEnd GUICtrlSlider_SetSelStart GUICtrlSlider_SetThumbLength GUICtrlSlider_SetTic GUICtrlSlider_SetTicFreq GUICtrlSlider_SetTipSide GUICtrlSlider_SetToolTips GUICtrlSlider_SetUnicodeFormat GUICtrlStatusBar_Create GUICtrlStatusBar_Destroy GUICtrlStatusBar_EmbedControl GUICtrlStatusBar_GetBorders GUICtrlStatusBar_GetBordersHorz GUICtrlStatusBar_GetBordersRect GUICtrlStatusBar_GetBordersVert GUICtrlStatusBar_GetCount GUICtrlStatusBar_GetHeight GUICtrlStatusBar_GetIcon GUICtrlStatusBar_GetParts GUICtrlStatusBar_GetRect GUICtrlStatusBar_GetRectEx GUICtrlStatusBar_GetText GUICtrlStatusBar_GetTextFlags GUICtrlStatusBar_GetTextLength GUICtrlStatusBar_GetTextLengthEx GUICtrlStatusBar_GetTipText GUICtrlStatusBar_GetUnicodeFormat GUICtrlStatusBar_GetWidth GUICtrlStatusBar_IsSimple GUICtrlStatusBar_Resize GUICtrlStatusBar_SetBkColor GUICtrlStatusBar_SetIcon GUICtrlStatusBar_SetMinHeight GUICtrlStatusBar_SetParts GUICtrlStatusBar_SetSimple GUICtrlStatusBar_SetText GUICtrlStatusBar_SetTipText GUICtrlStatusBar_SetUnicodeFormat GUICtrlStatusBar_ShowHide GUICtrlTab_ActivateTab GUICtrlTab_ClickTab GUICtrlTab_Create GUICtrlTab_DeleteAllItems GUICtrlTab_DeleteItem GUICtrlTab_DeselectAll GUICtrlTab_Destroy GUICtrlTab_FindTab GUICtrlTab_GetCurFocus GUICtrlTab_GetCurSel GUICtrlTab_GetDisplayRect GUICtrlTab_GetDisplayRectEx GUICtrlTab_GetExtendedStyle GUICtrlTab_GetImageList GUICtrlTab_GetItem GUICtrlTab_GetItemCount GUICtrlTab_GetItemImage GUICtrlTab_GetItemParam GUICtrlTab_GetItemRect GUICtrlTab_GetItemRectEx GUICtrlTab_GetItemState GUICtrlTab_GetItemText GUICtrlTab_GetRowCount GUICtrlTab_GetToolTips GUICtrlTab_GetUnicodeFormat GUICtrlTab_HighlightItem GUICtrlTab_HitTest GUICtrlTab_InsertItem GUICtrlTab_RemoveImage GUICtrlTab_SetCurFocus GUICtrlTab_SetCurSel GUICtrlTab_SetExtendedStyle GUICtrlTab_SetImageList GUICtrlTab_SetItem GUICtrlTab_SetItemImage GUICtrlTab_SetItemParam GUICtrlTab_SetItemSize GUICtrlTab_SetItemState GUICtrlTab_SetItemText GUICtrlTab_SetMinTabWidth GUICtrlTab_SetPadding GUICtrlTab_SetToolTips GUICtrlTab_SetUnicodeFormat GUICtrlToolbar_AddBitmap GUICtrlToolbar_AddButton GUICtrlToolbar_AddButtonSep GUICtrlToolbar_AddString GUICtrlToolbar_ButtonCount GUICtrlToolbar_CheckButton GUICtrlToolbar_ClickAccel GUICtrlToolbar_ClickButton GUICtrlToolbar_ClickIndex GUICtrlToolbar_CommandToIndex GUICtrlToolbar_Create GUICtrlToolbar_Customize GUICtrlToolbar_DeleteButton GUICtrlToolbar_Destroy GUICtrlToolbar_EnableButton GUICtrlToolbar_FindToolbar GUICtrlToolbar_GetAnchorHighlight GUICtrlToolbar_GetBitmapFlags GUICtrlToolbar_GetButtonBitmap GUICtrlToolbar_GetButtonInfo GUICtrlToolbar_GetButtonInfoEx GUICtrlToolbar_GetButtonParam GUICtrlToolbar_GetButtonRect GUICtrlToolbar_GetButtonRectEx GUICtrlToolbar_GetButtonSize GUICtrlToolbar_GetButtonState GUICtrlToolbar_GetButtonStyle GUICtrlToolbar_GetButtonText GUICtrlToolbar_GetColorScheme GUICtrlToolbar_GetDisabledImageList GUICtrlToolbar_GetExtendedStyle GUICtrlToolbar_GetHotImageList GUICtrlToolbar_GetHotItem GUICtrlToolbar_GetImageList GUICtrlToolbar_GetInsertMark GUICtrlToolbar_GetInsertMarkColor GUICtrlToolbar_GetMaxSize GUICtrlToolbar_GetMetrics GUICtrlToolbar_GetPadding GUICtrlToolbar_GetRows GUICtrlToolbar_GetString GUICtrlToolbar_GetStyle GUICtrlToolbar_GetStyleAltDrag GUICtrlToolbar_GetStyleCustomErase GUICtrlToolbar_GetStyleFlat GUICtrlToolbar_GetStyleList GUICtrlToolbar_GetStyleRegisterDrop GUICtrlToolbar_GetStyleToolTips GUICtrlToolbar_GetStyleTransparent GUICtrlToolbar_GetStyleWrapable GUICtrlToolbar_GetTextRows GUICtrlToolbar_GetToolTips GUICtrlToolbar_GetUnicodeFormat GUICtrlToolbar_HideButton GUICtrlToolbar_HighlightButton GUICtrlToolbar_HitTest GUICtrlToolbar_IndexToCommand GUICtrlToolbar_InsertButton GUICtrlToolbar_InsertMarkHitTest GUICtrlToolbar_IsButtonChecked GUICtrlToolbar_IsButtonEnabled GUICtrlToolbar_IsButtonHidden GUICtrlToolbar_IsButtonHighlighted GUICtrlToolbar_IsButtonIndeterminate GUICtrlToolbar_IsButtonPressed GUICtrlToolbar_LoadBitmap GUICtrlToolbar_LoadImages GUICtrlToolbar_MapAccelerator GUICtrlToolbar_MoveButton GUICtrlToolbar_PressButton GUICtrlToolbar_SetAnchorHighlight GUICtrlToolbar_SetBitmapSize GUICtrlToolbar_SetButtonBitMap GUICtrlToolbar_SetButtonInfo GUICtrlToolbar_SetButtonInfoEx GUICtrlToolbar_SetButtonParam GUICtrlToolbar_SetButtonSize GUICtrlToolbar_SetButtonState GUICtrlToolbar_SetButtonStyle GUICtrlToolbar_SetButtonText GUICtrlToolbar_SetButtonWidth GUICtrlToolbar_SetCmdID GUICtrlToolbar_SetColorScheme GUICtrlToolbar_SetDisabledImageList GUICtrlToolbar_SetDrawTextFlags GUICtrlToolbar_SetExtendedStyle GUICtrlToolbar_SetHotImageList GUICtrlToolbar_SetHotItem GUICtrlToolbar_SetImageList GUICtrlToolbar_SetIndent GUICtrlToolbar_SetIndeterminate GUICtrlToolbar_SetInsertMark GUICtrlToolbar_SetInsertMarkColor GUICtrlToolbar_SetMaxTextRows GUICtrlToolbar_SetMetrics GUICtrlToolbar_SetPadding GUICtrlToolbar_SetParent GUICtrlToolbar_SetRows GUICtrlToolbar_SetStyle GUICtrlToolbar_SetStyleAltDrag GUICtrlToolbar_SetStyleCustomErase GUICtrlToolbar_SetStyleFlat GUICtrlToolbar_SetStyleList GUICtrlToolbar_SetStyleRegisterDrop GUICtrlToolbar_SetStyleToolTips GUICtrlToolbar_SetStyleTransparent GUICtrlToolbar_SetStyleWrapable GUICtrlToolbar_SetToolTips GUICtrlToolbar_SetUnicodeFormat GUICtrlToolbar_SetWindowTheme GUICtrlTreeView_Add GUICtrlTreeView_AddChild GUICtrlTreeView_AddChildFirst GUICtrlTreeView_AddFirst GUICtrlTreeView_BeginUpdate GUICtrlTreeView_ClickItem GUICtrlTreeView_Create GUICtrlTreeView_CreateDragImage GUICtrlTreeView_CreateSolidBitMap GUICtrlTreeView_Delete GUICtrlTreeView_DeleteAll GUICtrlTreeView_DeleteChildren GUICtrlTreeView_Destroy GUICtrlTreeView_DisplayRect GUICtrlTreeView_DisplayRectEx GUICtrlTreeView_EditText GUICtrlTreeView_EndEdit GUICtrlTreeView_EndUpdate GUICtrlTreeView_EnsureVisible GUICtrlTreeView_Expand GUICtrlTreeView_ExpandedOnce GUICtrlTreeView_FindItem GUICtrlTreeView_FindItemEx GUICtrlTreeView_GetBkColor GUICtrlTreeView_GetBold GUICtrlTreeView_GetChecked GUICtrlTreeView_GetChildCount GUICtrlTreeView_GetChildren GUICtrlTreeView_GetCount GUICtrlTreeView_GetCut GUICtrlTreeView_GetDropTarget GUICtrlTreeView_GetEditControl GUICtrlTreeView_GetExpanded GUICtrlTreeView_GetFirstChild GUICtrlTreeView_GetFirstItem GUICtrlTreeView_GetFirstVisible GUICtrlTreeView_GetFocused GUICtrlTreeView_GetHeight GUICtrlTreeView_GetImageIndex GUICtrlTreeView_GetImageListIconHandle GUICtrlTreeView_GetIndent GUICtrlTreeView_GetInsertMarkColor GUICtrlTreeView_GetISearchString GUICtrlTreeView_GetItemByIndex GUICtrlTreeView_GetItemHandle GUICtrlTreeView_GetItemParam GUICtrlTreeView_GetLastChild GUICtrlTreeView_GetLineColor GUICtrlTreeView_GetNext GUICtrlTreeView_GetNextChild GUICtrlTreeView_GetNextSibling GUICtrlTreeView_GetNextVisible GUICtrlTreeView_GetNormalImageList GUICtrlTreeView_GetParentHandle GUICtrlTreeView_GetParentParam GUICtrlTreeView_GetPrev GUICtrlTreeView_GetPrevChild GUICtrlTreeView_GetPrevSibling GUICtrlTreeView_GetPrevVisible GUICtrlTreeView_GetScrollTime GUICtrlTreeView_GetSelected GUICtrlTreeView_GetSelectedImageIndex GUICtrlTreeView_GetSelection GUICtrlTreeView_GetSiblingCount GUICtrlTreeView_GetState GUICtrlTreeView_GetStateImageIndex GUICtrlTreeView_GetStateImageList GUICtrlTreeView_GetText GUICtrlTreeView_GetTextColor GUICtrlTreeView_GetToolTips GUICtrlTreeView_GetTree GUICtrlTreeView_GetUnicodeFormat GUICtrlTreeView_GetVisible GUICtrlTreeView_GetVisibleCount GUICtrlTreeView_HitTest GUICtrlTreeView_HitTestEx GUICtrlTreeView_HitTestItem GUICtrlTreeView_Index GUICtrlTreeView_InsertItem GUICtrlTreeView_IsFirstItem GUICtrlTreeView_IsParent GUICtrlTreeView_Level GUICtrlTreeView_SelectItem GUICtrlTreeView_SelectItemByIndex GUICtrlTreeView_SetBkColor GUICtrlTreeView_SetBold GUICtrlTreeView_SetChecked GUICtrlTreeView_SetCheckedByIndex GUICtrlTreeView_SetChildren GUICtrlTreeView_SetCut GUICtrlTreeView_SetDropTarget GUICtrlTreeView_SetFocused GUICtrlTreeView_SetHeight GUICtrlTreeView_SetIcon GUICtrlTreeView_SetImageIndex GUICtrlTreeView_SetIndent GUICtrlTreeView_SetInsertMark GUICtrlTreeView_SetInsertMarkColor GUICtrlTreeView_SetItemHeight GUICtrlTreeView_SetItemParam GUICtrlTreeView_SetLineColor GUICtrlTreeView_SetNormalImageList GUICtrlTreeView_SetScrollTime GUICtrlTreeView_SetSelected GUICtrlTreeView_SetSelectedImageIndex GUICtrlTreeView_SetState GUICtrlTreeView_SetStateImageIndex GUICtrlTreeView_SetStateImageList GUICtrlTreeView_SetText GUICtrlTreeView_SetTextColor GUICtrlTreeView_SetToolTips GUICtrlTreeView_SetUnicodeFormat GUICtrlTreeView_Sort GUIImageList_Add GUIImageList_AddBitmap GUIImageList_AddIcon GUIImageList_AddMasked GUIImageList_BeginDrag GUIImageList_Copy GUIImageList_Create GUIImageList_Destroy GUIImageList_DestroyIcon GUIImageList_DragEnter GUIImageList_DragLeave GUIImageList_DragMove GUIImageList_Draw GUIImageList_DrawEx GUIImageList_Duplicate GUIImageList_EndDrag GUIImageList_GetBkColor GUIImageList_GetIcon GUIImageList_GetIconHeight GUIImageList_GetIconSize GUIImageList_GetIconSizeEx GUIImageList_GetIconWidth GUIImageList_GetImageCount GUIImageList_GetImageInfoEx GUIImageList_Remove GUIImageList_ReplaceIcon GUIImageList_SetBkColor GUIImageList_SetIconSize GUIImageList_SetImageCount GUIImageList_Swap GUIScrollBars_EnableScrollBar GUIScrollBars_GetScrollBarInfoEx GUIScrollBars_GetScrollBarRect GUIScrollBars_GetScrollBarRGState GUIScrollBars_GetScrollBarXYLineButton GUIScrollBars_GetScrollBarXYThumbBottom GUIScrollBars_GetScrollBarXYThumbTop GUIScrollBars_GetScrollInfo GUIScrollBars_GetScrollInfoEx GUIScrollBars_GetScrollInfoMax GUIScrollBars_GetScrollInfoMin GUIScrollBars_GetScrollInfoPage GUIScrollBars_GetScrollInfoPos GUIScrollBars_GetScrollInfoTrackPos GUIScrollBars_GetScrollPos GUIScrollBars_GetScrollRange GUIScrollBars_Init GUIScrollBars_ScrollWindow GUIScrollBars_SetScrollInfo GUIScrollBars_SetScrollInfoMax GUIScrollBars_SetScrollInfoMin GUIScrollBars_SetScrollInfoPage GUIScrollBars_SetScrollInfoPos GUIScrollBars_SetScrollRange GUIScrollBars_ShowScrollBar GUIToolTip_Activate GUIToolTip_AddTool GUIToolTip_AdjustRect GUIToolTip_BitsToTTF GUIToolTip_Create GUIToolTip_Deactivate GUIToolTip_DelTool GUIToolTip_Destroy GUIToolTip_EnumTools GUIToolTip_GetBubbleHeight GUIToolTip_GetBubbleSize GUIToolTip_GetBubbleWidth GUIToolTip_GetCurrentTool GUIToolTip_GetDelayTime GUIToolTip_GetMargin GUIToolTip_GetMarginEx GUIToolTip_GetMaxTipWidth GUIToolTip_GetText GUIToolTip_GetTipBkColor GUIToolTip_GetTipTextColor GUIToolTip_GetTitleBitMap GUIToolTip_GetTitleText GUIToolTip_GetToolCount GUIToolTip_GetToolInfo GUIToolTip_HitTest GUIToolTip_NewToolRect GUIToolTip_Pop GUIToolTip_PopUp GUIToolTip_SetDelayTime GUIToolTip_SetMargin GUIToolTip_SetMaxTipWidth GUIToolTip_SetTipBkColor GUIToolTip_SetTipTextColor GUIToolTip_SetTitle GUIToolTip_SetToolInfo GUIToolTip_SetWindowTheme GUIToolTip_ToolExists GUIToolTip_ToolToArray GUIToolTip_TrackActivate GUIToolTip_TrackPosition GUIToolTip_Update GUIToolTip_UpdateTipText HexToString IEAction IEAttach IEBodyReadHTML IEBodyReadText IEBodyWriteHTML IECreate IECreateEmbedded IEDocGetObj IEDocInsertHTML IEDocInsertText IEDocReadHTML IEDocWriteHTML IEErrorNotify IEFormElementCheckBoxSelect IEFormElementGetCollection IEFormElementGetObjByName IEFormElementGetValue IEFormElementOptionSelect IEFormElementRadioSelect IEFormElementSetValue IEFormGetCollection IEFormGetObjByName IEFormImageClick IEFormReset IEFormSubmit IEFrameGetCollection IEFrameGetObjByName IEGetObjById IEGetObjByName IEHeadInsertEventScript IEImgClick IEImgGetCollection IEIsFrameSet IELinkClickByIndex IELinkClickByText IELinkGetCollection IELoadWait IELoadWaitTimeout IENavigate IEPropertyGet IEPropertySet IEQuit IETableGetCollection IETableWriteToArray IETagNameAllGetCollection IETagNameGetCollection IE_Example IE_Introduction IE_VersionInfo INetExplorerCapable INetGetSource INetMail INetSmtpMail IsPressed MathCheckDiv Max MemGlobalAlloc MemGlobalFree MemGlobalLock MemGlobalSize MemGlobalUnlock MemMoveMemory MemVirtualAlloc MemVirtualAllocEx MemVirtualFree MemVirtualFreeEx Min MouseTrap NamedPipes_CallNamedPipe NamedPipes_ConnectNamedPipe NamedPipes_CreateNamedPipe NamedPipes_CreatePipe NamedPipes_DisconnectNamedPipe NamedPipes_GetNamedPipeHandleState NamedPipes_GetNamedPipeInfo NamedPipes_PeekNamedPipe NamedPipes_SetNamedPipeHandleState NamedPipes_TransactNamedPipe NamedPipes_WaitNamedPipe Net_Share_ConnectionEnum Net_Share_FileClose Net_Share_FileEnum Net_Share_FileGetInfo Net_Share_PermStr Net_Share_ResourceStr Net_Share_SessionDel Net_Share_SessionEnum Net_Share_SessionGetInfo Net_Share_ShareAdd Net_Share_ShareCheck Net_Share_ShareDel Net_Share_ShareEnum Net_Share_ShareGetInfo Net_Share_ShareSetInfo Net_Share_StatisticsGetSvr Net_Share_StatisticsGetWrk Now NowCalc NowCalcDate NowDate NowTime PathFull PathGetRelative PathMake PathSplit ProcessGetName ProcessGetPriority Radian ReplaceStringInFile RunDos ScreenCapture_Capture ScreenCapture_CaptureWnd ScreenCapture_SaveImage ScreenCapture_SetBMPFormat ScreenCapture_SetJPGQuality ScreenCapture_SetTIFColorDepth ScreenCapture_SetTIFCompression Security__AdjustTokenPrivileges Security__CreateProcessWithToken Security__DuplicateTokenEx Security__GetAccountSid Security__GetLengthSid Security__GetTokenInformation Security__ImpersonateSelf Security__IsValidSid Security__LookupAccountName Security__LookupAccountSid Security__LookupPrivilegeValue Security__OpenProcessToken Security__OpenThreadToken Security__OpenThreadTokenEx Security__SetPrivilege Security__SetTokenInformation Security__SidToStringSid Security__SidTypeStr Security__StringSidToSid SendMessage SendMessageA SetDate SetTime Singleton SoundClose SoundLength SoundOpen SoundPause SoundPlay SoundPos SoundResume SoundSeek SoundStatus SoundStop SQLite_Changes SQLite_Close SQLite_Display2DResult SQLite_Encode SQLite_ErrCode SQLite_ErrMsg SQLite_Escape SQLite_Exec SQLite_FastEncode SQLite_FastEscape SQLite_FetchData SQLite_FetchNames SQLite_GetTable SQLite_GetTable2d SQLite_LastInsertRowID SQLite_LibVersion SQLite_Open SQLite_Query SQLite_QueryFinalize SQLite_QueryReset SQLite_QuerySingleRow SQLite_SafeMode SQLite_SetTimeout SQLite_Shutdown SQLite_SQLiteExe SQLite_Startup SQLite_TotalChanges StringBetween StringExplode StringInsert StringProper StringRepeat StringTitleCase StringToHex TCPIpToName TempFile TicksToTime Timer_Diff Timer_GetIdleTime Timer_GetTimerID Timer_Init Timer_KillAllTimers Timer_KillTimer Timer_SetTimer TimeToTicks VersionCompare viClose viExecCommand viFindGpib viGpibBusReset viGTL viInteractiveControl viOpen viSetAttribute viSetTimeout WeekNumberISO WinAPI_AbortPath WinAPI_ActivateKeyboardLayout WinAPI_AddClipboardFormatListener WinAPI_AddFontMemResourceEx WinAPI_AddFontResourceEx WinAPI_AddIconOverlay WinAPI_AddIconTransparency WinAPI_AddMRUString WinAPI_AdjustBitmap WinAPI_AdjustTokenPrivileges WinAPI_AdjustWindowRectEx WinAPI_AlphaBlend WinAPI_AngleArc WinAPI_AnimateWindow WinAPI_Arc WinAPI_ArcTo WinAPI_ArrayToStruct WinAPI_AssignProcessToJobObject WinAPI_AssocGetPerceivedType WinAPI_AssocQueryString WinAPI_AttachConsole WinAPI_AttachThreadInput WinAPI_BackupRead WinAPI_BackupReadAbort WinAPI_BackupSeek WinAPI_BackupWrite WinAPI_BackupWriteAbort WinAPI_Beep WinAPI_BeginBufferedPaint WinAPI_BeginDeferWindowPos WinAPI_BeginPaint WinAPI_BeginPath WinAPI_BeginUpdateResource WinAPI_BitBlt WinAPI_BringWindowToTop WinAPI_BroadcastSystemMessage WinAPI_BrowseForFolderDlg WinAPI_BufferedPaintClear WinAPI_BufferedPaintInit WinAPI_BufferedPaintSetAlpha WinAPI_BufferedPaintUnInit WinAPI_CallNextHookEx WinAPI_CallWindowProc WinAPI_CallWindowProcW WinAPI_CascadeWindows WinAPI_ChangeWindowMessageFilterEx WinAPI_CharToOem WinAPI_ChildWindowFromPointEx WinAPI_ClientToScreen WinAPI_ClipCursor WinAPI_CloseDesktop WinAPI_CloseEnhMetaFile WinAPI_CloseFigure WinAPI_CloseHandle WinAPI_CloseThemeData WinAPI_CloseWindow WinAPI_CloseWindowStation WinAPI_CLSIDFromProgID WinAPI_CoInitialize WinAPI_ColorAdjustLuma WinAPI_ColorHLSToRGB WinAPI_ColorRGBToHLS WinAPI_CombineRgn WinAPI_CombineTransform WinAPI_CommandLineToArgv WinAPI_CommDlgExtendedError WinAPI_CommDlgExtendedErrorEx WinAPI_CompareString WinAPI_CompressBitmapBits WinAPI_CompressBuffer WinAPI_ComputeCrc32 WinAPI_ConfirmCredentials WinAPI_CopyBitmap WinAPI_CopyCursor WinAPI_CopyEnhMetaFile WinAPI_CopyFileEx WinAPI_CopyIcon WinAPI_CopyImage WinAPI_CopyRect WinAPI_CopyStruct WinAPI_CoTaskMemAlloc WinAPI_CoTaskMemFree WinAPI_CoTaskMemRealloc WinAPI_CoUninitialize WinAPI_Create32BitHBITMAP WinAPI_Create32BitHICON WinAPI_CreateANDBitmap WinAPI_CreateBitmap WinAPI_CreateBitmapIndirect WinAPI_CreateBrushIndirect WinAPI_CreateBuffer WinAPI_CreateBufferFromStruct WinAPI_CreateCaret WinAPI_CreateColorAdjustment WinAPI_CreateCompatibleBitmap WinAPI_CreateCompatibleBitmapEx WinAPI_CreateCompatibleDC WinAPI_CreateDesktop WinAPI_CreateDIB WinAPI_CreateDIBColorTable WinAPI_CreateDIBitmap WinAPI_CreateDIBSection WinAPI_CreateDirectory WinAPI_CreateDirectoryEx WinAPI_CreateEllipticRgn WinAPI_CreateEmptyIcon WinAPI_CreateEnhMetaFile WinAPI_CreateEvent WinAPI_CreateFile WinAPI_CreateFileEx WinAPI_CreateFileMapping WinAPI_CreateFont WinAPI_CreateFontEx WinAPI_CreateFontIndirect WinAPI_CreateGUID WinAPI_CreateHardLink WinAPI_CreateIcon WinAPI_CreateIconFromResourceEx WinAPI_CreateIconIndirect WinAPI_CreateJobObject WinAPI_CreateMargins WinAPI_CreateMRUList WinAPI_CreateMutex WinAPI_CreateNullRgn WinAPI_CreateNumberFormatInfo WinAPI_CreateObjectID WinAPI_CreatePen WinAPI_CreatePoint WinAPI_CreatePolygonRgn WinAPI_CreateProcess WinAPI_CreateProcessWithToken WinAPI_CreateRect WinAPI_CreateRectEx WinAPI_CreateRectRgn WinAPI_CreateRectRgnIndirect WinAPI_CreateRoundRectRgn WinAPI_CreateSemaphore WinAPI_CreateSize WinAPI_CreateSolidBitmap WinAPI_CreateSolidBrush WinAPI_CreateStreamOnHGlobal WinAPI_CreateString WinAPI_CreateSymbolicLink WinAPI_CreateTransform WinAPI_CreateWindowEx WinAPI_CreateWindowStation WinAPI_DecompressBuffer WinAPI_DecryptFile WinAPI_DeferWindowPos WinAPI_DefineDosDevice WinAPI_DefRawInputProc WinAPI_DefSubclassProc WinAPI_DefWindowProc WinAPI_DefWindowProcW WinAPI_DeleteDC WinAPI_DeleteEnhMetaFile WinAPI_DeleteFile WinAPI_DeleteObject WinAPI_DeleteObjectID WinAPI_DeleteVolumeMountPoint WinAPI_DeregisterShellHookWindow WinAPI_DestroyCaret WinAPI_DestroyCursor WinAPI_DestroyIcon WinAPI_DestroyWindow WinAPI_DeviceIoControl WinAPI_DisplayStruct WinAPI_DllGetVersion WinAPI_DllInstall WinAPI_DllUninstall WinAPI_DPtoLP WinAPI_DragAcceptFiles WinAPI_DragFinish WinAPI_DragQueryFileEx WinAPI_DragQueryPoint WinAPI_DrawAnimatedRects WinAPI_DrawBitmap WinAPI_DrawEdge WinAPI_DrawFocusRect WinAPI_DrawFrameControl WinAPI_DrawIcon WinAPI_DrawIconEx WinAPI_DrawLine WinAPI_DrawShadowText WinAPI_DrawText WinAPI_DrawThemeBackground WinAPI_DrawThemeEdge WinAPI_DrawThemeIcon WinAPI_DrawThemeParentBackground WinAPI_DrawThemeText WinAPI_DrawThemeTextEx WinAPI_DuplicateEncryptionInfoFile WinAPI_DuplicateHandle WinAPI_DuplicateTokenEx WinAPI_DwmDefWindowProc WinAPI_DwmEnableBlurBehindWindow WinAPI_DwmEnableComposition WinAPI_DwmExtendFrameIntoClientArea WinAPI_DwmGetColorizationColor WinAPI_DwmGetColorizationParameters WinAPI_DwmGetWindowAttribute WinAPI_DwmInvalidateIconicBitmaps WinAPI_DwmIsCompositionEnabled WinAPI_DwmQueryThumbnailSourceSize WinAPI_DwmRegisterThumbnail WinAPI_DwmSetColorizationParameters WinAPI_DwmSetIconicLivePreviewBitmap WinAPI_DwmSetIconicThumbnail WinAPI_DwmSetWindowAttribute WinAPI_DwmUnregisterThumbnail WinAPI_DwmUpdateThumbnailProperties WinAPI_DWordToFloat WinAPI_DWordToInt WinAPI_EjectMedia WinAPI_Ellipse WinAPI_EmptyWorkingSet WinAPI_EnableWindow WinAPI_EncryptFile WinAPI_EncryptionDisable WinAPI_EndBufferedPaint WinAPI_EndDeferWindowPos WinAPI_EndPaint WinAPI_EndPath WinAPI_EndUpdateResource WinAPI_EnumChildProcess WinAPI_EnumChildWindows WinAPI_EnumDesktops WinAPI_EnumDesktopWindows WinAPI_EnumDeviceDrivers WinAPI_EnumDisplayDevices WinAPI_EnumDisplayMonitors WinAPI_EnumDisplaySettings WinAPI_EnumDllProc WinAPI_EnumFiles WinAPI_EnumFileStreams WinAPI_EnumFontFamilies WinAPI_EnumHardLinks WinAPI_EnumMRUList WinAPI_EnumPageFiles WinAPI_EnumProcessHandles WinAPI_EnumProcessModules WinAPI_EnumProcessThreads WinAPI_EnumProcessWindows WinAPI_EnumRawInputDevices WinAPI_EnumResourceLanguages WinAPI_EnumResourceNames WinAPI_EnumResourceTypes WinAPI_EnumSystemGeoID WinAPI_EnumSystemLocales WinAPI_EnumUILanguages WinAPI_EnumWindows WinAPI_EnumWindowsPopup WinAPI_EnumWindowStations WinAPI_EnumWindowsTop WinAPI_EqualMemory WinAPI_EqualRect WinAPI_EqualRgn WinAPI_ExcludeClipRect WinAPI_ExpandEnvironmentStrings WinAPI_ExtCreatePen WinAPI_ExtCreateRegion WinAPI_ExtFloodFill WinAPI_ExtractIcon WinAPI_ExtractIconEx WinAPI_ExtSelectClipRgn WinAPI_FatalAppExit WinAPI_FatalExit WinAPI_FileEncryptionStatus WinAPI_FileExists WinAPI_FileIconInit WinAPI_FileInUse WinAPI_FillMemory WinAPI_FillPath WinAPI_FillRect WinAPI_FillRgn WinAPI_FindClose WinAPI_FindCloseChangeNotification WinAPI_FindExecutable WinAPI_FindFirstChangeNotification WinAPI_FindFirstFile WinAPI_FindFirstFileName WinAPI_FindFirstStream WinAPI_FindNextChangeNotification WinAPI_FindNextFile WinAPI_FindNextFileName WinAPI_FindNextStream WinAPI_FindResource WinAPI_FindResourceEx WinAPI_FindTextDlg WinAPI_FindWindow WinAPI_FlashWindow WinAPI_FlashWindowEx WinAPI_FlattenPath WinAPI_FloatToDWord WinAPI_FloatToInt WinAPI_FlushFileBuffers WinAPI_FlushFRBuffer WinAPI_FlushViewOfFile WinAPI_FormatDriveDlg WinAPI_FormatMessage WinAPI_FrameRect WinAPI_FrameRgn WinAPI_FreeLibrary WinAPI_FreeMemory WinAPI_FreeMRUList WinAPI_FreeResource WinAPI_GdiComment WinAPI_GetActiveWindow WinAPI_GetAllUsersProfileDirectory WinAPI_GetAncestor WinAPI_GetApplicationRestartSettings WinAPI_GetArcDirection WinAPI_GetAsyncKeyState WinAPI_GetBinaryType WinAPI_GetBitmapBits WinAPI_GetBitmapDimension WinAPI_GetBitmapDimensionEx WinAPI_GetBkColor WinAPI_GetBkMode WinAPI_GetBoundsRect WinAPI_GetBrushOrg WinAPI_GetBufferedPaintBits WinAPI_GetBufferedPaintDC WinAPI_GetBufferedPaintTargetDC WinAPI_GetBufferedPaintTargetRect WinAPI_GetBValue WinAPI_GetCaretBlinkTime WinAPI_GetCaretPos WinAPI_GetCDType WinAPI_GetClassInfoEx WinAPI_GetClassLongEx WinAPI_GetClassName WinAPI_GetClientHeight WinAPI_GetClientRect WinAPI_GetClientWidth WinAPI_GetClipboardSequenceNumber WinAPI_GetClipBox WinAPI_GetClipCursor WinAPI_GetClipRgn WinAPI_GetColorAdjustment WinAPI_GetCompressedFileSize WinAPI_GetCompression WinAPI_GetConnectedDlg WinAPI_GetCurrentDirectory WinAPI_GetCurrentHwProfile WinAPI_GetCurrentObject WinAPI_GetCurrentPosition WinAPI_GetCurrentProcess WinAPI_GetCurrentProcessExplicitAppUserModelID WinAPI_GetCurrentProcessID WinAPI_GetCurrentThemeName WinAPI_GetCurrentThread WinAPI_GetCurrentThreadId WinAPI_GetCursor WinAPI_GetCursorInfo WinAPI_GetDateFormat WinAPI_GetDC WinAPI_GetDCEx WinAPI_GetDefaultPrinter WinAPI_GetDefaultUserProfileDirectory WinAPI_GetDesktopWindow WinAPI_GetDeviceCaps WinAPI_GetDeviceDriverBaseName WinAPI_GetDeviceDriverFileName WinAPI_GetDeviceGammaRamp WinAPI_GetDIBColorTable WinAPI_GetDIBits WinAPI_GetDiskFreeSpaceEx WinAPI_GetDlgCtrlID WinAPI_GetDlgItem WinAPI_GetDllDirectory WinAPI_GetDriveBusType WinAPI_GetDriveGeometryEx WinAPI_GetDriveNumber WinAPI_GetDriveType WinAPI_GetDurationFormat WinAPI_GetEffectiveClientRect WinAPI_GetEnhMetaFile WinAPI_GetEnhMetaFileBits WinAPI_GetEnhMetaFileDescription WinAPI_GetEnhMetaFileDimension WinAPI_GetEnhMetaFileHeader WinAPI_GetErrorMessage WinAPI_GetErrorMode WinAPI_GetExitCodeProcess WinAPI_GetExtended WinAPI_GetFileAttributes WinAPI_GetFileID WinAPI_GetFileInformationByHandle WinAPI_GetFileInformationByHandleEx WinAPI_GetFilePointerEx WinAPI_GetFileSizeEx WinAPI_GetFileSizeOnDisk WinAPI_GetFileTitle WinAPI_GetFileType WinAPI_GetFileVersionInfo WinAPI_GetFinalPathNameByHandle WinAPI_GetFinalPathNameByHandleEx WinAPI_GetFocus WinAPI_GetFontMemoryResourceInfo WinAPI_GetFontName WinAPI_GetFontResourceInfo WinAPI_GetForegroundWindow WinAPI_GetFRBuffer WinAPI_GetFullPathName WinAPI_GetGeoInfo WinAPI_GetGlyphOutline WinAPI_GetGraphicsMode WinAPI_GetGuiResources WinAPI_GetGUIThreadInfo WinAPI_GetGValue WinAPI_GetHandleInformation WinAPI_GetHGlobalFromStream WinAPI_GetIconDimension WinAPI_GetIconInfo WinAPI_GetIconInfoEx WinAPI_GetIdleTime WinAPI_GetKeyboardLayout WinAPI_GetKeyboardLayoutList WinAPI_GetKeyboardState WinAPI_GetKeyboardType WinAPI_GetKeyNameText WinAPI_GetKeyState WinAPI_GetLastActivePopup WinAPI_GetLastError WinAPI_GetLastErrorMessage WinAPI_GetLayeredWindowAttributes WinAPI_GetLocaleInfo WinAPI_GetLogicalDrives WinAPI_GetMapMode WinAPI_GetMemorySize WinAPI_GetMessageExtraInfo WinAPI_GetModuleFileNameEx WinAPI_GetModuleHandle WinAPI_GetModuleHandleEx WinAPI_GetModuleInformation WinAPI_GetMonitorInfo WinAPI_GetMousePos WinAPI_GetMousePosX WinAPI_GetMousePosY WinAPI_GetMUILanguage WinAPI_GetNumberFormat WinAPI_GetObject WinAPI_GetObjectID WinAPI_GetObjectInfoByHandle WinAPI_GetObjectNameByHandle WinAPI_GetObjectType WinAPI_GetOpenFileName WinAPI_GetOutlineTextMetrics WinAPI_GetOverlappedResult WinAPI_GetParent WinAPI_GetParentProcess WinAPI_GetPerformanceInfo WinAPI_GetPEType WinAPI_GetPhysicallyInstalledSystemMemory WinAPI_GetPixel WinAPI_GetPolyFillMode WinAPI_GetPosFromRect WinAPI_GetPriorityClass WinAPI_GetProcAddress WinAPI_GetProcessAffinityMask WinAPI_GetProcessCommandLine WinAPI_GetProcessFileName WinAPI_GetProcessHandleCount WinAPI_GetProcessID WinAPI_GetProcessIoCounters WinAPI_GetProcessMemoryInfo WinAPI_GetProcessName WinAPI_GetProcessShutdownParameters WinAPI_GetProcessTimes WinAPI_GetProcessUser WinAPI_GetProcessWindowStation WinAPI_GetProcessWorkingDirectory WinAPI_GetProfilesDirectory WinAPI_GetPwrCapabilities WinAPI_GetRawInputBuffer WinAPI_GetRawInputBufferLength WinAPI_GetRawInputData WinAPI_GetRawInputDeviceInfo WinAPI_GetRegionData WinAPI_GetRegisteredRawInputDevices WinAPI_GetRegKeyNameByHandle WinAPI_GetRgnBox WinAPI_GetROP2 WinAPI_GetRValue WinAPI_GetSaveFileName WinAPI_GetShellWindow WinAPI_GetStartupInfo WinAPI_GetStdHandle WinAPI_GetStockObject WinAPI_GetStretchBltMode WinAPI_GetString WinAPI_GetSysColor WinAPI_GetSysColorBrush WinAPI_GetSystemDefaultLangID WinAPI_GetSystemDefaultLCID WinAPI_GetSystemDefaultUILanguage WinAPI_GetSystemDEPPolicy WinAPI_GetSystemInfo WinAPI_GetSystemMetrics WinAPI_GetSystemPowerStatus WinAPI_GetSystemTimes WinAPI_GetSystemWow64Directory WinAPI_GetTabbedTextExtent WinAPI_GetTempFileName WinAPI_GetTextAlign WinAPI_GetTextCharacterExtra WinAPI_GetTextColor WinAPI_GetTextExtentPoint32 WinAPI_GetTextFace WinAPI_GetTextMetrics WinAPI_GetThemeAppProperties WinAPI_GetThemeBackgroundContentRect WinAPI_GetThemeBackgroundExtent WinAPI_GetThemeBackgroundRegion WinAPI_GetThemeBitmap WinAPI_GetThemeBool WinAPI_GetThemeColor WinAPI_GetThemeDocumentationProperty WinAPI_GetThemeEnumValue WinAPI_GetThemeFilename WinAPI_GetThemeFont WinAPI_GetThemeInt WinAPI_GetThemeMargins WinAPI_GetThemeMetric WinAPI_GetThemePartSize WinAPI_GetThemePosition WinAPI_GetThemePropertyOrigin WinAPI_GetThemeRect WinAPI_GetThemeString WinAPI_GetThemeSysBool WinAPI_GetThemeSysColor WinAPI_GetThemeSysColorBrush WinAPI_GetThemeSysFont WinAPI_GetThemeSysInt WinAPI_GetThemeSysSize WinAPI_GetThemeSysString WinAPI_GetThemeTextExtent WinAPI_GetThemeTextMetrics WinAPI_GetThemeTransitionDuration WinAPI_GetThreadDesktop WinAPI_GetThreadErrorMode WinAPI_GetThreadLocale WinAPI_GetThreadUILanguage WinAPI_GetTickCount WinAPI_GetTickCount64 WinAPI_GetTimeFormat WinAPI_GetTopWindow WinAPI_GetUDFColorMode WinAPI_GetUpdateRect WinAPI_GetUpdateRgn WinAPI_GetUserDefaultLangID WinAPI_GetUserDefaultLCID WinAPI_GetUserDefaultUILanguage WinAPI_GetUserGeoID WinAPI_GetUserObjectInformation WinAPI_GetVersion WinAPI_GetVersionEx WinAPI_GetVolumeInformation WinAPI_GetVolumeInformationByHandle WinAPI_GetVolumeNameForVolumeMountPoint WinAPI_GetWindow WinAPI_GetWindowDC WinAPI_GetWindowDisplayAffinity WinAPI_GetWindowExt WinAPI_GetWindowFileName WinAPI_GetWindowHeight WinAPI_GetWindowInfo WinAPI_GetWindowLong WinAPI_GetWindowOrg WinAPI_GetWindowPlacement WinAPI_GetWindowRect WinAPI_GetWindowRgn WinAPI_GetWindowRgnBox WinAPI_GetWindowSubclass WinAPI_GetWindowText WinAPI_GetWindowTheme WinAPI_GetWindowThreadProcessId WinAPI_GetWindowWidth WinAPI_GetWorkArea WinAPI_GetWorldTransform WinAPI_GetXYFromPoint WinAPI_GlobalMemoryStatus WinAPI_GradientFill WinAPI_GUIDFromString WinAPI_GUIDFromStringEx WinAPI_HashData WinAPI_HashString WinAPI_HiByte WinAPI_HideCaret WinAPI_HiDWord WinAPI_HiWord WinAPI_InflateRect WinAPI_InitMUILanguage WinAPI_InProcess WinAPI_IntersectClipRect WinAPI_IntersectRect WinAPI_IntToDWord WinAPI_IntToFloat WinAPI_InvalidateRect WinAPI_InvalidateRgn WinAPI_InvertANDBitmap WinAPI_InvertColor WinAPI_InvertRect WinAPI_InvertRgn WinAPI_IOCTL WinAPI_IsAlphaBitmap WinAPI_IsBadCodePtr WinAPI_IsBadReadPtr WinAPI_IsBadStringPtr WinAPI_IsBadWritePtr WinAPI_IsChild WinAPI_IsClassName WinAPI_IsDoorOpen WinAPI_IsElevated WinAPI_IsHungAppWindow WinAPI_IsIconic WinAPI_IsInternetConnected WinAPI_IsLoadKBLayout WinAPI_IsMemory WinAPI_IsNameInExpression WinAPI_IsNetworkAlive WinAPI_IsPathShared WinAPI_IsProcessInJob WinAPI_IsProcessorFeaturePresent WinAPI_IsRectEmpty WinAPI_IsThemeActive WinAPI_IsThemeBackgroundPartiallyTransparent WinAPI_IsThemePartDefined WinAPI_IsValidLocale WinAPI_IsWindow WinAPI_IsWindowEnabled WinAPI_IsWindowUnicode WinAPI_IsWindowVisible WinAPI_IsWow64Process WinAPI_IsWritable WinAPI_IsZoomed WinAPI_Keybd_Event WinAPI_KillTimer WinAPI_LineDDA WinAPI_LineTo WinAPI_LoadBitmap WinAPI_LoadCursor WinAPI_LoadCursorFromFile WinAPI_LoadIcon WinAPI_LoadIconMetric WinAPI_LoadIconWithScaleDown WinAPI_LoadImage WinAPI_LoadIndirectString WinAPI_LoadKeyboardLayout WinAPI_LoadLibrary WinAPI_LoadLibraryEx WinAPI_LoadMedia WinAPI_LoadResource WinAPI_LoadShell32Icon WinAPI_LoadString WinAPI_LoadStringEx WinAPI_LoByte WinAPI_LocalFree WinAPI_LockDevice WinAPI_LockFile WinAPI_LockResource WinAPI_LockWindowUpdate WinAPI_LockWorkStation WinAPI_LoDWord WinAPI_LongMid WinAPI_LookupIconIdFromDirectoryEx WinAPI_LoWord WinAPI_LPtoDP WinAPI_MAKELANGID WinAPI_MAKELCID WinAPI_MakeLong WinAPI_MakeQWord WinAPI_MakeWord WinAPI_MapViewOfFile WinAPI_MapVirtualKey WinAPI_MaskBlt WinAPI_MessageBeep WinAPI_MessageBoxCheck WinAPI_MessageBoxIndirect WinAPI_MirrorIcon WinAPI_ModifyWorldTransform WinAPI_MonitorFromPoint WinAPI_MonitorFromRect WinAPI_MonitorFromWindow WinAPI_Mouse_Event WinAPI_MoveFileEx WinAPI_MoveMemory WinAPI_MoveTo WinAPI_MoveToEx WinAPI_MoveWindow WinAPI_MsgBox WinAPI_MulDiv WinAPI_MultiByteToWideChar WinAPI_MultiByteToWideCharEx WinAPI_NtStatusToDosError WinAPI_OemToChar WinAPI_OffsetClipRgn WinAPI_OffsetPoints WinAPI_OffsetRect WinAPI_OffsetRgn WinAPI_OffsetWindowOrg WinAPI_OpenDesktop WinAPI_OpenFileById WinAPI_OpenFileDlg WinAPI_OpenFileMapping WinAPI_OpenIcon WinAPI_OpenInputDesktop WinAPI_OpenJobObject WinAPI_OpenMutex WinAPI_OpenProcess WinAPI_OpenProcessToken WinAPI_OpenSemaphore WinAPI_OpenThemeData WinAPI_OpenWindowStation WinAPI_PageSetupDlg WinAPI_PaintDesktop WinAPI_PaintRgn WinAPI_ParseURL WinAPI_ParseUserName WinAPI_PatBlt WinAPI_PathAddBackslash WinAPI_PathAddExtension WinAPI_PathAppend WinAPI_PathBuildRoot WinAPI_PathCanonicalize WinAPI_PathCommonPrefix WinAPI_PathCompactPath WinAPI_PathCompactPathEx WinAPI_PathCreateFromUrl WinAPI_PathFindExtension WinAPI_PathFindFileName WinAPI_PathFindNextComponent WinAPI_PathFindOnPath WinAPI_PathGetArgs WinAPI_PathGetCharType WinAPI_PathGetDriveNumber WinAPI_PathIsContentType WinAPI_PathIsDirectory WinAPI_PathIsDirectoryEmpty WinAPI_PathIsExe WinAPI_PathIsFileSpec WinAPI_PathIsLFNFileSpec WinAPI_PathIsRelative WinAPI_PathIsRoot WinAPI_PathIsSameRoot WinAPI_PathIsSystemFolder WinAPI_PathIsUNC WinAPI_PathIsUNCServer WinAPI_PathIsUNCServerShare WinAPI_PathMakeSystemFolder WinAPI_PathMatchSpec WinAPI_PathParseIconLocation WinAPI_PathRelativePathTo WinAPI_PathRemoveArgs WinAPI_PathRemoveBackslash WinAPI_PathRemoveExtension WinAPI_PathRemoveFileSpec WinAPI_PathRenameExtension WinAPI_PathSearchAndQualify WinAPI_PathSkipRoot WinAPI_PathStripPath WinAPI_PathStripToRoot WinAPI_PathToRegion WinAPI_PathUndecorate WinAPI_PathUnExpandEnvStrings WinAPI_PathUnmakeSystemFolder WinAPI_PathUnquoteSpaces WinAPI_PathYetAnotherMakeUniqueName WinAPI_PickIconDlg WinAPI_PlayEnhMetaFile WinAPI_PlaySound WinAPI_PlgBlt WinAPI_PointFromRect WinAPI_PolyBezier WinAPI_PolyBezierTo WinAPI_PolyDraw WinAPI_Polygon WinAPI_PostMessage WinAPI_PrimaryLangId WinAPI_PrintDlg WinAPI_PrintDlgEx WinAPI_PrintWindow WinAPI_ProgIDFromCLSID WinAPI_PtInRect WinAPI_PtInRectEx WinAPI_PtInRegion WinAPI_PtVisible WinAPI_QueryDosDevice WinAPI_QueryInformationJobObject WinAPI_QueryPerformanceCounter WinAPI_QueryPerformanceFrequency WinAPI_RadialGradientFill WinAPI_ReadDirectoryChanges WinAPI_ReadFile WinAPI_ReadProcessMemory WinAPI_Rectangle WinAPI_RectInRegion WinAPI_RectIsEmpty WinAPI_RectVisible WinAPI_RedrawWindow WinAPI_RegCloseKey WinAPI_RegConnectRegistry WinAPI_RegCopyTree WinAPI_RegCopyTreeEx WinAPI_RegCreateKey WinAPI_RegDeleteEmptyKey WinAPI_RegDeleteKey WinAPI_RegDeleteKeyValue WinAPI_RegDeleteTree WinAPI_RegDeleteTreeEx WinAPI_RegDeleteValue WinAPI_RegDisableReflectionKey WinAPI_RegDuplicateHKey WinAPI_RegEnableReflectionKey WinAPI_RegEnumKey WinAPI_RegEnumValue WinAPI_RegFlushKey WinAPI_RegisterApplicationRestart WinAPI_RegisterClass WinAPI_RegisterClassEx WinAPI_RegisterHotKey WinAPI_RegisterPowerSettingNotification WinAPI_RegisterRawInputDevices WinAPI_RegisterShellHookWindow WinAPI_RegisterWindowMessage WinAPI_RegLoadMUIString WinAPI_RegNotifyChangeKeyValue WinAPI_RegOpenKey WinAPI_RegQueryInfoKey WinAPI_RegQueryLastWriteTime WinAPI_RegQueryMultipleValues WinAPI_RegQueryReflectionKey WinAPI_RegQueryValue WinAPI_RegRestoreKey WinAPI_RegSaveKey WinAPI_RegSetValue WinAPI_ReleaseCapture WinAPI_ReleaseDC WinAPI_ReleaseMutex WinAPI_ReleaseSemaphore WinAPI_ReleaseStream WinAPI_RemoveClipboardFormatListener WinAPI_RemoveDirectory WinAPI_RemoveFontMemResourceEx WinAPI_RemoveFontResourceEx WinAPI_RemoveWindowSubclass WinAPI_ReOpenFile WinAPI_ReplaceFile WinAPI_ReplaceTextDlg WinAPI_ResetEvent WinAPI_RestartDlg WinAPI_RestoreDC WinAPI_RGB WinAPI_RotatePoints WinAPI_RoundRect WinAPI_SaveDC WinAPI_SaveFileDlg WinAPI_SaveHBITMAPToFile WinAPI_SaveHICONToFile WinAPI_ScaleWindowExt WinAPI_ScreenToClient WinAPI_SearchPath WinAPI_SelectClipPath WinAPI_SelectClipRgn WinAPI_SelectObject WinAPI_SendMessageTimeout WinAPI_SetActiveWindow WinAPI_SetArcDirection WinAPI_SetBitmapBits WinAPI_SetBitmapDimensionEx WinAPI_SetBkColor WinAPI_SetBkMode WinAPI_SetBoundsRect WinAPI_SetBrushOrg WinAPI_SetCapture WinAPI_SetCaretBlinkTime WinAPI_SetCaretPos WinAPI_SetClassLongEx WinAPI_SetColorAdjustment WinAPI_SetCompression WinAPI_SetCurrentDirectory WinAPI_SetCurrentProcessExplicitAppUserModelID WinAPI_SetCursor WinAPI_SetDCBrushColor WinAPI_SetDCPenColor WinAPI_SetDefaultPrinter WinAPI_SetDeviceGammaRamp WinAPI_SetDIBColorTable WinAPI_SetDIBits WinAPI_SetDIBitsToDevice WinAPI_SetDllDirectory WinAPI_SetEndOfFile WinAPI_SetEnhMetaFileBits WinAPI_SetErrorMode WinAPI_SetEvent WinAPI_SetFileAttributes WinAPI_SetFileInformationByHandleEx WinAPI_SetFilePointer WinAPI_SetFilePointerEx WinAPI_SetFileShortName WinAPI_SetFileValidData WinAPI_SetFocus WinAPI_SetFont WinAPI_SetForegroundWindow WinAPI_SetFRBuffer WinAPI_SetGraphicsMode WinAPI_SetHandleInformation WinAPI_SetInformationJobObject WinAPI_SetKeyboardLayout WinAPI_SetKeyboardState WinAPI_SetLastError WinAPI_SetLayeredWindowAttributes WinAPI_SetLocaleInfo WinAPI_SetMapMode WinAPI_SetMessageExtraInfo WinAPI_SetParent WinAPI_SetPixel WinAPI_SetPolyFillMode WinAPI_SetPriorityClass WinAPI_SetProcessAffinityMask WinAPI_SetProcessShutdownParameters WinAPI_SetProcessWindowStation WinAPI_SetRectRgn WinAPI_SetROP2 WinAPI_SetSearchPathMode WinAPI_SetStretchBltMode WinAPI_SetSysColors WinAPI_SetSystemCursor WinAPI_SetTextAlign WinAPI_SetTextCharacterExtra WinAPI_SetTextColor WinAPI_SetTextJustification WinAPI_SetThemeAppProperties WinAPI_SetThreadDesktop WinAPI_SetThreadErrorMode WinAPI_SetThreadExecutionState WinAPI_SetThreadLocale WinAPI_SetThreadUILanguage WinAPI_SetTimer WinAPI_SetUDFColorMode WinAPI_SetUserGeoID WinAPI_SetUserObjectInformation WinAPI_SetVolumeMountPoint WinAPI_SetWindowDisplayAffinity WinAPI_SetWindowExt WinAPI_SetWindowLong WinAPI_SetWindowOrg WinAPI_SetWindowPlacement WinAPI_SetWindowPos WinAPI_SetWindowRgn WinAPI_SetWindowsHookEx WinAPI_SetWindowSubclass WinAPI_SetWindowText WinAPI_SetWindowTheme WinAPI_SetWinEventHook WinAPI_SetWorldTransform WinAPI_SfcIsFileProtected WinAPI_SfcIsKeyProtected WinAPI_ShellAboutDlg WinAPI_ShellAddToRecentDocs WinAPI_ShellChangeNotify WinAPI_ShellChangeNotifyDeregister WinAPI_ShellChangeNotifyRegister WinAPI_ShellCreateDirectory WinAPI_ShellEmptyRecycleBin WinAPI_ShellExecute WinAPI_ShellExecuteEx WinAPI_ShellExtractAssociatedIcon WinAPI_ShellExtractIcon WinAPI_ShellFileOperation WinAPI_ShellFlushSFCache WinAPI_ShellGetFileInfo WinAPI_ShellGetIconOverlayIndex WinAPI_ShellGetImageList WinAPI_ShellGetKnownFolderIDList WinAPI_ShellGetKnownFolderPath WinAPI_ShellGetLocalizedName WinAPI_ShellGetPathFromIDList WinAPI_ShellGetSetFolderCustomSettings WinAPI_ShellGetSettings WinAPI_ShellGetSpecialFolderLocation WinAPI_ShellGetSpecialFolderPath WinAPI_ShellGetStockIconInfo WinAPI_ShellILCreateFromPath WinAPI_ShellNotifyIcon WinAPI_ShellNotifyIconGetRect WinAPI_ShellObjectProperties WinAPI_ShellOpenFolderAndSelectItems WinAPI_ShellOpenWithDlg WinAPI_ShellQueryRecycleBin WinAPI_ShellQueryUserNotificationState WinAPI_ShellRemoveLocalizedName WinAPI_ShellRestricted WinAPI_ShellSetKnownFolderPath WinAPI_ShellSetLocalizedName WinAPI_ShellSetSettings WinAPI_ShellStartNetConnectionDlg WinAPI_ShellUpdateImage WinAPI_ShellUserAuthenticationDlg WinAPI_ShellUserAuthenticationDlgEx WinAPI_ShortToWord WinAPI_ShowCaret WinAPI_ShowCursor WinAPI_ShowError WinAPI_ShowLastError WinAPI_ShowMsg WinAPI_ShowOwnedPopups WinAPI_ShowWindow WinAPI_ShutdownBlockReasonCreate WinAPI_ShutdownBlockReasonDestroy WinAPI_ShutdownBlockReasonQuery WinAPI_SizeOfResource WinAPI_StretchBlt WinAPI_StretchDIBits WinAPI_StrFormatByteSize WinAPI_StrFormatByteSizeEx WinAPI_StrFormatKBSize WinAPI_StrFromTimeInterval WinAPI_StringFromGUID WinAPI_StringLenA WinAPI_StringLenW WinAPI_StrLen WinAPI_StrokeAndFillPath WinAPI_StrokePath WinAPI_StructToArray WinAPI_SubLangId WinAPI_SubtractRect WinAPI_SwapDWord WinAPI_SwapQWord WinAPI_SwapWord WinAPI_SwitchColor WinAPI_SwitchDesktop WinAPI_SwitchToThisWindow WinAPI_SystemParametersInfo WinAPI_TabbedTextOut WinAPI_TerminateJobObject WinAPI_TerminateProcess WinAPI_TextOut WinAPI_TileWindows WinAPI_TrackMouseEvent WinAPI_TransparentBlt WinAPI_TwipsPerPixelX WinAPI_TwipsPerPixelY WinAPI_UnhookWindowsHookEx WinAPI_UnhookWinEvent WinAPI_UnionRect WinAPI_UnionStruct WinAPI_UniqueHardwareID WinAPI_UnloadKeyboardLayout WinAPI_UnlockFile WinAPI_UnmapViewOfFile WinAPI_UnregisterApplicationRestart WinAPI_UnregisterClass WinAPI_UnregisterHotKey WinAPI_UnregisterPowerSettingNotification WinAPI_UpdateLayeredWindow WinAPI_UpdateLayeredWindowEx WinAPI_UpdateLayeredWindowIndirect WinAPI_UpdateResource WinAPI_UpdateWindow WinAPI_UrlApplyScheme WinAPI_UrlCanonicalize WinAPI_UrlCombine WinAPI_UrlCompare WinAPI_UrlCreateFromPath WinAPI_UrlFixup WinAPI_UrlGetPart WinAPI_UrlHash WinAPI_UrlIs WinAPI_UserHandleGrantAccess WinAPI_ValidateRect WinAPI_ValidateRgn WinAPI_VerQueryRoot WinAPI_VerQueryValue WinAPI_VerQueryValueEx WinAPI_WaitForInputIdle WinAPI_WaitForMultipleObjects WinAPI_WaitForSingleObject WinAPI_WideCharToMultiByte WinAPI_WidenPath WinAPI_WindowFromDC WinAPI_WindowFromPoint WinAPI_WordToShort WinAPI_Wow64EnableWow64FsRedirection WinAPI_WriteConsole WinAPI_WriteFile WinAPI_WriteProcessMemory WinAPI_ZeroMemory WinNet_AddConnection WinNet_AddConnection2 WinNet_AddConnection3 WinNet_CancelConnection WinNet_CancelConnection2 WinNet_CloseEnum WinNet_ConnectionDialog WinNet_ConnectionDialog1 WinNet_DisconnectDialog WinNet_DisconnectDialog1 WinNet_EnumResource WinNet_GetConnection WinNet_GetConnectionPerformance WinNet_GetLastError WinNet_GetNetworkInformation WinNet_GetProviderName WinNet_GetResourceInformation WinNet_GetResourceParent WinNet_GetUniversalName WinNet_GetUser WinNet_OpenEnum WinNet_RestoreConnection WinNet_UseConnection Word_Create Word_DocAdd Word_DocAttach Word_DocClose Word_DocExport Word_DocFind Word_DocFindReplace Word_DocGet Word_DocLinkAdd Word_DocLinkGet Word_DocOpen Word_DocPictureAdd Word_DocPrint Word_DocRangeSet Word_DocSave Word_DocSaveAs Word_DocTableRead Word_DocTableWrite Word_Quit\",r={\nvariants:[e.COMMENT(\";\",\"$\",{relevance:0}),e.COMMENT(\"#cs\",\"#ce\"),e.COMMENT(\"#comments-start\",\"#comments-end\")]},a={className:\"variable\",begin:\"\\\\$[A-z0-9_]+\"},o={className:\"string\",variants:[{begin:/\"/,end:/\"/,contains:[{begin:/\"\"/,relevance:0}]},{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]}]},s={variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]},l={className:\"preprocessor\",begin:\"#\",end:\"$\",keywords:\"include include-once NoTrayIcon OnAutoItStartRegister RequireAdmin pragma Au3Stripper_Ignore_Funcs Au3Stripper_Ignore_Variables Au3Stripper_Off Au3Stripper_On Au3Stripper_Parameters AutoIt3Wrapper_Add_Constants AutoIt3Wrapper_Au3Check_Parameters AutoIt3Wrapper_Au3Check_Stop_OnWarning AutoIt3Wrapper_Aut2Exe AutoIt3Wrapper_AutoIt3 AutoIt3Wrapper_AutoIt3Dir AutoIt3Wrapper_Change2CUI AutoIt3Wrapper_Compile_Both AutoIt3Wrapper_Compression AutoIt3Wrapper_EndIf AutoIt3Wrapper_Icon AutoIt3Wrapper_If_Compile AutoIt3Wrapper_If_Run AutoIt3Wrapper_Jump_To_First_Error AutoIt3Wrapper_OutFile AutoIt3Wrapper_OutFile_Type AutoIt3Wrapper_OutFile_X64 AutoIt3Wrapper_PlugIn_Funcs AutoIt3Wrapper_Res_Comment Autoit3Wrapper_Res_Compatibility AutoIt3Wrapper_Res_Description AutoIt3Wrapper_Res_Field AutoIt3Wrapper_Res_File_Add AutoIt3Wrapper_Res_FileVersion AutoIt3Wrapper_Res_FileVersion_AutoIncrement AutoIt3Wrapper_Res_Icon_Add AutoIt3Wrapper_Res_Language AutoIt3Wrapper_Res_LegalCopyright AutoIt3Wrapper_Res_ProductVersion AutoIt3Wrapper_Res_requestedExecutionLevel AutoIt3Wrapper_Res_SaveSource AutoIt3Wrapper_Run_After AutoIt3Wrapper_Run_Au3Check AutoIt3Wrapper_Run_Au3Stripper AutoIt3Wrapper_Run_Before AutoIt3Wrapper_Run_Debug_Mode AutoIt3Wrapper_Run_SciTE_Minimized AutoIt3Wrapper_Run_SciTE_OutputPane_Minimized AutoIt3Wrapper_Run_Tidy AutoIt3Wrapper_ShowProgress AutoIt3Wrapper_Testing AutoIt3Wrapper_Tidy_Stop_OnError AutoIt3Wrapper_UPX_Parameters AutoIt3Wrapper_UseUPX AutoIt3Wrapper_UseX64 AutoIt3Wrapper_Version AutoIt3Wrapper_Versioning AutoIt3Wrapper_Versioning_Parameters Tidy_Off Tidy_On Tidy_Parameters EndRegion Region\",contains:[{begin:/\\\\\\n/,relevance:0},{beginKeywords:\"include\",end:\"$\",contains:[o,{className:\"string\",variants:[{begin:\"<\",end:\">\"},{begin:/\"/,end:/\"/,contains:[{begin:/\"\"/,relevance:0}]},{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]}]}]},o,r]},c={className:\"constant\",begin:\"@[A-z0-9_]+\"},d={className:\"function\",beginKeywords:\"Func\",end:\"$\",excludeEnd:!0,illegal:\"\\\\$|\\\\[|%\",contains:[e.UNDERSCORE_TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:[a,o,s]}]};return{case_insensitive:!0,illegal:/\\/\\*/,keywords:{keyword:t,built_in:i,literal:n},contains:[r,a,o,s,l,c,d]}}),e.registerLanguage(\"avrasm\",function(e){return{case_insensitive:!0,lexemes:\"\\\\.?\"+e.IDENT_RE,keywords:{keyword:\"adc add adiw and andi asr bclr bld brbc brbs brcc brcs break breq brge brhc brhs brid brie brlo brlt brmi brne brpl brsh brtc brts brvc brvs bset bst call cbi cbr clc clh cli cln clr cls clt clv clz com cp cpc cpi cpse dec eicall eijmp elpm eor fmul fmuls fmulsu icall ijmp in inc jmp ld ldd ldi lds lpm lsl lsr mov movw mul muls mulsu neg nop or ori out pop push rcall ret reti rjmp rol ror sbc sbr sbrc sbrs sec seh sbi sbci sbic sbis sbiw sei sen ser ses set sev sez sleep spm st std sts sub subi swap tst wdr\",built_in:\"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 x|0 xh xl y|0 yh yl z|0 zh zl ucsr1c udr1 ucsr1a ucsr1b ubrr1l ubrr1h ucsr0c ubrr0h tccr3c tccr3a tccr3b tcnt3h tcnt3l ocr3ah ocr3al ocr3bh ocr3bl ocr3ch ocr3cl icr3h icr3l etimsk etifr tccr1c ocr1ch ocr1cl twcr twdr twar twsr twbr osccal xmcra xmcrb eicra spmcsr spmcr portg ddrg ping portf ddrf sreg sph spl xdiv rampz eicrb eimsk gimsk gicr eifr gifr timsk tifr mcucr mcucsr tccr0 tcnt0 ocr0 assr tccr1a tccr1b tcnt1h tcnt1l ocr1ah ocr1al ocr1bh ocr1bl icr1h icr1l tccr2 tcnt2 ocr2 ocdr wdtcr sfior eearh eearl eedr eecr porta ddra pina portb ddrb pinb portc ddrc pinc portd ddrd pind spdr spsr spcr udr0 ucsr0a ucsr0b ubrr0l acsr admux adcsr adch adcl porte ddre pine pinf\",preprocessor:\".byte .cseg .db .def .device .dseg .dw .endmacro .equ .eseg .exit .include .list .listmac .macro .nolist .org .set\"},contains:[e.C_BLOCK_COMMENT_MODE,e.COMMENT(\";\",\"$\",{relevance:0}),e.C_NUMBER_MODE,e.BINARY_NUMBER_MODE,{className:\"number\",begin:\"\\\\b(\\\\$[a-zA-Z0-9]+|0o[0-7]+)\"},e.QUOTE_STRING_MODE,{className:\"string\",begin:\"'\",end:\"[^\\\\\\\\]'\",illegal:\"[^\\\\\\\\][^']\"},{className:\"label\",begin:\"^[A-Za-z0-9_.$]+:\"},{className:\"preprocessor\",begin:\"#\",end:\"$\"},{className:\"localvars\",begin:\"@[0-9]+\"}]}}),e.registerLanguage(\"axapta\",function(e){return{keywords:\"false int abstract private char boolean static null if for true while long throw finally protected final return void enum else break new catch byte super case short default double public try this switch continue reverse firstfast firstonly forupdate nofetch sum avg minof maxof count order group by asc desc index hint like dispaly edit client server ttsbegin ttscommit str real date container anytype common div mod\",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,{className:\"preprocessor\",begin:\"#\",end:\"$\"},{className:\"class\",beginKeywords:\"class interface\",end:\"{\",excludeEnd:!0,illegal:\":\",contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]}]}}),e.registerLanguage(\"bash\",function(e){var t={className:\"variable\",variants:[{begin:/\\$[\\w\\d#@][\\w\\d_]*/},{begin:/\\$\\{(.*?)}/}]},n={className:\"string\",begin:/\"/,end:/\"/,contains:[e.BACKSLASH_ESCAPE,t,{className:\"variable\",begin:/\\$\\(/,end:/\\)/,contains:[e.BACKSLASH_ESCAPE]}]},i={className:\"string\",begin:/'/,end:/'/};return{aliases:[\"sh\",\"zsh\"],lexemes:/-?[a-z\\.]+/,keywords:{keyword:\"if then else elif fi for while in do done case esac function\",literal:\"true false\",built_in:\"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp\",operator:\"-ne -eq -lt -gt -f -d -e -s -l -a\"},contains:[{className:\"shebang\",begin:/^#![^\\n]+sh\\s*$/,relevance:10},{className:\"function\",begin:/\\w[\\w\\d_]*\\s*\\(\\s*\\)\\s*\\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\\w[\\w\\d_]*/})],relevance:0},e.HASH_COMMENT_MODE,e.NUMBER_MODE,n,i,t]}}),e.registerLanguage(\"brainfuck\",function(e){var t={className:\"literal\",begin:\"[\\\\+\\\\-]\",relevance:0};return{aliases:[\"bf\"],contains:[e.COMMENT(\"[^\\\\[\\\\]\\\\.,\\\\+\\\\-<> \\r\\n]\",\"[\\\\[\\\\]\\\\.,\\\\+\\\\-<> \\r\\n]\",{returnEnd:!0,relevance:0}),{className:\"title\",begin:\"[\\\\[\\\\]]\",relevance:0},{className:\"string\",begin:\"[\\\\.,]\",relevance:0},{begin:/\\+\\+|\\-\\-/,returnBegin:!0,contains:[t]},t]}}),e.registerLanguage(\"cal\",function(e){var t=\"div mod in and or not xor asserterror begin case do downto else end exit for if of repeat then to until while with var\",n=\"false true\",i=[e.C_LINE_COMMENT_MODE,e.COMMENT(/\\{/,/\\}/,{relevance:0}),e.COMMENT(/\\(\\*/,/\\*\\)/,{relevance:10})],r={className:\"string\",begin:/'/,end:/'/,contains:[{begin:/''/}]},a={className:\"string\",begin:/(#\\d+)+/},o={className:\"date\",begin:\"\\\\b\\\\d+(\\\\.\\\\d+)?(DT|D|T)\",relevance:0},s={className:\"variable\",begin:'\"',end:'\"'},l={className:\"function\",beginKeywords:\"procedure\",end:/[:;]/,keywords:\"procedure|10\",contains:[e.TITLE_MODE,{className:\"params\",begin:/\\(/,end:/\\)/,keywords:t,contains:[r,a]}].concat(i)},c={className:\"class\",begin:\"OBJECT (Table|Form|Report|Dataport|Codeunit|XMLport|MenuSuite|Page|Query) (\\\\d+) ([^\\\\r\\\\n]+)\",returnBegin:!0,contains:[e.TITLE_MODE,l]};return{case_insensitive:!0,keywords:{keyword:t,literal:n},illegal:/\\/\\*/,contains:[r,a,o,s,e.NUMBER_MODE,c,l]}}),e.registerLanguage(\"capnproto\",function(e){return{aliases:[\"capnp\"],keywords:{keyword:\"struct enum interface union group import using const annotation extends in of on as with from fixed\",built_in:\"Void Bool Int8 Int16 Int32 Int64 UInt8 UInt16 UInt32 UInt64 Float32 Float64 Text Data AnyPointer AnyStruct Capability List\",literal:\"true false\"},contains:[e.QUOTE_STRING_MODE,e.NUMBER_MODE,e.HASH_COMMENT_MODE,{className:\"shebang\",begin:/@0x[\\w\\d]{16};/,illegal:/\\n/},{className:\"number\",begin:/@\\d+\\b/},{className:\"class\",beginKeywords:\"struct enum\",end:/\\{/,illegal:/\\n/,contains:[e.inherit(e.TITLE_MODE,{starts:{endsWithParent:!0,excludeEnd:!0}})]},{className:\"class\",beginKeywords:\"interface\",end:/\\{/,illegal:/\\n/,contains:[e.inherit(e.TITLE_MODE,{starts:{endsWithParent:!0,excludeEnd:!0}})]}]}}),e.registerLanguage(\"ceylon\",function(e){var t=\"assembly module package import alias class interface object given value assign void function new of extends satisfies abstracts in out return break continue throw assert dynamic if else switch case for while try catch finally then let this outer super is exists nonempty\",n=\"shared abstract formal default actual variable late native deprecatedfinal sealed annotation suppressWarnings small\",i=\"doc by license see throws tagged\",r=n+\" \"+i,a={className:\"subst\",excludeBegin:!0,excludeEnd:!0,begin:/``/,end:/``/,keywords:t,relevance:10},o=[{className:\"string\",begin:'\"\"\"',end:'\"\"\"',relevance:10},{className:\"string\",begin:'\"',end:'\"',contains:[a]},{className:\"string\",begin:\"'\",end:\"'\"},{className:\"number\",begin:\"#[0-9a-fA-F_]+|\\\\$[01_]+|[0-9_]+(?:\\\\.[0-9_](?:[eE][+-]?\\\\d+)?)?[kMGTPmunpf]?\",relevance:0}];return a.contains=o,{keywords:{keyword:t,annotation:r},illegal:\"\\\\$[^01]|#[^0-9a-fA-F]\",contains:[e.C_LINE_COMMENT_MODE,e.COMMENT(\"/\\\\*\",\"\\\\*/\",{contains:[\"self\"]}),{className:\"annotation\",begin:'@[a-z]\\\\w*(?:\\\\:\"[^\"]*\")?'}].concat(o)}}),e.registerLanguage(\"clojure\",function(e){var t={built_in:\"def defonce cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize\"},n=\"a-zA-Z_\\\\-!.?+*=<>&#'\",i=\"[\"+n+\"][\"+n+\"0-9/;:]*\",r=\"[-+]?\\\\d+(\\\\.\\\\d+)?\",a={begin:i,relevance:0},o={className:\"number\",begin:r,relevance:0},s=e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),l=e.COMMENT(\";\",\"$\",{relevance:0}),c={className:\"literal\",begin:/\\b(true|false|nil)\\b/},d={className:\"collection\",begin:\"[\\\\[\\\\{]\",end:\"[\\\\]\\\\}]\"},u={className:\"comment\",begin:\"\\\\^\"+i},p=e.COMMENT(\"\\\\^\\\\{\",\"\\\\}\"),m={className:\"attribute\",begin:\"[:]\"+i},g={className:\"list\",begin:\"\\\\(\",end:\"\\\\)\"},h={endsWithParent:!0,relevance:0},f={keywords:t,lexemes:i,className:\"keyword\",begin:i,starts:h},_=[g,s,u,p,l,m,d,o,c,a];return g.contains=[e.COMMENT(\"comment\",\"\"),f,h],h.contains=_,d.contains=_,{aliases:[\"clj\"],illegal:/\\S/,contains:[g,s,u,p,l,m,d,o,c]}}),e.registerLanguage(\"clojure-repl\",function(e){return{contains:[{className:\"prompt\",begin:/^([\\w.-]+|\\s*#_)=>/,starts:{end:/$/,subLanguage:\"clojure\"}}]}}),e.registerLanguage(\"cmake\",function(e){return{aliases:[\"cmake.in\"],case_insensitive:!0,keywords:{keyword:\"add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_minimum_required cmake_policy configure_file create_test_sourcelist define_property else elseif enable_language enable_testing endforeach endfunction endif endmacro endwhile execute_process export find_file find_library find_package find_path find_program fltk_wrap_ui foreach function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property if include include_directories include_external_msproject include_regular_expression install link_directories load_cache load_command macro mark_as_advanced message option output_required_files project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_link_libraries try_compile try_run unset variable_watch while build_name exec_program export_library_dependencies install_files install_programs install_targets link_libraries make_directory remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file qt5_use_modules qt5_use_package qt5_wrap_cpp on off true false and or\",operator:\"equal less greater strless strgreater strequal matches\"},contains:[{className:\"envvar\",begin:\"\\\\${\",end:\"}\"},e.HASH_COMMENT_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE]}}),e.registerLanguage(\"coffeescript\",function(e){var t={keyword:\"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not\",literal:\"true false null undefined yes no on off\",built_in:\"npm require console print module global window document\"},n=\"[A-Za-z$_][0-9A-Za-z$_]*\",i={className:\"subst\",begin:/#\\{/,end:/}/,keywords:t},r=[e.BINARY_NUMBER_MODE,e.inherit(e.C_NUMBER_MODE,{starts:{end:\"(\\\\s*/)?\",relevance:0}}),{className:\"string\",variants:[{begin:/'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/,contains:[e.BACKSLASH_ESCAPE]},{begin:/\"\"\"/,end:/\"\"\"/,contains:[e.BACKSLASH_ESCAPE,i]},{begin:/\"/,end:/\"/,contains:[e.BACKSLASH_ESCAPE,i]}]},{className:\"regexp\",variants:[{begin:\"///\",end:\"///\",contains:[i,e.HASH_COMMENT_MODE]},{begin:\"//[gim]*\",relevance:0},{begin:/\\/(?![ *])(\\\\\\/|.)*?\\/[gim]*(?=\\W|$)/}]},{className:\"property\",begin:\"@\"+n},{begin:\"`\",end:\"`\",excludeBegin:!0,excludeEnd:!0,subLanguage:\"javascript\"}];i.contains=r;var a=e.inherit(e.TITLE_MODE,{begin:n}),o=\"(\\\\(.*\\\\))?\\\\s*\\\\B[-=]>\",s={className:\"params\",begin:\"\\\\([^\\\\(]\",returnBegin:!0,contains:[{begin:/\\(/,end:/\\)/,keywords:t,contains:[\"self\"].concat(r)}]};return{aliases:[\"coffee\",\"cson\",\"iced\"],keywords:t,illegal:/\\/\\*/,contains:r.concat([e.COMMENT(\"###\",\"###\"),e.HASH_COMMENT_MODE,{className:\"function\",begin:\"^\\\\s*\"+n+\"\\\\s*=\\\\s*\"+o,end:\"[-=]>\",returnBegin:!0,contains:[a,s]},{begin:/[:\\(,=]\\s*/,relevance:0,contains:[{className:\"function\",begin:o,end:\"[-=]>\",returnBegin:!0,contains:[s]}]},{className:\"class\",beginKeywords:\"class\",end:\"$\",illegal:/[:=\"\\[\\]]/,contains:[{beginKeywords:\"extends\",endsWithParent:!0,illegal:/[:=\"\\[\\]]/,contains:[a]},a]},{className:\"attribute\",begin:n+\":\",end:\":\",returnBegin:!0,returnEnd:!0,relevance:0}])}}),e.registerLanguage(\"cpp\",function(e){var t={className:\"keyword\",begin:\"\\\\b[a-z\\\\d_]*_t\\\\b\"},n={className:\"string\",variants:[e.inherit(e.QUOTE_STRING_MODE,{begin:'((u8?|U)|L)?\"'}),{begin:'(u8?|U)?R\"',end:'\"',contains:[e.BACKSLASH_ESCAPE]},{begin:\"'\\\\\\\\?.\",end:\"'\",illegal:\".\"}]},i={className:\"number\",variants:[{begin:\"\\\\b(\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)(u|U|l|L|ul|UL|f|F)\"},{begin:e.C_NUMBER_RE}]},r={className:\"preprocessor\",begin:\"#\",end:\"$\",keywords:\"if else elif endif define undef warning error line pragma ifdef ifndef\",contains:[{begin:/\\\\\\n/,relevance:0},{beginKeywords:\"include\",end:\"$\",contains:[n,{className:\"string\",begin:\"<\",end:\">\",illegal:\"\\\\n\"}]},n,i,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},a=e.IDENT_RE+\"\\\\s*\\\\(\",o={keyword:\"int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong\",built_in:\"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf\",literal:\"true false nullptr NULL\"};return{aliases:[\"c\",\"cc\",\"h\",\"c++\",\"h++\",\"hpp\"],keywords:o,illegal:\"</\",contains:[t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i,n,r,{begin:\"\\\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\\\s*<\",end:\">\",keywords:o,contains:[\"self\",t]},{begin:e.IDENT_RE+\"::\",keywords:o},{beginKeywords:\"new throw return else\",relevance:0},{className:\"function\",begin:\"(\"+e.IDENT_RE+\"[\\\\*&\\\\s]+)+\"+a,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:o,illegal:/[^\\w\\s\\*&]/,contains:[{begin:a,returnBegin:!0,contains:[e.TITLE_MODE],relevance:0},{className:\"params\",begin:/\\(/,end:/\\)/,keywords:o,relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n,i]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,r]}]}}),e.registerLanguage(\"crmsh\",function(e){var t=\"primitive rsc_template\",n=\"group clone ms master location colocation order fencing_topology rsc_ticket acl_target acl_group user role tag xml\",i=\"property rsc_defaults op_defaults\",r=\"params meta operations op rule attributes utilization\",a=\"read write deny defined not_defined in_range date spec in ref reference attribute type xpath version and or lt gt tag lte gte eq ne \\\\\",o=\"number string\",s=\"Master Started Slave Stopped start promote demote stop monitor true false\";return{aliases:[\"crm\",\"pcmk\"],case_insensitive:!0,keywords:{keyword:r,operator:a,type:o,literal:s},contains:[e.HASH_COMMENT_MODE,{beginKeywords:\"node\",starts:{className:\"identifier\",end:\"\\\\s*([\\\\w_-]+:)?\",starts:{className:\"title\",end:\"\\\\s*[\\\\$\\\\w_][\\\\w_-]*\"}}},{beginKeywords:t,starts:{className:\"title\",end:\"\\\\s*[\\\\$\\\\w_][\\\\w_-]*\",starts:{className:\"pragma\",end:\"\\\\s*@?[\\\\w_][\\\\w_\\\\.:-]*\"}}},{begin:\"\\\\b(\"+n.split(\" \").join(\"|\")+\")\\\\s+\",keywords:n,starts:{className:\"title\",end:\"[\\\\$\\\\w_][\\\\w_-]*\"}},{beginKeywords:i,starts:{className:\"title\",end:\"\\\\s*([\\\\w_-]+:)?\"}},e.QUOTE_STRING_MODE,{className:\"pragma\",begin:\"(ocf|systemd|service|lsb):[\\\\w_:-]+\",relevance:0},{className:\"number\",begin:\"\\\\b\\\\d+(\\\\.\\\\d+)?(ms|s|h|m)?\",relevance:0},{className:\"number\",begin:\"[-]?(infinity|inf)\",relevance:0},{className:\"variable\",begin:/([A-Za-z\\$_\\#][\\w_-]+)=/,relevance:0},{className:\"tag\",begin:\"</?\",end:\"/?>\",relevance:0}]}}),e.registerLanguage(\"crystal\",function(e){function t(e,t){var n=[{begin:e,end:t}];return n[0].contains=n,n}var n=\"(_[uif](8|16|32|64))?\",i=\"[a-zA-Z_]\\\\w*[!?=]?\",r=\"!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~\",a=\"[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\][=?]?\",o={keyword:\"abstract alias as asm begin break case class def do else elsif end ensure enum extend for fun if ifdef include instance_sizeof is_a? lib macro module next of out pointerof private protected rescue responds_to? return require self sizeof struct super then type typeof union unless until when while with yield __DIR__ __FILE__ __LINE__\",literal:\"false nil true\"},s={className:\"subst\",begin:\"#{\",end:\"}\",keywords:o},l={className:\"expansion\",variants:[{begin:\"\\\\{\\\\{\",end:\"\\\\}\\\\}\"},{begin:\"\\\\{%\",end:\"%\\\\}\"}],keywords:o,relevance:10},c={className:\"string\",contains:[e.BACKSLASH_ESCAPE,s],variants:[{begin:/'/,end:/'/},{begin:/\"/,end:/\"/},{begin:/`/,end:/`/},{begin:\"%w?\\\\(\",end:\"\\\\)\",contains:t(\"\\\\(\",\"\\\\)\")},{begin:\"%w?\\\\[\",end:\"\\\\]\",contains:t(\"\\\\[\",\"\\\\]\")},{begin:\"%w?{\",end:\"}\",contains:t(\"{\",\"}\")},{begin:\"%w?<\",end:\">\",contains:t(\"<\",\">\")},{begin:\"%w?/\",end:\"/\"},{begin:\"%w?%\",end:\"%\"},{begin:\"%w?-\",end:\"-\"},{begin:\"%w?\\\\|\",end:\"\\\\|\"}],relevance:0},d={begin:\"(\"+r+\")\\\\s*\",contains:[{className:\"regexp\",contains:[e.BACKSLASH_ESCAPE,s],variants:[{begin:\"/\",end:\"/[a-z]*\"},{begin:\"%r\\\\(\",end:\"\\\\)\",contains:t(\"\\\\(\",\"\\\\)\")},{begin:\"%r\\\\[\",end:\"\\\\]\",contains:t(\"\\\\[\",\"\\\\]\")},{begin:\"%r{\",end:\"}\",contains:t(\"{\",\"}\")},{begin:\"%r<\",end:\">\",contains:t(\"<\",\">\")},{begin:\"%r/\",end:\"/\"},{begin:\"%r%\",end:\"%\"},{begin:\"%r-\",end:\"-\"},{begin:\"%r\\\\|\",end:\"\\\\|\"}]}],relevance:0},u={className:\"regexp\",contains:[e.BACKSLASH_ESCAPE,s],variants:[{begin:\"%r\\\\(\",end:\"\\\\)\",contains:t(\"\\\\(\",\"\\\\)\")},{begin:\"%r\\\\[\",end:\"\\\\]\",contains:t(\"\\\\[\",\"\\\\]\")},{begin:\"%r{\",end:\"}\",contains:t(\"{\",\"}\")},{begin:\"%r<\",end:\">\",contains:t(\"<\",\">\")},{begin:\"%r/\",end:\"/\"},{begin:\"%r%\",end:\"%\"},{begin:\"%r-\",end:\"-\"},{begin:\"%r\\\\|\",end:\"\\\\|\"}],relevance:0},p={className:\"annotation\",begin:\"@\\\\[\",end:\"\\\\]\",relevance:5},m=[l,c,d,u,p,e.HASH_COMMENT_MODE,{className:\"class\",beginKeywords:\"class module struct\",end:\"$|;\",illegal:/=/,contains:[e.HASH_COMMENT_MODE,e.inherit(e.TITLE_MODE,{begin:\"[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?\"}),{className:\"inheritance\",begin:\"<\\\\s*\",contains:[{className:\"parent\",begin:\"(\"+e.IDENT_RE+\"::)?\"+e.IDENT_RE}]}]},{className:\"class\",beginKeywords:\"lib enum union\",end:\"$|;\",illegal:/=/,contains:[e.HASH_COMMENT_MODE,e.inherit(e.TITLE_MODE,{begin:\"[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?\"})],relevance:10},{className:\"function\",beginKeywords:\"def\",end:/\\B\\b/,contains:[e.inherit(e.TITLE_MODE,{begin:a,endsParent:!0})]},{className:\"function\",beginKeywords:\"fun macro\",end:/\\B\\b/,contains:[e.inherit(e.TITLE_MODE,{begin:a,endsParent:!0})],relevance:5},{className:\"constant\",begin:\"(::)?(\\\\b[A-Z]\\\\w*(::)?)+\",relevance:0},{className:\"symbol\",begin:e.UNDERSCORE_IDENT_RE+\"(\\\\!|\\\\?)?:\",relevance:0},{className:\"symbol\",begin:\":\",contains:[c,{begin:a}],relevance:0},{className:\"number\",variants:[{begin:\"\\\\b0b([01_]*[01])\"+n},{begin:\"\\\\b0o([0-7_]*[0-7])\"+n},{begin:\"\\\\b0x([A-Fa-f0-9_]*[A-Fa-f0-9])\"+n},{begin:\"\\\\b(([0-9][0-9_]*[0-9]|[0-9])(\\\\.[0-9_]*[0-9])?([eE][+-]?[0-9_]*[0-9])?)\"+n}],relevance:0},{className:\"variable\",begin:\"(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?|%)(\\\\w+))\"}];return s.contains=m,p.contains=m,l.contains=m.slice(1),{aliases:[\"cr\"],lexemes:i,keywords:o,contains:m}}),e.registerLanguage(\"cs\",function(e){var t=\"abstract as base bool break byte case catch char checked const continue decimal dynamic default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long null when object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async protected public private internal ascending descending from get group into join let orderby partial select set value var where yield\",n=e.IDENT_RE+\"(<\"+e.IDENT_RE+\">)?\";return{aliases:[\"csharp\"],keywords:t,illegal:/::/,contains:[e.COMMENT(\"///\",\"$\",{returnBegin:!0,contains:[{className:\"xmlDocTag\",variants:[{begin:\"///\",relevance:0},{begin:\"<!--|-->\"},{begin:\"</?\",end:\">\"}]}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"preprocessor\",begin:\"#\",end:\"$\",keywords:\"if else elif endif define undef warning error line region endregion pragma checksum\"},{className:\"string\",begin:'@\"',end:'\"',contains:[{begin:'\"\"'}]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,{beginKeywords:\"class interface\",end:/[{;=]/,illegal:/[^\\s:]/,contains:[e.TITLE_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:\"namespace\",end:/[{;=]/,illegal:/[^\\s:]/,contains:[{className:\"title\",begin:\"[a-zA-Z](\\\\.?\\\\w)*\",relevance:0},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:\"new return throw await\",relevance:0},{className:\"function\",begin:\"(\"+n+\"\\\\s+)+\"+e.IDENT_RE+\"\\\\s*\\\\(\",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:t,contains:[{begin:e.IDENT_RE+\"\\\\s*\\\\(\",returnBegin:!0,contains:[e.TITLE_MODE],relevance:0},{className:\"params\",begin:/\\(/,end:/\\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,relevance:0,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]}]}}),e.registerLanguage(\"css\",function(e){var t=\"[a-zA-Z-][a-zA-Z0-9_-]*\",n={className:\"function\",begin:t+\"\\\\(\",returnBegin:!0,excludeEnd:!0,end:\"\\\\(\"},i={className:\"rule\",begin:/[A-Z\\_\\.\\-]+\\s*:/,returnBegin:!0,end:\";\",endsWithParent:!0,contains:[{className:\"attribute\",begin:/\\S/,end:\":\",excludeEnd:!0,starts:{className:\"value\",endsWithParent:!0,excludeEnd:!0,contains:[n,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"hexcolor\",begin:\"#[0-9A-Fa-f]+\"},{className:\"important\",begin:\"!important\"}]}}]};return{case_insensitive:!0,illegal:/[=\\/|'\\$]/,contains:[e.C_BLOCK_COMMENT_MODE,{className:\"id\",begin:/\\#[A-Za-z0-9_-]+/},{className:\"class\",begin:/\\.[A-Za-z0-9_-]+/},{className:\"attr_selector\",begin:/\\[/,end:/\\]/,illegal:\"$\"},{className:\"pseudo\",begin:/:(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\"']+/},{className:\"at_rule\",begin:\"@(font-face|page)\",lexemes:\"[a-z-]+\",keywords:\"font-face page\"},{className:\"at_rule\",begin:\"@\",end:\"[{;]\",contains:[{className:\"keyword\",begin:/\\S+/},{begin:/\\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,contains:[n,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}]},{className:\"tag\",begin:t,relevance:0},{className:\"rules\",begin:\"{\",end:\"}\",illegal:/\\S/,contains:[e.C_BLOCK_COMMENT_MODE,i]}]}}),e.registerLanguage(\"d\",function(e){var t={keyword:\"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__\",built_in:\"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring\",literal:\"false null true\"},n=\"(0|[1-9][\\\\d_]*)\",i=\"(0|[1-9][\\\\d_]*|\\\\d[\\\\d_]*|[\\\\d_]+?\\\\d)\",r=\"0[bB][01_]+\",a=\"([\\\\da-fA-F][\\\\da-fA-F_]*|_[\\\\da-fA-F][\\\\da-fA-F_]*)\",o=\"0[xX]\"+a,s=\"([eE][+-]?\"+i+\")\",l=\"(\"+i+\"(\\\\.\\\\d*|\"+s+\")|\\\\d+\\\\.\"+i+i+\"|\\\\.\"+n+s+\"?)\",c=\"(0[xX](\"+a+\"\\\\.\"+a+\"|\\\\.?\"+a+\")[pP][+-]?\"+i+\")\",d=\"(\"+n+\"|\"+r+\"|\"+o+\")\",u=\"(\"+c+\"|\"+l+\")\",p=\"\\\\\\\\(['\\\"\\\\?\\\\\\\\abfnrtv]|u[\\\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\\\dA-Fa-f]{2}|U[\\\\dA-Fa-f]{8})|&[a-zA-Z\\\\d]{2,};\",m={className:\"number\",begin:\"\\\\b\"+d+\"(L|u|U|Lu|LU|uL|UL)?\",relevance:0},g={className:\"number\",begin:\"\\\\b(\"+u+\"([fF]|L|i|[fF]i|Li)?|\"+d+\"(i|[fF]i|Li))\",relevance:0},h={className:\"string\",begin:\"'(\"+p+\"|.)\",end:\"'\",illegal:\".\"},f={begin:p,relevance:0},_={className:\"string\",begin:'\"',contains:[f],end:'\"[cwd]?'},b={className:\"string\",begin:'[rq]\"',end:'\"[cwd]?',relevance:5},v={className:\"string\",begin:\"`\",end:\"`[cwd]?\"},C={className:\"string\",begin:'x\"[\\\\da-fA-F\\\\s\\\\n\\\\r]*\"[cwd]?',relevance:10},I={className:\"string\",begin:'q\"\\\\{',end:'\\\\}\"'},y={className:\"shebang\",begin:\"^#!\",end:\"$\",relevance:5},S={className:\"preprocessor\",begin:\"#(line)\",end:\"$\",relevance:5},E={className:\"keyword\",begin:\"@[a-zA-Z_][a-zA-Z_\\\\d]*\"},x=e.COMMENT(\"\\\\/\\\\+\",\"\\\\+\\\\/\",{contains:[\"self\"],relevance:10});return{lexemes:e.UNDERSCORE_IDENT_RE,keywords:t,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,x,C,_,b,v,I,g,m,h,y,S,E]}}),e.registerLanguage(\"markdown\",function(e){return{aliases:[\"md\",\"mkdown\",\"mkd\"],contains:[{className:\"header\",variants:[{begin:\"^#{1,6}\",end:\"$\"},{begin:\"^.+?\\\\n[=-]{2,}$\"}]},{begin:\"<\",end:\">\",subLanguage:\"xml\",relevance:0},{className:\"bullet\",begin:\"^([*+-]|(\\\\d+\\\\.))\\\\s+\"},{className:\"strong\",begin:\"[*_]{2}.+?[*_]{2}\"},{className:\"emphasis\",variants:[{begin:\"\\\\*.+?\\\\*\"},{begin:\"_.+?_\",relevance:0}]},{className:\"blockquote\",begin:\"^>\\\\s+\",end:\"$\"},{className:\"code\",variants:[{begin:\"`.+?`\"},{begin:\"^( {4}|\t)\",end:\"$\",relevance:0}]},{className:\"horizontal_rule\",begin:\"^[-\\\\*]{3,}\",end:\"$\"},{begin:\"\\\\[.+?\\\\][\\\\(\\\\[].*?[\\\\)\\\\]]\",returnBegin:!0,contains:[{className:\"link_label\",begin:\"\\\\[\",end:\"\\\\]\",excludeBegin:!0,returnEnd:!0,relevance:0},{className:\"link_url\",begin:\"\\\\]\\\\(\",end:\"\\\\)\",excludeBegin:!0,excludeEnd:!0},{className:\"link_reference\",begin:\"\\\\]\\\\[\",end:\"\\\\]\",excludeBegin:!0,excludeEnd:!0}],relevance:10},{begin:\"^\\\\[.+\\\\]:\",returnBegin:!0,contains:[{className:\"link_reference\",begin:\"\\\\[\",end:\"\\\\]:\",excludeBegin:!0,excludeEnd:!0,starts:{className:\"link_url\",end:\"$\"}}]}]}}),e.registerLanguage(\"dart\",function(e){var t={className:\"subst\",begin:\"\\\\$\\\\{\",end:\"}\",keywords:\"true false null this is new super\"},n={className:\"string\",variants:[{begin:\"r'''\",end:\"'''\"},{begin:'r\"\"\"',end:'\"\"\"'},{begin:\"r'\",end:\"'\",illegal:\"\\\\n\"},{\nbegin:'r\"',end:'\"',illegal:\"\\\\n\"},{begin:\"'''\",end:\"'''\",contains:[e.BACKSLASH_ESCAPE,t]},{begin:'\"\"\"',end:'\"\"\"',contains:[e.BACKSLASH_ESCAPE,t]},{begin:\"'\",end:\"'\",illegal:\"\\\\n\",contains:[e.BACKSLASH_ESCAPE,t]},{begin:'\"',end:'\"',illegal:\"\\\\n\",contains:[e.BACKSLASH_ESCAPE,t]}]};t.contains=[e.C_NUMBER_MODE,n];var i={keyword:\"assert break case catch class const continue default do else enum extends false final finally for if in is new null rethrow return super switch this throw true try var void while with\",literal:\"abstract as dynamic export external factory get implements import library operator part set static typedef\",built_in:\"print Comparable DateTime Duration Function Iterable Iterator List Map Match Null Object Pattern RegExp Set Stopwatch String StringBuffer StringSink Symbol Type Uri bool double int num document window querySelector querySelectorAll Element ElementList\"};return{keywords:i,contains:[n,e.COMMENT(\"/\\\\*\\\\*\",\"\\\\*/\",{subLanguage:\"markdown\"}),e.COMMENT(\"///\",\"$\",{subLanguage:\"markdown\"}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"class\",beginKeywords:\"class interface\",end:\"{\",excludeEnd:!0,contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]},e.C_NUMBER_MODE,{className:\"annotation\",begin:\"@[A-Za-z]+\"},{begin:\"=>\"}]}}),e.registerLanguage(\"delphi\",function(e){var t=\"exports register file shl array record property for mod while set ally label uses raise not stored class safecall var interface or private static exit index inherited to else stdcall override shr asm far resourcestring finalization packed virtual out and protected library do xorwrite goto near function end div overload object unit begin string on inline repeat until destructor write message program with read initialization except default nil if case cdecl in downto threadvar of try pascal const external constructor type public then implementation finally published procedure\",n=[e.C_LINE_COMMENT_MODE,e.COMMENT(/\\{/,/\\}/,{relevance:0}),e.COMMENT(/\\(\\*/,/\\*\\)/,{relevance:10})],i={className:\"string\",begin:/'/,end:/'/,contains:[{begin:/''/}]},r={className:\"string\",begin:/(#\\d+)+/},a={begin:e.IDENT_RE+\"\\\\s*=\\\\s*class\\\\s*\\\\(\",returnBegin:!0,contains:[e.TITLE_MODE]},o={className:\"function\",beginKeywords:\"function constructor destructor procedure\",end:/[:;]/,keywords:\"function constructor|10 destructor|10 procedure|10\",contains:[e.TITLE_MODE,{className:\"params\",begin:/\\(/,end:/\\)/,keywords:t,contains:[i,r]}].concat(n)};return{case_insensitive:!0,keywords:t,illegal:/\"|\\$[G-Zg-z]|\\/\\*|<\\/|\\|/,contains:[i,r,e.NUMBER_MODE,a,o].concat(n)}}),e.registerLanguage(\"diff\",function(e){return{aliases:[\"patch\"],contains:[{className:\"chunk\",relevance:10,variants:[{begin:/^@@ +\\-\\d+,\\d+ +\\+\\d+,\\d+ +@@$/},{begin:/^\\*\\*\\* +\\d+,\\d+ +\\*\\*\\*\\*$/},{begin:/^\\-\\-\\- +\\d+,\\d+ +\\-\\-\\-\\-$/}]},{className:\"header\",variants:[{begin:/Index: /,end:/$/},{begin:/=====/,end:/=====$/},{begin:/^\\-\\-\\-/,end:/$/},{begin:/^\\*{3} /,end:/$/},{begin:/^\\+\\+\\+/,end:/$/},{begin:/\\*{5}/,end:/\\*{5}$/}]},{className:\"addition\",begin:\"^\\\\+\",end:\"$\"},{className:\"deletion\",begin:\"^\\\\-\",end:\"$\"},{className:\"change\",begin:\"^\\\\!\",end:\"$\"}]}}),e.registerLanguage(\"django\",function(e){var t={className:\"filter\",begin:/\\|[A-Za-z]+:?/,keywords:\"truncatewords removetags linebreaksbr yesno get_digit timesince random striptags filesizeformat escape linebreaks length_is ljust rjust cut urlize fix_ampersands title floatformat capfirst pprint divisibleby add make_list unordered_list urlencode timeuntil urlizetrunc wordcount stringformat linenumbers slice date dictsort dictsortreversed default_if_none pluralize lower join center default truncatewords_html upper length phone2numeric wordwrap time addslashes slugify first escapejs force_escape iriencode last safe safeseq truncatechars localize unlocalize localtime utc timezone\",contains:[{className:\"argument\",begin:/\"/,end:/\"/},{className:\"argument\",begin:/'/,end:/'/}]};return{aliases:[\"jinja\"],case_insensitive:!0,subLanguage:\"xml\",contains:[e.COMMENT(/\\{%\\s*comment\\s*%}/,/\\{%\\s*endcomment\\s*%}/),e.COMMENT(/\\{#/,/#}/),{className:\"template_tag\",begin:/\\{%/,end:/%}/,keywords:\"comment endcomment load templatetag ifchanged endifchanged if endif firstof for endfor in ifnotequal endifnotequal widthratio extends include spaceless endspaceless regroup by as ifequal endifequal ssi now with cycle url filter endfilter debug block endblock else autoescape endautoescape csrf_token empty elif endwith static trans blocktrans endblocktrans get_static_prefix get_media_prefix plural get_current_language language get_available_languages get_current_language_bidi get_language_info get_language_info_list localize endlocalize localtime endlocaltime timezone endtimezone get_current_timezone verbatim\",contains:[t]},{className:\"variable\",begin:/\\{\\{/,end:/}}/,contains:[t]}]}}),e.registerLanguage(\"dns\",function(e){return{aliases:[\"bind\",\"zone\"],keywords:{keyword:\"IN A AAAA AFSDB APL CAA CDNSKEY CDS CERT CNAME DHCID DLV DNAME DNSKEY DS HIP IPSECKEY KEY KX LOC MX NAPTR NS NSEC NSEC3 NSEC3PARAM PTR RRSIG RP SIG SOA SRV SSHFP TA TKEY TLSA TSIG TXT\"},contains:[e.COMMENT(\";\",\"$\"),{className:\"operator\",beginKeywords:\"$TTL $GENERATE $INCLUDE $ORIGIN\"},{className:\"number\",begin:\"((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)(\\\\.(25[0-5]|2[0-4]\\\\d|1\\\\d\\\\d|[1-9]?\\\\d)){3}))|:)))\"},{className:\"number\",begin:\"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\"}]}}),e.registerLanguage(\"dockerfile\",function(e){return{aliases:[\"docker\"],case_insensitive:!0,keywords:{built_ins:\"from maintainer cmd expose add copy entrypoint volume user workdir onbuild run env label\"},contains:[e.HASH_COMMENT_MODE,{keywords:{built_in:\"run cmd entrypoint volume add copy workdir onbuild label\"},begin:/^ *(onbuild +)?(run|cmd|entrypoint|volume|add|copy|workdir|label) +/,starts:{end:/[^\\\\]\\n/,subLanguage:\"bash\"}},{keywords:{built_in:\"from maintainer expose env user onbuild\"},begin:/^ *(onbuild +)?(from|maintainer|expose|env|user|onbuild) +/,end:/[^\\\\]\\n/,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,e.HASH_COMMENT_MODE]}]}}),e.registerLanguage(\"dos\",function(e){var t=e.COMMENT(/@?rem\\b/,/$/,{relevance:10}),n={className:\"label\",begin:\"^\\\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\\\s+label)\",relevance:0};return{aliases:[\"bat\",\"cmd\"],case_insensitive:!0,illegal:/\\/\\*/,keywords:{flow:\"if else goto for in do call exit not exist errorlevel defined\",operator:\"equ neq lss leq gtr geq\",keyword:\"shift cd dir echo setlocal endlocal set pause copy\",stream:\"prn nul lpt3 lpt2 lpt1 con com4 com3 com2 com1 aux\",winutils:\"ping net ipconfig taskkill xcopy ren del\",built_in:\"append assoc at attrib break cacls cd chcp chdir chkdsk chkntfs cls cmd color comp compact convert date dir diskcomp diskcopy doskey erase fs find findstr format ftype graftabl help keyb label md mkdir mode more move path pause print popd pushd promt rd recover rem rename replace restore rmdir shiftsort start subst time title tree type ver verify vol\"},contains:[{className:\"envvar\",begin:/%%[^ ]|%[^ ]+?%|![^ ]+?!/},{className:\"function\",begin:n.begin,end:\"goto:eof\",contains:[e.inherit(e.TITLE_MODE,{begin:\"([_a-zA-Z]\\\\w*\\\\.)*([_a-zA-Z]\\\\w*:)?[_a-zA-Z]\\\\w*\"}),t]},{className:\"number\",begin:\"\\\\b\\\\d+\",relevance:0},t]}}),e.registerLanguage(\"dust\",function(e){var t=\"if eq ne lt lte gt gte select default math sep\";return{aliases:[\"dst\"],case_insensitive:!0,subLanguage:\"xml\",contains:[{className:\"expression\",begin:\"{\",end:\"}\",relevance:0,contains:[{className:\"begin-block\",begin:\"#[a-zA-Z- .]+\",keywords:t},{className:\"string\",begin:'\"',end:'\"'},{className:\"end-block\",begin:\"\\\\/[a-zA-Z- .]+\",keywords:t},{className:\"variable\",begin:\"[a-zA-Z-.]+\",keywords:t,relevance:0}]}]}}),e.registerLanguage(\"elixir\",function(e){var t=\"[a-zA-Z_][a-zA-Z0-9_]*(\\\\!|\\\\?)?\",n=\"[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?\",i=\"and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote\",r={className:\"subst\",begin:\"#\\\\{\",end:\"}\",lexemes:t,keywords:i},a={className:\"string\",contains:[e.BACKSLASH_ESCAPE,r],variants:[{begin:/'/,end:/'/},{begin:/\"/,end:/\"/}]},o={className:\"function\",beginKeywords:\"def defp defmacro\",end:/\\B\\b/,contains:[e.inherit(e.TITLE_MODE,{begin:t,endsParent:!0})]},s=e.inherit(o,{className:\"class\",beginKeywords:\"defmodule defrecord\",end:/\\bdo\\b|$|;/}),l=[a,e.HASH_COMMENT_MODE,s,o,{className:\"constant\",begin:\"(\\\\b[A-Z_]\\\\w*(.)?)+\",relevance:0},{className:\"symbol\",begin:\":\",contains:[a,{begin:n}],relevance:0},{className:\"symbol\",begin:t+\":\",relevance:0},{className:\"number\",begin:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",relevance:0},{className:\"variable\",begin:\"(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?)(\\\\w+))\"},{begin:\"->\"},{begin:\"(\"+e.RE_STARTERS_RE+\")\\\\s*\",contains:[e.HASH_COMMENT_MODE,{className:\"regexp\",illegal:\"\\\\n\",contains:[e.BACKSLASH_ESCAPE,r],variants:[{begin:\"/\",end:\"/[a-z]*\"},{begin:\"%r\\\\[\",end:\"\\\\][a-z]*\"}]}],relevance:0}];return r.contains=l,{lexemes:t,keywords:i,contains:l}}),e.registerLanguage(\"elm\",function(e){var t=[e.COMMENT(\"--\",\"$\"),e.COMMENT(\"{-\",\"-}\",{contains:[\"self\"]})],n={className:\"type\",begin:\"\\\\b[A-Z][\\\\w']*\",relevance:0},i={className:\"container\",begin:\"\\\\(\",end:\"\\\\)\",illegal:'\"',contains:[{className:\"type\",begin:\"\\\\b[A-Z][\\\\w]*(\\\\((\\\\.\\\\.|,|\\\\w+)\\\\))?\"}].concat(t)},r={className:\"container\",begin:\"{\",end:\"}\",contains:i.contains};return{keywords:\"let in if then else case of where module import exposing type alias as infix infixl infixr port\",contains:[{className:\"module\",begin:\"\\\\bmodule\\\\b\",end:\"where\",keywords:\"module where\",contains:[i].concat(t),illegal:\"\\\\W\\\\.|;\"},{className:\"import\",begin:\"\\\\bimport\\\\b\",end:\"$\",keywords:\"import|0 as exposing\",contains:[i].concat(t),illegal:\"\\\\W\\\\.|;\"},{className:\"typedef\",begin:\"\\\\btype\\\\b\",end:\"$\",keywords:\"type alias\",contains:[n,i,r].concat(t)},{className:\"infix\",beginKeywords:\"infix infixl infixr\",end:\"$\",contains:[e.C_NUMBER_MODE].concat(t)},{className:\"foreign\",begin:\"\\\\bport\\\\b\",end:\"$\",keywords:\"port\",contains:t},e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,n,e.inherit(e.TITLE_MODE,{begin:\"^[_a-z][\\\\w']*\"}),{begin:\"->|<-\"}].concat(t)}}),e.registerLanguage(\"ruby\",function(e){var t=\"[a-zA-Z_]\\\\w*[!?=]?|[-+~]\\\\@|<<|>>|=~|===?|<=>|[<>]=?|\\\\*\\\\*|[-/+%^&*~`|]|\\\\[\\\\]=?\",n=\"and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor\",i={className:\"doctag\",begin:\"@[A-Za-z]+\"},r={className:\"value\",begin:\"#<\",end:\">\"},a=[e.COMMENT(\"#\",\"$\",{contains:[i]}),e.COMMENT(\"^\\\\=begin\",\"^\\\\=end\",{contains:[i],relevance:10}),e.COMMENT(\"^__END__\",\"\\\\n$\")],o={className:\"subst\",begin:\"#\\\\{\",end:\"}\",keywords:n},s={className:\"string\",contains:[e.BACKSLASH_ESCAPE,o],variants:[{begin:/'/,end:/'/},{begin:/\"/,end:/\"/},{begin:/`/,end:/`/},{begin:\"%[qQwWx]?\\\\(\",end:\"\\\\)\"},{begin:\"%[qQwWx]?\\\\[\",end:\"\\\\]\"},{begin:\"%[qQwWx]?{\",end:\"}\"},{begin:\"%[qQwWx]?<\",end:\">\"},{begin:\"%[qQwWx]?/\",end:\"/\"},{begin:\"%[qQwWx]?%\",end:\"%\"},{begin:\"%[qQwWx]?-\",end:\"-\"},{begin:\"%[qQwWx]?\\\\|\",end:\"\\\\|\"},{begin:/\\B\\?(\\\\\\d{1,3}|\\\\x[A-Fa-f0-9]{1,2}|\\\\u[A-Fa-f0-9]{4}|\\\\?\\S)\\b/}]},l={className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",keywords:n},c=[s,r,{className:\"class\",beginKeywords:\"class module\",end:\"$|;\",illegal:/=/,contains:[e.inherit(e.TITLE_MODE,{begin:\"[A-Za-z_]\\\\w*(::\\\\w+)*(\\\\?|\\\\!)?\"}),{className:\"inheritance\",begin:\"<\\\\s*\",contains:[{className:\"parent\",begin:\"(\"+e.IDENT_RE+\"::)?\"+e.IDENT_RE}]}].concat(a)},{className:\"function\",beginKeywords:\"def\",end:\"$|;\",contains:[e.inherit(e.TITLE_MODE,{begin:t}),l].concat(a)},{className:\"constant\",begin:\"(::)?(\\\\b[A-Z]\\\\w*(::)?)+\",relevance:0},{className:\"symbol\",begin:e.UNDERSCORE_IDENT_RE+\"(\\\\!|\\\\?)?:\",relevance:0},{className:\"symbol\",begin:\":\",contains:[s,{begin:t}],relevance:0},{className:\"number\",begin:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",relevance:0},{className:\"variable\",begin:\"(\\\\$\\\\W)|((\\\\$|\\\\@\\\\@?)(\\\\w+))\"},{begin:\"(\"+e.RE_STARTERS_RE+\")\\\\s*\",contains:[r,{className:\"regexp\",contains:[e.BACKSLASH_ESCAPE,o],illegal:/\\n/,variants:[{begin:\"/\",end:\"/[a-z]*\"},{begin:\"%r{\",end:\"}[a-z]*\"},{begin:\"%r\\\\(\",end:\"\\\\)[a-z]*\"},{begin:\"%r!\",end:\"![a-z]*\"},{begin:\"%r\\\\[\",end:\"\\\\][a-z]*\"}]}].concat(a),relevance:0}].concat(a);o.contains=c,l.contains=c;var d=\"[>?]>\",u=\"[\\\\w#]+\\\\(\\\\w+\\\\):\\\\d+:\\\\d+>\",p=\"(\\\\w+-)?\\\\d+\\\\.\\\\d+\\\\.\\\\d(p\\\\d+)?[^>]+>\",m=[{begin:/^\\s*=>/,className:\"status\",starts:{end:\"$\",contains:c}},{className:\"prompt\",begin:\"^(\"+d+\"|\"+u+\"|\"+p+\")\",starts:{end:\"$\",contains:c}}];return{aliases:[\"rb\",\"gemspec\",\"podspec\",\"thor\",\"irb\"],keywords:n,illegal:/\\/\\*/,contains:a.concat(m).concat(c)}}),e.registerLanguage(\"erb\",function(e){return{subLanguage:\"xml\",contains:[e.COMMENT(\"<%#\",\"%>\"),{begin:\"<%[%=-]?\",end:\"[%-]?%>\",subLanguage:\"ruby\",excludeBegin:!0,excludeEnd:!0}]}}),e.registerLanguage(\"erlang-repl\",function(e){return{keywords:{special_functions:\"spawn spawn_link self\",reserved:\"after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse|10 query receive rem try when xor\"},contains:[{className:\"prompt\",begin:\"^[0-9]+> \",relevance:10},e.COMMENT(\"%\",\"$\"),{className:\"number\",begin:\"\\\\b(\\\\d+#[a-fA-F0-9]+|\\\\d+(\\\\.\\\\d+)?([eE][-+]?\\\\d+)?)\",relevance:0},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:\"constant\",begin:\"\\\\?(::)?([A-Z]\\\\w*(::)?)+\"},{className:\"arrow\",begin:\"->\"},{className:\"ok\",begin:\"ok\"},{className:\"exclamation_mark\",begin:\"!\"},{className:\"function_or_atom\",begin:\"(\\\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\\\b[a-z'][a-zA-Z0-9_']*)\",relevance:0},{className:\"variable\",begin:\"[A-Z][a-zA-Z0-9_']*\",relevance:0}]}}),e.registerLanguage(\"erlang\",function(e){var t=\"[a-z'][a-zA-Z0-9_']*\",n=\"(\"+t+\":\"+t+\"|\"+t+\")\",i={keyword:\"after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if let not of orelse|10 query receive rem try when xor\",literal:\"false true\"},r=e.COMMENT(\"%\",\"$\"),a={className:\"number\",begin:\"\\\\b(\\\\d+#[a-fA-F0-9]+|\\\\d+(\\\\.\\\\d+)?([eE][-+]?\\\\d+)?)\",relevance:0},o={begin:\"fun\\\\s+\"+t+\"/\\\\d+\"},s={begin:n+\"\\\\(\",end:\"\\\\)\",returnBegin:!0,relevance:0,contains:[{className:\"function_name\",begin:n,relevance:0},{begin:\"\\\\(\",end:\"\\\\)\",endsWithParent:!0,returnEnd:!0,relevance:0}]},l={className:\"tuple\",begin:\"{\",end:\"}\",relevance:0},c={className:\"variable\",begin:\"\\\\b_([A-Z][A-Za-z0-9_]*)?\",relevance:0},d={className:\"variable\",begin:\"[A-Z][a-zA-Z0-9_]*\",relevance:0},u={begin:\"#\"+e.UNDERSCORE_IDENT_RE,relevance:0,returnBegin:!0,contains:[{className:\"record_name\",begin:\"#\"+e.UNDERSCORE_IDENT_RE,relevance:0},{begin:\"{\",end:\"}\",relevance:0}]},p={beginKeywords:\"fun receive if try case\",end:\"end\",keywords:i};p.contains=[r,o,e.inherit(e.APOS_STRING_MODE,{className:\"\"}),p,s,e.QUOTE_STRING_MODE,a,l,c,d,u];var m=[r,o,p,s,e.QUOTE_STRING_MODE,a,l,c,d,u];s.contains[1].contains=m,l.contains=m,u.contains[1].contains=m;var g={className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:m};return{aliases:[\"erl\"],keywords:i,illegal:\"(</|\\\\*=|\\\\+=|-=|/\\\\*|\\\\*/|\\\\(\\\\*|\\\\*\\\\))\",contains:[{className:\"function\",begin:\"^\"+t+\"\\\\s*\\\\(\",end:\"->\",returnBegin:!0,illegal:\"\\\\(|#|//|/\\\\*|\\\\\\\\|:|;\",contains:[g,e.inherit(e.TITLE_MODE,{begin:t})],starts:{end:\";|\\\\.\",keywords:i,contains:m}},r,{className:\"pp\",begin:\"^-\",end:\"\\\\.\",relevance:0,excludeEnd:!0,returnBegin:!0,lexemes:\"-\"+e.IDENT_RE,keywords:\"-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn -import -include -include_lib -compile -define -else -endif -file -behaviour -behavior -spec\",contains:[g]},a,e.QUOTE_STRING_MODE,u,c,d,l,{begin:/\\.$/}]}}),e.registerLanguage(\"fix\",function(e){return{contains:[{begin:/[^\\u2401\\u0001]+/,end:/[\\u2401\\u0001]/,excludeEnd:!0,returnBegin:!0,returnEnd:!1,contains:[{begin:/([^\\u2401\\u0001=]+)/,end:/=([^\\u2401\\u0001=]+)/,returnEnd:!0,returnBegin:!1,className:\"attribute\"},{begin:/=/,end:/([\\u2401\\u0001])/,excludeEnd:!0,excludeBegin:!0,className:\"string\"}]}],case_insensitive:!0}}),e.registerLanguage(\"fortran\",function(e){var t={className:\"params\",begin:\"\\\\(\",end:\"\\\\)\"},n={constant:\".False. .True.\",type:\"integer real character complex logical dimension allocatable|10 parameter external implicit|10 none double precision assign intent optional pointer target in out common equivalence data\",keyword:\"kind do while private call intrinsic where elsewhere type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. goto save else use module select case access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit continue format pause cycle exit c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg synchronous nopass non_overridable pass protected volatile abstract extends import non_intrinsic value deferred generic final enumerator class associate bind enum c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure\",built_in:\"alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_ofacosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image\"};return{case_insensitive:!0,aliases:[\"f90\",\"f95\"],keywords:n,illegal:/\\/\\*/,contains:[e.inherit(e.APOS_STRING_MODE,{className:\"string\",relevance:0}),e.inherit(e.QUOTE_STRING_MODE,{className:\"string\",relevance:0}),{className:\"function\",beginKeywords:\"subroutine function program\",illegal:\"[${=\\\\n]\",contains:[e.UNDERSCORE_TITLE_MODE,t]},e.COMMENT(\"!\",\"$\",{relevance:0}),{className:\"number\",begin:\"(?=\\\\b|\\\\+|\\\\-|\\\\.)(?=\\\\.\\\\d|\\\\d)(?:\\\\d+)?(?:\\\\.?\\\\d*)(?:[de][+-]?\\\\d+)?\\\\b\\\\.?\",relevance:0}]}}),e.registerLanguage(\"fsharp\",function(e){var t={begin:\"<\",end:\">\",contains:[e.inherit(e.TITLE_MODE,{begin:/'[a-zA-Z0-9_]+/})]};return{aliases:[\"fs\"],keywords:\"abstract and as assert base begin class default delegate do done downcast downto elif else end exception extern false finally for fun function global if in inherit inline interface internal lazy let match member module mutable namespace new null of open or override private public rec return sig static struct then to true try type upcast use val void when while with yield\",illegal:/\\/\\*/,contains:[{className:\"keyword\",begin:/\\b(yield|return|let|do)!/},{className:\"string\",begin:'@\"',end:'\"',contains:[{begin:'\"\"'}]},{className:\"string\",begin:'\"\"\"',end:'\"\"\"'},e.COMMENT(\"\\\\(\\\\*\",\"\\\\*\\\\)\"),{className:\"class\",beginKeywords:\"type\",end:\"\\\\(|=|$\",excludeEnd:!0,contains:[e.UNDERSCORE_TITLE_MODE,t]},{className:\"annotation\",begin:\"\\\\[<\",end:\">\\\\]\",relevance:10},{className:\"attribute\",begin:\"\\\\B('[A-Za-z])\\\\b\",contains:[e.BACKSLASH_ESCAPE]},e.C_LINE_COMMENT_MODE,e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),e.C_NUMBER_MODE]}}),e.registerLanguage(\"gams\",function(e){var t=\"abort acronym acronyms alias all and assign binary card diag display else1 eps eq equation equations file files for1 free ge gt if inf integer le loop lt maximizing minimizing model models na ne negative no not option options or ord parameter parameters positive prod putpage puttl repeat sameas scalar scalars semicont semiint set1 sets smax smin solve sos1 sos2 sum system table then until using variable variables while1 xor yes\";return{aliases:[\"gms\"],case_insensitive:!0,keywords:t,contains:[{className:\"section\",beginKeywords:\"sets parameters variables equations\",end:\";\",contains:[{begin:\"/\",end:\"/\",contains:[e.NUMBER_MODE]}]},{className:\"string\",begin:\"\\\\*{3}\",end:\"\\\\*{3}\"},e.NUMBER_MODE,{className:\"number\",begin:\"\\\\$[a-zA-Z0-9]+\"}]}}),e.registerLanguage(\"gcode\",function(e){var t=\"[A-Z_][A-Z0-9_.]*\",n=\"\\\\%\",i={literal:\"\",built_in:\"\",keyword:\"IF DO WHILE ENDWHILE CALL ENDIF SUB ENDSUB GOTO REPEAT ENDREPEAT EQ LT GT NE GE LE OR XOR\"},r={className:\"preprocessor\",begin:\"([O])([0-9]+)\"},a=[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.COMMENT(/\\(/,/\\)/),e.inherit(e.C_NUMBER_MODE,{begin:\"([-+]?([0-9]*\\\\.?[0-9]+\\\\.?))|\"+e.C_NUMBER_RE}),e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:\"keyword\",begin:\"([G])([0-9]+\\\\.?[0-9]?)\"},{className:\"title\",begin:\"([M])([0-9]+\\\\.?[0-9]?)\"},{className:\"title\",begin:\"(VC|VS|#)\",end:\"(\\\\d+)\"},{className:\"title\",begin:\"(VZOFX|VZOFY|VZOFZ)\"},{className:\"built_in\",begin:\"(ATAN|ABS|ACOS|ASIN|SIN|COS|EXP|FIX|FUP|ROUND|LN|TAN)(\\\\[)\",end:\"([-+]?([0-9]*\\\\.?[0-9]+\\\\.?))(\\\\])\"},{className:\"label\",variants:[{begin:\"N\",end:\"\\\\d+\",illegal:\"\\\\W\"}]}];return{aliases:[\"nc\"],case_insensitive:!0,lexemes:t,keywords:i,contains:[{className:\"preprocessor\",begin:n},r].concat(a)}}),e.registerLanguage(\"gherkin\",function(e){return{aliases:[\"feature\"],keywords:\"Feature Background Ability Business Need Scenario Scenarios Scenario Outline Scenario Template Examples Given And Then But When\",contains:[{className:\"keyword\",begin:\"\\\\*\"},e.COMMENT(\"@[^@\\r\\n\t ]+\",\"$\"),{begin:\"\\\\|\",end:\"\\\\|\\\\w*$\",contains:[{className:\"string\",begin:\"[^|]+\"}]},{className:\"variable\",begin:\"<\",end:\">\"},e.HASH_COMMENT_MODE,{className:\"string\",begin:'\"\"\"',end:'\"\"\"'},e.QUOTE_STRING_MODE]}}),e.registerLanguage(\"glsl\",function(e){return{keywords:{keyword:\"atomic_uint attribute bool break bvec2 bvec3 bvec4 case centroid coherent const continue default discard dmat2 dmat2x2 dmat2x3 dmat2x4 dmat3 dmat3x2 dmat3x3 dmat3x4 dmat4 dmat4x2 dmat4x3 dmat4x4 do double dvec2 dvec3 dvec4 else flat float for highp if iimage1D iimage1DArray iimage2D iimage2DArray iimage2DMS iimage2DMSArray iimage2DRect iimage3D iimageBuffer iimageCube iimageCubeArray image1D image1DArray image2D image2DArray image2DMS image2DMSArray image2DRect image3D imageBuffer imageCube imageCubeArray in inout int invariant isampler1D isampler1DArray isampler2D isampler2DArray isampler2DMS isampler2DMSArray isampler2DRect isampler3D isamplerBuffer isamplerCube isamplerCubeArray ivec2 ivec3 ivec4 layout lowp mat2 mat2x2 mat2x3 mat2x4 mat3 mat3x2 mat3x3 mat3x4 mat4 mat4x2 mat4x3 mat4x4 mediump noperspective out patch precision readonly restrict return sample sampler1D sampler1DArray sampler1DArrayShadow sampler1DShadow sampler2D sampler2DArray sampler2DArrayShadow sampler2DMS sampler2DMSArray sampler2DRect sampler2DRectShadow sampler2DShadow sampler3D samplerBuffer samplerCube samplerCubeArray samplerCubeArrayShadow samplerCubeShadow smooth struct subroutine switch uimage1D uimage1DArray uimage2D uimage2DArray uimage2DMS uimage2DMSArray uimage2DRect uimage3D uimageBuffer uimageCube uimageCubeArray uint uniform usampler1D usampler1DArray usampler2D usampler2DArray usampler2DMS usampler2DMSArray usampler2DRect usampler3D usamplerBuffer usamplerCube usamplerCubeArray uvec2 uvec3 uvec4 varying vec2 vec3 vec4 void volatile while writeonly\",built_in:\"gl_BackColor gl_BackLightModelProduct gl_BackLightProduct gl_BackMaterial gl_BackSecondaryColor gl_ClipDistance gl_ClipPlane gl_ClipVertex gl_Color gl_DepthRange gl_EyePlaneQ gl_EyePlaneR gl_EyePlaneS gl_EyePlaneT gl_Fog gl_FogCoord gl_FogFragCoord gl_FragColor gl_FragCoord gl_FragData gl_FragDepth gl_FrontColor gl_FrontFacing gl_FrontLightModelProduct gl_FrontLightProduct gl_FrontMaterial gl_FrontSecondaryColor gl_InstanceID gl_InvocationID gl_Layer gl_LightModel gl_LightSource gl_MaxAtomicCounterBindings gl_MaxAtomicCounterBufferSize gl_MaxClipDistances gl_MaxClipPlanes gl_MaxCombinedAtomicCounterBuffers gl_MaxCombinedAtomicCounters gl_MaxCombinedImageUniforms gl_MaxCombinedImageUnitsAndFragmentOutputs gl_MaxCombinedTextureImageUnits gl_MaxDrawBuffers gl_MaxFragmentAtomicCounterBuffers gl_MaxFragmentAtomicCounters gl_MaxFragmentImageUniforms gl_MaxFragmentInputComponents gl_MaxFragmentUniformComponents gl_MaxFragmentUniformVectors gl_MaxGeometryAtomicCounterBuffers gl_MaxGeometryAtomicCounters gl_MaxGeometryImageUniforms gl_MaxGeometryInputComponents gl_MaxGeometryOutputComponents gl_MaxGeometryOutputVertices gl_MaxGeometryTextureImageUnits gl_MaxGeometryTotalOutputComponents gl_MaxGeometryUniformComponents gl_MaxGeometryVaryingComponents gl_MaxImageSamples gl_MaxImageUnits gl_MaxLights gl_MaxPatchVertices gl_MaxProgramTexelOffset gl_MaxTessControlAtomicCounterBuffers gl_MaxTessControlAtomicCounters gl_MaxTessControlImageUniforms gl_MaxTessControlInputComponents gl_MaxTessControlOutputComponents gl_MaxTessControlTextureImageUnits gl_MaxTessControlTotalOutputComponents gl_MaxTessControlUniformComponents gl_MaxTessEvaluationAtomicCounterBuffers gl_MaxTessEvaluationAtomicCounters gl_MaxTessEvaluationImageUniforms gl_MaxTessEvaluationInputComponents gl_MaxTessEvaluationOutputComponents gl_MaxTessEvaluationTextureImageUnits gl_MaxTessEvaluationUniformComponents gl_MaxTessGenLevel gl_MaxTessPatchComponents gl_MaxTextureCoords gl_MaxTextureImageUnits gl_MaxTextureUnits gl_MaxVaryingComponents gl_MaxVaryingFloats gl_MaxVaryingVectors gl_MaxVertexAtomicCounterBuffers gl_MaxVertexAtomicCounters gl_MaxVertexAttribs gl_MaxVertexImageUniforms gl_MaxVertexOutputComponents gl_MaxVertexTextureImageUnits gl_MaxVertexUniformComponents gl_MaxVertexUniformVectors gl_MaxViewports gl_MinProgramTexelOffsetgl_ModelViewMatrix gl_ModelViewMatrixInverse gl_ModelViewMatrixInverseTranspose gl_ModelViewMatrixTranspose gl_ModelViewProjectionMatrix gl_ModelViewProjectionMatrixInverse gl_ModelViewProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixTranspose gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_Normal gl_NormalMatrix gl_NormalScale gl_ObjectPlaneQ gl_ObjectPlaneR gl_ObjectPlaneS gl_ObjectPlaneT gl_PatchVerticesIn gl_PerVertex gl_Point gl_PointCoord gl_PointSize gl_Position gl_PrimitiveID gl_PrimitiveIDIn gl_ProjectionMatrix gl_ProjectionMatrixInverse gl_ProjectionMatrixInverseTranspose gl_ProjectionMatrixTranspose gl_SampleID gl_SampleMask gl_SampleMaskIn gl_SamplePosition gl_SecondaryColor gl_TessCoord gl_TessLevelInner gl_TessLevelOuter gl_TexCoord gl_TextureEnvColor gl_TextureMatrixInverseTranspose gl_TextureMatrixTranspose gl_Vertex gl_VertexID gl_ViewportIndex gl_in gl_out EmitStreamVertex EmitVertex EndPrimitive EndStreamPrimitive abs acos acosh all any asin asinh atan atanh atomicCounter atomicCounterDecrement atomicCounterIncrement barrier bitCount bitfieldExtract bitfieldInsert bitfieldReverse ceil clamp cos cosh cross dFdx dFdy degrees determinant distance dot equal exp exp2 faceforward findLSB findMSB floatBitsToInt floatBitsToUint floor fma fract frexp ftransform fwidth greaterThan greaterThanEqual imageAtomicAdd imageAtomicAnd imageAtomicCompSwap imageAtomicExchange imageAtomicMax imageAtomicMin imageAtomicOr imageAtomicXor imageLoad imageStore imulExtended intBitsToFloat interpolateAtCentroid interpolateAtOffset interpolateAtSample inverse inversesqrt isinf isnan ldexp length lessThan lessThanEqual log log2 matrixCompMult max memoryBarrier min mix mod modf noise1 noise2 noise3 noise4 normalize not notEqual outerProduct packDouble2x32 packHalf2x16 packSnorm2x16 packSnorm4x8 packUnorm2x16 packUnorm4x8 pow radians reflect refract round roundEven shadow1D shadow1DLod shadow1DProj shadow1DProjLod shadow2D shadow2DLod shadow2DProj shadow2DProjLod sign sin sinh smoothstep sqrt step tan tanh texelFetch texelFetchOffset texture texture1D texture1DLod texture1DProj texture1DProjLod texture2D texture2DLod texture2DProj texture2DProjLod texture3D texture3DLod texture3DProj texture3DProjLod textureCube textureCubeLod textureGather textureGatherOffset textureGatherOffsets textureGrad textureGradOffset textureLod textureLodOffset textureOffset textureProj textureProjGrad textureProjGradOffset textureProjLod textureProjLodOffset textureProjOffset textureQueryLod textureSize transpose trunc uaddCarry uintBitsToFloat umulExtended unpackDouble2x32 unpackHalf2x16 unpackSnorm2x16 unpackSnorm4x8 unpackUnorm2x16 unpackUnorm4x8 usubBorrow gl_TextureMatrix gl_TextureMatrixInverse\",literal:\"true false\"},illegal:'\"',contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.C_NUMBER_MODE,{className:\"preprocessor\",begin:\"#\",end:\"$\"}]}}),e.registerLanguage(\"go\",function(e){var t={keyword:\"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer\",\nconstant:\"true false iota nil\",typename:\"bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune\",built_in:\"append cap close complex copy imag len make new panic print println real recover delete\"};return{aliases:[\"golang\"],keywords:t,illegal:\"</\",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.QUOTE_STRING_MODE,{className:\"string\",begin:\"'\",end:\"[^\\\\\\\\]'\"},{className:\"string\",begin:\"`\",end:\"`\"},{className:\"number\",begin:e.C_NUMBER_RE+\"[dflsi]?\",relevance:0},e.C_NUMBER_MODE]}}),e.registerLanguage(\"golo\",function(e){return{keywords:{keyword:\"println readln print import module function local return let var while for foreach times in case when match with break continue augment augmentation each find filter reduce if then else otherwise try catch finally raise throw orIfNull\",typename:\"DynamicObject|10 DynamicVariable struct Observable map set vector list array\",literal:\"true false null\"},contains:[e.HASH_COMMENT_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,{className:\"annotation\",begin:\"@[A-Za-z]+\"}]}}),e.registerLanguage(\"gradle\",function(e){return{case_insensitive:!0,keywords:{keyword:\"task project allprojects subprojects artifacts buildscript configurations dependencies repositories sourceSets description delete from into include exclude source classpath destinationDir includes options sourceCompatibility targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant def abstract break case catch continue default do else extends final finally for if implements instanceof native new private protected public return static switch synchronized throw throws transient try volatile while strictfp package import false null super this true antlrtask checkstyle codenarc copy boolean byte char class double float int interface long short void compile runTime file fileTree abs any append asList asWritable call collect compareTo count div dump each eachByte eachFile eachLine every find findAll flatten getAt getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter newReader newWriter next plus pop power previous print println push putAt read readBytes readLines reverse reverseEach round size sort splitEachLine step subMap times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader withStream withWriter withWriterAppend write writeLine\"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,e.REGEXP_MODE]}}),e.registerLanguage(\"groovy\",function(e){return{keywords:{typename:\"byte short char int long boolean float double void\",literal:\"true false null\",keyword:\"def as in assert trait super this abstract static volatile transient public private protected synchronized final class interface enum if else for while switch case break default continue throw throws try catch finally implements extends new import package return instanceof\"},contains:[e.COMMENT(\"/\\\\*\\\\*\",\"\\\\*/\",{relevance:0,contains:[{className:\"doctag\",begin:\"@[A-Za-z]+\"}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"string\",begin:'\"\"\"',end:'\"\"\"'},{className:\"string\",begin:\"'''\",end:\"'''\"},{className:\"string\",begin:\"\\\\$/\",end:\"/\\\\$\",relevance:10},e.APOS_STRING_MODE,{className:\"regexp\",begin:/~?\\/[^\\/\\n]+\\//,contains:[e.BACKSLASH_ESCAPE]},e.QUOTE_STRING_MODE,{className:\"shebang\",begin:\"^#!/usr/bin/env\",end:\"$\",illegal:\"\\n\"},e.BINARY_NUMBER_MODE,{className:\"class\",beginKeywords:\"class interface trait enum\",end:\"{\",illegal:\":\",contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]},e.C_NUMBER_MODE,{className:\"annotation\",begin:\"@[A-Za-z]+\"},{className:\"string\",begin:/[^\\?]{0}[A-Za-z0-9_$]+ *:/},{begin:/\\?/,end:/\\:/},{className:\"label\",begin:\"^\\\\s*[A-Za-z0-9_$]+:\",relevance:0}],illegal:/#/}}),e.registerLanguage(\"haml\",function(e){return{case_insensitive:!0,contains:[{className:\"doctype\",begin:\"^!!!( (5|1\\\\.1|Strict|Frameset|Basic|Mobile|RDFa|XML\\\\b.*))?$\",relevance:10},e.COMMENT(\"^\\\\s*(!=#|=#|-#|/).*$\",!1,{relevance:0}),{begin:\"^\\\\s*(-|=|!=)(?!#)\",starts:{end:\"\\\\n\",subLanguage:\"ruby\"}},{className:\"tag\",begin:\"^\\\\s*%\",contains:[{className:\"title\",begin:\"\\\\w+\"},{className:\"value\",begin:\"[#\\\\.][\\\\w-]+\"},{begin:\"{\\\\s*\",end:\"\\\\s*}\",excludeEnd:!0,contains:[{begin:\":\\\\w+\\\\s*=>\",end:\",\\\\s+\",returnBegin:!0,endsWithParent:!0,contains:[{className:\"symbol\",begin:\":\\\\w+\"},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{begin:\"\\\\w+\",relevance:0}]}]},{begin:\"\\\\(\\\\s*\",end:\"\\\\s*\\\\)\",excludeEnd:!0,contains:[{begin:\"\\\\w+\\\\s*=\",end:\"\\\\s+\",returnBegin:!0,endsWithParent:!0,contains:[{className:\"attribute\",begin:\"\\\\w+\",relevance:0},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{begin:\"\\\\w+\",relevance:0}]}]}]},{className:\"bullet\",begin:\"^\\\\s*[=~]\\\\s*\",relevance:0},{begin:\"#{\",starts:{end:\"}\",subLanguage:\"ruby\"}}]}}),e.registerLanguage(\"handlebars\",function(e){var t=\"each in with if else unless bindattr action collection debugger log outlet template unbound view yield\";return{aliases:[\"hbs\",\"html.hbs\",\"html.handlebars\"],case_insensitive:!0,subLanguage:\"xml\",contains:[{className:\"expression\",begin:\"{{\",end:\"}}\",contains:[{className:\"begin-block\",begin:\"#[a-zA-Z- .]+\",keywords:t},{className:\"string\",begin:'\"',end:'\"'},{className:\"end-block\",begin:\"\\\\/[a-zA-Z- .]+\",keywords:t},{className:\"variable\",begin:\"[a-zA-Z-.]+\",keywords:t}]}]}}),e.registerLanguage(\"haskell\",function(e){var t=[e.COMMENT(\"--\",\"$\"),e.COMMENT(\"{-\",\"-}\",{contains:[\"self\"]})],n={className:\"pragma\",begin:\"{-#\",end:\"#-}\"},i={className:\"preprocessor\",begin:\"^#\",end:\"$\"},r={className:\"type\",begin:\"\\\\b[A-Z][\\\\w']*\",relevance:0},a={className:\"container\",begin:\"\\\\(\",end:\"\\\\)\",illegal:'\"',contains:[n,i,{className:\"type\",begin:\"\\\\b[A-Z][\\\\w]*(\\\\((\\\\.\\\\.|,|\\\\w+)\\\\))?\"},e.inherit(e.TITLE_MODE,{begin:\"[_a-z][\\\\w']*\"})].concat(t)},o={className:\"container\",begin:\"{\",end:\"}\",contains:a.contains};return{aliases:[\"hs\"],keywords:\"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec\",contains:[{className:\"module\",begin:\"\\\\bmodule\\\\b\",end:\"where\",keywords:\"module where\",contains:[a].concat(t),illegal:\"\\\\W\\\\.|;\"},{className:\"import\",begin:\"\\\\bimport\\\\b\",end:\"$\",keywords:\"import|0 qualified as hiding\",contains:[a].concat(t),illegal:\"\\\\W\\\\.|;\"},{className:\"class\",begin:\"^(\\\\s*)?(class|instance)\\\\b\",end:\"where\",keywords:\"class family instance where\",contains:[r,a].concat(t)},{className:\"typedef\",begin:\"\\\\b(data|(new)?type)\\\\b\",end:\"$\",keywords:\"data family type newtype deriving\",contains:[n,r,a,o].concat(t)},{className:\"default\",beginKeywords:\"default\",end:\"$\",contains:[r,a].concat(t)},{className:\"infix\",beginKeywords:\"infix infixl infixr\",end:\"$\",contains:[e.C_NUMBER_MODE].concat(t)},{className:\"foreign\",begin:\"\\\\bforeign\\\\b\",end:\"$\",keywords:\"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe\",contains:[r,e.QUOTE_STRING_MODE].concat(t)},{className:\"shebang\",begin:\"#!\\\\/usr\\\\/bin\\\\/env runhaskell\",end:\"$\"},n,i,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,r,e.inherit(e.TITLE_MODE,{begin:\"^[_a-z][\\\\w']*\"}),{begin:\"->|<-\"}].concat(t)}}),e.registerLanguage(\"haxe\",function(e){var t=\"([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)\";return{aliases:[\"hx\"],keywords:{keyword:\"break callback case cast catch class continue default do dynamic else enum extends extern for function here if implements import in inline interface never new override package private public return static super switch this throw trace try typedef untyped using var while\",literal:\"true false null\"},contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.C_NUMBER_MODE,{className:\"class\",beginKeywords:\"class interface\",end:\"{\",excludeEnd:!0,contains:[{beginKeywords:\"extends implements\"},e.TITLE_MODE]},{className:\"preprocessor\",begin:\"#\",end:\"$\",keywords:\"if else elseif end error\"},{className:\"function\",beginKeywords:\"function\",end:\"[{;]\",excludeEnd:!0,illegal:\"\\\\S\",contains:[e.TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:\"type\",begin:\":\",end:t,relevance:10}]}]}}),e.registerLanguage(\"http\",function(e){return{aliases:[\"https\"],illegal:\"\\\\S\",contains:[{className:\"status\",begin:\"^HTTP/[0-9\\\\.]+\",end:\"$\",contains:[{className:\"number\",begin:\"\\\\b\\\\d{3}\\\\b\"}]},{className:\"request\",begin:\"^[A-Z]+ (.*?) HTTP/[0-9\\\\.]+$\",returnBegin:!0,end:\"$\",contains:[{className:\"string\",begin:\" \",end:\" \",excludeBegin:!0,excludeEnd:!0}]},{className:\"attribute\",begin:\"^\\\\w\",end:\": \",excludeEnd:!0,illegal:\"\\\\n|\\\\s|=\",starts:{className:\"string\",end:\"$\"}},{begin:\"\\\\n\\\\n\",starts:{subLanguage:[],endsWithParent:!0}}]}}),e.registerLanguage(\"inform7\",function(e){var t=\"\\\\[\",n=\"\\\\]\";return{aliases:[\"i7\"],case_insensitive:!0,keywords:{keyword:\"thing room person man woman animal container supporter backdrop door scenery open closed locked inside gender is are say understand kind of rule\"},contains:[{className:\"string\",begin:'\"',end:'\"',relevance:0,contains:[{className:\"subst\",begin:t,end:n}]},{className:\"title\",begin:/^(Volume|Book|Part|Chapter|Section|Table)\\b/,end:\"$\"},{begin:/^(Check|Carry out|Report|Instead of|To|Rule|When|Before|After)\\b/,end:\":\",contains:[{begin:\"\\\\b\\\\(This\",end:\"\\\\)\"}]},{className:\"comment\",begin:t,end:n,contains:[\"self\"]}]}}),e.registerLanguage(\"ini\",function(e){var t={className:\"string\",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:\"'''\",end:\"'''\",relevance:10},{begin:'\"\"\"',end:'\"\"\"',relevance:10},{begin:'\"',end:'\"'},{begin:\"'\",end:\"'\"}]};return{aliases:[\"toml\"],case_insensitive:!0,illegal:/\\S/,contains:[e.COMMENT(\";\",\"$\"),e.HASH_COMMENT_MODE,{className:\"title\",begin:/^\\s*\\[+/,end:/\\]+/},{className:\"setting\",begin:/^[a-z0-9\\[\\]_-]+\\s*=\\s*/,end:\"$\",contains:[{className:\"value\",endsWithParent:!0,keywords:\"on off true false yes no\",contains:[{className:\"variable\",variants:[{begin:/\\$[\\w\\d\"][\\w\\d_]*/},{begin:/\\$\\{(.*?)}/}]},t,{className:\"number\",begin:/([\\+\\-]+)?[\\d]+_[\\d_]+/},e.NUMBER_MODE],relevance:0}]}]}}),e.registerLanguage(\"irpf90\",function(e){var t={className:\"params\",begin:\"\\\\(\",end:\"\\\\)\"},n={constant:\".False. .True.\",type:\"integer real character complex logical dimension allocatable|10 parameter external implicit|10 none double precision assign intent optional pointer target in out common equivalence data\",keyword:\"kind do while private call intrinsic where elsewhere type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. goto save else use module select case access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit continue format pause cycle exit c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg synchronous nopass non_overridable pass protected volatile abstract extends import non_intrinsic value deferred generic final enumerator class associate bind enum c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure begin_provider &begin_provider end_provider begin_shell end_shell begin_template end_template subst assert touch soft_touch provide no_dep free irp_if irp_else irp_endif irp_write irp_read\",built_in:\"alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_ofacosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image IRP_ALIGN irp_here\"};return{case_insensitive:!0,keywords:n,illegal:/\\/\\*/,contains:[e.inherit(e.APOS_STRING_MODE,{className:\"string\",relevance:0}),e.inherit(e.QUOTE_STRING_MODE,{className:\"string\",relevance:0}),{className:\"function\",beginKeywords:\"subroutine function program\",illegal:\"[${=\\\\n]\",contains:[e.UNDERSCORE_TITLE_MODE,t]},e.COMMENT(\"!\",\"$\",{relevance:0}),e.COMMENT(\"begin_doc\",\"end_doc\",{relevance:10}),{className:\"number\",begin:\"(?=\\\\b|\\\\+|\\\\-|\\\\.)(?=\\\\.\\\\d|\\\\d)(?:\\\\d+)?(?:\\\\.?\\\\d*)(?:[de][+-]?\\\\d+)?\\\\b\\\\.?\",relevance:0}]}}),e.registerLanguage(\"java\",function(e){var t=e.UNDERSCORE_IDENT_RE+\"(<\"+e.UNDERSCORE_IDENT_RE+\">)?\",n=\"false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private\",i=\"\\\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+)(\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))?|\\\\.([\\\\d]+[\\\\d_]+[\\\\d]+|[\\\\d]+))([eE][-+]?\\\\d+)?)[lLfF]?\",r={className:\"number\",begin:i,relevance:0};return{aliases:[\"jsp\"],keywords:n,illegal:/<\\/|#/,contains:[e.COMMENT(\"/\\\\*\\\\*\",\"\\\\*/\",{relevance:0,contains:[{className:\"doctag\",begin:\"@[A-Za-z]+\"}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:\"class\",beginKeywords:\"class interface\",end:/[{;=]/,excludeEnd:!0,keywords:\"class interface\",illegal:/[:\"\\[\\]]/,contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:\"new throw return else\",relevance:0},{className:\"function\",begin:\"(\"+t+\"\\\\s+)+\"+e.UNDERSCORE_IDENT_RE+\"\\\\s*\\\\(\",returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:n,contains:[{begin:e.UNDERSCORE_IDENT_RE+\"\\\\s*\\\\(\",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:\"params\",begin:/\\(/,end:/\\)/,keywords:n,relevance:0,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},r,{className:\"annotation\",begin:\"@[A-Za-z]+\"}]}}),e.registerLanguage(\"javascript\",function(e){return{aliases:[\"js\"],keywords:{keyword:\"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await\",literal:\"true false null undefined NaN Infinity\",built_in:\"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise\"},contains:[{className:\"pi\",relevance:10,begin:/^\\s*['\"]use (strict|asm)['\"]/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:\"string\",begin:\"`\",end:\"`\",contains:[e.BACKSLASH_ESCAPE,{className:\"subst\",begin:\"\\\\$\\\\{\",end:\"\\\\}\"}]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"number\",variants:[{begin:\"\\\\b(0[bB][01]+)\"},{begin:\"\\\\b(0[oO][0-7]+)\"},{begin:e.C_NUMBER_RE}],relevance:0},{begin:\"(\"+e.RE_STARTERS_RE+\"|\\\\b(case|return|throw)\\\\b)\\\\s*\",keywords:\"return throw case\",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.REGEXP_MODE,{begin:/</,end:/>\\s*[);\\]]/,relevance:0,subLanguage:\"xml\"}],relevance:0},{className:\"function\",beginKeywords:\"function\",end:/\\{/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{className:\"params\",begin:/\\(/,end:/\\)/,excludeBegin:!0,excludeEnd:!0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]}],illegal:/\\[|%/},{begin:/\\$[(.]/},{begin:\"\\\\.\"+e.IDENT_RE,relevance:0},{beginKeywords:\"import\",end:\"[;$]\",keywords:\"import from as\",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},{className:\"class\",beginKeywords:\"class\",end:/[{;=]/,excludeEnd:!0,illegal:/[:\"\\[\\]]/,contains:[{beginKeywords:\"extends\"},e.UNDERSCORE_TITLE_MODE]}],illegal:/#/}}),e.registerLanguage(\"json\",function(e){var t={literal:\"true false null\"},n=[e.QUOTE_STRING_MODE,e.C_NUMBER_MODE],i={className:\"value\",end:\",\",endsWithParent:!0,excludeEnd:!0,contains:n,keywords:t},r={begin:\"{\",end:\"}\",contains:[{className:\"attribute\",begin:'\\\\s*\"',end:'\"\\\\s*:\\\\s*',excludeBegin:!0,excludeEnd:!0,contains:[e.BACKSLASH_ESCAPE],illegal:\"\\\\n\",starts:i}],illegal:\"\\\\S\"},a={begin:\"\\\\[\",end:\"\\\\]\",contains:[e.inherit(i,{className:null})],illegal:\"\\\\S\"};return n.splice(n.length,0,r,a),{contains:n,keywords:t,illegal:\"\\\\S\"}}),e.registerLanguage(\"julia\",function(e){var t={keyword:\"in abstract baremodule begin bitstype break catch ccall const continue do else elseif end export finally for function global if immutable import importall let local macro module quote return try type typealias using while\",literal:\"true false ANY ARGS CPU_CORES C_NULL DL_LOAD_PATH DevNull ENDIAN_BOM ENV I|0 Inf Inf16 Inf32 InsertionSort JULIA_HOME LOAD_PATH MS_ASYNC MS_INVALIDATE MS_SYNC MergeSort NaN NaN16 NaN32 OS_NAME QuickSort RTLD_DEEPBIND RTLD_FIRST RTLD_GLOBAL RTLD_LAZY RTLD_LOCAL RTLD_NODELETE RTLD_NOLOAD RTLD_NOW RoundDown RoundFromZero RoundNearest RoundToZero RoundUp STDERR STDIN STDOUT VERSION WORD_SIZE catalan cglobal e|0 eu|0 eulergamma golden im nothing pi γ π φ\",built_in:\"ASCIIString AbstractArray AbstractRNG AbstractSparseArray Any ArgumentError Array Associative Base64Pipe Bidiagonal BigFloat BigInt BitArray BitMatrix BitVector Bool BoundsError Box CFILE Cchar Cdouble Cfloat Char CharString Cint Clong Clonglong ClusterManager Cmd Coff_t Colon Complex Complex128 Complex32 Complex64 Condition Cptrdiff_t Cshort Csize_t Cssize_t Cuchar Cuint Culong Culonglong Cushort Cwchar_t DArray DataType DenseArray Diagonal Dict DimensionMismatch DirectIndexString Display DivideError DomainError EOFError EachLine Enumerate ErrorException Exception Expr Factorization FileMonitor FileOffset Filter Float16 Float32 Float64 FloatRange FloatingPoint Function GetfieldNode GotoNode Hermitian IO IOBuffer IOStream IPv4 IPv6 InexactError Int Int128 Int16 Int32 Int64 Int8 IntSet Integer InterruptException IntrinsicFunction KeyError LabelNode LambdaStaticData LineNumberNode LoadError LocalProcess MIME MathConst MemoryError MersenneTwister Method MethodError MethodTable Module NTuple NewvarNode Nothing Number ObjectIdDict OrdinalRange OverflowError ParseError PollingFileWatcher ProcessExitedException ProcessGroup Ptr QuoteNode Range Range1 Ranges Rational RawFD Real Regex RegexMatch RemoteRef RepString RevString RopeString RoundingMode Set SharedArray Signed SparseMatrixCSC StackOverflowError Stat StatStruct StepRange String SubArray SubString SymTridiagonal Symbol SymbolNode Symmetric SystemError Task TextDisplay Timer TmStruct TopNode Triangular Tridiagonal Type TypeConstructor TypeError TypeName TypeVar UTF16String UTF32String UTF8String UdpSocket Uint Uint128 Uint16 Uint32 Uint64 Uint8 UndefRefError UndefVarError UniformScaling UnionType UnitRange Unsigned Vararg VersionNumber WString WeakKeyDict WeakRef Woodbury Zip\"},n=\"[A-Za-z_\\\\u00A1-\\\\uFFFF][A-Za-z_0-9\\\\u00A1-\\\\uFFFF]*\",i={lexemes:n,keywords:t},r={className:\"type-annotation\",begin:/::/},a={className:\"subtype\",begin:/<:/},o={className:\"number\",begin:/(\\b0x[\\d_]*(\\.[\\d_]*)?|0x\\.\\d[\\d_]*)p[-+]?\\d+|\\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\\b\\d[\\d_]*(\\.[\\d_]*)?|\\.\\d[\\d_]*)([eEfF][-+]?\\d+)?/,relevance:0},s={className:\"char\",begin:/'(.|\\\\[xXuU][a-zA-Z0-9]+)'/},l={className:\"subst\",begin:/\\$\\(/,end:/\\)/,keywords:t},c={className:\"variable\",begin:\"\\\\$\"+n},d={className:\"string\",contains:[e.BACKSLASH_ESCAPE,l,c],variants:[{begin:/\\w*\"/,end:/\"\\w*/},{begin:/\\w*\"\"\"/,end:/\"\"\"\\w*/}]},u={className:\"string\",contains:[e.BACKSLASH_ESCAPE,l,c],begin:\"`\",end:\"`\"},p={className:\"macrocall\",begin:\"@\"+n},m={className:\"comment\",variants:[{begin:\"#=\",end:\"=#\",relevance:10},{begin:\"#\",end:\"$\"}]};return i.contains=[o,s,r,a,d,u,p,m,e.HASH_COMMENT_MODE],l.contains=i.contains,i}),e.registerLanguage(\"kotlin\",function(e){var t=\"val var get set class trait object public open private protected final enum if else do while for when break continue throw try catch finally import package is as in return fun override default companion reified inline volatile transient native\";return{keywords:{typename:\"Byte Short Char Int Long Boolean Float Double Void Unit Nothing\",literal:\"true false null\",keyword:t},contains:[e.COMMENT(\"/\\\\*\\\\*\",\"\\\\*/\",{relevance:0,contains:[{className:\"doctag\",begin:\"@[A-Za-z]+\"}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"type\",begin:/</,end:/>/,returnBegin:!0,excludeEnd:!1,relevance:0},{className:\"function\",beginKeywords:\"fun\",end:\"[(]|$\",returnBegin:!0,excludeEnd:!0,keywords:t,illegal:/fun\\s+(<.*>)?[^\\s\\(]+(\\s+[^\\s\\(]+)\\s*=/,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+\"\\\\s*\\\\(\",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:\"type\",begin:/</,end:/>/,keywords:\"reified\",relevance:0},{className:\"params\",begin:/\\(/,end:/\\)/,keywords:t,relevance:0,illegal:/\\([^\\(,\\s:]+,/,contains:[{className:\"typename\",begin:/:\\s*/,end:/\\s*[=\\)]/,excludeBegin:!0,returnEnd:!0,relevance:0}]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:\"class\",beginKeywords:\"class trait\",end:/[:\\{(]|$/,excludeEnd:!0,illegal:\"extends implements\",contains:[e.UNDERSCORE_TITLE_MODE,{className:\"type\",begin:/</,end:/>/,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:\"typename\",begin:/[,:]\\s*/,end:/[<\\(,]|$/,excludeBegin:!0,returnEnd:!0}]},{className:\"variable\",beginKeywords:\"var val\",end:/\\s*[=:$]/,excludeEnd:!0},e.QUOTE_STRING_MODE,{className:\"shebang\",begin:\"^#!/usr/bin/env\",end:\"$\",illegal:\"\\n\"},e.C_NUMBER_MODE]}}),e.registerLanguage(\"lasso\",function(e){var t=\"[a-zA-Z_][a-zA-Z0-9_.]*\",n=\"<\\\\?(lasso(script)?|=)\",i=\"\\\\]|\\\\?>\",r={literal:\"true false none minimal full all void bw nbw ew new cn ncn lt lte gt gte eq neq rx nrx ft\",built_in:\"array date decimal duration integer map pair string tag xml null boolean bytes keyword list locale queue set stack staticarray local var variable global data self inherited currentcapture givenblock\",keyword:\"error_code error_msg error_pop error_push error_reset cache database_names database_schemanames database_tablenames define_tag define_type email_batch encode_set html_comment handle handle_error header if inline iterate ljax_target link link_currentaction link_currentgroup link_currentrecord link_detail link_firstgroup link_firstrecord link_lastgroup link_lastrecord link_nextgroup link_nextrecord link_prevgroup link_prevrecord log loop namespace_using output_none portal private protect records referer referrer repeating resultset rows search_args search_arguments select sort_args sort_arguments thread_atomic value_list while abort case else if_empty if_false if_null if_true loop_abort loop_continue loop_count params params_up return return_value run_children soap_definetag soap_lastrequest soap_lastresponse tag_name ascending average by define descending do equals frozen group handle_failure import in into join let match max min on order parent protected provide public require returnhome skip split_thread sum take thread to trait type where with yield yieldhome\"},a=e.COMMENT(\"<!--\",\"-->\",{relevance:0}),o={className:\"preprocessor\",begin:\"\\\\[noprocess\\\\]\",starts:{className:\"markup\",end:\"\\\\[/noprocess\\\\]\",returnEnd:!0,contains:[a]}},s={className:\"preprocessor\",begin:\"\\\\[/noprocess|\"+n},l={className:\"variable\",begin:\"'\"+t+\"'\"},c=[e.COMMENT(\"/\\\\*\\\\*!\",\"\\\\*/\"),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(e.C_NUMBER_MODE,{begin:e.C_NUMBER_RE+\"|(infinity|nan)\\\\b\"}),e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:\"string\",begin:\"`\",end:\"`\"},{className:\"variable\",variants:[{begin:\"[#$]\"+t},{begin:\"#\",end:\"\\\\d+\",illegal:\"\\\\W\"}]},{className:\"tag\",begin:\"::\\\\s*\",end:t,illegal:\"\\\\W\"},{className:\"attribute\",variants:[{begin:\"-(?!infinity)\"+e.UNDERSCORE_IDENT_RE,relevance:0},{begin:\"(\\\\.\\\\.\\\\.)\"}]},{className:\"subst\",variants:[{begin:\"->\\\\s*\",contains:[l]},{begin:\"->|\\\\\\\\|&&?|\\\\|\\\\||!(?!=|>)|(and|or|not)\\\\b\",relevance:0}]},{className:\"built_in\",begin:\"\\\\.\\\\.?\\\\s*\",relevance:0,contains:[l]},{className:\"class\",beginKeywords:\"define\",returnEnd:!0,end:\"\\\\(|=>\",contains:[e.inherit(e.TITLE_MODE,{begin:e.UNDERSCORE_IDENT_RE+\"(=(?!>))?\"})]}];return{aliases:[\"ls\",\"lassoscript\"],case_insensitive:!0,lexemes:t+\"|&[lg]t;\",keywords:r,contains:[{className:\"preprocessor\",begin:i,relevance:0,starts:{className:\"markup\",end:\"\\\\[|\"+n,returnEnd:!0,relevance:0,contains:[a]}},o,s,{className:\"preprocessor\",begin:\"\\\\[no_square_brackets\",starts:{end:\"\\\\[/no_square_brackets\\\\]\",lexemes:t+\"|&[lg]t;\",keywords:r,contains:[{className:\"preprocessor\",begin:i,relevance:0,starts:{className:\"markup\",end:\"\\\\[noprocess\\\\]|\"+n,returnEnd:!0,contains:[a]}},o,s].concat(c)}},{className:\"preprocessor\",begin:\"\\\\[\",relevance:0},{className:\"shebang\",begin:\"^#!.+lasso9\\\\b\",relevance:10}].concat(c)}}),e.registerLanguage(\"less\",function(e){var t=\"[\\\\w-]+\",n=\"(\"+t+\"|@{\"+t+\"})\",i=[],r=[],a=function(e){return{className:\"string\",begin:\"~?\"+e+\".*?\"+e}},o=function(e,t,n){return{className:e,begin:t,relevance:n}},s=function(t,n,i){return e.inherit({className:t,begin:n+\"\\\\(\",end:\"\\\\(\",returnBegin:!0,excludeEnd:!0,relevance:0},i)},l={begin:\"\\\\(\",end:\"\\\\)\",contains:r,relevance:0};r.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a(\"'\"),a('\"'),e.CSS_NUMBER_MODE,o(\"hexcolor\",\"#[0-9A-Fa-f]+\\\\b\"),s(\"function\",\"(url|data-uri)\",{starts:{className:\"string\",end:\"[\\\\)\\\\n]\",excludeEnd:!0}}),s(\"function\",t),l,o(\"variable\",\"@@?\"+t,10),o(\"variable\",\"@{\"+t+\"}\"),o(\"built_in\",\"~?`[^`]*?`\"),{className:\"attribute\",begin:t+\"\\\\s*:\",end:\":\",returnBegin:!0,excludeEnd:!0});var c=r.concat({begin:\"{\",end:\"}\",contains:i}),d={beginKeywords:\"when\",endsWithParent:!0,contains:[{beginKeywords:\"and not\"}].concat(r)},u={className:\"attribute\",begin:n,end:\":\",excludeEnd:!0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:/\\S/,starts:{end:\"[;}]\",returnEnd:!0,contains:r,illegal:\"[<=$]\"}},p={className:\"at_rule\",begin:\"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\\\b\",starts:{end:\"[;{}]\",returnEnd:!0,contains:r,relevance:0}},m={className:\"variable\",variants:[{begin:\"@\"+t+\"\\\\s*:\",relevance:15},{begin:\"@\"+t}],starts:{end:\"[;}]\",returnEnd:!0,contains:c}},g={variants:[{begin:\"[\\\\.#:&\\\\[]\",end:\"[;{}]\"},{begin:n+\"[^;]*{\",end:\"{\"}],returnBegin:!0,returnEnd:!0,illegal:\"[<='$\\\"]\",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,d,o(\"keyword\",\"all\\\\b\"),o(\"variable\",\"@{\"+t+\"}\"),o(\"tag\",n+\"%?\",0),o(\"id\",\"#\"+n),o(\"class\",\"\\\\.\"+n,0),o(\"keyword\",\"&\",0),s(\"pseudo\",\":not\"),s(\"keyword\",\":extend\"),o(\"pseudo\",\"::?\"+n),{className:\"attr_selector\",begin:\"\\\\[\",end:\"\\\\]\"},{begin:\"\\\\(\",end:\"\\\\)\",contains:c},{begin:\"!important\"}]};return i.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,p,m,g,u),{case_insensitive:!0,illegal:\"[=>'/<($\\\"]\",contains:i}}),e.registerLanguage(\"lisp\",function(e){var t=\"[a-zA-Z_\\\\-\\\\+\\\\*\\\\/\\\\<\\\\=\\\\>\\\\&\\\\#][a-zA-Z0-9_\\\\-\\\\+\\\\*\\\\/\\\\<\\\\=\\\\>\\\\&\\\\#!]*\",n=\"\\\\|[^]*?\\\\|\",i=\"(\\\\-|\\\\+)?\\\\d+(\\\\.\\\\d+|\\\\/\\\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\\\+|\\\\-)?\\\\d+)?\",r={className:\"shebang\",begin:\"^#!\",end:\"$\"},a={className:\"literal\",begin:\"\\\\b(t{1}|nil)\\\\b\"},o={className:\"number\",variants:[{begin:i,relevance:0},{begin:\"#(b|B)[0-1]+(/[0-1]+)?\"},{begin:\"#(o|O)[0-7]+(/[0-7]+)?\"},{begin:\"#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?\"},{begin:\"#(c|C)\\\\(\"+i+\" +\"+i,end:\"\\\\)\"}]},s=e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),l=e.COMMENT(\";\",\"$\",{relevance:0}),c={className:\"variable\",begin:\"\\\\*\",end:\"\\\\*\"},d={className:\"keyword\",begin:\"[:&]\"+t},u={begin:t,relevance:0},p={begin:n},m={begin:\"\\\\(\",end:\"\\\\)\",contains:[\"self\",a,s,o,u]},g={className:\"quoted\",contains:[o,s,c,d,m,u],variants:[{begin:\"['`]\\\\(\",end:\"\\\\)\"},{begin:\"\\\\(quote \",end:\"\\\\)\",keywords:\"quote\"},{begin:\"'\"+n}]},h={className:\"quoted\",variants:[{begin:\"'\"+t},{begin:\"#'\"+t+\"(::\"+t+\")*\"}]},f={className:\"list\",begin:\"\\\\(\\\\s*\",end:\"\\\\)\"},_={endsWithParent:!0,relevance:0};return f.contains=[{className:\"keyword\",variants:[{begin:t},{begin:n}]},_],_.contains=[g,h,f,a,o,s,l,c,d,p,u],{illegal:/\\S/,contains:[o,r,a,s,l,g,h,f,u]}}),e.registerLanguage(\"livecodeserver\",function(e){var t={className:\"variable\",begin:\"\\\\b[gtps][A-Z]+[A-Za-z0-9_\\\\-]*\\\\b|\\\\$_[A-Z]+\",relevance:0},n=[e.C_BLOCK_COMMENT_MODE,e.HASH_COMMENT_MODE,e.COMMENT(\"--\",\"$\"),e.COMMENT(\"[^:]//\",\"$\")],i=e.inherit(e.TITLE_MODE,{variants:[{begin:\"\\\\b_*rig[A-Z]+[A-Za-z0-9_\\\\-]*\"},{begin:\"\\\\b_[a-z0-9\\\\-]+\"}]}),r=e.inherit(e.TITLE_MODE,{begin:\"\\\\b([A-Za-z0-9_\\\\-]+)\\\\b\"});return{case_insensitive:!1,keywords:{keyword:\"$_COOKIE $_FILES $_GET $_GET_BINARY $_GET_RAW $_POST $_POST_BINARY $_POST_RAW $_SESSION $_SERVER codepoint codepoints segment segments codeunit codeunits sentence sentences trueWord trueWords paragraph after byte bytes english the until http forever descending using line real8 with seventh for stdout finally element word words fourth before black ninth sixth characters chars stderr uInt1 uInt1s uInt2 uInt2s stdin string lines relative rel any fifth items from middle mid at else of catch then third it file milliseconds seconds second secs sec int1 int1s int4 int4s internet int2 int2s normal text item last long detailed effective uInt4 uInt4s repeat end repeat URL in try into switch to words https token binfile each tenth as ticks tick system real4 by dateItems without char character ascending eighth whole dateTime numeric short first ftp integer abbreviated abbr abbrev private case while if\",\nconstant:\"SIX TEN FORMFEED NINE ZERO NONE SPACE FOUR FALSE COLON CRLF PI COMMA ENDOFFILE EOF EIGHT FIVE QUOTE EMPTY ONE TRUE RETURN CR LINEFEED RIGHT BACKSLASH NULL SEVEN TAB THREE TWO six ten formfeed nine zero none space four false colon crlf pi comma endoffile eof eight five quote empty one true return cr linefeed right backslash null seven tab three two RIVERSION RISTATE FILE_READ_MODE FILE_WRITE_MODE FILE_WRITE_MODE DIR_WRITE_MODE FILE_READ_UMASK FILE_WRITE_UMASK DIR_READ_UMASK DIR_WRITE_UMASK\",operator:\"div mod wrap and or bitAnd bitNot bitOr bitXor among not in a an within contains ends with begins the keys of keys\",built_in:\"put abs acos aliasReference annuity arrayDecode arrayEncode asin atan atan2 average avg avgDev base64Decode base64Encode baseConvert binaryDecode binaryEncode byteOffset byteToNum cachedURL cachedURLs charToNum cipherNames codepointOffset codepointProperty codepointToNum codeunitOffset commandNames compound compress constantNames cos date dateFormat decompress directories diskSpace DNSServers exp exp1 exp2 exp10 extents files flushEvents folders format functionNames geometricMean global globals hasMemory harmonicMean hostAddress hostAddressToName hostName hostNameToAddress isNumber ISOToMac itemOffset keys len length libURLErrorData libUrlFormData libURLftpCommand libURLLastHTTPHeaders libURLLastRHHeaders libUrlMultipartFormAddPart libUrlMultipartFormData libURLVersion lineOffset ln ln1 localNames log log2 log10 longFilePath lower macToISO matchChunk matchText matrixMultiply max md5Digest median merge millisec millisecs millisecond milliseconds min monthNames nativeCharToNum normalizeText num number numToByte numToChar numToCodepoint numToNativeChar offset open openfiles openProcesses openProcessIDs openSockets paragraphOffset paramCount param params peerAddress pendingMessages platform popStdDev populationStandardDeviation populationVariance popVariance processID random randomBytes replaceText result revCreateXMLTree revCreateXMLTreeFromFile revCurrentRecord revCurrentRecordIsFirst revCurrentRecordIsLast revDatabaseColumnCount revDatabaseColumnIsNull revDatabaseColumnLengths revDatabaseColumnNames revDatabaseColumnNamed revDatabaseColumnNumbered revDatabaseColumnTypes revDatabaseConnectResult revDatabaseCursors revDatabaseID revDatabaseTableNames revDatabaseType revDataFromQuery revdb_closeCursor revdb_columnbynumber revdb_columncount revdb_columnisnull revdb_columnlengths revdb_columnnames revdb_columntypes revdb_commit revdb_connect revdb_connections revdb_connectionerr revdb_currentrecord revdb_cursorconnection revdb_cursorerr revdb_cursors revdb_dbtype revdb_disconnect revdb_execute revdb_iseof revdb_isbof revdb_movefirst revdb_movelast revdb_movenext revdb_moveprev revdb_query revdb_querylist revdb_recordcount revdb_rollback revdb_tablenames revGetDatabaseDriverPath revNumberOfRecords revOpenDatabase revOpenDatabases revQueryDatabase revQueryDatabaseBlob revQueryResult revQueryIsAtStart revQueryIsAtEnd revUnixFromMacPath revXMLAttribute revXMLAttributes revXMLAttributeValues revXMLChildContents revXMLChildNames revXMLCreateTreeFromFileWithNamespaces revXMLCreateTreeWithNamespaces revXMLDataFromXPathQuery revXMLEvaluateXPath revXMLFirstChild revXMLMatchingNode revXMLNextSibling revXMLNodeContents revXMLNumberOfChildren revXMLParent revXMLPreviousSibling revXMLRootNode revXMLRPC_CreateRequest revXMLRPC_Documents revXMLRPC_Error revXMLRPC_GetHost revXMLRPC_GetMethod revXMLRPC_GetParam revXMLText revXMLRPC_Execute revXMLRPC_GetParamCount revXMLRPC_GetParamNode revXMLRPC_GetParamType revXMLRPC_GetPath revXMLRPC_GetPort revXMLRPC_GetProtocol revXMLRPC_GetRequest revXMLRPC_GetResponse revXMLRPC_GetSocket revXMLTree revXMLTrees revXMLValidateDTD revZipDescribeItem revZipEnumerateItems revZipOpenArchives round sampVariance sec secs seconds sentenceOffset sha1Digest shell shortFilePath sin specialFolderPath sqrt standardDeviation statRound stdDev sum sysError systemVersion tan tempName textDecode textEncode tick ticks time to tokenOffset toLower toUpper transpose truewordOffset trunc uniDecode uniEncode upper URLDecode URLEncode URLStatus uuid value variableNames variance version waitDepth weekdayNames wordOffset xsltApplyStylesheet xsltApplyStylesheetFromFile xsltLoadStylesheet xsltLoadStylesheetFromFile add breakpoint cancel clear local variable file word line folder directory URL close socket process combine constant convert create new alias folder directory decrypt delete variable word line folder directory URL dispatch divide do encrypt filter get include intersect kill libURLDownloadToFile libURLFollowHttpRedirects libURLftpUpload libURLftpUploadFile libURLresetAll libUrlSetAuthCallback libURLSetCustomHTTPHeaders libUrlSetExpect100 libURLSetFTPListCommand libURLSetFTPMode libURLSetFTPStopTime libURLSetStatusCallback load multiply socket prepare process post seek rel relative read from process rename replace require resetAll resolve revAddXMLNode revAppendXML revCloseCursor revCloseDatabase revCommitDatabase revCopyFile revCopyFolder revCopyXMLNode revDeleteFolder revDeleteXMLNode revDeleteAllXMLTrees revDeleteXMLTree revExecuteSQL revGoURL revInsertXMLNode revMoveFolder revMoveToFirstRecord revMoveToLastRecord revMoveToNextRecord revMoveToPreviousRecord revMoveToRecord revMoveXMLNode revPutIntoXMLNode revRollBackDatabase revSetDatabaseDriverPath revSetXMLAttribute revXMLRPC_AddParam revXMLRPC_DeleteAllDocuments revXMLAddDTD revXMLRPC_Free revXMLRPC_FreeAll revXMLRPC_DeleteDocument revXMLRPC_DeleteParam revXMLRPC_SetHost revXMLRPC_SetMethod revXMLRPC_SetPort revXMLRPC_SetProtocol revXMLRPC_SetSocket revZipAddItemWithData revZipAddItemWithFile revZipAddUncompressedItemWithData revZipAddUncompressedItemWithFile revZipCancel revZipCloseArchive revZipDeleteItem revZipExtractItemToFile revZipExtractItemToVariable revZipSetProgressCallback revZipRenameItem revZipReplaceItemWithData revZipReplaceItemWithFile revZipOpenArchive send set sort split start stop subtract union unload wait write\"},contains:[t,{className:\"keyword\",begin:\"\\\\bend\\\\sif\\\\b\"},{className:\"function\",beginKeywords:\"function\",end:\"$\",contains:[t,r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE,i]},{className:\"function\",begin:\"\\\\bend\\\\s+\",end:\"$\",keywords:\"end\",contains:[r,i]},{className:\"command\",beginKeywords:\"command on\",end:\"$\",contains:[t,r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE,i]},{className:\"preprocessor\",variants:[{begin:\"<\\\\?(rev|lc|livecode)\",relevance:10},{begin:\"<\\\\?\"},{begin:\"\\\\?>\"}]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE,i].concat(n),illegal:\";$|^\\\\[|^=\"}}),e.registerLanguage(\"livescript\",function(e){var t={keyword:\"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger case default function var with then unless until loop of by when and or is isnt not it that otherwise from to til fallthrough super case default function var void const let enum export import native __hasProp __extends __slice __bind __indexOf\",literal:\"true false null undefined yes no on off it that void\",built_in:\"npm require console print module global window document\"},n=\"[A-Za-z$_](?:-[0-9A-Za-z$_]|[0-9A-Za-z$_])*\",i=e.inherit(e.TITLE_MODE,{begin:n}),r={className:\"subst\",begin:/#\\{/,end:/}/,keywords:t},a={className:\"subst\",begin:/#[A-Za-z$_]/,end:/(?:\\-[0-9A-Za-z$_]|[0-9A-Za-z$_])*/,keywords:t},o=[e.BINARY_NUMBER_MODE,{className:\"number\",begin:\"(\\\\b0[xX][a-fA-F0-9_]+)|(\\\\b\\\\d(\\\\d|_\\\\d)*(\\\\.(\\\\d(\\\\d|_\\\\d)*)?)?(_*[eE]([-+]\\\\d(_\\\\d|\\\\d)*)?)?[_a-z]*)\",relevance:0,starts:{end:\"(\\\\s*/)?\",relevance:0}},{className:\"string\",variants:[{begin:/'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/,contains:[e.BACKSLASH_ESCAPE]},{begin:/\"\"\"/,end:/\"\"\"/,contains:[e.BACKSLASH_ESCAPE,r,a]},{begin:/\"/,end:/\"/,contains:[e.BACKSLASH_ESCAPE,r,a]},{begin:/\\\\/,end:/(\\s|$)/,excludeEnd:!0}]},{className:\"pi\",variants:[{begin:\"//\",end:\"//[gim]*\",contains:[r,e.HASH_COMMENT_MODE]},{begin:/\\/(?![ *])(\\\\\\/|.)*?\\/[gim]*(?=\\W|$)/}]},{className:\"property\",begin:\"@\"+n},{begin:\"``\",end:\"``\",excludeBegin:!0,excludeEnd:!0,subLanguage:\"javascript\"}];r.contains=o;var s={className:\"params\",begin:\"\\\\(\",returnBegin:!0,contains:[{begin:/\\(/,end:/\\)/,keywords:t,contains:[\"self\"].concat(o)}]};return{aliases:[\"ls\"],keywords:t,illegal:/\\/\\*/,contains:o.concat([e.COMMENT(\"\\\\/\\\\*\",\"\\\\*\\\\/\"),e.HASH_COMMENT_MODE,{className:\"function\",contains:[i,s],returnBegin:!0,variants:[{begin:\"(\"+n+\"\\\\s*(?:=|:=)\\\\s*)?(\\\\(.*\\\\))?\\\\s*\\\\B\\\\->\\\\*?\",end:\"\\\\->\\\\*?\"},{begin:\"(\"+n+\"\\\\s*(?:=|:=)\\\\s*)?!?(\\\\(.*\\\\))?\\\\s*\\\\B[-~]{1,2}>\\\\*?\",end:\"[-~]{1,2}>\\\\*?\"},{begin:\"(\"+n+\"\\\\s*(?:=|:=)\\\\s*)?(\\\\(.*\\\\))?\\\\s*\\\\B!?[-~]{1,2}>\\\\*?\",end:\"!?[-~]{1,2}>\\\\*?\"}]},{className:\"class\",beginKeywords:\"class\",end:\"$\",illegal:/[:=\"\\[\\]]/,contains:[{beginKeywords:\"extends\",endsWithParent:!0,illegal:/[:=\"\\[\\]]/,contains:[i]},i]},{className:\"attribute\",begin:n+\":\",end:\":\",returnBegin:!0,returnEnd:!0,relevance:0}])}}),e.registerLanguage(\"lua\",function(e){var t=\"\\\\[=*\\\\[\",n=\"\\\\]=*\\\\]\",i={begin:t,end:n,contains:[\"self\"]},r=[e.COMMENT(\"--(?!\"+t+\")\",\"$\"),e.COMMENT(\"--\"+t,n,{contains:[i],relevance:10})];return{lexemes:e.UNDERSCORE_IDENT_RE,keywords:{keyword:\"and break do else elseif end false for if in local nil not or repeat return then true until while\",built_in:\"_G _VERSION assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall coroutine debug io math os package string table\"},contains:r.concat([{className:\"function\",beginKeywords:\"function\",end:\"\\\\)\",contains:[e.inherit(e.TITLE_MODE,{begin:\"([_a-zA-Z]\\\\w*\\\\.)*([_a-zA-Z]\\\\w*:)?[_a-zA-Z]\\\\w*\"}),{className:\"params\",begin:\"\\\\(\",endsWithParent:!0,contains:r}].concat(r)},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:\"string\",begin:t,end:n,contains:[i],relevance:5}])}}),e.registerLanguage(\"makefile\",function(e){var t={className:\"variable\",begin:/\\$\\(/,end:/\\)/,contains:[e.BACKSLASH_ESCAPE]};return{aliases:[\"mk\",\"mak\"],contains:[e.HASH_COMMENT_MODE,{begin:/^\\w+\\s*\\W*=/,returnBegin:!0,relevance:0,starts:{className:\"constant\",end:/\\s*\\W*=/,excludeEnd:!0,starts:{end:/$/,relevance:0,contains:[t]}}},{className:\"title\",begin:/^[\\w]+:\\s*$/},{className:\"phony\",begin:/^\\.PHONY:/,end:/$/,keywords:\".PHONY\",lexemes:/[\\.\\w]+/},{begin:/^\\t+/,end:/$/,relevance:0,contains:[e.QUOTE_STRING_MODE,t]}]}}),e.registerLanguage(\"mathematica\",function(e){return{aliases:[\"mma\"],lexemes:\"(\\\\$|\\\\b)\"+e.IDENT_RE+\"\\\\b\",keywords:\"AbelianGroup Abort AbortKernels AbortProtect Above Abs Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Active ActiveItem ActiveStyle AcyclicGraphQ AddOnHelpPath AddTo AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AffineTransform After AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowedDimensions AllowGroupClose AllowInlineCells AllowKernelInitialization AllowReverseGroupClose AllowScriptLevelChange AlphaChannel AlternatingGroup AlternativeHypothesis Alternatives AmbientLight Analytic AnchoredSearch And AndersonDarlingTest AngerJ AngleBracket AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotation Annuity AnnuityDue Antialiasing Antisymmetric Apart ApartSquareFree Appearance AppearanceElements AppellF1 Append AppendTo Apply ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess ARProcess Array ArrayComponents ArrayDepth ArrayFlatten ArrayPad ArrayPlot ArrayQ ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads AspectRatio AspectRatioFixed Assert Assuming Assumptions AstronomicalData Asynchronous AsynchronousTaskObject AsynchronousTasks AtomQ Attributes AugmentedSymmetricPolynomial AutoAction AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords Axes AxesEdge AxesLabel AxesOrigin AxesStyle Axis BabyMonsterGroupB Back Background BackgroundTasksSettings Backslash Backsubstitution Backward Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseForm Baseline BaselinePosition BaseStyle BatesDistribution BattleLemarieWavelet Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized BetweennessCentrality BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms Booleans BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryStyle Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BubbleChart BubbleChart3D BubbleScale BubbleSizes BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteCount ByteOrdering C CachedValue CacheGraphics CalendarData CalendarType CallPacket CanberraDistance Cancel CancelButton CandlestickChart Cap CapForm CapitalDifferentialD CardinalBSplineBasis CarmichaelLambda Cases Cashflow Casoratian Catalan CatalanNumber Catch CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterDot CentralMoment CentralMomentGeneratingFunction CForm ChampernowneNumber ChanVeseBinarize Character CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop Circle CircleBox CircleDot CircleMinus CirclePlus CircleTimes CirculantGraph CityData Clear ClearAll ClearAttributes ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent ClusteringComponents CMYKColor Coarse Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorCombine ColorConvert ColorData ColorDataFunction ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorSpace Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CommonDefaultFormatTypes Commonest CommonestFilter CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledFunction Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComponentMeasurements ComponentwiseContextMenu Compose ComposeList ComposeSeries Composition CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath Congruent Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphQ ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray Constants ConstrainedMax ConstrainedMin ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFilename ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean Control ControlActive ControlAlignment ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateDialog CreateDirectory CreateDocument CreateIntermediateDirectories CreatePalette CreatePalettePacket CreateScheduledTask CreateTemporary CreateWindow CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossingDetect CrossMatrix Csc Csch CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrentImage CurrentlySpeakingPacket CurrentValue CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecomposition D DagumDistribution DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DataCompression DataDistribution DataRange DataReversed Date DateDelimiters DateDifference DateFunction DateList DateListLogPlot DateListPlot DatePattern DatePlus DateRange DateString DateTicksFormat DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayMatchQ DayName DayPlus DayRange DayRound DeBruijnGraph Debug DebugTag Decimal DeclareKnownSymbols DeclarePackage Decompose Decrement DedekindEta Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic Deinitialization Del Deletable Delete DeleteBorderComponents DeleteCases DeleteContents DeleteDirectory DeleteDuplicates DeleteFile DeleteSmallComponents DeleteWithContents DeletionWarning Delimiter DelimiterFlashTime DelimiterMatching Delimiters Denominator DensityGraphics DensityHistogram DensityPlot DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DescriptorStateSpace DesignMatrix Det DGaussianWavelet DiacriticalPositioning Diagonal DiagonalMatrix Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DifferenceDelta DifferenceOrder DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralGroup Dilation Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletCharacter DirichletConvolve DirichletDistribution DirichletL DirichletTransform DirichletWindow DisableConsolePrintPacket DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform DiscreteWaveletTransform Discriminant Disjunction Disk DiskBox DiskMatrix Dispatch DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentNotebook DominantColors DOSTextFormat Dot DotDashed DotEqual Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DSolve Dt DualLinearProgramming DualSystemsModel DumpGet DumpSave DuplicateFreeQ Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptions E EccentricityCentrality EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeCost EdgeCount EdgeCoverQ EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData Eliminate EliminationOrder EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EnableConsolePrintPacket Enabled Encode End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfFile EndOfLine EndOfString EndPackage EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entropy EntropyFilter Environment Epilog Equal EqualColumns EqualRows EqualTilde EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerE EulerGamma EulerianGraphQ EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluationCell EvaluationCompletionAction EvaluationElements EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpToTrig ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalCall ExternalDataCharacterEncoding Extract ExtractArchive ExtremeValueDistribution FaceForm FaceGrids FaceGridsStyle Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail FailureDistribution False FARIMAProcess FEDisableConsolePrintPacket FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket Fibonacci FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileDate FileExistsQ FileExtension FileFormat FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileType FilledCurve FilledCurveBox Filling FillingStyle FillingTransform FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindArgMax FindArgMin FindClique FindClusters FindCurvePath FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEulerianCycle FindFaces FindFile FindFit FindGeneratingFunction FindGeoLocation FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMaximum FindMaximumFlow FindMaxValue FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindPermutation FindPostmanTour FindProcessParameters FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindThreshold FindVertexCover FindVertexCut Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstPassageTimeDistribution FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FittedModel FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlatTopWindow FlipView Floor FlushPrintOutputPacket Fold FoldList Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrequencySamplingFilterKernel FresnelC FresnelS Friday FrobeniusNumber FrobeniusSolve FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullOptions FullSimplify Function FunctionExpand FunctionInterpolation FunctionSpace FussellVeselyImportance GaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins Gamma GammaDistribution GammaRegularized GapPenalty Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateConditions GeneratedCell GeneratedParameters GeneratingFunction Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDistance GeoGridPosition GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoPosition GeoPositionENU GeoPositionXYZ GeoProjectionData GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter Graph GraphAssortativity GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel GreatCircleDistance Greater GreaterEqual GreaterEqualLess GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterTilde Green Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain Gudermannian GumbelDistribution HaarWavelet HadamardMatrix HalfNormalDistribution HamiltonianGraphQ HammingDistance HammingWindow HankelH1 HankelH2 HankelMatrix HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash HashTable Haversine HazardFunction Head HeadCompose Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenSurface HighlightGraph HighlightImage HighpassFilter HigmanSimsGroupHS HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HitMissTransform HITSCentrality HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HotellingTSquareDistribution HoytDistribution HTMLSave Hue HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestData I Identity IdentityMatrix If IgnoreCase Im Image Image3D Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageAspectRatio ImageAssemble ImageCache ImageCacheValid ImageCapture ImageChannels ImageClip ImageColorSpace ImageCompose ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDataPacket ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDistance ImageEffect ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageForestingComponents ImageForwardTransformation ImageHistogram ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarkers ImageMeasurements ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImageQ ImageRangeCache ImageReflect ImageRegion ImageResize ImageResolution ImageRotate ImageRotated ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions Implies Import ImportAutoReplacements ImportString ImprovementImportance In IncidenceGraph IncidenceList IncidenceMatrix IncludeConstantBasis IncludeFileExtension IncludePods IncludeSingularTerm Increment Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentUnit IndependentVertexSetQ Indeterminate IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers Infinity Infix Information Inherited InheritScope Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InlineCounterAssignments InlineCounterIncrements InlineRules Inner Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionPointObject InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Install InstallService InString Integer IntegerDigits IntegerExponent IntegerLength IntegerPart IntegerPartitions IntegerQ Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction InterpretTemplate InterquartileRange Interrupt InterruptSettings Intersection Interval IntervalIntersection IntervalMemberQ IntervalUnion Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHaversine InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InversePermutation InverseRadon InverseSeries InverseSurvivalFunction InverseWaveletTransform InverseWeierstrassP InverseZTransform Invisible InvisibleApplication InvisibleTimes IrreduciblePolynomialQ IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcess JaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join Joined JoinedCurve JoinedCurveBox JoinForm JordanDecomposition JordanModelDecomposition K KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelMixtureDistribution KernelObject Kernels Ket Khinchin KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnightTourGraph KnotData KnownUnitQ KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter Label Labeled LabeledSlider LabelingFunction LabelStyle LaguerreL LambdaComponents LambertW LanczosWindow LandauDistribution Language LanguageCategory LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCM LeafCount LeapYearQ LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessFullEqual LessGreater LessLess LessSlantEqual LessTilde LetterCharacter LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox LinearFilter LinearFractionalTransform LinearModelFit LinearOffsetFunction LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBreak LinebreakAdjustments LineBreakChart LineBreakWithin LineColor LineForm LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRead LinkReadHeld LinkReadyQ Links LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot Listen ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalClusteringCoefficient LocalizeVariables LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestAscendingSequence LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow Loopback LoopFreeGraphQ LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LyapunovSolve LyonsGroupLy MachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules MangoldtLambda ManhattanDistance Manipulate Manipulator MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixPlot MatrixPower MatrixQ MatrixRank Max MaxBend MaxDetect MaxExtraBandwidths MaxExtraConditions MaxFeatures MaxFilter Maximize MaxIterations MaxMemoryUsed MaxMixtureKernels MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxValue MaxwellDistribution McLaughlinGroupMcL Mean MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter Median MedianDeviation MedianFilter Medium MeijerG MeixnerDistribution MemberQ MemoryConstrained MemoryInUse Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuPacket MenuSortingValue MenuStyle MenuView MergeDifferences Mesh MeshFunctions MeshRange MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation Method MethodOptions MexicanHatWavelet MeyerWavelet Min MinDetect MinFilter MinimalPolynomial MinimalStateSpaceModel Minimize Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingDataMethod MittagLefflerE MixedRadix MixedRadixQuantity MixtureDistribution Mod Modal Mode Modular ModularLambda Module Modulus MoebiusMu Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction Monday Monitor MonomialList MonomialOrder MonsterGroupM MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform Most MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovingAverage MovingMedian MoyalDistribution MultiedgeStyle MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistribution N NakagamiDistribution NameQ Names NamespaceBox Nand NArgMax NArgMin NBernoulliB NCache NDSolve NDSolveValue Nearest NearestFunction NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeMultinomialDistribution NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestList NestWhile NestWhileList NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextPrime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants None NonlinearModelFit NonlocalMeansFilter NonNegative NonPositive Nor NorlundB Norm Normal NormalDistribution NormalGrouping Normalize NormalizedSquaredEuclideanDistance NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde NotHumpDownHump NotHumpEqual NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms Null NullRecords NullSpace NullWords Number NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator NumberSigns NumberString Numerator NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlot O ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OddQ Off Offset OLEData On ONanGroupON OneIdentity Opacity Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering Orderless OrnsteinUhlenbeckProcess Orthogonalize Out Outer OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OwenT OwnValues PackingMethod PaddedForm Padding PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageWidth PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParetoDistribution Part PartialCorrelationFunction PartialD ParticleData Partition PartitionsP PartitionsQ ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PerformanceGoal PeriodicInterpolation Periodogram PeriodogramArray PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PERTDistribution PetersenGraph PhaseMargins Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest Pink Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarGraphQ Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangePadding PlotRegion PlotStyle Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox PointBox PointFigureChart PointForm PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonBox PolygonBoxOptions PolygonHoleScale PolygonIntersections PolygonScale PolyhedronData PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position Positive PositiveDefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement PredictionRoot PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependTo PreserveImageOptions Previous PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitiveRoot PrincipalComponents PrincipalValue Print PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessEstimator ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptions QBinomial QFactorial QGamma QHypergeometricPFQ QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ Quantile QuantilePlot Quantity QuantityForm QuantityMagnitude QuantityQ QuantityUnit Quartics QuartileDeviation Quartiles QuartileSkewness QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainder RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Random RandomChoice RandomComplex RandomFunction RandomGraph RandomImage RandomInteger RandomPermutation RandomPrime RandomReal RandomSample RandomSeed RandomVariate RandomWalkProcess Range RangeFilter RangeSpecification RankedMax RankedMin Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios Raw RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadList ReadProtected Real RealBlockDiagonalForm RealDigits RealExponent Reals Reap Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate RegionBinarize RegionFunction RegionPlot RegionPlot3D RegularExpression Regularization Reinstall Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot Remove RemoveAlphaChannel RemoveAsynchronousTask Removed RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart Repeated RepeatedNull RepeatedString Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated Resampling Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask Residue Resolve Rest Resultant ResumePacket Return ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulerUnits Run RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilarity SameQ SameTest SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveDefinitions SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTaskActiveQ ScheduledTaskData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition Sec Sech SechDistribution SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemialgebraicComponentInstances SendMail Sequence SequenceAlignment SequenceForm SequenceHold SequenceLimit Series SeriesCoefficient SeriesData SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPrecision SetProperty SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share Sharpen ShearingMatrix ShearingTransform ShenCastanMatrix Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortUpArrow Show ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiegelTheta SiegelTukeyTest Sign Signature SignedRankTest SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution Skip SliceDistribution Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDelayCompensator SmithWatermanSimilarity SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SocialMediaData Socket SokalSneathDissimilarity Solve SolveAlways SolveDelayed Sort SortBy Sound SoundAndGraphics SoundNote SoundVolume Sow Space SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution Speak SpeakTextPacket SpearmanRankTest SpearmanRho Spectrogram SpectrogramArray Specularity SpellingCorrection SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackInhibit StandardDeviation StandardDeviationFilter StandardForm Standardize StandbyDistribution Star StarGraph StartAsynchronousTask StartingStepSize StartOfLine StartOfString StartScheduledTask StartupSound StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringCount StringDrop StringExpression StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPosition StringQ StringReplace StringReplaceList StringReplacePart StringReverse StringRotateLeft StringRotateRight StringSkeleton StringSplit StringTake StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleBoxOptions StyleData StyleDefinitions StyleForm StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subset SubsetEqual Subsets SubStar Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde SuchThat Sum SumConvergence Sunday SuperDagger SuperMinus SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceColor SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SystemDialogInput SystemException SystemHelpPath SystemInformation SystemInformationData SystemOpen SystemOptions SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemStub Tab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeWhile Tally Tan Tanh TargetFunctions TargetUnits TautologyQ TelegraphProcess TemplateBox TemplateBoxOptions TemplateSlotSequence TemporalData Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCell TextClipboardType TextData TextForm TextJustification TextLine TextPacket TextParagraph TextRecognize TextRendering TextStyle Texture TextureCoordinateFunction TextureCoordinateScaling Therefore ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreeJSymbol Threshold Through Throw Thumbnail Thursday Ticks TicksStyle Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint Times TimesBy TimeSeriesForecast TimeSeriesInvertibility TimeUsed TimeValue TimeZone Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate ToDiscreteTimeModel ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform TopologicalSort ToRadicals ToRules ToString Total TotalHeight TotalVariationFilter TotalWidth TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField Translate TranslationTransform TransparentColor Transpose TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle TriangleWave TriangularDistribution Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean True TrueQ TruncatedDistribution TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow Tuples TuranGraph TuringMachine Transparent UnateQ Uncompress Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UndirectedEdge UndirectedGraph UndirectedGraphQ UndocumentedTestFEParserPacket UndocumentedTestGetSelectionPacket Unequal Unevaluated UniformDistribution UniformGraphDistribution UniformSumDistribution Uninstall Union UnionPlus Unique UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitTriangle UnitVector Unprotect UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpValues URL URLFetch URLFetchAsynchronous URLSave URLSaveAsynchronous UseGraphicsRange Using UsingFrontEnd V2Get ValidationLength Value ValueBox ValueBoxOptions ValueForm ValueQ ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerifyConvergence VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoigtDistribution VonMisesDistribution WaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeberE Wedge Wednesday WeibullDistribution WeierstrassHalfPeriods WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WilksW WilksWTest WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult Word WordBoundary WordCharacter WordData WordSearch WordSeparators WorkingPrecision Write WriteString Wronskian XMLElement XMLObject Xnor Xor Yellow YuleDissimilarity ZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZipfDistribution ZTest ZTransform $Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AssertFunction $Assumptions $AsynchronousTask $BaseDirectory $BatchInput $BatchOutput $BoxForms $ByteOrdering $Canceled $CharacterEncoding $CharacterEncodings $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $CreationDate $CurrentLink $DateStringFormat $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $Epilog $ExportFormats $Failed $FinancialDataSource $FormatType $FrontEnd $FrontEndSession $GeoLocation $HistoryLength $HomeDirectory $HTTPCookies $IgnoreEOF $ImagingDevices $ImportFormats $InitialDirectory $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $ModuleNumber $NetworkLicense $NewMessage $NewSymbol $Notebooks $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $PipeSupported $Post $Pre $PreferencesDirectory $PrePrint $PreRead $PrintForms $PrintLiteral $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $RandomState $RecursionLimit $ReleaseNumber $RootDirectory $ScheduledTask $ScriptCommandLine $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemWordLength $TemporaryDirectory $TemporaryPrefix $TextStyle $TimedOut $TimeUnit $TimeZone $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $Urgent $UserAddOnsDirectory $UserBaseDirectory $UserDocumentsDirectory $UserName $Version $VersionNumber\",\ncontains:[{className:\"comment\",begin:/\\(\\*/,end:/\\*\\)/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,{className:\"list\",begin:/\\{/,end:/\\}/,illegal:/:/}]}}),e.registerLanguage(\"matlab\",function(e){var t=[e.C_NUMBER_MODE,{className:\"string\",begin:\"'\",end:\"'\",contains:[e.BACKSLASH_ESCAPE,{begin:\"''\"}]}],n={relevance:0,contains:[{className:\"operator\",begin:/'['\\.]*/}]};return{keywords:{keyword:\"break case catch classdef continue else elseif end enumerated events for function global if methods otherwise parfor persistent properties return spmd switch try while\",built_in:\"sin sind sinh asin asind asinh cos cosd cosh acos acosd acosh tan tand tanh atan atand atan2 atanh sec secd sech asec asecd asech csc cscd csch acsc acscd acsch cot cotd coth acot acotd acoth hypot exp expm1 log log1p log10 log2 pow2 realpow reallog realsqrt sqrt nthroot nextpow2 abs angle complex conj imag real unwrap isreal cplxpair fix floor ceil round mod rem sign airy besselj bessely besselh besseli besselk beta betainc betaln ellipj ellipke erf erfc erfcx erfinv expint gamma gammainc gammaln psi legendre cross dot factor isprime primes gcd lcm rat rats perms nchoosek factorial cart2sph cart2pol pol2cart sph2cart hsv2rgb rgb2hsv zeros ones eye repmat rand randn linspace logspace freqspace meshgrid accumarray size length ndims numel disp isempty isequal isequalwithequalnans cat reshape diag blkdiag tril triu fliplr flipud flipdim rot90 find sub2ind ind2sub bsxfun ndgrid permute ipermute shiftdim circshift squeeze isscalar isvector ans eps realmax realmin pi i inf nan isnan isinf isfinite j why compan gallery hadamard hankel hilb invhilb magic pascal rosser toeplitz vander wilkinson\"},illegal:'(//|\"|#|/\\\\*|\\\\s+/\\\\w+)',contains:[{className:\"function\",beginKeywords:\"function\",end:\"$\",contains:[e.UNDERSCORE_TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\"},{className:\"params\",begin:\"\\\\[\",end:\"\\\\]\"}]},{begin:/[a-zA-Z_][a-zA-Z_0-9]*'['\\.]*/,returnBegin:!0,relevance:0,contains:[{begin:/[a-zA-Z_][a-zA-Z_0-9]*/,relevance:0},n.contains[0]]},{className:\"matrix\",begin:\"\\\\[\",end:\"\\\\]\",contains:t,relevance:0,starts:n},{className:\"cell\",begin:\"\\\\{\",end:/}/,contains:t,relevance:0,starts:n},{begin:/\\)/,relevance:0,starts:n},e.COMMENT(\"^\\\\s*\\\\%\\\\{\\\\s*$\",\"^\\\\s*\\\\%\\\\}\\\\s*$\"),e.COMMENT(\"\\\\%\",\"$\")].concat(t)}}),e.registerLanguage(\"mel\",function(e){return{keywords:\"int float string vector matrix if else switch case default while do for in break continue global proc return about abs addAttr addAttributeEditorNodeHelp addDynamic addNewShelfTab addPP addPanelCategory addPrefixToName advanceToNextDrivenKey affectedNet affects aimConstraint air alias aliasAttr align alignCtx alignCurve alignSurface allViewFit ambientLight angle angleBetween animCone animCurveEditor animDisplay animView annotate appendStringArray applicationName applyAttrPreset applyTake arcLenDimContext arcLengthDimension arclen arrayMapper art3dPaintCtx artAttrCtx artAttrPaintVertexCtx artAttrSkinPaintCtx artAttrTool artBuildPaintMenu artFluidAttrCtx artPuttyCtx artSelectCtx artSetPaintCtx artUserPaintCtx assignCommand assignInputDevice assignViewportFactories attachCurve attachDeviceAttr attachSurface attrColorSliderGrp attrCompatibility attrControlGrp attrEnumOptionMenu attrEnumOptionMenuGrp attrFieldGrp attrFieldSliderGrp attrNavigationControlGrp attrPresetEditWin attributeExists attributeInfo attributeMenu attributeQuery autoKeyframe autoPlace bakeClip bakeFluidShading bakePartialHistory bakeResults bakeSimulation basename basenameEx batchRender bessel bevel bevelPlus binMembership bindSkin blend2 blendShape blendShapeEditor blendShapePanel blendTwoAttr blindDataType boneLattice boundary boxDollyCtx boxZoomCtx bufferCurve buildBookmarkMenu buildKeyframeMenu button buttonManip CBG cacheFile cacheFileCombine cacheFileMerge cacheFileTrack camera cameraView canCreateManip canvas capitalizeString catch catchQuiet ceil changeSubdivComponentDisplayLevel changeSubdivRegion channelBox character characterMap characterOutlineEditor characterize chdir checkBox checkBoxGrp checkDefaultRenderGlobals choice circle circularFillet clamp clear clearCache clip clipEditor clipEditorCurrentTimeCtx clipSchedule clipSchedulerOutliner clipTrimBefore closeCurve closeSurface cluster cmdFileOutput cmdScrollFieldExecuter cmdScrollFieldReporter cmdShell coarsenSubdivSelectionList collision color colorAtPoint colorEditor colorIndex colorIndexSliderGrp colorSliderButtonGrp colorSliderGrp columnLayout commandEcho commandLine commandPort compactHairSystem componentEditor compositingInterop computePolysetVolume condition cone confirmDialog connectAttr connectControl connectDynamic connectJoint connectionInfo constrain constrainValue constructionHistory container containsMultibyte contextInfo control convertFromOldLayers convertIffToPsd convertLightmap convertSolidTx convertTessellation convertUnit copyArray copyFlexor copyKey copySkinWeights cos cpButton cpCache cpClothSet cpCollision cpConstraint cpConvClothToMesh cpForces cpGetSolverAttr cpPanel cpProperty cpRigidCollisionFilter cpSeam cpSetEdit cpSetSolverAttr cpSolver cpSolverTypes cpTool cpUpdateClothUVs createDisplayLayer createDrawCtx createEditor createLayeredPsdFile createMotionField createNewShelf createNode createRenderLayer createSubdivRegion cross crossProduct ctxAbort ctxCompletion ctxEditMode ctxTraverse currentCtx currentTime currentTimeCtx currentUnit curve curveAddPtCtx curveCVCtx curveEPCtx curveEditorCtx curveIntersect curveMoveEPCtx curveOnSurface curveSketchCtx cutKey cycleCheck cylinder dagPose date defaultLightListCheckBox defaultNavigation defineDataServer defineVirtualDevice deformer deg_to_rad delete deleteAttr deleteShadingGroupsAndMaterials deleteShelfTab deleteUI deleteUnusedBrushes delrandstr detachCurve detachDeviceAttr detachSurface deviceEditor devicePanel dgInfo dgdirty dgeval dgtimer dimWhen directKeyCtx directionalLight dirmap dirname disable disconnectAttr disconnectJoint diskCache displacementToPoly displayAffected displayColor displayCull displayLevelOfDetail displayPref displayRGBColor displaySmoothness displayStats displayString displaySurface distanceDimContext distanceDimension doBlur dolly dollyCtx dopeSheetEditor dot dotProduct doubleProfileBirailSurface drag dragAttrContext draggerContext dropoffLocator duplicate duplicateCurve duplicateSurface dynCache dynControl dynExport dynExpression dynGlobals dynPaintEditor dynParticleCtx dynPref dynRelEdPanel dynRelEditor dynamicLoad editAttrLimits editDisplayLayerGlobals editDisplayLayerMembers editRenderLayerAdjustment editRenderLayerGlobals editRenderLayerMembers editor editorTemplate effector emit emitter enableDevice encodeString endString endsWith env equivalent equivalentTol erf error eval evalDeferred evalEcho event exactWorldBoundingBox exclusiveLightCheckBox exec executeForEachObject exists exp expression expressionEditorListen extendCurve extendSurface extrude fcheck fclose feof fflush fgetline fgetword file fileBrowserDialog fileDialog fileExtension fileInfo filetest filletCurve filter filterCurve filterExpand filterStudioImport findAllIntersections findAnimCurves findKeyframe findMenuItem findRelatedSkinCluster finder firstParentOf fitBspline flexor floatEq floatField floatFieldGrp floatScrollBar floatSlider floatSlider2 floatSliderButtonGrp floatSliderGrp floor flow fluidCacheInfo fluidEmitter fluidVoxelInfo flushUndo fmod fontDialog fopen formLayout format fprint frameLayout fread freeFormFillet frewind fromNativePath fwrite gamma gauss geometryConstraint getApplicationVersionAsFloat getAttr getClassification getDefaultBrush getFileList getFluidAttr getInputDeviceRange getMayaPanelTypes getModifiers getPanel getParticleAttr getPluginResource getenv getpid glRender glRenderEditor globalStitch gmatch goal gotoBindPose grabColor gradientControl gradientControlNoAttr graphDollyCtx graphSelectContext graphTrackCtx gravity grid gridLayout group groupObjectsByName HfAddAttractorToAS HfAssignAS HfBuildEqualMap HfBuildFurFiles HfBuildFurImages HfCancelAFR HfConnectASToHF HfCreateAttractor HfDeleteAS HfEditAS HfPerformCreateAS HfRemoveAttractorFromAS HfSelectAttached HfSelectAttractors HfUnAssignAS hardenPointCurve hardware hardwareRenderPanel headsUpDisplay headsUpMessage help helpLine hermite hide hilite hitTest hotBox hotkey hotkeyCheck hsv_to_rgb hudButton hudSlider hudSliderButton hwReflectionMap hwRender hwRenderLoad hyperGraph hyperPanel hyperShade hypot iconTextButton iconTextCheckBox iconTextRadioButton iconTextRadioCollection iconTextScrollList iconTextStaticLabel ikHandle ikHandleCtx ikHandleDisplayScale ikSolver ikSplineHandleCtx ikSystem ikSystemInfo ikfkDisplayMethod illustratorCurves image imfPlugins inheritTransform insertJoint insertJointCtx insertKeyCtx insertKnotCurve insertKnotSurface instance instanceable instancer intField intFieldGrp intScrollBar intSlider intSliderGrp interToUI internalVar intersect iprEngine isAnimCurve isConnected isDirty isParentOf isSameObject isTrue isValidObjectName isValidString isValidUiName isolateSelect itemFilter itemFilterAttr itemFilterRender itemFilterType joint jointCluster jointCtx jointDisplayScale jointLattice keyTangent keyframe keyframeOutliner keyframeRegionCurrentTimeCtx keyframeRegionDirectKeyCtx keyframeRegionDollyCtx keyframeRegionInsertKeyCtx keyframeRegionMoveKeyCtx keyframeRegionScaleKeyCtx keyframeRegionSelectKeyCtx keyframeRegionSetKeyCtx keyframeRegionTrackCtx keyframeStats lassoContext lattice latticeDeformKeyCtx launch launchImageEditor layerButton layeredShaderPort layeredTexturePort layout layoutDialog lightList lightListEditor lightListPanel lightlink lineIntersection linearPrecision linstep listAnimatable listAttr listCameras listConnections listDeviceAttachments listHistory listInputDeviceAxes listInputDeviceButtons listInputDevices listMenuAnnotation listNodeTypes listPanelCategories listRelatives listSets listTransforms listUnselected listerEditor loadFluid loadNewShelf loadPlugin loadPluginLanguageResources loadPrefObjects localizedPanelLabel lockNode loft log longNameOf lookThru ls lsThroughFilter lsType lsUI Mayatomr mag makeIdentity makeLive makePaintable makeRoll makeSingleSurface makeTubeOn makebot manipMoveContext manipMoveLimitsCtx manipOptions manipRotateContext manipRotateLimitsCtx manipScaleContext manipScaleLimitsCtx marker match max memory menu menuBarLayout menuEditor menuItem menuItemToShelf menuSet menuSetPref messageLine min minimizeApp mirrorJoint modelCurrentTimeCtx modelEditor modelPanel mouse movIn movOut move moveIKtoFK moveKeyCtx moveVertexAlongDirection multiProfileBirailSurface mute nParticle nameCommand nameField namespace namespaceInfo newPanelItems newton nodeCast nodeIconButton nodeOutliner nodePreset nodeType noise nonLinear normalConstraint normalize nurbsBoolean nurbsCopyUVSet nurbsCube nurbsEditUV nurbsPlane nurbsSelect nurbsSquare nurbsToPoly nurbsToPolygonsPref nurbsToSubdiv nurbsToSubdivPref nurbsUVSet nurbsViewDirectionVector objExists objectCenter objectLayer objectType objectTypeUI obsoleteProc oceanNurbsPreviewPlane offsetCurve offsetCurveOnSurface offsetSurface openGLExtension openMayaPref optionMenu optionMenuGrp optionVar orbit orbitCtx orientConstraint outlinerEditor outlinerPanel overrideModifier paintEffectsDisplay pairBlend palettePort paneLayout panel panelConfiguration panelHistory paramDimContext paramDimension paramLocator parent parentConstraint particle particleExists particleInstancer particleRenderInfo partition pasteKey pathAnimation pause pclose percent performanceOptions pfxstrokes pickWalk picture pixelMove planarSrf plane play playbackOptions playblast plugAttr plugNode pluginInfo pluginResourceUtil pointConstraint pointCurveConstraint pointLight pointMatrixMult pointOnCurve pointOnSurface pointPosition poleVectorConstraint polyAppend polyAppendFacetCtx polyAppendVertex polyAutoProjection polyAverageNormal polyAverageVertex polyBevel polyBlendColor polyBlindData polyBoolOp polyBridgeEdge polyCacheMonitor polyCheck polyChipOff polyClipboard polyCloseBorder polyCollapseEdge polyCollapseFacet polyColorBlindData polyColorDel polyColorPerVertex polyColorSet polyCompare polyCone polyCopyUV polyCrease polyCreaseCtx polyCreateFacet polyCreateFacetCtx polyCube polyCut polyCutCtx polyCylinder polyCylindricalProjection polyDelEdge polyDelFacet polyDelVertex polyDuplicateAndConnect polyDuplicateEdge polyEditUV polyEditUVShell polyEvaluate polyExtrudeEdge polyExtrudeFacet polyExtrudeVertex polyFlipEdge polyFlipUV polyForceUV polyGeoSampler polyHelix polyInfo polyInstallAction polyLayoutUV polyListComponentConversion polyMapCut polyMapDel polyMapSew polyMapSewMove polyMergeEdge polyMergeEdgeCtx polyMergeFacet polyMergeFacetCtx polyMergeUV polyMergeVertex polyMirrorFace polyMoveEdge polyMoveFacet polyMoveFacetUV polyMoveUV polyMoveVertex polyNormal polyNormalPerVertex polyNormalizeUV polyOptUvs polyOptions polyOutput polyPipe polyPlanarProjection polyPlane polyPlatonicSolid polyPoke polyPrimitive polyPrism polyProjection polyPyramid polyQuad polyQueryBlindData polyReduce polySelect polySelectConstraint polySelectConstraintMonitor polySelectCtx polySelectEditCtx polySeparate polySetToFaceNormal polySewEdge polyShortestPathCtx polySmooth polySoftEdge polySphere polySphericalProjection polySplit polySplitCtx polySplitEdge polySplitRing polySplitVertex polyStraightenUVBorder polySubdivideEdge polySubdivideFacet polyToSubdiv polyTorus polyTransfer polyTriangulate polyUVSet polyUnite polyWedgeFace popen popupMenu pose pow preloadRefEd print progressBar progressWindow projFileViewer projectCurve projectTangent projectionContext projectionManip promptDialog propModCtx propMove psdChannelOutliner psdEditTextureFile psdExport psdTextureFile putenv pwd python querySubdiv quit rad_to_deg radial radioButton radioButtonGrp radioCollection radioMenuItemCollection rampColorPort rand randomizeFollicles randstate rangeControl readTake rebuildCurve rebuildSurface recordAttr recordDevice redo reference referenceEdit referenceQuery refineSubdivSelectionList refresh refreshAE registerPluginResource rehash reloadImage removeJoint removeMultiInstance removePanelCategory rename renameAttr renameSelectionList renameUI render renderGlobalsNode renderInfo renderLayerButton renderLayerParent renderLayerPostProcess renderLayerUnparent renderManip renderPartition renderQualityNode renderSettings renderThumbnailUpdate renderWindowEditor renderWindowSelectContext renderer reorder reorderDeformers requires reroot resampleFluid resetAE resetPfxToPolyCamera resetTool resolutionNode retarget reverseCurve reverseSurface revolve rgb_to_hsv rigidBody rigidSolver roll rollCtx rootOf rot rotate rotationInterpolation roundConstantRadius rowColumnLayout rowLayout runTimeCommand runup sampleImage saveAllShelves saveAttrPreset saveFluid saveImage saveInitialState saveMenu savePrefObjects savePrefs saveShelf saveToolSettings scale scaleBrushBrightness scaleComponents scaleConstraint scaleKey scaleKeyCtx sceneEditor sceneUIReplacement scmh scriptCtx scriptEditorInfo scriptJob scriptNode scriptTable scriptToShelf scriptedPanel scriptedPanelType scrollField scrollLayout sculpt searchPathArray seed selLoadSettings select selectContext selectCurveCV selectKey selectKeyCtx selectKeyframeRegionCtx selectMode selectPref selectPriority selectType selectedNodes selectionConnection separator setAttr setAttrEnumResource setAttrMapping setAttrNiceNameResource setConstraintRestPosition setDefaultShadingGroup setDrivenKeyframe setDynamic setEditCtx setEditor setFluidAttr setFocus setInfinity setInputDeviceMapping setKeyCtx setKeyPath setKeyframe setKeyframeBlendshapeTargetWts setMenuMode setNodeNiceNameResource setNodeTypeFlag setParent setParticleAttr setPfxToPolyCamera setPluginResource setProject setStampDensity setStartupMessage setState setToolTo setUITemplate setXformManip sets shadingConnection shadingGeometryRelCtx shadingLightRelCtx shadingNetworkCompare shadingNode shapeCompare shelfButton shelfLayout shelfTabLayout shellField shortNameOf showHelp showHidden showManipCtx showSelectionInTitle showShadingGroupAttrEditor showWindow sign simplify sin singleProfileBirailSurface size sizeBytes skinCluster skinPercent smoothCurve smoothTangentSurface smoothstep snap2to2 snapKey snapMode snapTogetherCtx snapshot soft softMod softModCtx sort sound soundControl source spaceLocator sphere sphrand spotLight spotLightPreviewPort spreadSheetEditor spring sqrt squareSurface srtContext stackTrace startString startsWith stitchAndExplodeShell stitchSurface stitchSurfacePoints strcmp stringArrayCatenate stringArrayContains stringArrayCount stringArrayInsertAtIndex stringArrayIntersector stringArrayRemove stringArrayRemoveAtIndex stringArrayRemoveDuplicates stringArrayRemoveExact stringArrayToString stringToStringArray strip stripPrefixFromName stroke subdAutoProjection subdCleanTopology subdCollapse subdDuplicateAndConnect subdEditUV subdListComponentConversion subdMapCut subdMapSewMove subdMatchTopology subdMirror subdToBlind subdToPoly subdTransferUVsToCache subdiv subdivCrease subdivDisplaySmoothness substitute substituteAllString substituteGeometry substring surface surfaceSampler surfaceShaderList swatchDisplayPort switchTable symbolButton symbolCheckBox sysFile system tabLayout tan tangentConstraint texLatticeDeformContext texManipContext texMoveContext texMoveUVShellContext texRotateContext texScaleContext texSelectContext texSelectShortestPathCtx texSmudgeUVContext texWinToolCtx text textCurves textField textFieldButtonGrp textFieldGrp textManip textScrollList textToShelf textureDisplacePlane textureHairColor texturePlacementContext textureWindow threadCount threePointArcCtx timeControl timePort timerX toNativePath toggle toggleAxis toggleWindowVisibility tokenize tokenizeList tolerance tolower toolButton toolCollection toolDropped toolHasOptions toolPropertyWindow torus toupper trace track trackCtx transferAttributes transformCompare transformLimits translator trim trunc truncateFluidCache truncateHairCache tumble tumbleCtx turbulence twoPointArcCtx uiRes uiTemplate unassignInputDevice undo undoInfo ungroup uniform unit unloadPlugin untangleUV untitledFileName untrim upAxis updateAE userCtx uvLink uvSnapshot validateShelfName vectorize view2dToolCtx viewCamera viewClipPlane viewFit viewHeadOn viewLookAt viewManip viewPlace viewSet visor volumeAxis vortex waitCursor warning webBrowser webBrowserPrefs whatIs window windowPref wire wireContext workspace wrinkle wrinkleContext writeTake xbmLangPathList xform\",illegal:\"</\",contains:[e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:\"string\",begin:\"`\",end:\"`\",contains:[e.BACKSLASH_ESCAPE]},{className:\"variable\",variants:[{begin:\"\\\\$\\\\d\"},{begin:\"[\\\\$\\\\%\\\\@](\\\\^\\\\w\\\\b|#\\\\w+|[^\\\\s\\\\w{]|{\\\\w+}|\\\\w+)\"},{begin:\"\\\\*(\\\\^\\\\w\\\\b|#\\\\w+|[^\\\\s\\\\w{]|{\\\\w+}|\\\\w+)\",relevance:0}]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]}}),e.registerLanguage(\"mercury\",function(e){var t={keyword:\"module use_module import_module include_module end_module initialise mutable initialize finalize finalise interface implementation pred mode func type inst solver any_pred any_func is semidet det nondet multi erroneous failure cc_nondet cc_multi typeclass instance where pragma promise external trace atomic or_else require_complete_switch require_det require_semidet require_multi require_nondet require_cc_multi require_cc_nondet require_erroneous require_failure\",pragma:\"inline no_inline type_spec source_file fact_table obsolete memo loop_check minimal_model terminates does_not_terminate check_termination promise_equivalent_clauses\",preprocessor:\"foreign_proc foreign_decl foreign_code foreign_type foreign_import_module foreign_export_enum foreign_export foreign_enum may_call_mercury will_not_call_mercury thread_safe not_thread_safe maybe_thread_safe promise_pure promise_semipure tabled_for_io local untrailed trailed attach_to_io_state can_pass_as_mercury_type stable will_not_throw_exception may_modify_trail will_not_modify_trail may_duplicate may_not_duplicate affects_liveness does_not_affect_liveness doesnt_affect_liveness no_sharing unknown_sharing sharing\",built_in:\"some all not if then else true fail false try catch catch_any semidet_true semidet_false semidet_fail impure_true impure semipure\"},n={className:\"label\",begin:\"XXX\",end:\"$\",endsWithParent:!0,relevance:0},i=e.inherit(e.C_LINE_COMMENT_MODE,{begin:\"%\"}),r=e.inherit(e.C_BLOCK_COMMENT_MODE,{relevance:0});i.contains.push(n),r.contains.push(n);var a={className:\"number\",begin:\"0'.\\\\|0[box][0-9a-fA-F]*\"},o=e.inherit(e.APOS_STRING_MODE,{relevance:0}),s=e.inherit(e.QUOTE_STRING_MODE,{relevance:0}),l={className:\"constant\",begin:\"\\\\\\\\[abfnrtv]\\\\|\\\\\\\\x[0-9a-fA-F]*\\\\\\\\\\\\|%[-+# *.0-9]*[dioxXucsfeEgGp]\",relevance:0};s.contains.push(l);var c={className:\"built_in\",variants:[{begin:\"<=>\"},{begin:\"<=\",relevance:0},{begin:\"=>\",relevance:0},{begin:\"/\\\\\\\\\"},{begin:\"\\\\\\\\/\"}]},d={className:\"built_in\",variants:[{begin:\":-\\\\|-->\"},{begin:\"=\",relevance:0}]};return{aliases:[\"m\",\"moo\"],keywords:t,contains:[c,d,i,r,a,e.NUMBER_MODE,o,s,{begin:/:-/}]}}),e.registerLanguage(\"mizar\",function(e){return{keywords:\"environ vocabularies notations constructors definitions registrations theorems schemes requirements begin end definition registration cluster existence pred func defpred deffunc theorem proof let take assume then thus hence ex for st holds consider reconsider such that and in provided of as from be being by means equals implies iff redefine define now not or attr is mode suppose per cases set thesis contradiction scheme reserve struct correctness compatibility coherence symmetry assymetry reflexivity irreflexivity connectedness uniqueness commutativity idempotence involutiveness projectivity\",contains:[e.COMMENT(\"::\",\"$\")]}}),e.registerLanguage(\"perl\",function(e){var t=\"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when\",n={className:\"subst\",begin:\"[$@]\\\\{\",end:\"\\\\}\",keywords:t},i={begin:\"->{\",end:\"}\"},r={className:\"variable\",variants:[{begin:/\\$\\d/},{begin:/[\\$%@](\\^\\w\\b|#\\w+(::\\w+)*|{\\w+}|\\w+(::\\w*)*)/},{begin:/[\\$%@][^\\s\\w{]/,relevance:0}]},a=[e.BACKSLASH_ESCAPE,n,r],o=[r,e.HASH_COMMENT_MODE,e.COMMENT(\"^\\\\=\\\\w\",\"\\\\=cut\",{endsWithParent:!0}),i,{className:\"string\",contains:a,variants:[{begin:\"q[qwxr]?\\\\s*\\\\(\",end:\"\\\\)\",relevance:5},{begin:\"q[qwxr]?\\\\s*\\\\[\",end:\"\\\\]\",relevance:5},{begin:\"q[qwxr]?\\\\s*\\\\{\",end:\"\\\\}\",relevance:5},{begin:\"q[qwxr]?\\\\s*\\\\|\",end:\"\\\\|\",relevance:5},{begin:\"q[qwxr]?\\\\s*\\\\<\",end:\"\\\\>\",relevance:5},{begin:\"qw\\\\s+q\",end:\"q\",relevance:5},{begin:\"'\",end:\"'\",contains:[e.BACKSLASH_ESCAPE]},{begin:'\"',end:'\"'},{begin:\"`\",end:\"`\",contains:[e.BACKSLASH_ESCAPE]},{begin:\"{\\\\w+}\",contains:[],relevance:0},{begin:\"-?\\\\w+\\\\s*\\\\=\\\\>\",contains:[],relevance:0}]},{className:\"number\",begin:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",relevance:0},{begin:\"(\\\\/\\\\/|\"+e.RE_STARTERS_RE+\"|\\\\b(split|return|print|reverse|grep)\\\\b)\\\\s*\",keywords:\"split return print reverse grep\",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:\"regexp\",begin:\"(s|tr|y)/(\\\\\\\\.|[^/])*/(\\\\\\\\.|[^/])*/[a-z]*\",relevance:10},{className:\"regexp\",begin:\"(m|qr)?/\",end:\"/[a-z]*\",contains:[e.BACKSLASH_ESCAPE],relevance:0}]},{className:\"sub\",beginKeywords:\"sub\",end:\"(\\\\s*\\\\(.*?\\\\))?[;{]\",relevance:5},{className:\"operator\",begin:\"-\\\\w\\\\b\",relevance:0},{begin:\"^__DATA__$\",end:\"^__END__$\",subLanguage:\"mojolicious\",contains:[{begin:\"^@@.*\",end:\"$\",className:\"comment\"}]}];return n.contains=o,i.contains=o,{aliases:[\"pl\"],keywords:t,contains:o}}),e.registerLanguage(\"mojolicious\",function(e){return{subLanguage:\"xml\",contains:[{className:\"preprocessor\",begin:\"^__(END|DATA)__$\"},{begin:\"^\\\\s*%{1,2}={0,2}\",end:\"$\",subLanguage:\"perl\"},{begin:\"<%{1,2}={0,2}\",end:\"={0,1}%>\",subLanguage:\"perl\",excludeBegin:!0,excludeEnd:!0}]}}),e.registerLanguage(\"monkey\",function(e){var t={className:\"number\",relevance:0,variants:[{begin:\"[$][a-fA-F0-9]+\"},e.NUMBER_MODE]};return{case_insensitive:!0,keywords:{keyword:\"public private property continue exit extern new try catch eachin not abstract final select case default const local global field end if then else elseif endif while wend repeat until forever for to step next return module inline throw\",built_in:\"DebugLog DebugStop Error Print ACos ACosr ASin ASinr ATan ATan2 ATan2r ATanr Abs Abs Ceil Clamp Clamp Cos Cosr Exp Floor Log Max Max Min Min Pow Sgn Sgn Sin Sinr Sqrt Tan Tanr Seed PI HALFPI TWOPI\",literal:\"true false null and or shl shr mod\"},illegal:/\\/\\*/,contains:[e.COMMENT(\"#rem\",\"#end\"),e.COMMENT(\"'\",\"$\",{relevance:0}),{className:\"function\",beginKeywords:\"function method\",end:\"[(=:]|$\",illegal:/\\n/,contains:[e.UNDERSCORE_TITLE_MODE]},{className:\"class\",beginKeywords:\"class interface\",end:\"$\",contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]},{className:\"variable\",begin:\"\\\\b(self|super)\\\\b\"},{className:\"preprocessor\",beginKeywords:\"import\",end:\"$\"},{className:\"preprocessor\",begin:\"\\\\s*#\",end:\"$\",keywords:\"if else elseif endif end then\"},{className:\"pi\",begin:\"^\\\\s*strict\\\\b\"},{beginKeywords:\"alias\",end:\"=\",contains:[e.UNDERSCORE_TITLE_MODE]},e.QUOTE_STRING_MODE,t]}}),e.registerLanguage(\"nginx\",function(e){var t={className:\"variable\",variants:[{begin:/\\$\\d+/},{begin:/\\$\\{/,end:/}/},{begin:\"[\\\\$\\\\@]\"+e.UNDERSCORE_IDENT_RE}]},n={endsWithParent:!0,lexemes:\"[a-z/_]+\",keywords:{built_in:\"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll\"},relevance:0,illegal:\"=>\",contains:[e.HASH_COMMENT_MODE,{className:\"string\",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:/\"/,end:/\"/},{begin:/'/,end:/'/}]},{className:\"url\",begin:\"([a-z]+):/\",end:\"\\\\s\",endsWithParent:!0,excludeEnd:!0,contains:[t]},{className:\"regexp\",contains:[e.BACKSLASH_ESCAPE,t],variants:[{begin:\"\\\\s\\\\^\",end:\"\\\\s|{|;\",returnEnd:!0},{begin:\"~\\\\*?\\\\s+\",end:\"\\\\s|{|;\",returnEnd:!0},{begin:\"\\\\*(\\\\.[a-z\\\\-]+)+\"},{begin:\"([a-z\\\\-]+\\\\.)+\\\\*\"}]},{className:\"number\",begin:\"\\\\b\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}(:\\\\d{1,5})?\\\\b\"},{className:\"number\",begin:\"\\\\b\\\\d+[kKmMgGdshdwy]*\\\\b\",relevance:0},t]};return{aliases:[\"nginxconf\"],contains:[e.HASH_COMMENT_MODE,{begin:e.UNDERSCORE_IDENT_RE+\"\\\\s\",end:\";|{\",returnBegin:!0,contains:[{className:\"title\",begin:e.UNDERSCORE_IDENT_RE,starts:n}],relevance:0}],illegal:\"[^\\\\s\\\\}]\"}}),e.registerLanguage(\"nimrod\",function(e){return{aliases:[\"nim\"],keywords:{keyword:\"addr and as asm bind block break|0 case|0 cast const|0 continue|0 converter discard distinct|10 div do elif else|0 end|0 enum|0 except export finally for from generic if|0 import|0 in include|0 interface is isnot|10 iterator|10 let|0 macro method|10 mixin mod nil not notin|10 object|0 of or out proc|10 ptr raise ref|10 return shl shr static template try|0 tuple type|0 using|0 var|0 when while|0 with without xor yield\",literal:\"shared guarded stdin stdout stderr result|10 true false\"},contains:[{className:\"decorator\",begin:/{\\./,end:/\\.}/,relevance:10},{className:\"string\",begin:/[a-zA-Z]\\w*\"/,end:/\"/,contains:[{begin:/\"\"/}]},{className:\"string\",begin:/([a-zA-Z]\\w*)?\"\"\"/,end:/\"\"\"/},e.QUOTE_STRING_MODE,{className:\"type\",begin:/\\b[A-Z]\\w+\\b/,relevance:0},{className:\"type\",begin:/\\b(int|int8|int16|int32|int64|uint|uint8|uint16|uint32|uint64|float|float32|float64|bool|char|string|cstring|pointer|expr|stmt|void|auto|any|range|array|openarray|varargs|seq|set|clong|culong|cchar|cschar|cshort|cint|csize|clonglong|cfloat|cdouble|clongdouble|cuchar|cushort|cuint|culonglong|cstringarray|semistatic)\\b/},{className:\"number\",begin:/\\b(0[xX][0-9a-fA-F][_0-9a-fA-F]*)('?[iIuU](8|16|32|64))?/,relevance:0},{className:\"number\",begin:/\\b(0o[0-7][_0-7]*)('?[iIuUfF](8|16|32|64))?/,relevance:0},{className:\"number\",begin:/\\b(0(b|B)[01][_01]*)('?[iIuUfF](8|16|32|64))?/,relevance:0},{className:\"number\",begin:/\\b(\\d[_\\d]*)('?[iIuUfF](8|16|32|64))?/,relevance:0},e.HASH_COMMENT_MODE]}}),e.registerLanguage(\"nix\",function(e){var t={keyword:\"rec with let in inherit assert if else then\",constant:\"true false or and null\",built_in:\"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation\"},n={className:\"subst\",begin:/\\$\\{/,end:/}/,keywords:t},i={className:\"variable\",begin:/[a-zA-Z0-9-_]+(\\s*=)/,relevance:0},r={className:\"string\",begin:\"''\",end:\"''\",contains:[n]},a={className:\"string\",begin:'\"',end:'\"',contains:[n]},o=[e.NUMBER_MODE,e.HASH_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,r,a,i];return n.contains=o,{aliases:[\"nixos\"],keywords:t,contains:o}}),e.registerLanguage(\"nsis\",function(e){var t={className:\"symbol\",begin:\"\\\\$(ADMINTOOLS|APPDATA|CDBURN_AREA|CMDLINE|COMMONFILES32|COMMONFILES64|COMMONFILES|COOKIES|DESKTOP|DOCUMENTS|EXEDIR|EXEFILE|EXEPATH|FAVORITES|FONTS|HISTORY|HWNDPARENT|INSTDIR|INTERNET_CACHE|LANGUAGE|LOCALAPPDATA|MUSIC|NETHOOD|OUTDIR|PICTURES|PLUGINSDIR|PRINTHOOD|PROFILE|PROGRAMFILES32|PROGRAMFILES64|PROGRAMFILES|QUICKLAUNCH|RECENT|RESOURCES_LOCALIZED|RESOURCES|SENDTO|SMPROGRAMS|SMSTARTUP|STARTMENU|SYSDIR|TEMP|TEMPLATES|VIDEOS|WINDIR)\"},n={className:\"constant\",begin:\"\\\\$+{[a-zA-Z0-9_]+}\"},i={className:\"variable\",begin:\"\\\\$+[a-zA-Z0-9_]+\",illegal:\"\\\\(\\\\){}\"},r={className:\"constant\",begin:\"\\\\$+\\\\([a-zA-Z0-9_]+\\\\)\"},a={className:\"params\",begin:\"(ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)\"},o={className:\"constant\",begin:\"\\\\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversionsystem|ifdef|ifmacrodef|ifmacrondef|ifndef|if|include|insertmacro|macroend|macro|makensis|packhdr|searchparse|searchreplace|tempfile|undef|verbose|warning)\"};return{case_insensitive:!1,keywords:{keyword:\"Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ChangeUI CheckBitmap ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exch Exec ExecShell ExecWait ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileReadUTF16LE FileReadWord FileSeek FileWrite FileWriteByte FileWriteUTF16LE FileWriteWord FindClose FindFirst FindNext FindWindow FlushINI FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LockWindow LogSet LogText ManifestDPIAware ManifestSupportedOS MessageBox MiscButtonText Name Nop OutFile Page PageCallbacks PageExEnd Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename RequestExecutionLevel ReserveFile Return RMDir SearchPath SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionGroupEnd SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetPluginUnload SetRebootFlag SetRegView SetShellVarContext SetSilent ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCmpS StrCpy StrLen SubCaption SubSectionEnd Unicode UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL Var VIAddVersionKey VIFileVersion VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle\",\nliteral:\"admin all auto both colored current false force hide highest lastused leave listonly none normal notset off on open print show silent silentlog smooth textonly true user \"},contains:[e.HASH_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"string\",begin:'\"',end:'\"',illegal:\"\\\\n\",contains:[{className:\"symbol\",begin:\"\\\\$(\\\\\\\\(n|r|t)|\\\\$)\"},t,n,i,r]},e.COMMENT(\";\",\"$\",{relevance:0}),{className:\"function\",beginKeywords:\"Function PageEx Section SectionGroup SubSection\",end:\"$\"},o,n,i,r,a,e.NUMBER_MODE,{className:\"literal\",begin:e.IDENT_RE+\"::\"+e.IDENT_RE}]}}),e.registerLanguage(\"objectivec\",function(e){var t={className:\"built_in\",begin:\"(AV|CA|CF|CG|CI|MK|MP|NS|UI)\\\\w+\"},n={keyword:\"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required\",literal:\"false true FALSE TRUE nil YES NO NULL\",built_in:\"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once\"},i=/[a-zA-Z@][a-zA-Z0-9_]*/,r=\"@interface @class @protocol @implementation\";return{aliases:[\"mm\",\"objc\",\"obj-c\"],keywords:n,lexemes:i,illegal:\"</\",contains:[t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.C_NUMBER_MODE,e.QUOTE_STRING_MODE,{className:\"string\",variants:[{begin:'@\"',end:'\"',illegal:\"\\\\n\",contains:[e.BACKSLASH_ESCAPE]},{begin:\"'\",end:\"[^\\\\\\\\]'\",illegal:\"[^\\\\\\\\][^']\"}]},{className:\"preprocessor\",begin:\"#\",end:\"$\",contains:[{className:\"title\",variants:[{begin:'\"',end:'\"'},{begin:\"<\",end:\">\"}]}]},{className:\"class\",begin:\"(\"+r.split(\" \").join(\"|\")+\")\\\\b\",end:\"({|$)\",excludeEnd:!0,keywords:r,lexemes:i,contains:[e.UNDERSCORE_TITLE_MODE]},{className:\"variable\",begin:\"\\\\.\"+e.UNDERSCORE_IDENT_RE,relevance:0}]}}),e.registerLanguage(\"ocaml\",function(e){return{aliases:[\"ml\"],keywords:{keyword:\"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value\",built_in:\"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref\",literal:\"true false\"},illegal:/\\/\\/|>>/,lexemes:\"[a-z_]\\\\w*!?\",contains:[{className:\"literal\",begin:\"\\\\[(\\\\|\\\\|)?\\\\]|\\\\(\\\\)\",relevance:0},e.COMMENT(\"\\\\(\\\\*\",\"\\\\*\\\\)\",{contains:[\"self\"]}),{className:\"symbol\",begin:\"'[A-Za-z_](?!')[\\\\w']*\"},{className:\"tag\",begin:\"`[A-Z][\\\\w']*\"},{className:\"type\",begin:\"\\\\b[A-Z][\\\\w']*\",relevance:0},{begin:\"[a-z_]\\\\w*'[\\\\w']*\"},e.inherit(e.APOS_STRING_MODE,{className:\"char\",relevance:0}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:\"number\",begin:\"\\\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)\",relevance:0},{begin:/[-=]>/}]}}),e.registerLanguage(\"openscad\",function(e){var t={className:\"keyword\",begin:\"\\\\$(f[asn]|t|vp[rtd]|children)\"},n={className:\"literal\",begin:\"false|true|PI|undef\"},i={className:\"number\",begin:\"\\\\b\\\\d+(\\\\.\\\\d+)?(e-?\\\\d+)?\",relevance:0},r=e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),a={className:\"preprocessor\",keywords:\"include use\",begin:\"include|use <\",end:\">\"},o={className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:[\"self\",i,r,t,n]},s={className:\"built_in\",begin:\"[*!#%]\",relevance:0},l={className:\"function\",beginKeywords:\"module function\",end:\"\\\\=|\\\\{\",contains:[o,e.UNDERSCORE_TITLE_MODE]};return{aliases:[\"scad\"],keywords:{keyword:\"function module include use for intersection_for if else \\\\%\",literal:\"false true PI undef\",built_in:\"circle square polygon text sphere cube cylinder polyhedron translate rotate scale resize mirror multmatrix color offset hull minkowski union difference intersection abs sign sin cos tan acos asin atan atan2 floor round ceil ln log pow sqrt exp rands min max concat lookup str chr search version version_num norm cross parent_module echo import import_dxf dxf_linear_extrude linear_extrude rotate_extrude surface projection render children dxf_cross dxf_dim let assign\"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i,a,r,t,s,l]}}),e.registerLanguage(\"oxygene\",function(e){var t=\"abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained\",n=e.COMMENT(\"{\",\"}\",{relevance:0}),i=e.COMMENT(\"\\\\(\\\\*\",\"\\\\*\\\\)\",{relevance:10}),r={className:\"string\",begin:\"'\",end:\"'\",contains:[{begin:\"''\"}]},a={className:\"string\",begin:\"(#\\\\d+)+\"},o={className:\"function\",beginKeywords:\"function constructor destructor procedure method\",end:\"[:;]\",keywords:\"function constructor|10 destructor|10 procedure|10 method|10\",contains:[e.TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",keywords:t,contains:[r,a]},n,i]};return{case_insensitive:!0,keywords:t,illegal:'(\"|\\\\$[G-Zg-z]|\\\\/\\\\*|</|=>|->)',contains:[n,i,e.C_LINE_COMMENT_MODE,r,a,e.NUMBER_MODE,o,{className:\"class\",begin:\"=\\\\bclass\\\\b\",end:\"end;\",keywords:t,contains:[r,a,n,i,e.C_LINE_COMMENT_MODE,o]}]}}),e.registerLanguage(\"parser3\",function(e){var t=e.COMMENT(\"{\",\"}\",{contains:[\"self\"]});return{subLanguage:\"xml\",relevance:0,contains:[e.COMMENT(\"^#\",\"$\"),e.COMMENT(\"\\\\^rem{\",\"}\",{relevance:10,contains:[t]}),{className:\"preprocessor\",begin:\"^@(?:BASE|USE|CLASS|OPTIONS)$\",relevance:10},{className:\"title\",begin:\"@[\\\\w\\\\-]+\\\\[[\\\\w^;\\\\-]*\\\\](?:\\\\[[\\\\w^;\\\\-]*\\\\])?(?:.*)$\"},{className:\"variable\",begin:\"\\\\$\\\\{?[\\\\w\\\\-\\\\.\\\\:]+\\\\}?\"},{className:\"keyword\",begin:\"\\\\^[\\\\w\\\\-\\\\.\\\\:]+\"},{className:\"number\",begin:\"\\\\^#[0-9a-fA-F]+\"},e.C_NUMBER_MODE]}}),e.registerLanguage(\"pf\",function(e){var t={className:\"variable\",begin:/\\$[\\w\\d#@][\\w\\d_]*/},n={className:\"variable\",begin:/</,end:/>/};return{aliases:[\"pf.conf\"],lexemes:/[a-z0-9_<>-]+/,keywords:{built_in:\"block match pass load anchor|5 antispoof|10 set table\",keyword:\"in out log quick on rdomain inet inet6 proto from port os to routeallow-opts divert-packet divert-reply divert-to flags group icmp-typeicmp6-type label once probability recieved-on rtable prio queuetos tag tagged user keep fragment for os dropaf-to|10 binat-to|10 nat-to|10 rdr-to|10 bitmask least-stats random round-robinsource-hash static-portdup-to reply-to route-toparent bandwidth default min max qlimitblock-policy debug fingerprints hostid limit loginterface optimizationreassemble ruleset-optimization basic none profile skip state-defaultsstate-policy timeoutconst counters persistno modulate synproxy state|5 floating if-bound no-sync pflow|10 sloppysource-track global rule max-src-nodes max-src-states max-src-connmax-src-conn-rate overload flushscrub|5 max-mss min-ttl no-df|10 random-id\",literal:\"all any no-route self urpf-failed egress|5 unknown\"},contains:[e.HASH_COMMENT_MODE,e.NUMBER_MODE,e.QUOTE_STRING_MODE,t,n]}}),e.registerLanguage(\"php\",function(e){var t={className:\"variable\",begin:\"\\\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*\"},n={className:\"preprocessor\",begin:/<\\?(php)?|\\?>/},i={className:\"string\",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:'b\"',end:'\"'},{begin:\"b'\",end:\"'\"},e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null})]},r={variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]};return{aliases:[\"php3\",\"php4\",\"php5\",\"php6\"],case_insensitive:!0,keywords:\"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally\",contains:[e.C_LINE_COMMENT_MODE,e.HASH_COMMENT_MODE,e.COMMENT(\"/\\\\*\",\"\\\\*/\",{contains:[{className:\"doctag\",begin:\"@[A-Za-z]+\"},n]}),e.COMMENT(\"__halt_compiler.+?;\",!1,{endsWithParent:!0,keywords:\"__halt_compiler\",lexemes:e.UNDERSCORE_IDENT_RE}),{className:\"string\",begin:/<<<['\"]?\\w+['\"]?$/,end:/^\\w+;?$/,contains:[e.BACKSLASH_ESCAPE,{className:\"subst\",variants:[{begin:/\\$\\w+/},{begin:/\\{\\$/,end:/\\}/}]}]},n,t,{begin:/(::|->)+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/},{className:\"function\",beginKeywords:\"function\",end:/[;{]/,excludeEnd:!0,illegal:\"\\\\$|\\\\[|%\",contains:[e.UNDERSCORE_TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:[\"self\",t,e.C_BLOCK_COMMENT_MODE,i,r]}]},{className:\"class\",beginKeywords:\"class interface\",end:\"{\",excludeEnd:!0,illegal:/[:\\(\\$\"]/,contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:\"namespace\",end:\";\",illegal:/[\\.']/,contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:\"use\",end:\";\",contains:[e.UNDERSCORE_TITLE_MODE]},{begin:\"=>\"},i,r]}}),e.registerLanguage(\"powershell\",function(e){var t={begin:\"`[\\\\s\\\\S]\",relevance:0},n={className:\"variable\",variants:[{begin:/\\$[\\w\\d][\\w\\d_:]*/}]},i={className:\"string\",begin:/\"/,end:/\"/,contains:[t,n,{className:\"variable\",begin:/\\$[A-z]/,end:/[^A-z]/}]},r={className:\"string\",begin:/'/,end:/'/};return{aliases:[\"ps\"],lexemes:/-?[A-z\\.\\-]+/,case_insensitive:!0,keywords:{keyword:\"if else foreach return function do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch\",literal:\"$null $true $false\",built_in:\"Add-Content Add-History Add-Member Add-PSSnapin Clear-Content Clear-Item Clear-Item Property Clear-Variable Compare-Object ConvertFrom-SecureString Convert-Path ConvertTo-Html ConvertTo-SecureString Copy-Item Copy-ItemProperty Export-Alias Export-Clixml Export-Console Export-Csv ForEach-Object Format-Custom Format-List Format-Table Format-Wide Get-Acl Get-Alias Get-AuthenticodeSignature Get-ChildItem Get-Command Get-Content Get-Credential Get-Culture Get-Date Get-EventLog Get-ExecutionPolicy Get-Help Get-History Get-Host Get-Item Get-ItemProperty Get-Location Get-Member Get-PfxCertificate Get-Process Get-PSDrive Get-PSProvider Get-PSSnapin Get-Service Get-TraceSource Get-UICulture Get-Unique Get-Variable Get-WmiObject Group-Object Import-Alias Import-Clixml Import-Csv Invoke-Expression Invoke-History Invoke-Item Join-Path Measure-Command Measure-Object Move-Item Move-ItemProperty New-Alias New-Item New-ItemProperty New-Object New-PSDrive New-Service New-TimeSpan New-Variable Out-Default Out-File Out-Host Out-Null Out-Printer Out-String Pop-Location Push-Location Read-Host Remove-Item Remove-ItemProperty Remove-PSDrive Remove-PSSnapin Remove-Variable Rename-Item Rename-ItemProperty Resolve-Path Restart-Service Resume-Service Select-Object Select-String Set-Acl Set-Alias Set-AuthenticodeSignature Set-Content Set-Date Set-ExecutionPolicy Set-Item Set-ItemProperty Set-Location Set-PSDebug Set-Service Set-TraceSource Set-Variable Sort-Object Split-Path Start-Service Start-Sleep Start-Transcript Stop-Process Stop-Service Stop-Transcript Suspend-Service Tee-Object Test-Path Trace-Command Update-FormatData Update-TypeData Where-Object Write-Debug Write-Error Write-Host Write-Output Write-Progress Write-Verbose Write-Warning\",operator:\"-ne -eq -lt -gt -ge -le -not -like -notlike -match -notmatch -contains -notcontains -in -notin -replace\"},contains:[e.HASH_COMMENT_MODE,e.NUMBER_MODE,i,r,n]}}),e.registerLanguage(\"processing\",function(e){return{keywords:{keyword:\"BufferedReader PVector PFont PImage PGraphics HashMap boolean byte char color double float int long String Array FloatDict FloatList IntDict IntList JSONArray JSONObject Object StringDict StringList Table TableRow XML false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private\",constant:\"P2D P3D HALF_PI PI QUARTER_PI TAU TWO_PI\",variable:\"displayHeight displayWidth mouseY mouseX mousePressed pmouseX pmouseY key keyCode pixels focused frameCount frameRate height width\",title:\"setup draw\",built_in:\"size createGraphics beginDraw createShape loadShape PShape arc ellipse line point quad rect triangle bezier bezierDetail bezierPoint bezierTangent curve curveDetail curvePoint curveTangent curveTightness shape shapeMode beginContour beginShape bezierVertex curveVertex endContour endShape quadraticVertex vertex ellipseMode noSmooth rectMode smooth strokeCap strokeJoin strokeWeight mouseClicked mouseDragged mouseMoved mousePressed mouseReleased mouseWheel keyPressed keyPressedkeyReleased keyTyped print println save saveFrame day hour millis minute month second year background clear colorMode fill noFill noStroke stroke alpha blue brightness color green hue lerpColor red saturation modelX modelY modelZ screenX screenY screenZ ambient emissive shininess specular add createImage beginCamera camera endCamera frustum ortho perspective printCamera printProjection cursor frameRate noCursor exit loop noLoop popStyle pushStyle redraw binary boolean byte char float hex int str unbinary unhex join match matchAll nf nfc nfp nfs split splitTokens trim append arrayCopy concat expand reverse shorten sort splice subset box sphere sphereDetail createInput createReader loadBytes loadJSONArray loadJSONObject loadStrings loadTable loadXML open parseXML saveTable selectFolder selectInput beginRaw beginRecord createOutput createWriter endRaw endRecord PrintWritersaveBytes saveJSONArray saveJSONObject saveStream saveStrings saveXML selectOutput popMatrix printMatrix pushMatrix resetMatrix rotate rotateX rotateY rotateZ scale shearX shearY translate ambientLight directionalLight lightFalloff lights lightSpecular noLights normal pointLight spotLight image imageMode loadImage noTint requestImage tint texture textureMode textureWrap blend copy filter get loadPixels set updatePixels blendMode loadShader PShaderresetShader shader createFont loadFont text textFont textAlign textLeading textMode textSize textWidth textAscent textDescent abs ceil constrain dist exp floor lerp log mag map max min norm pow round sq sqrt acos asin atan atan2 cos degrees radians sin tan noise noiseDetail noiseSeed random randomGaussian randomSeed\"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE]}}),e.registerLanguage(\"profile\",function(e){return{contains:[e.C_NUMBER_MODE,{className:\"built_in\",begin:\"{\",end:\"}$\",excludeBegin:!0,excludeEnd:!0,contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE],relevance:0},{className:\"filename\",begin:\"[a-zA-Z_][\\\\da-zA-Z_]+\\\\.[\\\\da-zA-Z_]{1,3}\",end:\":\",excludeEnd:!0},{className:\"header\",begin:\"(ncalls|tottime|cumtime)\",end:\"$\",keywords:\"ncalls tottime|10 cumtime|10 filename\",relevance:10},{className:\"summary\",begin:\"function calls\",end:\"$\",contains:[e.C_NUMBER_MODE],relevance:10},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:\"function\",begin:\"\\\\(\",end:\"\\\\)$\",contains:[e.UNDERSCORE_TITLE_MODE],relevance:0}]}}),e.registerLanguage(\"prolog\",function(e){var t={className:\"atom\",begin:/[a-z][A-Za-z0-9_]*/,relevance:0},n={className:\"name\",variants:[{begin:/[A-Z][a-zA-Z0-9_]*/},{begin:/_[A-Za-z0-9_]*/}],relevance:0},i={begin:/\\(/,end:/\\)/,relevance:0},r={begin:/\\[/,end:/\\]/},a={className:\"comment\",begin:/%/,end:/$/,contains:[e.PHRASAL_WORDS_MODE]},o={className:\"string\",begin:/`/,end:/`/,contains:[e.BACKSLASH_ESCAPE]},s={className:\"string\",begin:/0\\'(\\\\\\'|.)/},l={className:\"string\",begin:/0\\'\\\\s/},c={begin:/:-/},d=[t,n,i,c,r,a,e.C_BLOCK_COMMENT_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,o,s,l,e.C_NUMBER_MODE];return i.contains=d,r.contains=d,{contains:d.concat([{begin:/\\.$/}])}}),e.registerLanguage(\"protobuf\",function(e){return{keywords:{keyword:\"package import option optional required repeated group\",built_in:\"double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes\",literal:\"true false\"},contains:[e.QUOTE_STRING_MODE,e.NUMBER_MODE,e.C_LINE_COMMENT_MODE,{className:\"class\",beginKeywords:\"message enum service\",end:/\\{/,illegal:/\\n/,contains:[e.inherit(e.TITLE_MODE,{starts:{endsWithParent:!0,excludeEnd:!0}})]},{className:\"function\",beginKeywords:\"rpc\",end:/;/,excludeEnd:!0,keywords:\"rpc returns\"},{className:\"constant\",begin:/^\\s*[A-Z_]+/,end:/\\s*=/,excludeEnd:!0}]}}),e.registerLanguage(\"puppet\",function(e){var t={keyword:\"and case default else elsif false if in import enherits node or true undef unless main settings $string \",literal:\"alias audit before loglevel noop require subscribe tag owner ensure group mode name|0 changes context force incl lens load_path onlyif provider returns root show_diff type_check en_address ip_address realname command environment hour monute month monthday special target weekday creates cwd ogoutput refresh refreshonly tries try_sleep umask backup checksum content ctime force ignore links mtime purge recurse recurselimit replace selinux_ignore_defaults selrange selrole seltype seluser source souirce_permissions sourceselect validate_cmd validate_replacement allowdupe attribute_membership auth_membership forcelocal gid ia_load_module members system host_aliases ip allowed_trunk_vlans description device_url duplex encapsulation etherchannel native_vlan speed principals allow_root auth_class auth_type authenticate_user k_of_n mechanisms rule session_owner shared options device fstype enable hasrestart directory present absent link atboot blockdevice device dump pass remounts poller_tag use message withpath adminfile allow_virtual allowcdrom category configfiles flavor install_options instance package_settings platform responsefile status uninstall_options vendor unless_system_user unless_uid binary control flags hasstatus manifest pattern restart running start stop allowdupe auths expiry gid groups home iterations key_membership keys managehome membership password password_max_age password_min_age profile_membership profiles project purge_ssh_keys role_membership roles salt shell uid baseurl cost descr enabled enablegroups exclude failovermethod gpgcheck gpgkey http_caching include includepkgs keepalive metadata_expire metalink mirrorlist priority protect proxy proxy_password proxy_username repo_gpgcheck s3_enabled skip_if_unavailable sslcacert sslclientcert sslclientkey sslverify mounted\",built_in:\"architecture augeasversion blockdevices boardmanufacturer boardproductname boardserialnumber cfkey dhcp_servers domain ec2_ ec2_userdata facterversion filesystems ldom fqdn gid hardwareisa hardwaremodel hostname id|0 interfaces ipaddress ipaddress_ ipaddress6 ipaddress6_ iphostnumber is_virtual kernel kernelmajversion kernelrelease kernelversion kernelrelease kernelversion lsbdistcodename lsbdistdescription lsbdistid lsbdistrelease lsbmajdistrelease lsbminordistrelease lsbrelease macaddress macaddress_ macosx_buildversion macosx_productname macosx_productversion macosx_productverson_major macosx_productversion_minor manufacturer memoryfree memorysize netmask metmask_ network_ operatingsystem operatingsystemmajrelease operatingsystemrelease osfamily partitions path physicalprocessorcount processor processorcount productname ps puppetversion rubysitedir rubyversion selinux selinux_config_mode selinux_config_policy selinux_current_mode selinux_current_mode selinux_enforced selinux_policyversion serialnumber sp_ sshdsakey sshecdsakey sshrsakey swapencrypted swapfree swapsize timezone type uniqueid uptime uptime_days uptime_hours uptime_seconds uuid virtual vlans xendomains zfs_version zonenae zones zpool_version\"},n=e.COMMENT(\"#\",\"$\"),i=\"([A-Za-z_]|::)(\\\\w|::)*\",r=e.inherit(e.TITLE_MODE,{begin:i}),a={className:\"variable\",begin:\"\\\\$\"+i},o={className:\"string\",contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:/'/,end:/'/},{begin:/\"/,end:/\"/}]};return{aliases:[\"pp\"],contains:[n,a,o,{beginKeywords:\"class\",end:\"\\\\{|;\",illegal:/=/,contains:[r,n]},{beginKeywords:\"define\",end:/\\{/,contains:[{className:\"title\",begin:e.IDENT_RE,endsParent:!0}]},{begin:e.IDENT_RE+\"\\\\s+\\\\{\",returnBegin:!0,end:/\\S/,contains:[{className:\"name\",begin:e.IDENT_RE},{begin:/\\{/,end:/\\}/,keywords:t,relevance:0,contains:[o,n,{begin:\"[a-zA-Z_]+\\\\s*=>\"},{className:\"number\",begin:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",relevance:0},a]}],relevance:0}]}}),e.registerLanguage(\"python\",function(e){var t={className:\"prompt\",begin:/^(>>>|\\.\\.\\.) /},n={className:\"string\",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/(u|b)?r?'''/,end:/'''/,contains:[t],relevance:10},{begin:/(u|b)?r?\"\"\"/,end:/\"\"\"/,contains:[t],relevance:10},{begin:/(u|r|ur)'/,end:/'/,relevance:10},{begin:/(u|r|ur)\"/,end:/\"/,relevance:10},{begin:/(b|br)'/,end:/'/},{begin:/(b|br)\"/,end:/\"/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},i={className:\"number\",relevance:0,variants:[{begin:e.BINARY_NUMBER_RE+\"[lLjJ]?\"},{begin:\"\\\\b(0o[0-7]+)[lLjJ]?\"},{begin:e.C_NUMBER_RE+\"[lLjJ]?\"}]},r={className:\"params\",begin:/\\(/,end:/\\)/,contains:[\"self\",t,i,n]};return{aliases:[\"py\",\"gyp\"],keywords:{keyword:\"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False\",built_in:\"Ellipsis NotImplemented\"},illegal:/(<\\/|->|\\?)/,contains:[t,i,n,e.HASH_COMMENT_MODE,{variants:[{className:\"function\",beginKeywords:\"def\",relevance:10},{className:\"class\",beginKeywords:\"class\"}],end:/:/,illegal:/[${=;\\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,r]},{className:\"decorator\",begin:/^[\\t ]*@/,end:/$/},{begin:/\\b(print|exec)\\(/}]}}),e.registerLanguage(\"q\",function(e){var t={keyword:\"do while select delete by update from\",constant:\"0b 1b\",built_in:\"neg not null string reciprocal floor ceiling signum mod xbar xlog and or each scan over prior mmu lsq inv md5 ltime gtime count first var dev med cov cor all any rand sums prds mins maxs fills deltas ratios avgs differ prev next rank reverse iasc idesc asc desc msum mcount mavg mdev xrank mmin mmax xprev rotate distinct group where flip type key til get value attr cut set upsert raze union inter except cross sv vs sublist enlist read0 read1 hopen hclose hdel hsym hcount peach system ltrim rtrim trim lower upper ssr view tables views cols xcols keys xkey xcol xasc xdesc fkeys meta lj aj aj0 ij pj asof uj ww wj wj1 fby xgroup ungroup ej save load rsave rload show csv parse eval min max avg wavg wsum sin cos tan sum\",typename:\"`float `double int `timestamp `timespan `datetime `time `boolean `symbol `char `byte `short `long `real `month `date `minute `second `guid\"};return{aliases:[\"k\",\"kdb\"],keywords:t,lexemes:/\\b(`?)[A-Za-z0-9_]+\\b/,contains:[e.C_LINE_COMMENT_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE]}}),e.registerLanguage(\"r\",function(e){var t=\"([a-zA-Z]|\\\\.[a-zA-Z.])[a-zA-Z0-9._]*\";return{contains:[e.HASH_COMMENT_MODE,{begin:t,lexemes:t,keywords:{keyword:\"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...\",literal:\"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10\"},relevance:0},{className:\"number\",begin:\"0[xX][0-9a-fA-F]+[Li]?\\\\b\",relevance:0},{className:\"number\",begin:\"\\\\d+(?:[eE][+\\\\-]?\\\\d*)?L\\\\b\",relevance:0},{className:\"number\",begin:\"\\\\d+\\\\.(?!\\\\d)(?:i\\\\b)?\",relevance:0},{className:\"number\",begin:\"\\\\d+(?:\\\\.\\\\d*)?(?:[eE][+\\\\-]?\\\\d*)?i?\\\\b\",relevance:0},{className:\"number\",begin:\"\\\\.\\\\d+(?:[eE][+\\\\-]?\\\\d*)?i?\\\\b\",relevance:0},{begin:\"`\",end:\"`\",relevance:0},{className:\"string\",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:'\"',end:'\"'},{begin:\"'\",end:\"'\"}]}]}}),e.registerLanguage(\"rib\",function(e){return{keywords:\"ArchiveRecord AreaLightSource Atmosphere Attribute AttributeBegin AttributeEnd Basis Begin Blobby Bound Clipping ClippingPlane Color ColorSamples ConcatTransform Cone CoordinateSystem CoordSysTransform CropWindow Curves Cylinder DepthOfField Detail DetailRange Disk Displacement Display End ErrorHandler Exposure Exterior Format FrameAspectRatio FrameBegin FrameEnd GeneralPolygon GeometricApproximation Geometry Hider Hyperboloid Identity Illuminate Imager Interior LightSource MakeCubeFaceEnvironment MakeLatLongEnvironment MakeShadow MakeTexture Matte MotionBegin MotionEnd NuPatch ObjectBegin ObjectEnd ObjectInstance Opacity Option Orientation Paraboloid Patch PatchMesh Perspective PixelFilter PixelSamples PixelVariance Points PointsGeneralPolygons PointsPolygons Polygon Procedural Projection Quantize ReadArchive RelativeDetail ReverseOrientation Rotate Scale ScreenWindow ShadingInterpolation ShadingRate Shutter Sides Skew SolidBegin SolidEnd Sphere SubdivisionMesh Surface TextureCoordinates Torus Transform TransformBegin TransformEnd TransformPoints Translate TrimCurve WorldBegin WorldEnd\",illegal:\"</\",contains:[e.HASH_COMMENT_MODE,e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]}}),e.registerLanguage(\"roboconf\",function(e){var t=\"[a-zA-Z-_][^\\n{\\r\\n]+\\\\{\";return{aliases:[\"graph\",\"instances\"],case_insensitive:!0,keywords:\"import\",contains:[{className:\"facet\",begin:\"^facet \"+t,end:\"}\",keywords:\"facet installer exports children extends\",contains:[e.HASH_COMMENT_MODE]},{className:\"instance-of\",begin:\"^instance of \"+t,end:\"}\",keywords:\"name count channels instance-data instance-state instance of\",contains:[{className:\"keyword\",begin:\"[a-zA-Z-_]+( |\t)*:\"},e.HASH_COMMENT_MODE]},{className:\"component\",begin:\"^\"+t,end:\"}\",lexemes:\"\\\\(?[a-zA-Z]+\\\\)?\",keywords:\"installer exports children extends imports facets alias (optional)\",contains:[{className:\"string\",begin:\"\\\\.[a-zA-Z-_]+\",end:\"\\\\s|,|;\",excludeEnd:!0},e.HASH_COMMENT_MODE]},e.HASH_COMMENT_MODE]}}),e.registerLanguage(\"rsl\",function(e){return{keywords:{keyword:\"float color point normal vector matrix while for if do return else break extern continue\",built_in:\"abs acos ambient area asin atan atmosphere attribute calculatenormal ceil cellnoise clamp comp concat cos degrees depth Deriv diffuse distance Du Dv environment exp faceforward filterstep floor format fresnel incident length lightsource log match max min mod noise normalize ntransform opposite option phong pnoise pow printf ptlined radians random reflect refract renderinfo round setcomp setxcomp setycomp setzcomp shadow sign sin smoothstep specular specularbrdf spline sqrt step tan texture textureinfo trace transform vtransform xcomp ycomp zcomp\"},illegal:\"</\",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_NUMBER_MODE,{className:\"preprocessor\",begin:\"#\",end:\"$\"},{className:\"shader\",beginKeywords:\"surface displacement light volume imager\",end:\"\\\\(\"},{className:\"shading\",beginKeywords:\"illuminate illuminance gather\",end:\"\\\\(\"}]}}),e.registerLanguage(\"ruleslanguage\",function(e){return{keywords:{keyword:\"BILL_PERIOD BILL_START BILL_STOP RS_EFFECTIVE_START RS_EFFECTIVE_STOP RS_JURIS_CODE RS_OPCO_CODE INTDADDATTRIBUTE|5 INTDADDVMSG|5 INTDBLOCKOP|5 INTDBLOCKOPNA|5 INTDCLOSE|5 INTDCOUNT|5 INTDCOUNTSTATUSCODE|5 INTDCREATEMASK|5 INTDCREATEDAYMASK|5 INTDCREATEFACTORMASK|5 INTDCREATEHANDLE|5 INTDCREATEOVERRIDEDAYMASK|5 INTDCREATEOVERRIDEMASK|5 INTDCREATESTATUSCODEMASK|5 INTDCREATETOUPERIOD|5 INTDDELETE|5 INTDDIPTEST|5 INTDEXPORT|5 INTDGETERRORCODE|5 INTDGETERRORMESSAGE|5 INTDISEQUAL|5 INTDJOIN|5 INTDLOAD|5 INTDLOADACTUALCUT|5 INTDLOADDATES|5 INTDLOADHIST|5 INTDLOADLIST|5 INTDLOADLISTDATES|5 INTDLOADLISTENERGY|5 INTDLOADLISTHIST|5 INTDLOADRELATEDCHANNEL|5 INTDLOADSP|5 INTDLOADSTAGING|5 INTDLOADUOM|5 INTDLOADUOMDATES|5 INTDLOADUOMHIST|5 INTDLOADVERSION|5 INTDOPEN|5 INTDREADFIRST|5 INTDREADNEXT|5 INTDRECCOUNT|5 INTDRELEASE|5 INTDREPLACE|5 INTDROLLAVG|5 INTDROLLPEAK|5 INTDSCALAROP|5 INTDSCALE|5 INTDSETATTRIBUTE|5 INTDSETDSTPARTICIPANT|5 INTDSETSTRING|5 INTDSETVALUE|5 INTDSETVALUESTATUS|5 INTDSHIFTSTARTTIME|5 INTDSMOOTH|5 INTDSORT|5 INTDSPIKETEST|5 INTDSUBSET|5 INTDTOU|5 INTDTOURELEASE|5 INTDTOUVALUE|5 INTDUPDATESTATS|5 INTDVALUE|5 STDEV INTDDELETEEX|5 INTDLOADEXACTUAL|5 INTDLOADEXCUT|5 INTDLOADEXDATES|5 INTDLOADEX|5 INTDLOADEXRELATEDCHANNEL|5 INTDSAVEEX|5 MVLOAD|5 MVLOADACCT|5 MVLOADACCTDATES|5 MVLOADACCTHIST|5 MVLOADDATES|5 MVLOADHIST|5 MVLOADLIST|5 MVLOADLISTDATES|5 MVLOADLISTHIST|5 IF FOR NEXT DONE SELECT END CALL ABORT CLEAR CHANNEL FACTOR LIST NUMBER OVERRIDE SET WEEK DISTRIBUTIONNODE ELSE WHEN THEN OTHERWISE IENUM CSV INCLUDE LEAVE RIDER SAVE DELETE NOVALUE SECTION WARN SAVE_UPDATE DETERMINANT LABEL REPORT REVENUE EACH IN FROM TOTAL CHARGE BLOCK AND OR CSV_FILE RATE_CODE AUXILIARY_DEMAND UIDACCOUNT RS BILL_PERIOD_SELECT HOURS_PER_MONTH INTD_ERROR_STOP SEASON_SCHEDULE_NAME ACCOUNTFACTOR ARRAYUPPERBOUND CALLSTOREDPROC GETADOCONNECTION GETCONNECT GETDATASOURCE GETQUALIFIER GETUSERID HASVALUE LISTCOUNT LISTOP LISTUPDATE LISTVALUE PRORATEFACTOR RSPRORATE SETBINPATH SETDBMONITOR WQ_OPEN BILLINGHOURS DATE DATEFROMFLOAT DATETIMEFROMSTRING DATETIMETOSTRING DATETOFLOAT DAY DAYDIFF DAYNAME DBDATETIME HOUR MINUTE MONTH MONTHDIFF MONTHHOURS MONTHNAME ROUNDDATE SAMEWEEKDAYLASTYEAR SECOND WEEKDAY WEEKDIFF YEAR YEARDAY YEARSTR COMPSUM HISTCOUNT HISTMAX HISTMIN HISTMINNZ HISTVALUE MAXNRANGE MAXRANGE MINRANGE COMPIKVA COMPKVA COMPKVARFROMKQKW COMPLF IDATTR FLAG LF2KW LF2KWH MAXKW POWERFACTOR READING2USAGE AVGSEASON MAXSEASON MONTHLYMERGE SEASONVALUE SUMSEASON ACCTREADDATES ACCTTABLELOAD CONFIGADD CONFIGGET CREATEOBJECT CREATEREPORT EMAILCLIENT EXPBLKMDMUSAGE EXPMDMUSAGE EXPORT_USAGE FACTORINEFFECT GETUSERSPECIFIEDSTOP INEFFECT ISHOLIDAY RUNRATE SAVE_PROFILE SETREPORTTITLE USEREXIT WATFORRUNRATE TO TABLE ACOS ASIN ATAN ATAN2 BITAND CEIL COS COSECANT COSH COTANGENT DIVQUOT DIVREM EXP FABS FLOOR FMOD FREPM FREXPN LOG LOG10 MAX MAXN MIN MINNZ MODF POW ROUND ROUND2VALUE ROUNDINT SECANT SIN SINH SQROOT TAN TANH FLOAT2STRING FLOAT2STRINGNC INSTR LEFT LEN LTRIM MID RIGHT RTRIM STRING STRINGNC TOLOWER TOUPPER TRIM NUMDAYS READ_DATE STAGING\",built_in:\"IDENTIFIER OPTIONS XML_ELEMENT XML_OP XML_ELEMENT_OF DOMDOCCREATE DOMDOCLOADFILE DOMDOCLOADXML DOMDOCSAVEFILE DOMDOCGETROOT DOMDOCADDPI DOMNODEGETNAME DOMNODEGETTYPE DOMNODEGETVALUE DOMNODEGETCHILDCT DOMNODEGETFIRSTCHILD DOMNODEGETSIBLING DOMNODECREATECHILDELEMENT DOMNODESETATTRIBUTE DOMNODEGETCHILDELEMENTCT DOMNODEGETFIRSTCHILDELEMENT DOMNODEGETSIBLINGELEMENT DOMNODEGETATTRIBUTECT DOMNODEGETATTRIBUTEI DOMNODEGETATTRIBUTEBYNAME DOMNODEGETBYNAME\"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,{className:\"array\",variants:[{begin:\"#\\\\s+[a-zA-Z\\\\ \\\\.]*\",\nrelevance:0},{begin:\"#[a-zA-Z\\\\ \\\\.]+\"}]}]}}),e.registerLanguage(\"rust\",function(e){var t=\"([uif](8|16|32|64|size))?\",n=e.inherit(e.C_BLOCK_COMMENT_MODE);return n.contains.push(\"self\"),{aliases:[\"rs\"],keywords:{keyword:\"alignof as be box break const continue crate do else enum extern false fn for if impl in let loop match mod mut offsetof once priv proc pub pure ref return self Self sizeof static struct super trait true type typeof unsafe unsized use virtual while where yield int i8 i16 i32 i64 uint u8 u32 u64 float f32 f64 str char bool\",built_in:\"Copy Send Sized Sync Drop Fn FnMut FnOnce drop Box ToOwned Clone PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator Option Some None Result Ok Err SliceConcatExt String ToString Vec assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln!\"},lexemes:e.IDENT_RE+\"!?\",illegal:\"</\",contains:[e.C_LINE_COMMENT_MODE,n,e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:\"string\",variants:[{begin:/r(#*)\".*?\"\\1(?!#)/},{begin:/'\\\\?(x\\w{2}|u\\w{4}|U\\w{8}|.)'/},{begin:/'[a-zA-Z_][a-zA-Z0-9_]*/}]},{className:\"number\",variants:[{begin:\"\\\\b0b([01_]+)\"+t},{begin:\"\\\\b0o([0-7_]+)\"+t},{begin:\"\\\\b0x([A-Fa-f0-9_]+)\"+t},{begin:\"\\\\b(\\\\d[\\\\d_]*(\\\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)\"+t}],relevance:0},{className:\"function\",beginKeywords:\"fn\",end:\"(\\\\(|<)\",excludeEnd:!0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:\"preprocessor\",begin:\"#\\\\!?\\\\[\",end:\"\\\\]\"},{beginKeywords:\"type\",end:\"(=|<)\",contains:[e.UNDERSCORE_TITLE_MODE],illegal:\"\\\\S\"},{beginKeywords:\"trait enum\",end:\"{\",contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{endsParent:!0})],illegal:\"[\\\\w\\\\d]\"},{begin:e.IDENT_RE+\"::\"},{begin:\"->\"}]}}),e.registerLanguage(\"scala\",function(e){var t={className:\"annotation\",begin:\"@[A-Za-z]+\"},n={className:\"string\",begin:'u?r?\"\"\"',end:'\"\"\"',relevance:10},i={className:\"symbol\",begin:\"'\\\\w[\\\\w\\\\d_]*(?!')\"},r={className:\"type\",begin:\"\\\\b[A-Z][A-Za-z0-9_]*\",relevance:0},a={className:\"title\",begin:/[^0-9\\n\\t \"'(),.`{}\\[\\]:;][^\\n\\t \"'(),.`{}\\[\\]:;]+|[^0-9\\n\\t \"'(),.`{}\\[\\]:;=]/,relevance:0},o={className:\"class\",beginKeywords:\"class object trait type\",end:/[:={\\[(\\n;]/,contains:[{className:\"keyword\",beginKeywords:\"extends with\",relevance:10},a]},s={className:\"function\",beginKeywords:\"def\",end:/[:={\\[(\\n;]/,contains:[a]};return{keywords:{literal:\"true false null\",keyword:\"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit\"},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n,e.QUOTE_STRING_MODE,i,r,s,o,e.C_NUMBER_MODE,t]}}),e.registerLanguage(\"scheme\",function(e){var t=\"[^\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}\\\",'`;#|\\\\\\\\\\\\s]+\",n=\"(\\\\-|\\\\+)?\\\\d+([./]\\\\d+)?\",i=n+\"[+\\\\-]\"+n+\"i\",r={built_in:\"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 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? 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?\"},a={className:\"shebang\",begin:\"^#!\",end:\"$\"},o={className:\"literal\",begin:\"(#t|#f|#\\\\\\\\\"+t+\"|#\\\\\\\\.)\"},s={className:\"number\",variants:[{begin:n,relevance:0},{begin:i,relevance:0},{begin:\"#b[0-1]+(/[0-1]+)?\"},{begin:\"#o[0-7]+(/[0-7]+)?\"},{begin:\"#x[0-9a-f]+(/[0-9a-f]+)?\"}]},l=e.QUOTE_STRING_MODE,c=[e.COMMENT(\";\",\"$\",{relevance:0}),e.COMMENT(\"#\\\\|\",\"\\\\|#\")],d={begin:t,relevance:0},u={className:\"variable\",begin:\"'\"+t},p={endsWithParent:!0,relevance:0},m={className:\"list\",variants:[{begin:\"\\\\(\",end:\"\\\\)\"},{begin:\"\\\\[\",end:\"\\\\]\"}],contains:[{className:\"keyword\",begin:t,lexemes:t,keywords:r},p]};return p.contains=[o,s,l,d,u,m].concat(c),{illegal:/\\S/,contains:[a,s,l,u,m].concat(c)}}),e.registerLanguage(\"scilab\",function(e){var t=[e.C_NUMBER_MODE,{className:\"string\",begin:\"'|\\\"\",end:\"'|\\\"\",contains:[e.BACKSLASH_ESCAPE,{begin:\"''\"}]}];return{aliases:[\"sci\"],keywords:{keyword:\"abort break case clear catch continue do elseif else endfunction end for functionglobal if pause return resume select try then while%f %F %t %T %pi %eps %inf %nan %e %i %z %s\",built_in:\"abs and acos asin atan ceil cd chdir clearglobal cosh cos cumprod deff disp errorexec execstr exists exp eye gettext floor fprintf fread fsolve imag isdef isemptyisinfisnan isvector lasterror length load linspace list listfiles log10 log2 logmax min msprintf mclose mopen ones or pathconvert poly printf prod pwd rand realround sinh sin size gsort sprintf sqrt strcat strcmps tring sum system tanh tantype typename warning zeros matrix\"},illegal:'(\"|#|/\\\\*|\\\\s+/\\\\w+)',contains:[{className:\"function\",beginKeywords:\"function endfunction\",end:\"$\",keywords:\"function endfunction|10\",contains:[e.UNDERSCORE_TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\"}]},{className:\"transposed_variable\",begin:\"[a-zA-Z_][a-zA-Z_0-9]*('+[\\\\.']*|[\\\\.']+)\",end:\"\",relevance:0},{className:\"matrix\",begin:\"\\\\[\",end:\"\\\\]'*[\\\\.']*\",relevance:0,contains:t},e.COMMENT(\"//\",\"$\")].concat(t)}}),e.registerLanguage(\"scss\",function(e){var t=\"[a-zA-Z-][a-zA-Z0-9_-]*\",n={className:\"variable\",begin:\"(\\\\$\"+t+\")\\\\b\"},i={className:\"function\",begin:t+\"\\\\(\",returnBegin:!0,excludeEnd:!0,end:\"\\\\(\"},r={className:\"hexcolor\",begin:\"#[0-9A-Fa-f]+\"};({className:\"attribute\",begin:\"[A-Z\\\\_\\\\.\\\\-]+\",end:\":\",excludeEnd:!0,illegal:\"[^\\\\s]\",starts:{className:\"value\",endsWithParent:!0,excludeEnd:!0,contains:[i,r,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"important\",begin:\"!important\"}]}});return{case_insensitive:!0,illegal:\"[=/|']\",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i,{className:\"id\",begin:\"\\\\#[A-Za-z0-9_-]+\",relevance:0},{className:\"class\",begin:\"\\\\.[A-Za-z0-9_-]+\",relevance:0},{className:\"attr_selector\",begin:\"\\\\[\",end:\"\\\\]\",illegal:\"$\"},{className:\"tag\",begin:\"\\\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\\\b\",relevance:0},{className:\"pseudo\",begin:\":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)\"},{className:\"pseudo\",begin:\"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)\"},n,{className:\"attribute\",begin:\"\\\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\\\b\",illegal:\"[^\\\\s]\"},{className:\"value\",begin:\"\\\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\\\b\"},{className:\"value\",begin:\":\",end:\";\",contains:[i,n,r,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{className:\"important\",begin:\"!important\"}]},{className:\"at_rule\",begin:\"@\",end:\"[{;]\",keywords:\"mixin include extend for if else each while charset import debug media page content font-face namespace warn\",contains:[i,n,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,r,e.CSS_NUMBER_MODE,{className:\"preprocessor\",begin:\"\\\\s[A-Za-z0-9_.-]+\",relevance:0}]}]}}),e.registerLanguage(\"smali\",function(e){var t=[\"add\",\"and\",\"cmp\",\"cmpg\",\"cmpl\",\"const\",\"div\",\"double\",\"float\",\"goto\",\"if\",\"int\",\"long\",\"move\",\"mul\",\"neg\",\"new\",\"nop\",\"not\",\"or\",\"rem\",\"return\",\"shl\",\"shr\",\"sput\",\"sub\",\"throw\",\"ushr\",\"xor\"],n=[\"aget\",\"aput\",\"array\",\"check\",\"execute\",\"fill\",\"filled\",\"goto/16\",\"goto/32\",\"iget\",\"instance\",\"invoke\",\"iput\",\"monitor\",\"packed\",\"sget\",\"sparse\"],i=[\"transient\",\"constructor\",\"abstract\",\"final\",\"synthetic\",\"public\",\"private\",\"protected\",\"static\",\"bridge\",\"system\"];return{aliases:[\"smali\"],contains:[{className:\"string\",begin:'\"',end:'\"',relevance:0},e.COMMENT(\"#\",\"$\",{relevance:0}),{className:\"keyword\",begin:\"\\\\s*\\\\.end\\\\s[a-zA-Z0-9]*\",relevance:1},{className:\"keyword\",begin:\"^[ ]*\\\\.[a-zA-Z]*\",relevance:0},{className:\"keyword\",begin:\"\\\\s:[a-zA-Z_0-9]*\",relevance:0},{className:\"keyword\",begin:\"\\\\s(\"+i.join(\"|\")+\")\",relevance:1},{className:\"keyword\",begin:\"\\\\[\",relevance:0},{className:\"instruction\",begin:\"\\\\s(\"+t.join(\"|\")+\")\\\\s\",relevance:1},{className:\"instruction\",begin:\"\\\\s(\"+t.join(\"|\")+\")((\\\\-|/)[a-zA-Z0-9]+)+\\\\s\",relevance:10},{className:\"instruction\",begin:\"\\\\s(\"+n.join(\"|\")+\")((\\\\-|/)[a-zA-Z0-9]+)*\\\\s\",relevance:10},{className:\"class\",begin:\"L[^(;:\\n]*;\",relevance:0},{className:\"function\",begin:'( |->)[^(\\n ;\"]*\\\\(',relevance:0},{className:\"function\",begin:\"\\\\)\",relevance:0},{className:\"variable\",begin:\"[vp][0-9]+\",relevance:0}]}}),e.registerLanguage(\"smalltalk\",function(e){var t=\"[a-z][a-zA-Z0-9_]*\",n={className:\"char\",begin:\"\\\\$.{1}\"},i={className:\"symbol\",begin:\"#\"+e.UNDERSCORE_IDENT_RE};return{aliases:[\"st\"],keywords:\"self super nil true false thisContext\",contains:[e.COMMENT('\"','\"'),e.APOS_STRING_MODE,{className:\"class\",begin:\"\\\\b[A-Z][A-Za-z0-9_]*\",relevance:0},{className:\"method\",begin:t+\":\",relevance:0},e.C_NUMBER_MODE,i,n,{className:\"localvars\",begin:\"\\\\|[ ]*\"+t+\"([ ]+\"+t+\")*[ ]*\\\\|\",returnBegin:!0,end:/\\|/,illegal:/\\S/,contains:[{begin:\"(\\\\|[ ]*)?\"+t}]},{className:\"array\",begin:\"\\\\#\\\\(\",end:\"\\\\)\",contains:[e.APOS_STRING_MODE,n,e.C_NUMBER_MODE,i]}]}}),e.registerLanguage(\"sml\",function(e){return{aliases:[\"ml\"],keywords:{keyword:\"abstype and andalso as case datatype do else end eqtype exception fn fun functor handle if in include infix infixr let local nonfix of op open orelse raise rec sharing sig signature struct structure then type val with withtype where while\",built_in:\"array bool char exn int list option order real ref string substring vector unit word\",literal:\"true false NONE SOME LESS EQUAL GREATER nil\"},illegal:/\\/\\/|>>/,lexemes:\"[a-z_]\\\\w*!?\",contains:[{className:\"literal\",begin:\"\\\\[(\\\\|\\\\|)?\\\\]|\\\\(\\\\)\"},e.COMMENT(\"\\\\(\\\\*\",\"\\\\*\\\\)\",{contains:[\"self\"]}),{className:\"symbol\",begin:\"'[A-Za-z_](?!')[\\\\w']*\"},{className:\"tag\",begin:\"`[A-Z][\\\\w']*\"},{className:\"type\",begin:\"\\\\b[A-Z][\\\\w']*\",relevance:0},{begin:\"[a-z_]\\\\w*'[\\\\w']*\"},e.inherit(e.APOS_STRING_MODE,{className:\"char\",relevance:0}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:\"number\",begin:\"\\\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)\",relevance:0},{begin:/[-=]>/}]}}),e.registerLanguage(\"sqf\",function(e){var t=[\"!\",\"-\",\"+\",\"!=\",\"%\",\"&&\",\"*\",\"/\",\"=\",\"==\",\">\",\">=\",\"<\",\"<=\",\"or\",\"plus\",\"^\",\":\",\">>\",\"abs\",\"accTime\",\"acos\",\"action\",\"actionKeys\",\"actionKeysImages\",\"actionKeysNames\",\"actionKeysNamesArray\",\"actionName\",\"activateAddons\",\"activatedAddons\",\"activateKey\",\"addAction\",\"addBackpack\",\"addBackpackCargo\",\"addBackpackCargoGlobal\",\"addBackpackGlobal\",\"addCamShake\",\"addCuratorAddons\",\"addCuratorCameraArea\",\"addCuratorEditableObjects\",\"addCuratorEditingArea\",\"addCuratorPoints\",\"addEditorObject\",\"addEventHandler\",\"addGoggles\",\"addGroupIcon\",\"addHandgunItem\",\"addHeadgear\",\"addItem\",\"addItemCargo\",\"addItemCargoGlobal\",\"addItemPool\",\"addItemToBackpack\",\"addItemToUniform\",\"addItemToVest\",\"addLiveStats\",\"addMagazine\",\"addMagazine array\",\"addMagazineAmmoCargo\",\"addMagazineCargo\",\"addMagazineCargoGlobal\",\"addMagazineGlobal\",\"addMagazinePool\",\"addMagazines\",\"addMagazineTurret\",\"addMenu\",\"addMenuItem\",\"addMissionEventHandler\",\"addMPEventHandler\",\"addMusicEventHandler\",\"addPrimaryWeaponItem\",\"addPublicVariableEventHandler\",\"addRating\",\"addResources\",\"addScore\",\"addScoreSide\",\"addSecondaryWeaponItem\",\"addSwitchableUnit\",\"addTeamMember\",\"addToRemainsCollector\",\"addUniform\",\"addVehicle\",\"addVest\",\"addWaypoint\",\"addWeapon\",\"addWeaponCargo\",\"addWeaponCargoGlobal\",\"addWeaponGlobal\",\"addWeaponPool\",\"addWeaponTurret\",\"agent\",\"agents\",\"AGLToASL\",\"aimedAtTarget\",\"aimPos\",\"airDensityRTD\",\"airportSide\",\"AISFinishHeal\",\"alive\",\"allControls\",\"allCurators\",\"allDead\",\"allDeadMen\",\"allDisplays\",\"allGroups\",\"allMapMarkers\",\"allMines\",\"allMissionObjects\",\"allow3DMode\",\"allowCrewInImmobile\",\"allowCuratorLogicIgnoreAreas\",\"allowDamage\",\"allowDammage\",\"allowFileOperations\",\"allowFleeing\",\"allowGetIn\",\"allPlayers\",\"allSites\",\"allTurrets\",\"allUnits\",\"allUnitsUAV\",\"allVariables\",\"ammo\",\"and\",\"animate\",\"animateDoor\",\"animationPhase\",\"animationState\",\"append\",\"armoryPoints\",\"arrayIntersect\",\"asin\",\"ASLToAGL\",\"ASLToATL\",\"assert\",\"assignAsCargo\",\"assignAsCargoIndex\",\"assignAsCommander\",\"assignAsDriver\",\"assignAsGunner\",\"assignAsTurret\",\"assignCurator\",\"assignedCargo\",\"assignedCommander\",\"assignedDriver\",\"assignedGunner\",\"assignedItems\",\"assignedTarget\",\"assignedTeam\",\"assignedVehicle\",\"assignedVehicleRole\",\"assignItem\",\"assignTeam\",\"assignToAirport\",\"atan\",\"atan2\",\"atg\",\"ATLToASL\",\"attachedObject\",\"attachedObjects\",\"attachedTo\",\"attachObject\",\"attachTo\",\"attackEnabled\",\"backpack\",\"backpackCargo\",\"backpackContainer\",\"backpackItems\",\"backpackMagazines\",\"backpackSpaceFor\",\"behaviour\",\"benchmark\",\"binocular\",\"blufor\",\"boundingBox\",\"boundingBoxReal\",\"boundingCenter\",\"breakOut\",\"breakTo\",\"briefingName\",\"buildingExit\",\"buildingPos\",\"buttonAction\",\"buttonSetAction\",\"cadetMode\",\"call\",\"callExtension\",\"camCommand\",\"camCommit\",\"camCommitPrepared\",\"camCommitted\",\"camConstuctionSetParams\",\"camCreate\",\"camDestroy\",\"cameraEffect\",\"cameraEffectEnableHUD\",\"cameraInterest\",\"cameraOn\",\"cameraView\",\"campaignConfigFile\",\"camPreload\",\"camPreloaded\",\"camPrepareBank\",\"camPrepareDir\",\"camPrepareDive\",\"camPrepareFocus\",\"camPrepareFov\",\"camPrepareFovRange\",\"camPreparePos\",\"camPrepareRelPos\",\"camPrepareTarget\",\"camSetBank\",\"camSetDir\",\"camSetDive\",\"camSetFocus\",\"camSetFov\",\"camSetFovRange\",\"camSetPos\",\"camSetRelPos\",\"camSetTarget\",\"camTarget\",\"camUseNVG\",\"canAdd\",\"canAddItemToBackpack\",\"canAddItemToUniform\",\"canAddItemToVest\",\"cancelSimpleTaskDestination\",\"canFire\",\"canMove\",\"canSlingLoad\",\"canStand\",\"canUnloadInCombat\",\"captive\",\"captiveNum\",\"case\",\"catch\",\"cbChecked\",\"cbSetChecked\",\"ceil\",\"cheatsEnabled\",\"checkAIFeature\",\"civilian\",\"className\",\"clearAllItemsFromBackpack\",\"clearBackpackCargo\",\"clearBackpackCargoGlobal\",\"clearGroupIcons\",\"clearItemCargo\",\"clearItemCargoGlobal\",\"clearItemPool\",\"clearMagazineCargo\",\"clearMagazineCargoGlobal\",\"clearMagazinePool\",\"clearOverlay\",\"clearRadio\",\"clearWeaponCargo\",\"clearWeaponCargoGlobal\",\"clearWeaponPool\",\"closeDialog\",\"closeDisplay\",\"closeOverlay\",\"collapseObjectTree\",\"combatMode\",\"commandArtilleryFire\",\"commandChat\",\"commander\",\"commandFire\",\"commandFollow\",\"commandFSM\",\"commandGetOut\",\"commandingMenu\",\"commandMove\",\"commandRadio\",\"commandStop\",\"commandTarget\",\"commandWatch\",\"comment\",\"commitOverlay\",\"compile\",\"compileFinal\",\"completedFSM\",\"composeText\",\"configClasses\",\"configFile\",\"configHierarchy\",\"configName\",\"configProperties\",\"configSourceMod\",\"configSourceModList\",\"connectTerminalToUAV\",\"controlNull\",\"controlsGroupCtrl\",\"copyFromClipboard\",\"copyToClipboard\",\"copyWaypoints\",\"cos\",\"count\",\"countEnemy\",\"countFriendly\",\"countSide\",\"countType\",\"countUnknown\",\"createAgent\",\"createCenter\",\"createDialog\",\"createDiaryLink\",\"createDiaryRecord\",\"createDiarySubject\",\"createDisplay\",\"createGearDialog\",\"createGroup\",\"createGuardedPoint\",\"createLocation\",\"createMarker\",\"createMarkerLocal\",\"createMenu\",\"createMine\",\"createMissionDisplay\",\"createSimpleTask\",\"createSite\",\"createSoundSource\",\"createTask\",\"createTeam\",\"createTrigger\",\"createUnit\",\"createUnit array\",\"createVehicle\",\"createVehicle array\",\"createVehicleCrew\",\"createVehicleLocal\",\"crew\",\"ctrlActivate\",\"ctrlAddEventHandler\",\"ctrlAutoScrollDelay\",\"ctrlAutoScrollRewind\",\"ctrlAutoScrollSpeed\",\"ctrlChecked\",\"ctrlClassName\",\"ctrlCommit\",\"ctrlCommitted\",\"ctrlCreate\",\"ctrlDelete\",\"ctrlEnable\",\"ctrlEnabled\",\"ctrlFade\",\"ctrlHTMLLoaded\",\"ctrlIDC\",\"ctrlIDD\",\"ctrlMapAnimAdd\",\"ctrlMapAnimClear\",\"ctrlMapAnimCommit\",\"ctrlMapAnimDone\",\"ctrlMapCursor\",\"ctrlMapMouseOver\",\"ctrlMapScale\",\"ctrlMapScreenToWorld\",\"ctrlMapWorldToScreen\",\"ctrlModel\",\"ctrlModelDirAndUp\",\"ctrlModelScale\",\"ctrlParent\",\"ctrlPosition\",\"ctrlRemoveAllEventHandlers\",\"ctrlRemoveEventHandler\",\"ctrlScale\",\"ctrlSetActiveColor\",\"ctrlSetAutoScrollDelay\",\"ctrlSetAutoScrollRewind\",\"ctrlSetAutoScrollSpeed\",\"ctrlSetBackgroundColor\",\"ctrlSetChecked\",\"ctrlSetEventHandler\",\"ctrlSetFade\",\"ctrlSetFocus\",\"ctrlSetFont\",\"ctrlSetFontH1\",\"ctrlSetFontH1B\",\"ctrlSetFontH2\",\"ctrlSetFontH2B\",\"ctrlSetFontH3\",\"ctrlSetFontH3B\",\"ctrlSetFontH4\",\"ctrlSetFontH4B\",\"ctrlSetFontH5\",\"ctrlSetFontH5B\",\"ctrlSetFontH6\",\"ctrlSetFontH6B\",\"ctrlSetFontHeight\",\"ctrlSetFontHeightH1\",\"ctrlSetFontHeightH2\",\"ctrlSetFontHeightH3\",\"ctrlSetFontHeightH4\",\"ctrlSetFontHeightH5\",\"ctrlSetFontHeightH6\",\"ctrlSetFontP\",\"ctrlSetFontPB\",\"ctrlSetForegroundColor\",\"ctrlSetModel\",\"ctrlSetModelDirAndUp\",\"ctrlSetModelScale\",\"ctrlSetPosition\",\"ctrlSetScale\",\"ctrlSetStructuredText\",\"ctrlSetText\",\"ctrlSetTextColor\",\"ctrlSetTooltip\",\"ctrlSetTooltipColorBox\",\"ctrlSetTooltipColorShade\",\"ctrlSetTooltipColorText\",\"ctrlShow\",\"ctrlShown\",\"ctrlText\",\"ctrlTextHeight\",\"ctrlType\",\"ctrlVisible\",\"curatorAddons\",\"curatorCamera\",\"curatorCameraArea\",\"curatorCameraAreaCeiling\",\"curatorCoef\",\"curatorEditableObjects\",\"curatorEditingArea\",\"curatorEditingAreaType\",\"curatorMouseOver\",\"curatorPoints\",\"curatorRegisteredObjects\",\"curatorSelected\",\"curatorWaypointCost\",\"currentChannel\",\"currentCommand\",\"currentMagazine\",\"currentMagazineDetail\",\"currentMagazineDetailTurret\",\"currentMagazineTurret\",\"currentMuzzle\",\"currentNamespace\",\"currentTask\",\"currentTasks\",\"currentThrowable\",\"currentVisionMode\",\"currentWaypoint\",\"currentWeapon\",\"currentWeaponMode\",\"currentWeaponTurret\",\"currentZeroing\",\"cursorTarget\",\"customChat\",\"customRadio\",\"cutFadeOut\",\"cutObj\",\"cutRsc\",\"cutText\",\"damage\",\"date\",\"dateToNumber\",\"daytime\",\"deActivateKey\",\"debriefingText\",\"debugFSM\",\"debugLog\",\"default\",\"deg\",\"deleteAt\",\"deleteCenter\",\"deleteCollection\",\"deleteEditorObject\",\"deleteGroup\",\"deleteIdentity\",\"deleteLocation\",\"deleteMarker\",\"deleteMarkerLocal\",\"deleteRange\",\"deleteResources\",\"deleteSite\",\"deleteStatus\",\"deleteTeam\",\"deleteVehicle\",\"deleteVehicleCrew\",\"deleteWaypoint\",\"detach\",\"detectedMines\",\"diag activeMissionFSMs\",\"diag activeSQFScripts\",\"diag activeSQSScripts\",\"diag captureFrame\",\"diag captureSlowFrame\",\"diag fps\",\"diag fpsMin\",\"diag frameNo\",\"diag log\",\"diag logSlowFrame\",\"diag tickTime\",\"dialog\",\"diarySubjectExists\",\"didJIP\",\"didJIPOwner\",\"difficulty\",\"difficultyEnabled\",\"difficultyEnabledRTD\",\"direction\",\"directSay\",\"disableAI\",\"disableCollisionWith\",\"disableConversation\",\"disableDebriefingStats\",\"disableSerialization\",\"disableTIEquipment\",\"disableUAVConnectability\",\"disableUserInput\",\"displayAddEventHandler\",\"displayCtrl\",\"displayNull\",\"displayRemoveAllEventHandlers\",\"displayRemoveEventHandler\",\"displaySetEventHandler\",\"dissolveTeam\",\"distance\",\"distance2D\",\"distanceSqr\",\"distributionRegion\",\"do\",\"doArtilleryFire\",\"doFire\",\"doFollow\",\"doFSM\",\"doGetOut\",\"doMove\",\"doorPhase\",\"doStop\",\"doTarget\",\"doWatch\",\"drawArrow\",\"drawEllipse\",\"drawIcon\",\"drawIcon3D\",\"drawLine\",\"drawLine3D\",\"drawLink\",\"drawLocation\",\"drawRectangle\",\"driver\",\"drop\",\"east\",\"echo\",\"editObject\",\"editorSetEventHandler\",\"effectiveCommander\",\"else\",\"emptyPositions\",\"enableAI\",\"enableAIFeature\",\"enableAttack\",\"enableCamShake\",\"enableCaustics\",\"enableCollisionWith\",\"enableCopilot\",\"enableDebriefingStats\",\"enableDiagLegend\",\"enableEndDialog\",\"enableEngineArtillery\",\"enableEnvironment\",\"enableFatigue\",\"enableGunLights\",\"enableIRLasers\",\"enableMimics\",\"enablePersonTurret\",\"enableRadio\",\"enableReload\",\"enableRopeAttach\",\"enableSatNormalOnDetail\",\"enableSaving\",\"enableSentences\",\"enableSimulation\",\"enableSimulationGlobal\",\"enableTeamSwitch\",\"enableUAVConnectability\",\"enableUAVWaypoints\",\"endLoadingScreen\",\"endMission\",\"engineOn\",\"enginesIsOnRTD\",\"enginesRpmRTD\",\"enginesTorqueRTD\",\"entities\",\"estimatedEndServerTime\",\"estimatedTimeLeft\",\"evalObjectArgument\",\"everyBackpack\",\"everyContainer\",\"exec\",\"execEditorScript\",\"execFSM\",\"execVM\",\"exit\",\"exitWith\",\"exp\",\"expectedDestination\",\"eyeDirection\",\"eyePos\",\"face\",\"faction\",\"fadeMusic\",\"fadeRadio\",\"fadeSound\",\"fadeSpeech\",\"failMission\",\"false\",\"fillWeaponsFromPool\",\"find\",\"findCover\",\"findDisplay\",\"findEditorObject\",\"findEmptyPosition\",\"findEmptyPositionReady\",\"findNearestEnemy\",\"finishMissionInit\",\"finite\",\"fire\",\"fireAtTarget\",\"firstBackpack\",\"flag\",\"flagOwner\",\"fleeing\",\"floor\",\"flyInHeight\",\"fog\",\"fogForecast\",\"fogParams\",\"for\",\"forceAddUniform\",\"forceEnd\",\"forceMap\",\"forceRespawn\",\"forceSpeed\",\"forceWalk\",\"forceWeaponFire\",\"forceWeatherChange\",\"forEach\",\"forEachMember\",\"forEachMemberAgent\",\"forEachMemberTeam\",\"format\",\"formation\",\"formationDirection\",\"formationLeader\",\"formationMembers\",\"formationPosition\",\"formationTask\",\"formatText\",\"formLeader\",\"freeLook\",\"from\",\"fromEditor\",\"fuel\",\"fullCrew\",\"gearSlotAmmoCount\",\"gearSlotData\",\"getAllHitPointsDamage\",\"getAmmoCargo\",\"getArray\",\"getArtilleryAmmo\",\"getArtilleryComputerSettings\",\"getArtilleryETA\",\"getAssignedCuratorLogic\",\"getAssignedCuratorUnit\",\"getBackpackCargo\",\"getBleedingRemaining\",\"getBurningValue\",\"getCargoIndex\",\"getCenterOfMass\",\"getClientState\",\"getConnectedUAV\",\"getDammage\",\"getDescription\",\"getDir\",\"getDirVisual\",\"getDLCs\",\"getEditorCamera\",\"getEditorMode\",\"getEditorObjectScope\",\"getElevationOffset\",\"getFatigue\",\"getFriend\",\"getFSMVariable\",\"getFuelCargo\",\"getGroupIcon\",\"getGroupIconParams\",\"getGroupIcons\",\"getHideFrom\",\"getHit\",\"getHitIndex\",\"getHitPointDamage\",\"getItemCargo\",\"getMagazineCargo\",\"getMarkerColor\",\"getMarkerPos\",\"getMarkerSize\",\"getMarkerType\",\"getMass\",\"getModelInfo\",\"getNumber\",\"getObjectArgument\",\"getObjectChildren\",\"getObjectDLC\",\"getObjectMaterials\",\"getObjectProxy\",\"getObjectTextures\",\"getObjectType\",\"getObjectViewDistance\",\"getOxygenRemaining\",\"getPersonUsedDLCs\",\"getPlayerChannel\",\"getPlayerUID\",\"getPos\",\"getPosASL\",\"getPosASLVisual\",\"getPosASLW\",\"getPosATL\",\"getPosATLVisual\",\"getPosVisual\",\"getPosWorld\",\"getRepairCargo\",\"getResolution\",\"getShadowDistance\",\"getSlingLoad\",\"getSpeed\",\"getSuppression\",\"getTerrainHeightASL\",\"getText\",\"getVariable\",\"getWeaponCargo\",\"getWPPos\",\"glanceAt\",\"globalChat\",\"globalRadio\",\"goggles\",\"goto\",\"group\",\"groupChat\",\"groupFromNetId\",\"groupIconSelectable\",\"groupIconsVisible\",\"groupId\",\"groupOwner\",\"groupRadio\",\"groupSelectedUnits\",\"groupSelectUnit\",\"grpNull\",\"gunner\",\"gusts\",\"halt\",\"handgunItems\",\"handgunMagazine\",\"handgunWeapon\",\"handsHit\",\"hasInterface\",\"hasWeapon\",\"hcAllGroups\",\"hcGroupParams\",\"hcLeader\",\"hcRemoveAllGroups\",\"hcRemoveGroup\",\"hcSelected\",\"hcSelectGroup\",\"hcSetGroup\",\"hcShowBar\",\"hcShownBar\",\"headgear\",\"hideBody\",\"hideObject\",\"hideObjectGlobal\",\"hint\",\"hintC\",\"hintCadet\",\"hintSilent\",\"hmd\",\"hostMission\",\"htmlLoad\",\"HUDMovementLevels\",\"humidity\",\"if\",\"image\",\"importAllGroups\",\"importance\",\"in\",\"incapacitatedState\",\"independent\",\"inflame\",\"inflamed\",\"inGameUISetEventHandler\",\"inheritsFrom\",\"initAmbientLife\",\"inputAction\",\"inRangeOfArtillery\",\"insertEditorObject\",\"intersect\",\"isAbleToBreathe\",\"isAgent\",\"isArray\",\"isAutoHoverOn\",\"isAutonomous\",\"isAutotest\",\"isBleeding\",\"isBurning\",\"isClass\",\"isCollisionLightOn\",\"isCopilotEnabled\",\"isDedicated\",\"isDLCAvailable\",\"isEngineOn\",\"isEqualTo\",\"isFlashlightOn\",\"isFlatEmpty\",\"isForcedWalk\",\"isFormationLeader\",\"isHidden\",\"isInRemainsCollector\",\"isInstructorFigureEnabled\",\"isIRLaserOn\",\"isKeyActive\",\"isKindOf\",\"isLightOn\",\"isLocalized\",\"isManualFire\",\"isMarkedForCollection\",\"isMultiplayer\",\"isNil\",\"isNull\",\"isNumber\",\"isObjectHidden\",\"isObjectRTD\",\"isOnRoad\",\"isPipEnabled\",\"isPlayer\",\"isRealTime\",\"isServer\",\"isShowing3DIcons\",\"isSteamMission\",\"isStreamFriendlyUIEnabled\",\"isText\",\"isTouchingGround\",\"isTurnedOut\",\"isTutHintsEnabled\",\"isUAVConnectable\",\"isUAVConnected\",\"isUniformAllowed\",\"isWalking\",\"isWeaponDeployed\",\"isWeaponRested\",\"itemCargo\",\"items\",\"itemsWithMagazines\",\"join\",\"joinAs\",\"joinAsSilent\",\"joinSilent\",\"joinString\",\"kbAddDatabase\",\"kbAddDatabaseTargets\",\"kbAddTopic\",\"kbHasTopic\",\"kbReact\",\"kbRemoveTopic\",\"kbTell\",\"kbWasSaid\",\"keyImage\",\"keyName\",\"knowsAbout\",\"land\",\"landAt\",\"landResult\",\"language\",\"laserTarget\",\"lbAdd\",\"lbClear\",\"lbColor\",\"lbCurSel\",\"lbData\",\"lbDelete\",\"lbIsSelected\",\"lbPicture\",\"lbSelection\",\"lbSetColor\",\"lbSetCurSel\",\"lbSetData\",\"lbSetPicture\",\"lbSetPictureColor\",\"lbSetPictureColorDisabled\",\"lbSetPictureColorSelected\",\"lbSetSelectColor\",\"lbSetSelectColorRight\",\"lbSetSelected\",\"lbSetTooltip\",\"lbSetValue\",\"lbSize\",\"lbSort\",\"lbSortByValue\",\"lbText\",\"lbValue\",\"leader\",\"leaderboardDeInit\",\"leaderboardGetRows\",\"leaderboardInit\",\"leaveVehicle\",\"libraryCredits\",\"libraryDisclaimers\",\"lifeState\",\"lightAttachObject\",\"lightDetachObject\",\"lightIsOn\",\"lightnings\",\"limitSpeed\",\"linearConversion\",\"lineBreak\",\"lineIntersects\",\"lineIntersectsObjs\",\"lineIntersectsSurfaces\",\"lineIntersectsWith\",\"linkItem\",\"list\",\"listObjects\",\"ln\",\"lnbAddArray\",\"lnbAddColumn\",\"lnbAddRow\",\"lnbClear\",\"lnbColor\",\"lnbCurSelRow\",\"lnbData\",\"lnbDeleteColumn\",\"lnbDeleteRow\",\"lnbGetColumnsPosition\",\"lnbPicture\",\"lnbSetColor\",\"lnbSetColumnsPos\",\"lnbSetCurSelRow\",\"lnbSetData\",\"lnbSetPicture\",\"lnbSetText\",\"lnbSetValue\",\"lnbSize\",\"lnbText\",\"lnbValue\",\"load\",\"loadAbs\",\"loadBackpack\",\"loadFile\",\"loadGame\",\"loadIdentity\",\"loadMagazine\",\"loadOverlay\",\"loadStatus\",\"loadUniform\",\"loadVest\",\"local\",\"localize\",\"locationNull\",\"locationPosition\",\"lock\",\"lockCameraTo\",\"lockCargo\",\"lockDriver\",\"locked\",\"lockedCargo\",\"lockedDriver\",\"lockedTurret\",\"lockTurret\",\"lockWP\",\"log\",\"logEntities\",\"lookAt\",\"lookAtPos\",\"magazineCargo\",\"magazines\",\"magazinesAllTurrets\",\"magazinesAmmo\",\"magazinesAmmoCargo\",\"magazinesAmmoFull\",\"magazinesDetail\",\"magazinesDetailBackpack\",\"magazinesDetailUniform\",\"magazinesDetailVest\",\"magazinesTurret\",\"magazineTurretAmmo\",\"mapAnimAdd\",\"mapAnimClear\",\"mapAnimCommit\",\"mapAnimDone\",\"mapCenterOnCamera\",\"mapGridPosition\",\"markAsFinishedOnSteam\",\"markerAlpha\",\"markerBrush\",\"markerColor\",\"markerDir\",\"markerPos\",\"markerShape\",\"markerSize\",\"markerText\",\"markerType\",\"max\",\"members\",\"min\",\"mineActive\",\"mineDetectedBy\",\"missionConfigFile\",\"missionName\",\"missionNamespace\",\"missionStart\",\"mod\",\"modelToWorld\",\"modelToWorldVisual\",\"moonIntensity\",\"morale\",\"move\",\"moveInAny\",\"moveInCargo\",\"moveInCommander\",\"moveInDriver\",\"moveInGunner\",\"moveInTurret\",\"moveObjectToEnd\",\"moveOut\",\"moveTime\",\"moveTo\",\"moveToCompleted\",\"moveToFailed\",\"musicVolume\",\"name\",\"name location\",\"nameSound\",\"nearEntities\",\"nearestBuilding\",\"nearestLocation\",\"nearestLocations\",\"nearestLocationWithDubbing\",\"nearestObject\",\"nearestObjects\",\"nearObjects\",\"nearObjectsReady\",\"nearRoads\",\"nearSupplies\",\"nearTargets\",\"needReload\",\"netId\",\"netObjNull\",\"newOverlay\",\"nextMenuItemIndex\",\"nextWeatherChange\",\"nil\",\"nMenuItems\",\"not\",\"numberToDate\",\"objectCurators\",\"objectFromNetId\",\"objectParent\",\"objNull\",\"objStatus\",\"onBriefingGroup\",\"onBriefingNotes\",\"onBriefingPlan\",\"onBriefingTeamSwitch\",\"onCommandModeChanged\",\"onDoubleClick\",\"onEachFrame\",\"onGroupIconClick\",\"onGroupIconOverEnter\",\"onGroupIconOverLeave\",\"onHCGroupSelectionChanged\",\"onMapSingleClick\",\"onPlayerConnected\",\"onPlayerDisconnected\",\"onPreloadFinished\",\"onPreloadStarted\",\"onShowNewObject\",\"onTeamSwitch\",\"openCuratorInterface\",\"openMap\",\"openYoutubeVideo\",\"opfor\",\"or\",\"orderGetIn\",\"overcast\",\"overcastForecast\",\"owner\",\"param\",\"params\",\"parseNumber\",\"parseText\",\"parsingNamespace\",\"particlesQuality\",\"pi\",\"pickWeaponPool\",\"pitch\",\"playableSlotsNumber\",\"playableUnits\",\"playAction\",\"playActionNow\",\"player\",\"playerRespawnTime\",\"playerSide\",\"playersNumber\",\"playGesture\",\"playMission\",\"playMove\",\"playMoveNow\",\"playMusic\",\"playScriptedMission\",\"playSound\",\"playSound3D\",\"position\",\"positionCameraToWorld\",\"posScreenToWorld\",\"posWorldToScreen\",\"ppEffectAdjust\",\"ppEffectCommit\",\"ppEffectCommitted\",\"ppEffectCreate\",\"ppEffectDestroy\",\"ppEffectEnable\",\"ppEffectForceInNVG\",\"precision\",\"preloadCamera\",\"preloadObject\",\"preloadSound\",\"preloadTitleObj\",\"preloadTitleRsc\",\"preprocessFile\",\"preprocessFileLineNumbers\",\"primaryWeapon\",\"primaryWeaponItems\",\"primaryWeaponMagazine\",\"priority\",\"private\",\"processDiaryLink\",\"productVersion\",\"profileName\",\"profileNamespace\",\"profileNameSteam\",\"progressLoadingScreen\",\"progressPosition\",\"progressSetPosition\",\"publicVariable\",\"publicVariableClient\",\"publicVariableServer\",\"pushBack\",\"putWeaponPool\",\"queryItemsPool\",\"queryMagazinePool\",\"queryWeaponPool\",\"rad\",\"radioChannelAdd\",\"radioChannelCreate\",\"radioChannelRemove\",\"radioChannelSetCallSign\",\"radioChannelSetLabel\",\"radioVolume\",\"rain\",\"rainbow\",\"random\",\"rank\",\"rankId\",\"rating\",\"rectangular\",\"registeredTasks\",\"registerTask\",\"reload\",\"reloadEnabled\",\"remoteControl\",\"remoteExec\",\"remoteExecCall\",\"removeAction\",\"removeAllActions\",\"removeAllAssignedItems\",\"removeAllContainers\",\"removeAllCuratorAddons\",\"removeAllCuratorCameraAreas\",\"removeAllCuratorEditingAreas\",\"removeAllEventHandlers\",\"removeAllHandgunItems\",\"removeAllItems\",\"removeAllItemsWithMagazines\",\"removeAllMissionEventHandlers\",\"removeAllMPEventHandlers\",\"removeAllMusicEventHandlers\",\"removeAllPrimaryWeaponItems\",\"removeAllWeapons\",\"removeBackpack\",\"removeBackpackGlobal\",\"removeCuratorAddons\",\"removeCuratorCameraArea\",\"removeCuratorEditableObjects\",\"removeCuratorEditingArea\",\"removeDrawIcon\",\"removeDrawLinks\",\"removeEventHandler\",\"removeFromRemainsCollector\",\"removeGoggles\",\"removeGroupIcon\",\"removeHandgunItem\",\"removeHeadgear\",\"removeItem\",\"removeItemFromBackpack\",\"removeItemFromUniform\",\"removeItemFromVest\",\"removeItems\",\"removeMagazine\",\"removeMagazineGlobal\",\"removeMagazines\",\"removeMagazinesTurret\",\"removeMagazineTurret\",\"removeMenuItem\",\"removeMissionEventHandler\",\"removeMPEventHandler\",\"removeMusicEventHandler\",\"removePrimaryWeaponItem\",\"removeSecondaryWeaponItem\",\"removeSimpleTask\",\"removeSwitchableUnit\",\"removeTeamMember\",\"removeUniform\",\"removeVest\",\"removeWeapon\",\"removeWeaponGlobal\",\"removeWeaponTurret\",\"requiredVersion\",\"resetCamShake\",\"resetSubgroupDirection\",\"resistance\",\"resize\",\"resources\",\"respawnVehicle\",\"restartEditorCamera\",\"reveal\",\"revealMine\",\"reverse\",\"reversedMouseY\",\"roadsConnectedTo\",\"roleDescription\",\"ropeAttachedObjects\",\"ropeAttachedTo\",\"ropeAttachEnabled\",\"ropeAttachTo\",\"ropeCreate\",\"ropeCut\",\"ropeEndPosition\",\"ropeLength\",\"ropes\",\"ropeUnwind\",\"ropeUnwound\",\"rotorsForcesRTD\",\"rotorsRpmRTD\",\"round\",\"runInitScript\",\"safeZoneH\",\"safeZoneW\",\"safeZoneWAbs\",\"safeZoneX\",\"safeZoneXAbs\",\"safeZoneY\",\"saveGame\",\"saveIdentity\",\"saveJoysticks\",\"saveOverlay\",\"saveProfileNamespace\",\"saveStatus\",\"saveVar\",\"savingEnabled\",\"say\",\"say2D\",\"say3D\",\"scopeName\",\"score\",\"scoreSide\",\"screenToWorld\",\"scriptDone\",\"scriptName\",\"scriptNull\",\"scudState\",\"secondaryWeapon\",\"secondaryWeaponItems\",\"secondaryWeaponMagazine\",\"select\",\"selectBestPlaces\",\"selectDiarySubject\",\"selectedEditorObjects\",\"selectEditorObject\",\"selectionPosition\",\"selectLeader\",\"selectNoPlayer\",\"selectPlayer\",\"selectWeapon\",\"selectWeaponTurret\",\"sendAUMessage\",\"sendSimpleCommand\",\"sendTask\",\"sendTaskResult\",\"sendUDPMessage\",\"serverCommand\",\"serverCommandAvailable\",\"serverCommandExecutable\",\"serverName\",\"serverTime\",\"set\",\"setAccTime\",\"setAirportSide\",\"setAmmo\",\"setAmmoCargo\",\"setAperture\",\"setApertureNew\",\"setArmoryPoints\",\"setAttributes\",\"setAutonomous\",\"setBehaviour\",\"setBleedingRemaining\",\"setCameraInterest\",\"setCamShakeDefParams\",\"setCamShakeParams\",\"setCamUseTi\",\"setCaptive\",\"setCenterOfMass\",\"setCollisionLight\",\"setCombatMode\",\"setCompassOscillation\",\"setCuratorCameraAreaCeiling\",\"setCuratorCoef\",\"setCuratorEditingAreaType\",\"setCuratorWaypointCost\",\"setCurrentChannel\",\"setCurrentTask\",\"setCurrentWaypoint\",\"setDamage\",\"setDammage\",\"setDate\",\"setDebriefingText\",\"setDefaultCamera\",\"setDestination\",\"setDetailMapBlendPars\",\"setDir\",\"setDirection\",\"setDrawIcon\",\"setDropInterval\",\"setEditorMode\",\"setEditorObjectScope\",\"setEffectCondition\",\"setFace\",\"setFaceAnimation\",\"setFatigue\",\"setFlagOwner\",\"setFlagSide\",\"setFlagTexture\",\"setFog\",\"setFog array\",\"setFormation\",\"setFormationTask\",\"setFormDir\",\"setFriend\",\"setFromEditor\",\"setFSMVariable\",\"setFuel\",\"setFuelCargo\",\"setGroupIcon\",\"setGroupIconParams\",\"setGroupIconsSelectable\",\"setGroupIconsVisible\",\"setGroupId\",\"setGroupIdGlobal\",\"setGroupOwner\",\"setGusts\",\"setHideBehind\",\"setHit\",\"setHitIndex\",\"setHitPointDamage\",\"setHorizonParallaxCoef\",\"setHUDMovementLevels\",\"setIdentity\",\"setImportance\",\"setLeader\",\"setLightAmbient\",\"setLightAttenuation\",\"setLightBrightness\",\"setLightColor\",\"setLightDayLight\",\"setLightFlareMaxDistance\",\"setLightFlareSize\",\"setLightIntensity\",\"setLightnings\",\"setLightUseFlare\",\"setLocalWindParams\",\"setMagazineTurretAmmo\",\"setMarkerAlpha\",\"setMarkerAlphaLocal\",\"setMarkerBrush\",\"setMarkerBrushLocal\",\"setMarkerColor\",\"setMarkerColorLocal\",\"setMarkerDir\",\"setMarkerDirLocal\",\"setMarkerPos\",\"setMarkerPosLocal\",\"setMarkerShape\",\"setMarkerShapeLocal\",\"setMarkerSize\",\"setMarkerSizeLocal\",\"setMarkerText\",\"setMarkerTextLocal\",\"setMarkerType\",\"setMarkerTypeLocal\",\"setMass\",\"setMimic\",\"setMousePosition\",\"setMusicEffect\",\"setMusicEventHandler\",\"setName\",\"setNameSound\",\"setObjectArguments\",\"setObjectMaterial\",\"setObjectProxy\",\"setObjectTexture\",\"setObjectTextureGlobal\",\"setObjectViewDistance\",\"setOvercast\",\"setOwner\",\"setOxygenRemaining\",\"setParticleCircle\",\"setParticleClass\",\"setParticleFire\",\"setParticleParams\",\"setParticleRandom\",\"setPilotLight\",\"setPiPEffect\",\"setPitch\",\"setPlayable\",\"setPlayerRespawnTime\",\"setPos\",\"setPosASL\",\"setPosASL2\",\"setPosASLW\",\"setPosATL\",\"setPosition\",\"setPosWorld\",\"setRadioMsg\",\"setRain\",\"setRainbow\",\"setRandomLip\",\"setRank\",\"setRectangular\",\"setRepairCargo\",\"setShadowDistance\",\"setSide\",\"setSimpleTaskDescription\",\"setSimpleTaskDestination\",\"setSimpleTaskTarget\",\"setSimulWeatherLayers\",\"setSize\",\"setSkill\",\"setSkill array\",\"setSlingLoad\",\"setSoundEffect\",\"setSpeaker\",\"setSpeech\",\"setSpeedMode\",\"setStatValue\",\"setSuppression\",\"setSystemOfUnits\",\"setTargetAge\",\"setTaskResult\",\"setTaskState\",\"setTerrainGrid\",\"setText\",\"setTimeMultiplier\",\"setTitleEffect\",\"setTriggerActivation\",\"setTriggerArea\",\"setTriggerStatements\",\"setTriggerText\",\"setTriggerTimeout\",\"setTriggerType\",\"setType\",\"setUnconscious\",\"setUnitAbility\",\"setUnitPos\",\"setUnitPosWeak\",\"setUnitRank\",\"setUnitRecoilCoefficient\",\"setUnloadInCombat\",\"setUserActionText\",\"setVariable\",\"setVectorDir\",\"setVectorDirAndUp\",\"setVectorUp\",\"setVehicleAmmo\",\"setVehicleAmmoDef\",\"setVehicleArmor\",\"setVehicleId\",\"setVehicleLock\",\"setVehiclePosition\",\"setVehicleTiPars\",\"setVehicleVarName\",\"setVelocity\",\"setVelocityTransformation\",\"setViewDistance\",\"setVisibleIfTreeCollapsed\",\"setWaves\",\"setWaypointBehaviour\",\"setWaypointCombatMode\",\"setWaypointCompletionRadius\",\"setWaypointDescription\",\"setWaypointFormation\",\"setWaypointHousePosition\",\"setWaypointLoiterRadius\",\"setWaypointLoiterType\",\"setWaypointName\",\"setWaypointPosition\",\"setWaypointScript\",\"setWaypointSpeed\",\"setWaypointStatements\",\"setWaypointTimeout\",\"setWaypointType\",\"setWaypointVisible\",\"setWeaponReloadingTime\",\"setWind\",\"setWindDir\",\"setWindForce\",\"setWindStr\",\"setWPPos\",\"show3DIcons\",\"showChat\",\"showCinemaBorder\",\"showCommandingMenu\",\"showCompass\",\"showCuratorCompass\",\"showGPS\",\"showHUD\",\"showLegend\",\"showMap\",\"shownArtilleryComputer\",\"shownChat\",\"shownCompass\",\"shownCuratorCompass\",\"showNewEditorObject\",\"shownGPS\",\"shownHUD\",\"shownMap\",\"shownPad\",\"shownRadio\",\"shownUAVFeed\",\"shownWarrant\",\"shownWatch\",\"showPad\",\"showRadio\",\"showSubtitles\",\"showUAVFeed\",\"showWarrant\",\"showWatch\",\"showWaypoint\",\"side\",\"sideChat\",\"sideEnemy\",\"sideFriendly\",\"sideLogic\",\"sideRadio\",\"sideUnknown\",\"simpleTasks\",\"simulationEnabled\",\"simulCloudDensity\",\"simulCloudOcclusion\",\"simulInClouds\",\"simulWeatherSync\",\"sin\",\"size\",\"sizeOf\",\"skill\",\"skillFinal\",\"skipTime\",\"sleep\",\"sliderPosition\",\"sliderRange\",\"sliderSetPosition\",\"sliderSetRange\",\"sliderSetSpeed\",\"sliderSpeed\",\"slingLoadAssistantShown\",\"soldierMagazines\",\"someAmmo\",\"sort\",\"soundVolume\",\"spawn\",\"speaker\",\"speed\",\"speedMode\",\"splitString\",\"sqrt\",\"squadParams\",\"stance\",\"startLoadingScreen\",\"step\",\"stop\",\"stopped\",\"str\",\"sunOrMoon\",\"supportInfo\",\"suppressFor\",\"surfaceIsWater\",\"surfaceNormal\",\"surfaceType\",\"swimInDepth\",\"switch\",\"switchableUnits\",\"switchAction\",\"switchCamera\",\"switchGesture\",\"switchLight\",\"switchMove\",\"synchronizedObjects\",\"synchronizedTriggers\",\"synchronizedWaypoints\",\"synchronizeObjectsAdd\",\"synchronizeObjectsRemove\",\"synchronizeTrigger\",\"synchronizeWaypoint\",\"synchronizeWaypoint trigger\",\"systemChat\",\"systemOfUnits\",\"tan\",\"targetKnowledge\",\"targetsAggregate\",\"targetsQuery\",\"taskChildren\",\"taskCompleted\",\"taskDescription\",\"taskDestination\",\"taskHint\",\"taskNull\",\"taskParent\",\"taskResult\",\"taskState\",\"teamMember\",\"teamMemberNull\",\"teamName\",\"teams\",\"teamSwitch\",\"teamSwitchEnabled\",\"teamType\",\"terminate\",\"terrainIntersect\",\"terrainIntersectASL\",\"text\",\"text location\",\"textLog\",\"textLogFormat\",\"tg\",\"then\",\"throw\",\"time\",\"timeMultiplier\",\"titleCut\",\"titleFadeOut\",\"titleObj\",\"titleRsc\",\"titleText\",\"to\",\"toArray\",\"toLower\",\"toString\",\"toUpper\",\"triggerActivated\",\"triggerActivation\",\"triggerArea\",\"triggerAttachedVehicle\",\"triggerAttachObject\",\"triggerAttachVehicle\",\"triggerStatements\",\"triggerText\",\"triggerTimeout\",\"triggerTimeoutCurrent\",\"triggerType\",\"true\",\"try\",\"turretLocal\",\"turretOwner\",\"turretUnit\",\"tvAdd\",\"tvClear\",\"tvCollapse\",\"tvCount\",\"tvCurSel\",\"tvData\",\"tvDelete\",\"tvExpand\",\"tvPicture\",\"tvSetCurSel\",\"tvSetData\",\"tvSetPicture\",\"tvSetPictureColor\",\"tvSetTooltip\",\"tvSetValue\",\"tvSort\",\"tvSortByValue\",\"tvText\",\"tvValue\",\"type\",\"typeName\",\"typeOf\",\"UAVControl\",\"uiNamespace\",\"uiSleep\",\"unassignCurator\",\"unassignItem\",\"unassignTeam\",\"unassignVehicle\",\"underwater\",\"uniform\",\"uniformContainer\",\"uniformItems\",\"uniformMagazines\",\"unitAddons\",\"unitBackpack\",\"unitPos\",\"unitReady\",\"unitRecoilCoefficient\",\"units\",\"unitsBelowHeight\",\"unlinkItem\",\"unlockAchievement\",\"unregisterTask\",\"updateDrawIcon\",\"updateMenuItem\",\"updateObjectTree\",\"useAudioTimeForMoves\",\"vectorAdd\",\"vectorCos\",\"vectorCrossProduct\",\"vectorDiff\",\"vectorDir\",\"vectorDirVisual\",\"vectorDistance\",\"vectorDistanceSqr\",\"vectorDotProduct\",\"vectorFromTo\",\"vectorMagnitude\",\"vectorMagnitudeSqr\",\"vectorMultiply\",\"vectorNormalized\",\"vectorUp\",\"vectorUpVisual\",\"vehicle\",\"vehicleChat\",\"vehicleRadio\",\"vehicles\",\"vehicleVarName\",\"velocity\",\"velocityModelSpace\",\"verifySignature\",\"vest\",\"vestContainer\",\"vestItems\",\"vestMagazines\",\"viewDistance\",\"visibleCompass\",\"visibleGPS\",\"visibleMap\",\"visiblePosition\",\"visiblePositionASL\",\"visibleWatch\",\"waitUntil\",\"waves\",\"waypointAttachedObject\",\"waypointAttachedVehicle\",\"waypointAttachObject\",\"waypointAttachVehicle\",\"waypointBehaviour\",\"waypointCombatMode\",\"waypointCompletionRadius\",\"waypointDescription\",\"waypointFormation\",\"waypointHousePosition\",\"waypointLoiterRadius\",\"waypointLoiterType\",\"waypointName\",\"waypointPosition\",\"waypoints\",\"waypointScript\",\"waypointsEnabledUAV\",\"waypointShow\",\"waypointSpeed\",\"waypointStatements\",\"waypointTimeout\",\"waypointTimeoutCurrent\",\"waypointType\",\"waypointVisible\",\"weaponAccessories\",\"weaponCargo\",\"weaponDirection\",\"weaponLowered\",\"weapons\",\"weaponsItems\",\"weaponsItemsCargo\",\"weaponState\",\"weaponsTurret\",\"weightRTD\",\"west\",\"WFSideText\",\"while\",\"wind\",\"windDir\",\"windStr\",\"wingsForcesRTD\",\"with\",\"worldName\",\"worldSize\",\"worldToModel\",\"worldToModelVisual\",\"worldToScreen\"],n=[\"case\",\"catch\",\"default\",\"do\",\"else\",\"exit\",\"exitWith|5\",\"for\",\"forEach\",\"from\",\"if\",\"switch\",\"then\",\"throw\",\"to\",\"try\",\"while\",\"with\"],i=[\"!\",\"-\",\"+\",\"!=\",\"%\",\"&&\",\"*\",\"/\",\"=\",\"==\",\">\",\">=\",\"<\",\"<=\",\"^\",\":\",\">>\"],r=[\"_forEachIndex|10\",\"_this|10\",\"_x|10\"],a=[\"true\",\"false\",\"nil\"],o=t.filter(function(e){\nreturn-1==n.indexOf(e)&&-1==a.indexOf(e)&&-1==i.indexOf(e)});o=o.concat(r);var s={className:\"string\",relevance:0,variants:[{begin:'\"',end:'\"',contains:[{begin:'\"\"'}]},{begin:\"'\",end:\"'\",contains:[{begin:\"''\"}]}]},l={className:\"number\",begin:e.NUMBER_RE,relevance:0},c={className:\"string\",variants:[e.QUOTE_STRING_MODE,{begin:\"'\\\\\\\\?.\",end:\"'\",illegal:\".\"}]},d={className:\"preprocessor\",begin:\"#\",end:\"$\",keywords:\"if else elif endif define undef warning error line pragma ifdef ifndef\",contains:[{begin:/\\\\\\n/,relevance:0},{beginKeywords:\"include\",end:\"$\",contains:[c,{className:\"string\",begin:\"<\",end:\">\",illegal:\"\\\\n\"}]},c,l,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]};return{aliases:[\"sqf\"],case_insensitive:!0,keywords:{keyword:n.join(\" \"),built_in:o.join(\" \"),literal:a.join(\" \")},contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,s,d]}}),e.registerLanguage(\"sql\",function(e){var t=e.COMMENT(\"--\",\"$\");return{case_insensitive:!0,illegal:/[<>{}*]/,contains:[{className:\"operator\",beginKeywords:\"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke\",end:/;/,endsWithParent:!0,keywords:{keyword:\"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes c cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle d data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration e each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract f failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function g general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http i id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists k keep keep_duplicates key keys kill l language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim m main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex n name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding p package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime t table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek\",literal:\"true false null\",built_in:\"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void\"},contains:[{className:\"string\",begin:\"'\",end:\"'\",contains:[e.BACKSLASH_ESCAPE,{begin:\"''\"}]},{className:\"string\",begin:'\"',end:'\"',contains:[e.BACKSLASH_ESCAPE,{begin:'\"\"'}]},{className:\"string\",begin:\"`\",end:\"`\",contains:[e.BACKSLASH_ESCAPE]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t]},e.C_BLOCK_COMMENT_MODE,t]}}),e.registerLanguage(\"stata\",function(e){return{aliases:[\"do\",\"ado\"],case_insensitive:!0,keywords:\"if else in foreach for forv forva forval forvalu forvalue forvalues by bys bysort xi quietly qui capture about ac ac_7 acprplot acprplot_7 adjust ado adopath adoupdate alpha ameans an ano anov anova anova_estat anova_terms anovadef aorder ap app appe appen append arch arch_dr arch_estat arch_p archlm areg areg_p args arima arima_dr arima_estat arima_p as asmprobit asmprobit_estat asmprobit_lf asmprobit_mfx__dlg asmprobit_p ass asse asser assert avplot avplot_7 avplots avplots_7 bcskew0 bgodfrey binreg bip0_lf biplot bipp_lf bipr_lf bipr_p biprobit bitest bitesti bitowt blogit bmemsize boot bootsamp bootstrap bootstrap_8 boxco_l boxco_p boxcox boxcox_6 boxcox_p bprobit br break brier bro brow brows browse brr brrstat bs bs_7 bsampl_w bsample bsample_7 bsqreg bstat bstat_7 bstat_8 bstrap bstrap_7 ca ca_estat ca_p cabiplot camat canon canon_8 canon_8_p canon_estat canon_p cap caprojection capt captu captur capture cat cc cchart cchart_7 cci cd censobs_table centile cf char chdir checkdlgfiles checkestimationsample checkhlpfiles checksum chelp ci cii cl class classutil clear cli clis clist clo clog clog_lf clog_p clogi clogi_sw clogit clogit_lf clogit_p clogitp clogl_sw cloglog clonevar clslistarray cluster cluster_measures cluster_stop cluster_tree cluster_tree_8 clustermat cmdlog cnr cnre cnreg cnreg_p cnreg_sw cnsreg codebook collaps4 collapse colormult_nb colormult_nw compare compress conf confi confir confirm conren cons const constr constra constrai constrain constraint continue contract copy copyright copysource cor corc corr corr2data corr_anti corr_kmo corr_smc corre correl correla correlat correlate corrgram cou coun count cox cox_p cox_sw coxbase coxhaz coxvar cprplot cprplot_7 crc cret cretu cretur creturn cross cs cscript cscript_log csi ct ct_is ctset ctst_5 ctst_st cttost cumsp cumsp_7 cumul cusum cusum_7 cutil d datasig datasign datasigna datasignat datasignatu datasignatur datasignature datetof db dbeta de dec deco decod decode deff des desc descr descri describ describe destring dfbeta dfgls dfuller di di_g dir dirstats dis discard disp disp_res disp_s displ displa display distinct do doe doed doedi doedit dotplot dotplot_7 dprobit drawnorm drop ds ds_util dstdize duplicates durbina dwstat dydx e ed edi edit egen eivreg emdef en enc enco encod encode eq erase ereg ereg_lf ereg_p ereg_sw ereghet ereghet_glf ereghet_glf_sh ereghet_gp ereghet_ilf ereghet_ilf_sh ereghet_ip eret eretu eretur ereturn err erro error est est_cfexist est_cfname est_clickable est_expand est_hold est_table est_unhold est_unholdok estat estat_default estat_summ estat_vce_only esti estimates etodow etof etomdy ex exi exit expand expandcl fac fact facto factor factor_estat factor_p factor_pca_rotated factor_rotate factormat fcast fcast_compute fcast_graph fdades fdadesc fdadescr fdadescri fdadescrib fdadescribe fdasav fdasave fdause fh_st file open file read file close file filefilter fillin find_hlp_file findfile findit findit_7 fit fl fli flis flist for5_0 form forma format fpredict frac_154 frac_adj frac_chk frac_cox frac_ddp frac_dis frac_dv frac_in frac_mun frac_pp frac_pq frac_pv frac_wgt frac_xo fracgen fracplot fracplot_7 fracpoly fracpred fron_ex fron_hn fron_p fron_tn fron_tn2 frontier ftodate ftoe ftomdy ftowdate g gamhet_glf gamhet_gp gamhet_ilf gamhet_ip gamma gamma_d2 gamma_p gamma_sw gammahet gdi_hexagon gdi_spokes ge gen gene gener genera generat generate genrank genstd genvmean gettoken gl gladder gladder_7 glim_l01 glim_l02 glim_l03 glim_l04 glim_l05 glim_l06 glim_l07 glim_l08 glim_l09 glim_l10 glim_l11 glim_l12 glim_lf glim_mu glim_nw1 glim_nw2 glim_nw3 glim_p glim_v1 glim_v2 glim_v3 glim_v4 glim_v5 glim_v6 glim_v7 glm glm_6 glm_p glm_sw glmpred glo glob globa global glogit glogit_8 glogit_p gmeans gnbre_lf gnbreg gnbreg_5 gnbreg_p gomp_lf gompe_sw gomper_p gompertz gompertzhet gomphet_glf gomphet_glf_sh gomphet_gp gomphet_ilf gomphet_ilf_sh gomphet_ip gphdot gphpen gphprint gprefs gprobi_p gprobit gprobit_8 gr gr7 gr_copy gr_current gr_db gr_describe gr_dir gr_draw gr_draw_replay gr_drop gr_edit gr_editviewopts gr_example gr_example2 gr_export gr_print gr_qscheme gr_query gr_read gr_rename gr_replay gr_save gr_set gr_setscheme gr_table gr_undo gr_use graph graph7 grebar greigen greigen_7 greigen_8 grmeanby grmeanby_7 gs_fileinfo gs_filetype gs_graphinfo gs_stat gsort gwood h hadimvo hareg hausman haver he heck_d2 heckma_p heckman heckp_lf heckpr_p heckprob hel help hereg hetpr_lf hetpr_p hetprob hettest hexdump hilite hist hist_7 histogram hlogit hlu hmeans hotel hotelling hprobit hreg hsearch icd9 icd9_ff icd9p iis impute imtest inbase include inf infi infil infile infix inp inpu input ins insheet insp inspe inspec inspect integ inten intreg intreg_7 intreg_p intrg2_ll intrg_ll intrg_ll2 ipolate iqreg ir irf irf_create irfm iri is_svy is_svysum isid istdize ivprob_1_lf ivprob_lf ivprobit ivprobit_p ivreg ivreg_footnote ivtob_1_lf ivtob_lf ivtobit ivtobit_p jackknife jacknife jknife jknife_6 jknife_8 jkstat joinby kalarma1 kap kap_3 kapmeier kappa kapwgt kdensity kdensity_7 keep ksm ksmirnov ktau kwallis l la lab labe label labelbook ladder levels levelsof leverage lfit lfit_p li lincom line linktest lis list lloghet_glf lloghet_glf_sh lloghet_gp lloghet_ilf lloghet_ilf_sh lloghet_ip llogi_sw llogis_p llogist llogistic llogistichet lnorm_lf lnorm_sw lnorma_p lnormal lnormalhet lnormhet_glf lnormhet_glf_sh lnormhet_gp lnormhet_ilf lnormhet_ilf_sh lnormhet_ip lnskew0 loadingplot loc loca local log logi logis_lf logistic logistic_p logit logit_estat logit_p loglogs logrank loneway lookfor lookup lowess lowess_7 lpredict lrecomp lroc lroc_7 lrtest ls lsens lsens_7 lsens_x lstat ltable ltable_7 ltriang lv lvr2plot lvr2plot_7 m ma mac macr macro makecns man manova manova_estat manova_p manovatest mantel mark markin markout marksample mat mat_capp mat_order mat_put_rr mat_rapp mata mata_clear mata_describe mata_drop mata_matdescribe mata_matsave mata_matuse mata_memory mata_mlib mata_mosave mata_rename mata_which matalabel matcproc matlist matname matr matri matrix matrix_input__dlg matstrik mcc mcci md0_ md1_ md1debug_ md2_ md2debug_ mds mds_estat mds_p mdsconfig mdslong mdsmat mdsshepard mdytoe mdytof me_derd mean means median memory memsize meqparse mer merg merge mfp mfx mhelp mhodds minbound mixed_ll mixed_ll_reparm mkassert mkdir mkmat mkspline ml ml_5 ml_adjs ml_bhhhs ml_c_d ml_check ml_clear ml_cnt ml_debug ml_defd ml_e0 ml_e0_bfgs ml_e0_cycle ml_e0_dfp ml_e0i ml_e1 ml_e1_bfgs ml_e1_bhhh ml_e1_cycle ml_e1_dfp ml_e2 ml_e2_cycle ml_ebfg0 ml_ebfr0 ml_ebfr1 ml_ebh0q ml_ebhh0 ml_ebhr0 ml_ebr0i ml_ecr0i ml_edfp0 ml_edfr0 ml_edfr1 ml_edr0i ml_eds ml_eer0i ml_egr0i ml_elf ml_elf_bfgs ml_elf_bhhh ml_elf_cycle ml_elf_dfp ml_elfi ml_elfs ml_enr0i ml_enrr0 ml_erdu0 ml_erdu0_bfgs ml_erdu0_bhhh ml_erdu0_bhhhq ml_erdu0_cycle ml_erdu0_dfp ml_erdu0_nrbfgs ml_exde ml_footnote ml_geqnr ml_grad0 ml_graph ml_hbhhh ml_hd0 ml_hold ml_init ml_inv ml_log ml_max ml_mlout ml_mlout_8 ml_model ml_nb0 ml_opt ml_p ml_plot ml_query ml_rdgrd ml_repor ml_s_e ml_score ml_searc ml_technique ml_unhold mleval mlf_ mlmatbysum mlmatsum mlog mlogi mlogit mlogit_footnote mlogit_p mlopts mlsum mlvecsum mnl0_ mor more mov move mprobit mprobit_lf mprobit_p mrdu0_ mrdu1_ mvdecode mvencode mvreg mvreg_estat n nbreg nbreg_al nbreg_lf nbreg_p nbreg_sw nestreg net newey newey_7 newey_p news nl nl_7 nl_9 nl_9_p nl_p nl_p_7 nlcom nlcom_p nlexp2 nlexp2_7 nlexp2a nlexp2a_7 nlexp3 nlexp3_7 nlgom3 nlgom3_7 nlgom4 nlgom4_7 nlinit nllog3 nllog3_7 nllog4 nllog4_7 nlog_rd nlogit nlogit_p nlogitgen nlogittree nlpred no nobreak noi nois noisi noisil noisily note notes notes_dlg nptrend numlabel numlist odbc old_ver olo olog ologi ologi_sw ologit ologit_p ologitp on one onew onewa oneway op_colnm op_comp op_diff op_inv op_str opr opro oprob oprob_sw oprobi oprobi_p oprobit oprobitp opts_exclusive order orthog orthpoly ou out outf outfi outfil outfile outs outsh outshe outshee outsheet ovtest pac pac_7 palette parse parse_dissim pause pca pca_8 pca_display pca_estat pca_p pca_rotate pcamat pchart pchart_7 pchi pchi_7 pcorr pctile pentium pergram pergram_7 permute permute_8 personal peto_st pkcollapse pkcross pkequiv pkexamine pkexamine_7 pkshape pksumm pksumm_7 pl plo plot plugin pnorm pnorm_7 poisgof poiss_lf poiss_sw poisso_p poisson poisson_estat post postclose postfile postutil pperron pr prais prais_e prais_e2 prais_p predict predictnl preserve print pro prob probi probit probit_estat probit_p proc_time procoverlay procrustes procrustes_estat procrustes_p profiler prog progr progra program prop proportion prtest prtesti pwcorr pwd q\\\\s qby qbys qchi qchi_7 qladder qladder_7 qnorm qnorm_7 qqplot qqplot_7 qreg qreg_c qreg_p qreg_sw qu quadchk quantile quantile_7 que quer query range ranksum ratio rchart rchart_7 rcof recast reclink recode reg reg3 reg3_p regdw regr regre regre_p2 regres regres_p regress regress_estat regriv_p remap ren rena renam rename renpfix repeat replace report reshape restore ret retu retur return rm rmdir robvar roccomp roccomp_7 roccomp_8 rocf_lf rocfit rocfit_8 rocgold rocplot rocplot_7 roctab roctab_7 rolling rologit rologit_p rot rota rotat rotate rotatemat rreg rreg_p ru run runtest rvfplot rvfplot_7 rvpplot rvpplot_7 sa safesum sample sampsi sav save savedresults saveold sc sca scal scala scalar scatter scm_mine sco scob_lf scob_p scobi_sw scobit scor score scoreplot scoreplot_help scree screeplot screeplot_help sdtest sdtesti se search separate seperate serrbar serrbar_7 serset set set_defaults sfrancia sh she shel shell shewhart shewhart_7 signestimationsample signrank signtest simul simul_7 simulate simulate_8 sktest sleep slogit slogit_d2 slogit_p smooth snapspan so sor sort spearman spikeplot spikeplot_7 spikeplt spline_x split sqreg sqreg_p sret sretu sretur sreturn ssc st st_ct st_hc st_hcd st_hcd_sh st_is st_issys st_note st_promo st_set st_show st_smpl st_subid stack statsby statsby_8 stbase stci stci_7 stcox stcox_estat stcox_fr stcox_fr_ll stcox_p stcox_sw stcoxkm stcoxkm_7 stcstat stcurv stcurve stcurve_7 stdes stem stepwise stereg stfill stgen stir stjoin stmc stmh stphplot stphplot_7 stphtest stphtest_7 stptime strate strate_7 streg streg_sw streset sts sts_7 stset stsplit stsum sttocc sttoct stvary stweib su suest suest_8 sum summ summa summar summari summariz summarize sunflower sureg survcurv survsum svar svar_p svmat svy svy_disp svy_dreg svy_est svy_est_7 svy_estat svy_get svy_gnbreg_p svy_head svy_header svy_heckman_p svy_heckprob_p svy_intreg_p svy_ivreg_p svy_logistic_p svy_logit_p svy_mlogit_p svy_nbreg_p svy_ologit_p svy_oprobit_p svy_poisson_p svy_probit_p svy_regress_p svy_sub svy_sub_7 svy_x svy_x_7 svy_x_p svydes svydes_8 svygen svygnbreg svyheckman svyheckprob svyintreg svyintreg_7 svyintrg svyivreg svylc svylog_p svylogit svymarkout svymarkout_8 svymean svymlog svymlogit svynbreg svyolog svyologit svyoprob svyoprobit svyopts svypois svypois_7 svypoisson svyprobit svyprobt svyprop svyprop_7 svyratio svyreg svyreg_p svyregress svyset svyset_7 svyset_8 svytab svytab_7 svytest svytotal sw sw_8 swcnreg swcox swereg swilk swlogis swlogit swologit swoprbt swpois swprobit swqreg swtobit swweib symmetry symmi symplot symplot_7 syntax sysdescribe sysdir sysuse szroeter ta tab tab1 tab2 tab_or tabd tabdi tabdis tabdisp tabi table tabodds tabodds_7 tabstat tabu tabul tabula tabulat tabulate te tempfile tempname tempvar tes test testnl testparm teststd tetrachoric time_it timer tis tob tobi tobit tobit_p tobit_sw token tokeni tokeniz tokenize tostring total translate translator transmap treat_ll treatr_p treatreg trim trnb_cons trnb_mean trpoiss_d2 trunc_ll truncr_p truncreg tsappend tset tsfill tsline tsline_ex tsreport tsrevar tsrline tsset tssmooth tsunab ttest ttesti tut_chk tut_wait tutorial tw tware_st two twoway twoway__fpfit_serset twoway__function_gen twoway__histogram_gen twoway__ipoint_serset twoway__ipoints_serset twoway__kdensity_gen twoway__lfit_serset twoway__normgen_gen twoway__pci_serset twoway__qfit_serset twoway__scatteri_serset twoway__sunflower_gen twoway_ksm_serset ty typ type typeof u unab unabbrev unabcmd update us use uselabel var var_mkcompanion var_p varbasic varfcast vargranger varirf varirf_add varirf_cgraph varirf_create varirf_ctable varirf_describe varirf_dir varirf_drop varirf_erase varirf_graph varirf_ograph varirf_rename varirf_set varirf_table varlist varlmar varnorm varsoc varstable varstable_w varstable_w2 varwle vce vec vec_fevd vec_mkphi vec_p vec_p_w vecirf_create veclmar veclmar_w vecnorm vecnorm_w vecrank vecstable verinst vers versi versio version view viewsource vif vwls wdatetof webdescribe webseek webuse weib1_lf weib2_lf weib_lf weib_lf0 weibhet_glf weibhet_glf_sh weibhet_glfa weibhet_glfa_sh weibhet_gp weibhet_ilf weibhet_ilf_sh weibhet_ilfa weibhet_ilfa_sh weibhet_ip weibu_sw weibul_p weibull weibull_c weibull_s weibullhet wh whelp whi which whil while wilc_st wilcoxon win wind windo window winexec wntestb wntestb_7 wntestq xchart xchart_7 xcorr xcorr_7 xi xi_6 xmlsav xmlsave xmluse xpose xsh xshe xshel xshell xt_iis xt_tis xtab_p xtabond xtbin_p xtclog xtcloglog xtcloglog_8 xtcloglog_d2 xtcloglog_pa_p xtcloglog_re_p xtcnt_p xtcorr xtdata xtdes xtfront_p xtfrontier xtgee xtgee_elink xtgee_estat xtgee_makeivar xtgee_p xtgee_plink xtgls xtgls_p xthaus xthausman xtht_p xthtaylor xtile xtint_p xtintreg xtintreg_8 xtintreg_d2 xtintreg_p xtivp_1 xtivp_2 xtivreg xtline xtline_ex xtlogit xtlogit_8 xtlogit_d2 xtlogit_fe_p xtlogit_pa_p xtlogit_re_p xtmixed xtmixed_estat xtmixed_p xtnb_fe xtnb_lf xtnbreg xtnbreg_pa_p xtnbreg_refe_p xtpcse xtpcse_p xtpois xtpoisson xtpoisson_d2 xtpoisson_pa_p xtpoisson_refe_p xtpred xtprobit xtprobit_8 xtprobit_d2 xtprobit_re_p xtps_fe xtps_lf xtps_ren xtps_ren_8 xtrar_p xtrc xtrc_p xtrchh xtrefe_p xtreg xtreg_be xtreg_fe xtreg_ml xtreg_pa_p xtreg_re xtregar xtrere_p xtset xtsf_ll xtsf_llti xtsum xttab xttest0 xttobit xttobit_8 xttobit_p xttrans yx yxview__barlike_draw yxview_area_draw yxview_bar_draw yxview_dot_draw yxview_dropline_draw yxview_function_draw yxview_iarrow_draw yxview_ilabels_draw yxview_normal_draw yxview_pcarrow_draw yxview_pcbarrow_draw yxview_pccapsym_draw yxview_pcscatter_draw yxview_pcspike_draw yxview_rarea_draw yxview_rbar_draw yxview_rbarm_draw yxview_rcap_draw yxview_rcapsym_draw yxview_rconnected_draw yxview_rline_draw yxview_rscatter_draw yxview_rspike_draw yxview_spike_draw yxview_sunflower_draw zap_s zinb zinb_llf zinb_plf zip zip_llf zip_p zip_plf zt_ct_5 zt_hc_5 zt_hcd_5 zt_is_5 zt_iss_5 zt_sho_5 zt_smp_5 ztbase_5 ztcox_5 ztdes_5 ztereg_5 ztfill_5 ztgen_5 ztir_5 ztjoin_5 ztnb ztnb_p ztp ztp_p zts_5 ztset_5 ztspli_5 ztsum_5 zttoct_5 ztvary_5 ztweib_5\",contains:[{className:\"label\",variants:[{begin:\"\\\\$\\\\{?[a-zA-Z0-9_]+\\\\}?\"},{begin:\"`[a-zA-Z0-9_]+'\"}]},{className:\"string\",variants:[{begin:'`\"[^\\r\\n]*?\"\\''},{begin:'\"[^\\r\\n\"]*\"'}]},{className:\"literal\",variants:[{begin:\"\\\\b(abs|acos|asin|atan|atan2|atanh|ceil|cloglog|comb|cos|digamma|exp|floor|invcloglog|invlogit|ln|lnfact|lnfactorial|lngamma|log|log10|max|min|mod|reldif|round|sign|sin|sqrt|sum|tan|tanh|trigamma|trunc|betaden|Binomial|binorm|binormal|chi2|chi2tail|dgammapda|dgammapdada|dgammapdadx|dgammapdx|dgammapdxdx|F|Fden|Ftail|gammaden|gammap|ibeta|invbinomial|invchi2|invchi2tail|invF|invFtail|invgammap|invibeta|invnchi2|invnFtail|invnibeta|invnorm|invnormal|invttail|nbetaden|nchi2|nFden|nFtail|nibeta|norm|normal|normalden|normd|npnchi2|tden|ttail|uniform|abbrev|char|index|indexnot|length|lower|ltrim|match|plural|proper|real|regexm|regexr|regexs|reverse|rtrim|string|strlen|strlower|strltrim|strmatch|strofreal|strpos|strproper|strreverse|strrtrim|strtrim|strupper|subinstr|subinword|substr|trim|upper|word|wordcount|_caller|autocode|byteorder|chop|clip|cond|e|epsdouble|epsfloat|group|inlist|inrange|irecode|matrix|maxbyte|maxdouble|maxfloat|maxint|maxlong|mi|minbyte|mindouble|minfloat|minint|minlong|missing|r|recode|replay|return|s|scalar|d|date|day|dow|doy|halfyear|mdy|month|quarter|week|year|d|daily|dofd|dofh|dofm|dofq|dofw|dofy|h|halfyearly|hofd|m|mofd|monthly|q|qofd|quarterly|tin|twithin|w|weekly|wofd|y|yearly|yh|ym|yofd|yq|yw|cholesky|colnumb|colsof|corr|det|diag|diag0cnt|el|get|hadamard|I|inv|invsym|issym|issymmetric|J|matmissing|matuniform|mreldif|nullmat|rownumb|rowsof|sweep|syminv|trace|vec|vecdiag)(?=\\\\(|$)\"}]},e.COMMENT(\"^[ \t]*\\\\*.*$\",!1),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]}}),e.registerLanguage(\"step21\",function(e){var t=\"[A-Z_][A-Z0-9_.]*\",n=\"END-ISO-10303-21;\",i={literal:\"\",built_in:\"\",keyword:\"HEADER ENDSEC DATA\"},r={className:\"preprocessor\",begin:\"ISO-10303-21;\",relevance:10},a=[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.COMMENT(\"/\\\\*\\\\*!\",\"\\\\*/\"),e.C_NUMBER_MODE,e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null}),{className:\"string\",begin:\"'\",end:\"'\"},{className:\"label\",variants:[{begin:\"#\",end:\"\\\\d+\",illegal:\"\\\\W\"}]}];return{aliases:[\"p21\",\"step\",\"stp\"],case_insensitive:!0,lexemes:t,keywords:i,contains:[{className:\"preprocessor\",begin:n,relevance:10},r].concat(a)}}),e.registerLanguage(\"stylus\",function(e){var t={className:\"variable\",begin:\"\\\\$\"+e.IDENT_RE},n={className:\"hexcolor\",begin:\"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})\",relevance:10},i=[\"charset\",\"css\",\"debug\",\"extend\",\"font-face\",\"for\",\"import\",\"include\",\"media\",\"mixin\",\"page\",\"warn\",\"while\"],r=[\"after\",\"before\",\"first-letter\",\"first-line\",\"active\",\"first-child\",\"focus\",\"hover\",\"lang\",\"link\",\"visited\"],a=[\"a\",\"abbr\",\"address\",\"article\",\"aside\",\"audio\",\"b\",\"blockquote\",\"body\",\"button\",\"canvas\",\"caption\",\"cite\",\"code\",\"dd\",\"del\",\"details\",\"dfn\",\"div\",\"dl\",\"dt\",\"em\",\"fieldset\",\"figcaption\",\"figure\",\"footer\",\"form\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"header\",\"hgroup\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"kbd\",\"label\",\"legend\",\"li\",\"mark\",\"menu\",\"nav\",\"object\",\"ol\",\"p\",\"q\",\"quote\",\"samp\",\"section\",\"span\",\"strong\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"tr\",\"ul\",\"var\",\"video\"],o=\"[\\\\.\\\\s\\\\n\\\\[\\\\:,]\",s=[\"align-content\",\"align-items\",\"align-self\",\"animation\",\"animation-delay\",\"animation-direction\",\"animation-duration\",\"animation-fill-mode\",\"animation-iteration-count\",\"animation-name\",\"animation-play-state\",\"animation-timing-function\",\"auto\",\"backface-visibility\",\"background\",\"background-attachment\",\"background-clip\",\"background-color\",\"background-image\",\"background-origin\",\"background-position\",\"background-repeat\",\"background-size\",\"border\",\"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\",\"bottom\",\"box-decoration-break\",\"box-shadow\",\"box-sizing\",\"break-after\",\"break-before\",\"break-inside\",\"caption-side\",\"clear\",\"clip\",\"clip-path\",\"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\",\"cursor\",\"direction\",\"display\",\"empty-cells\",\"filter\",\"flex\",\"flex-basis\",\"flex-direction\",\"flex-flow\",\"flex-grow\",\"flex-shrink\",\"flex-wrap\",\"float\",\"font\",\"font-family\",\"font-feature-settings\",\"font-kerning\",\"font-language-override\",\"font-size\",\"font-size-adjust\",\"font-stretch\",\"font-style\",\"font-variant\",\"font-variant-ligatures\",\"font-weight\",\"height\",\"hyphens\",\"icon\",\"image-orientation\",\"image-rendering\",\"image-resolution\",\"ime-mode\",\"inherit\",\"initial\",\"justify-content\",\"left\",\"letter-spacing\",\"line-height\",\"list-style\",\"list-style-image\",\"list-style-position\",\"list-style-type\",\"margin\",\"margin-bottom\",\"margin-left\",\"margin-right\",\"margin-top\",\"marks\",\"mask\",\"max-height\",\"max-width\",\"min-height\",\"min-width\",\"nav-down\",\"nav-index\",\"nav-left\",\"nav-right\",\"nav-up\",\"none\",\"normal\",\"object-fit\",\"object-position\",\"opacity\",\"order\",\"orphans\",\"outline\",\"outline-color\",\"outline-offset\",\"outline-style\",\"outline-width\",\"overflow\",\"overflow-wrap\",\"overflow-x\",\"overflow-y\",\"padding\",\"padding-bottom\",\"padding-left\",\"padding-right\",\"padding-top\",\"page-break-after\",\"page-break-before\",\"page-break-inside\",\"perspective\",\"perspective-origin\",\"pointer-events\",\"position\",\"quotes\",\"resize\",\"right\",\"tab-size\",\"table-layout\",\"text-align\",\"text-align-last\",\"text-decoration\",\"text-decoration-color\",\"text-decoration-line\",\"text-decoration-style\",\"text-indent\",\"text-overflow\",\"text-rendering\",\"text-shadow\",\"text-transform\",\"text-underline-position\",\"top\",\"transform\",\"transform-origin\",\"transform-style\",\"transition\",\"transition-delay\",\"transition-duration\",\"transition-property\",\"transition-timing-function\",\"unicode-bidi\",\"vertical-align\",\"visibility\",\"white-space\",\"widows\",\"width\",\"word-break\",\"word-spacing\",\"word-wrap\",\"z-index\"],l=[\"\\\\{\",\"\\\\}\",\"\\\\?\",\"(\\\\bReturn\\\\b)\",\"(\\\\bEnd\\\\b)\",\"(\\\\bend\\\\b)\",\";\",\"#\\\\s\",\"\\\\*\\\\s\",\"===\\\\s\",\"\\\\|\",\"%\"];\nreturn{aliases:[\"styl\"],case_insensitive:!1,illegal:\"(\"+l.join(\"|\")+\")\",keywords:\"if else for in\",contains:[e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n,{begin:\"\\\\.[a-zA-Z][a-zA-Z0-9_-]*\"+o,returnBegin:!0,contains:[{className:\"class\",begin:\"\\\\.[a-zA-Z][a-zA-Z0-9_-]*\"}]},{begin:\"\\\\#[a-zA-Z][a-zA-Z0-9_-]*\"+o,returnBegin:!0,contains:[{className:\"id\",begin:\"\\\\#[a-zA-Z][a-zA-Z0-9_-]*\"}]},{begin:\"\\\\b(\"+a.join(\"|\")+\")\"+o,returnBegin:!0,contains:[{className:\"tag\",begin:\"\\\\b[a-zA-Z][a-zA-Z0-9_-]*\"}]},{className:\"pseudo\",begin:\"&?:?:\\\\b(\"+r.join(\"|\")+\")\"+o},{className:\"at_rule\",begin:\"@(\"+i.join(\"|\")+\")\\\\b\"},t,e.CSS_NUMBER_MODE,e.NUMBER_MODE,{className:\"function\",begin:\"\\\\b[a-zA-Z][a-zA-Z0-9_-]*\\\\(.*\\\\)\",illegal:\"[\\\\n]\",returnBegin:!0,contains:[{className:\"title\",begin:\"\\\\b[a-zA-Z][a-zA-Z0-9_-]*\"},{className:\"params\",begin:/\\(/,end:/\\)/,contains:[n,t,e.APOS_STRING_MODE,e.CSS_NUMBER_MODE,e.NUMBER_MODE,e.QUOTE_STRING_MODE]}]},{className:\"attribute\",begin:\"\\\\b(\"+s.reverse().join(\"|\")+\")\\\\b\"}]}}),e.registerLanguage(\"swift\",function(e){var t={keyword:\"__COLUMN__ __FILE__ __FUNCTION__ __LINE__ as as! as? associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet\",literal:\"true false nil\",built_in:\"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip\"},n={className:\"type\",begin:\"\\\\b[A-Z][\\\\w']*\",relevance:0},i=e.COMMENT(\"/\\\\*\",\"\\\\*/\",{contains:[\"self\"]}),r={className:\"subst\",begin:/\\\\\\(/,end:\"\\\\)\",keywords:t,contains:[]},a={className:\"number\",begin:\"\\\\b([\\\\d_]+(\\\\.[\\\\deE_]+)?|0x[a-fA-F0-9_]+(\\\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\\\b\",relevance:0},o=e.inherit(e.QUOTE_STRING_MODE,{contains:[r,e.BACKSLASH_ESCAPE]});return r.contains=[a],{keywords:t,contains:[o,e.C_LINE_COMMENT_MODE,i,n,a,{className:\"func\",beginKeywords:\"func\",end:\"{\",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/,illegal:/\\(/}),{className:\"generics\",begin:/</,end:/>/,illegal:/>/},{className:\"params\",begin:/\\(/,end:/\\)/,endsParent:!0,keywords:t,contains:[\"self\",a,o,e.C_BLOCK_COMMENT_MODE,{begin:\":\"}],illegal:/[\"']/}],illegal:/\\[|%/},{className:\"class\",beginKeywords:\"struct protocol class extension enum\",keywords:t,end:\"\\\\{\",excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/})]},{className:\"preprocessor\",begin:\"(@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain)\"},{beginKeywords:\"import\",end:/$/,contains:[e.C_LINE_COMMENT_MODE,i]}]}}),e.registerLanguage(\"tcl\",function(e){return{aliases:[\"tk\"],keywords:\"after append apply array auto_execok auto_import auto_load auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror binary break catch cd chan clock close concat continue dde dict encoding eof error eval exec exit expr fblocked fconfigure fcopy file fileevent filename flush for foreach format gets glob global history http if incr info interp join lappend|10 lassign|10 lindex|10 linsert|10 list llength|10 load lrange|10 lrepeat|10 lreplace|10 lreverse|10 lsearch|10 lset|10 lsort|10 mathfunc mathop memory msgcat namespace open package parray pid pkg::create pkg_mkIndex platform platform::shell proc puts pwd read refchan regexp registry regsub|10 rename return safe scan seek set socket source split string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord tcl_startOfPreviousWord tcl_wordBreakAfter tcl_wordBreakBefore tcltest tclvars tell time tm trace unknown unload unset update uplevel upvar variable vwait while\",contains:[e.COMMENT(\";[ \\\\t]*#\",\"$\"),e.COMMENT(\"^[ \\\\t]*#\",\"$\"),{beginKeywords:\"proc\",end:\"[\\\\{]\",excludeEnd:!0,contains:[{className:\"symbol\",begin:\"[ \\\\t\\\\n\\\\r]+(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*\",end:\"[ \\\\t\\\\n\\\\r]\",endsWithParent:!0,excludeEnd:!0}]},{className:\"variable\",excludeEnd:!0,variants:[{begin:\"\\\\$(\\\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*\\\\(([a-zA-Z0-9_])*\\\\)\",end:\"[^a-zA-Z0-9_\\\\}\\\\$]\"},{begin:\"\\\\$(\\\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*\",end:\"(\\\\))?[^a-zA-Z0-9_\\\\}\\\\$]\"}]},{className:\"string\",contains:[e.BACKSLASH_ESCAPE],variants:[e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null})]},{className:\"number\",variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]}]}}),e.registerLanguage(\"tex\",function(e){var t={className:\"command\",begin:\"\\\\\\\\[a-zA-Zа-яА-я]+[\\\\*]?\"},n={className:\"command\",begin:\"\\\\\\\\[^a-zA-Zа-яА-я0-9]\"},i={className:\"special\",begin:\"[{}\\\\[\\\\]\\\\&#~]\",relevance:0};return{contains:[{begin:\"\\\\\\\\[a-zA-Zа-яА-я]+[\\\\*]? *= *-?\\\\d*\\\\.?\\\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?\",returnBegin:!0,contains:[t,n,{className:\"number\",begin:\" *=\",end:\"-?\\\\d*\\\\.?\\\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?\",excludeBegin:!0}],relevance:10},t,n,i,{className:\"formula\",begin:\"\\\\$\\\\$\",end:\"\\\\$\\\\$\",contains:[t,n,i],relevance:0},{className:\"formula\",begin:\"\\\\$\",end:\"\\\\$\",contains:[t,n,i],relevance:0},e.COMMENT(\"%\",\"$\",{relevance:0})]}}),e.registerLanguage(\"thrift\",function(e){var t=\"bool byte i16 i32 i64 double string binary\";return{keywords:{keyword:\"namespace const typedef struct enum service exception void oneway set list map required optional\",built_in:t,literal:\"true false\"},contains:[e.QUOTE_STRING_MODE,e.NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"class\",beginKeywords:\"struct enum service exception\",end:/\\{/,illegal:/\\n/,contains:[e.inherit(e.TITLE_MODE,{starts:{endsWithParent:!0,excludeEnd:!0}})]},{begin:\"\\\\b(set|list|map)\\\\s*<\",end:\">\",keywords:t,contains:[\"self\"]}]}}),e.registerLanguage(\"tp\",function(e){var t={className:\"number\",begin:\"[1-9][0-9]*\",relevance:0},n={className:\"comment\",begin:\":[^\\\\]]+\"},i={className:\"built_in\",begin:\"(AR|P|PAYLOAD|PR|R|SR|RSR|LBL|VR|UALM|MESSAGE|UTOOL|UFRAME|TIMER|    TIMER_OVERFLOW|JOINT_MAX_SPEED|RESUME_PROG|DIAG_REC)\\\\[\",end:\"\\\\]\",contains:[\"self\",t,n]},r={className:\"built_in\",begin:\"(AI|AO|DI|DO|F|RI|RO|UI|UO|GI|GO|SI|SO)\\\\[\",end:\"\\\\]\",contains:[\"self\",t,e.QUOTE_STRING_MODE,n]};return{keywords:{keyword:\"ABORT ACC ADJUST AND AP_LD BREAK CALL CNT COL CONDITION CONFIG DA DB DIV DETECT ELSE END ENDFOR ERR_NUM ERROR_PROG FINE FOR GP GUARD INC IF JMP LINEAR_MAX_SPEED LOCK MOD MONITOR OFFSET Offset OR OVERRIDE PAUSE PREG PTH RT_LD RUN SELECT SKIP Skip TA TB TO TOOL_OFFSET Tool_Offset UF UT UFRAME_NUM UTOOL_NUM UNLOCK WAIT X Y Z W P R STRLEN SUBSTR FINDSTR VOFFSET\",constant:\"ON OFF max_speed LPOS JPOS ENABLE DISABLE START STOP RESET\"},contains:[i,r,{className:\"keyword\",begin:\"/(PROG|ATTR|MN|POS|END)\\\\b\"},{className:\"keyword\",begin:\"(CALL|RUN|POINT_LOGIC|LBL)\\\\b\"},{className:\"keyword\",begin:\"\\\\b(ACC|CNT|Skip|Offset|PSPD|RT_LD|AP_LD|Tool_Offset)\"},{className:\"number\",begin:\"\\\\d+(sec|msec|mm/sec|cm/min|inch/min|deg/sec|mm|in|cm)?\\\\b\",relevance:0},e.COMMENT(\"//\",\"[;$]\"),e.COMMENT(\"!\",\"[;$]\"),e.COMMENT(\"--eg:\",\"$\"),e.QUOTE_STRING_MODE,{className:\"string\",begin:\"'\",end:\"'\"},e.C_NUMBER_MODE,{className:\"variable\",begin:\"\\\\$[A-Za-z0-9_]+\"}]}}),e.registerLanguage(\"twig\",function(e){var t={className:\"params\",begin:\"\\\\(\",end:\"\\\\)\"},n=\"attribute block constant cycle date dump include max min parent random range source template_from_string\",i={className:\"function\",beginKeywords:n,relevance:0,contains:[t]},r={className:\"filter\",begin:/\\|[A-Za-z_]+:?/,keywords:\"abs batch capitalize convert_encoding date date_modify default escape first format join json_encode keys last length lower merge nl2br number_format raw replace reverse round slice sort split striptags title trim upper url_encode\",contains:[i]},a=\"autoescape block do embed extends filter flush for if import include macro sandbox set spaceless use verbatim\";return a=a+\" \"+a.split(\" \").map(function(e){return\"end\"+e}).join(\" \"),{aliases:[\"craftcms\"],case_insensitive:!0,subLanguage:\"xml\",contains:[e.COMMENT(/\\{#/,/#}/),{className:\"template_tag\",begin:/\\{%/,end:/%}/,keywords:a,contains:[r,i]},{className:\"variable\",begin:/\\{\\{/,end:/}}/,contains:[r,i]}]}}),e.registerLanguage(\"typescript\",function(e){var t={keyword:\"in if for while finally var new function|0 do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private protected get set super static implements enum export import declare type namespace abstract\",literal:\"true false null undefined NaN Infinity\",built_in:\"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void\"};return{aliases:[\"ts\"],keywords:t,contains:[{className:\"pi\",begin:/^\\s*['\"]use strict['\"]/,relevance:0},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"number\",variants:[{begin:\"\\\\b(0[bB][01]+)\"},{begin:\"\\\\b(0[oO][0-7]+)\"},{begin:e.C_NUMBER_RE}],relevance:0},{begin:\"(\"+e.RE_STARTERS_RE+\"|\\\\b(case|return|throw)\\\\b)\\\\s*\",keywords:\"return throw case\",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.REGEXP_MODE],relevance:0},{className:\"function\",begin:\"function\",end:/[\\{;]/,excludeEnd:!0,keywords:t,contains:[\"self\",e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{className:\"params\",begin:/\\(/,end:/\\)/,excludeBegin:!0,excludeEnd:!0,keywords:t,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:/[\"'\\(]/}],illegal:/\\[|%/,relevance:0},{className:\"constructor\",beginKeywords:\"constructor\",end:/\\{/,excludeEnd:!0,relevance:10},{className:\"module\",beginKeywords:\"module\",end:/\\{/,excludeEnd:!0},{className:\"interface\",beginKeywords:\"interface\",end:/\\{/,excludeEnd:!0,keywords:\"interface extends\"},{begin:/\\$[(.]/},{begin:\"\\\\.\"+e.IDENT_RE,relevance:0}]}}),e.registerLanguage(\"vala\",function(e){return{keywords:{keyword:\"char uchar unichar int uint long ulong short ushort int8 int16 int32 int64 uint8 uint16 uint32 uint64 float double bool struct enum string void weak unowned owned async signal static abstract interface override while do for foreach else switch case break default return try catch public private protected internal using new this get set const stdout stdin stderr var\",built_in:\"DBus GLib CCode Gee Object\",literal:\"false true null\"},contains:[{className:\"class\",beginKeywords:\"class interface delegate namespace\",end:\"{\",excludeEnd:!0,illegal:\"[^,:\\\\n\\\\s\\\\.]\",contains:[e.UNDERSCORE_TITLE_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:\"string\",begin:'\"\"\"',end:'\"\"\"',relevance:5},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.C_NUMBER_MODE,{className:\"preprocessor\",begin:\"^#\",end:\"$\",relevance:2},{className:\"constant\",begin:\" [A-Z_]+ \",relevance:0}]}}),e.registerLanguage(\"vbnet\",function(e){return{aliases:[\"vb\"],case_insensitive:!0,keywords:{keyword:\"addhandler addressof alias and andalso aggregate ansi as assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into is isfalse isnot istrue join key let lib like loop me mid mod module mustinherit mustoverride mybase myclass namespace narrowing new next not notinheritable notoverridable of off on operator option optional or order orelse overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim rem removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly xor\",built_in:\"boolean byte cbool cbyte cchar cdate cdec cdbl char cint clng cobj csbyte cshort csng cstr ctype date decimal directcast double gettype getxmlnamespace iif integer long object sbyte short single string trycast typeof uinteger ulong ushort\",literal:\"true false nothing\"},illegal:\"//|{|}|endif|gosub|variant|wend\",contains:[e.inherit(e.QUOTE_STRING_MODE,{contains:[{begin:'\"\"'}]}),e.COMMENT(\"'\",\"$\",{returnBegin:!0,contains:[{className:\"xmlDocTag\",begin:\"'''|<!--|-->\",contains:[e.PHRASAL_WORDS_MODE]},{className:\"xmlDocTag\",begin:\"</?\",end:\">\",contains:[e.PHRASAL_WORDS_MODE]}]}),e.C_NUMBER_MODE,{className:\"preprocessor\",begin:\"#\",end:\"$\",keywords:\"if else elseif end region externalsource\"}]}}),e.registerLanguage(\"vbscript\",function(e){return{aliases:[\"vbs\"],case_insensitive:!0,keywords:{keyword:\"call class const dim do loop erase execute executeglobal exit for each next function if then else on error option explicit new private property let get public randomize redim rem select case set stop sub while wend with end to elseif is or xor and not class_initialize class_terminate default preserve in me byval byref step resume goto\",built_in:\"lcase month vartype instrrev ubound setlocale getobject rgb getref string weekdayname rnd dateadd monthname now day minute isarray cbool round formatcurrency conversions csng timevalue second year space abs clng timeserial fixs len asc isempty maths dateserial atn timer isobject filter weekday datevalue ccur isdate instr datediff formatdatetime replace isnull right sgn array snumeric log cdbl hex chr lbound msgbox ucase getlocale cos cdate cbyte rtrim join hour oct typename trim strcomp int createobject loadpicture tan formatnumber mid scriptenginebuildversion scriptengine split scriptengineminorversion cint sin datepart ltrim sqr scriptenginemajorversion time derived eval date formatpercent exp inputbox left ascw chrw regexp server response request cstr err\",literal:\"true false null nothing empty\"},illegal:\"//\",contains:[e.inherit(e.QUOTE_STRING_MODE,{contains:[{begin:'\"\"'}]}),e.COMMENT(/'/,/$/,{relevance:0}),e.C_NUMBER_MODE]}}),e.registerLanguage(\"vbscript-html\",function(e){return{subLanguage:\"xml\",contains:[{begin:\"<%\",end:\"%>\",subLanguage:\"vbscript\"}]}}),e.registerLanguage(\"verilog\",function(e){return{aliases:[\"v\"],case_insensitive:!0,keywords:{keyword:\"always and assign begin buf bufif0 bufif1 case casex casez cmos deassign default defparam disable edge else end endcase endfunction endmodule endprimitive endspecify endtable endtask event for force forever fork function if ifnone initial inout input join macromodule module nand negedge nmos nor not notif0 notif1 or output parameter pmos posedge primitive pulldown pullup rcmos release repeat rnmos rpmos rtran rtranif0 rtranif1 specify specparam table task timescale tran tranif0 tranif1 wait while xnor xor\",typename:\"highz0 highz1 integer large medium pull0 pull1 real realtime reg scalared signed small strong0 strong1 supply0 supply0 supply1 supply1 time tri tri0 tri1 triand trior trireg vectored wand weak0 weak1 wire wor\"},contains:[e.C_BLOCK_COMMENT_MODE,e.C_LINE_COMMENT_MODE,e.QUOTE_STRING_MODE,{className:\"number\",begin:\"\\\\b(\\\\d+'(b|h|o|d|B|H|O|D))?[0-9xzXZ]+\",contains:[e.BACKSLASH_ESCAPE],relevance:0},{className:\"typename\",begin:\"\\\\.\\\\w+\",relevance:0},{className:\"value\",begin:\"#\\\\((?!parameter).+\\\\)\"},{className:\"keyword\",begin:\"\\\\+|-|\\\\*|/|%|<|>|=|#|`|\\\\!|&|\\\\||@|:|\\\\^|~|\\\\{|\\\\}\",relevance:0}]}}),e.registerLanguage(\"vhdl\",function(e){var t=\"\\\\d(_|\\\\d)*\",n=\"[eE][-+]?\"+t,i=t+\"(\\\\.\"+t+\")?(\"+n+\")?\",r=\"\\\\w+\",a=t+\"#\"+r+\"(\\\\.\"+r+\")?#(\"+n+\")?\",o=\"\\\\b(\"+a+\"|\"+i+\")\";return{case_insensitive:!0,keywords:{keyword:\"abs access after alias all and architecture array assert attribute begin block body buffer bus case component configuration constant context cover disconnect downto default else elsif end entity exit fairness file for force function generate generic group guarded if impure in inertial inout is label library linkage literal loop map mod nand new next nor not null of on open or others out package port postponed procedure process property protected pure range record register reject release rem report restrict restrict_guarantee return rol ror select sequence severity shared signal sla sll sra srl strong subtype then to transport type unaffected units until use variable vmode vprop vunit wait when while with xnor xor\",typename:\"boolean bit character severity_level integer time delay_length natural positive string bit_vector file_open_kind file_open_status std_ulogic std_ulogic_vector std_logic std_logic_vector unsigned signed boolean_vector integer_vector real_vector time_vector\"},illegal:\"{\",contains:[e.C_BLOCK_COMMENT_MODE,e.COMMENT(\"--\",\"$\"),e.QUOTE_STRING_MODE,{className:\"number\",begin:o,relevance:0},{className:\"literal\",begin:\"'(U|X|0|1|Z|W|L|H|-)'\",contains:[e.BACKSLASH_ESCAPE]},{className:\"attribute\",begin:\"'[A-Za-z](_?[A-Za-z0-9])*\",contains:[e.BACKSLASH_ESCAPE]}]}}),e.registerLanguage(\"vim\",function(e){return{lexemes:/[!#@\\w]+/,keywords:{keyword:\"N|0 P|0 X|0 a|0 ab abc abo al am an|0 ar arga argd arge argdo argg argl argu as au aug aun b|0 bN ba bad bd be bel bf bl bm bn bo bp br brea breaka breakd breakl bro bufdo buffers bun bw c|0 cN cNf ca cabc caddb cad caddf cal cat cb cc ccl cd ce cex cf cfir cgetb cgete cg changes chd che checkt cl cla clo cm cmapc cme cn cnew cnf cno cnorea cnoreme co col colo com comc comp con conf cope cp cpf cq cr cs cst cu cuna cunme cw d|0 delm deb debugg delc delf dif diffg diffo diffp diffpu diffs diffthis dig di dl dell dj dli do doautoa dp dr ds dsp e|0 ea ec echoe echoh echom echon el elsei em en endfo endf endt endw ene ex exe exi exu f|0 files filet fin fina fini fir fix fo foldc foldd folddoc foldo for fu g|0 go gr grepa gu gv ha h|0 helpf helpg helpt hi hid his i|0 ia iabc if ij il im imapc ime ino inorea inoreme int is isp iu iuna iunme j|0 ju k|0 keepa kee keepj lN lNf l|0 lad laddb laddf la lan lat lb lc lch lcl lcs le lefta let lex lf lfir lgetb lgete lg lgr lgrepa lh ll lla lli lmak lm lmapc lne lnew lnf ln loadk lo loc lockv lol lope lp lpf lr ls lt lu lua luad luaf lv lvimgrepa lw m|0 ma mak map mapc marks mat me menut mes mk mks mksp mkv mkvie mod mz mzf nbc nb nbs n|0 new nm nmapc nme nn nnoreme noa no noh norea noreme norm nu nun nunme ol o|0 om omapc ome on ono onoreme opt ou ounme ow p|0 profd prof pro promptr pc ped pe perld po popu pp pre prev ps pt ptN ptf ptj ptl ptn ptp ptr pts pu pw py3 python3 py3d py3f py pyd pyf q|0 quita qa r|0 rec red redi redr redraws reg res ret retu rew ri rightb rub rubyd rubyf rund ru rv s|0 sN san sa sal sav sb sbN sba sbf sbl sbm sbn sbp sbr scrip scripte scs se setf setg setl sf sfir sh sim sig sil sl sla sm smap smapc sme sn sni sno snor snoreme sor so spelld spe spelli spellr spellu spellw sp spr sre st sta startg startr star stopi stj sts sun sunm sunme sus sv sw sy synti sync t|0 tN tabN tabc tabdo tabe tabf tabfir tabl tabm tabnew tabn tabo tabp tabr tabs tab ta tags tc tcld tclf te tf th tj tl tm tn to tp tr try ts tu u|0 undoj undol una unh unl unlo unm unme uns up v|0 ve verb vert vim vimgrepa vi viu vie vm vmapc vme vne vn vnoreme vs vu vunme windo w|0 wN wa wh wi winc winp wn wp wq wqa ws wu wv x|0 xa xmapc xm xme xn xnoreme xu xunme y|0 z|0 ~ Next Print append abbreviate abclear aboveleft all amenu anoremenu args argadd argdelete argedit argglobal arglocal argument ascii autocmd augroup aunmenu buffer bNext ball badd bdelete behave belowright bfirst blast bmodified bnext botright bprevious brewind break breakadd breakdel breaklist browse bunload bwipeout change cNext cNfile cabbrev cabclear caddbuffer caddexpr caddfile call catch cbuffer cclose center cexpr cfile cfirst cgetbuffer cgetexpr cgetfile chdir checkpath checktime clist clast close cmap cmapclear cmenu cnext cnewer cnfile cnoremap cnoreabbrev cnoremenu copy colder colorscheme command comclear compiler continue confirm copen cprevious cpfile cquit crewind cscope cstag cunmap cunabbrev cunmenu cwindow delete delmarks debug debuggreedy delcommand delfunction diffupdate diffget diffoff diffpatch diffput diffsplit digraphs display deletel djump dlist doautocmd doautoall deletep drop dsearch dsplit edit earlier echo echoerr echohl echomsg else elseif emenu endif endfor endfunction endtry endwhile enew execute exit exusage file filetype find finally finish first fixdel fold foldclose folddoopen folddoclosed foldopen function global goto grep grepadd gui gvim hardcopy help helpfind helpgrep helptags highlight hide history insert iabbrev iabclear ijump ilist imap imapclear imenu inoremap inoreabbrev inoremenu intro isearch isplit iunmap iunabbrev iunmenu join jumps keepalt keepmarks keepjumps lNext lNfile list laddexpr laddbuffer laddfile last language later lbuffer lcd lchdir lclose lcscope left leftabove lexpr lfile lfirst lgetbuffer lgetexpr lgetfile lgrep lgrepadd lhelpgrep llast llist lmake lmap lmapclear lnext lnewer lnfile lnoremap loadkeymap loadview lockmarks lockvar lolder lopen lprevious lpfile lrewind ltag lunmap luado luafile lvimgrep lvimgrepadd lwindow move mark make mapclear match menu menutranslate messages mkexrc mksession mkspell mkvimrc mkview mode mzscheme mzfile nbclose nbkey nbsart next nmap nmapclear nmenu nnoremap nnoremenu noautocmd noremap nohlsearch noreabbrev noremenu normal number nunmap nunmenu oldfiles open omap omapclear omenu only onoremap onoremenu options ounmap ounmenu ownsyntax print profdel profile promptfind promptrepl pclose pedit perl perldo pop popup ppop preserve previous psearch ptag ptNext ptfirst ptjump ptlast ptnext ptprevious ptrewind ptselect put pwd py3do py3file python pydo pyfile quit quitall qall read recover redo redir redraw redrawstatus registers resize retab return rewind right rightbelow ruby rubydo rubyfile rundo runtime rviminfo substitute sNext sandbox sargument sall saveas sbuffer sbNext sball sbfirst sblast sbmodified sbnext sbprevious sbrewind scriptnames scriptencoding scscope set setfiletype setglobal setlocal sfind sfirst shell simalt sign silent sleep slast smagic smapclear smenu snext sniff snomagic snoremap snoremenu sort source spelldump spellgood spellinfo spellrepall spellundo spellwrong split sprevious srewind stop stag startgreplace startreplace startinsert stopinsert stjump stselect sunhide sunmap sunmenu suspend sview swapname syntax syntime syncbind tNext tabNext tabclose tabedit tabfind tabfirst tablast tabmove tabnext tabonly tabprevious tabrewind tag tcl tcldo tclfile tearoff tfirst throw tjump tlast tmenu tnext topleft tprevious trewind tselect tunmenu undo undojoin undolist unabbreviate unhide unlet unlockvar unmap unmenu unsilent update vglobal version verbose vertical vimgrep vimgrepadd visual viusage view vmap vmapclear vmenu vnew vnoremap vnoremenu vsplit vunmap vunmenu write wNext wall while winsize wincmd winpos wnext wprevious wqall wsverb wundo wviminfo xit xall xmapclear xmap xmenu xnoremap xnoremenu xunmap xunmenu yank\",built_in:\"abs acos add and append argc argidx argv asin atan atan2 browse browsedir bufexists buflisted bufloaded bufname bufnr bufwinnr byte2line byteidx call ceil changenr char2nr cindent clearmatches col complete complete_add complete_check confirm copy cos cosh count cscope_connection cursor deepcopy delete did_filetype diff_filler diff_hlID empty escape eval eventhandler executable exists exp expand extend feedkeys filereadable filewritable filter finddir findfile float2nr floor fmod fnameescape fnamemodify foldclosed foldclosedend foldlevel foldtext foldtextresult foreground function garbagecollect get getbufline getbufvar getchar getcharmod getcmdline getcmdpos getcmdtype getcwd getfontname getfperm getfsize getftime getftype getline getloclist getmatches getpid getpos getqflist getreg getregtype gettabvar gettabwinvar getwinposx getwinposy getwinvar glob globpath has has_key haslocaldir hasmapto histadd histdel histget histnr hlexists hlID hostname iconv indent index input inputdialog inputlist inputrestore inputsave inputsecret insert invert isdirectory islocked items join keys len libcall libcallnr line line2byte lispindent localtime log log10 luaeval map maparg mapcheck match matchadd matcharg matchdelete matchend matchlist matchstr max min mkdir mode mzeval nextnonblank nr2char or pathshorten pow prevnonblank printf pumvisible py3eval pyeval range readfile reltime reltimestr remote_expr remote_foreground remote_peek remote_read remote_send remove rename repeat resolve reverse round screenattr screenchar screencol screenrow search searchdecl searchpair searchpairpos searchpos server2client serverlist setbufvar setcmdpos setline setloclist setmatches setpos setqflist setreg settabvar settabwinvar setwinvar sha256 shellescape shiftwidth simplify sin sinh sort soundfold spellbadword spellsuggest split sqrt str2float str2nr strchars strdisplaywidth strftime stridx string strlen strpart strridx strtrans strwidth submatch substitute synconcealed synID synIDattr synIDtrans synstack system tabpagebuflist tabpagenr tabpagewinnr tagfiles taglist tan tanh tempname tolower toupper tr trunc type undofile undotree values virtcol visualmode wildmenumode winbufnr wincol winheight winline winnr winrestcmd winrestview winsaveview winwidth writefile xor\"},illegal:/[{:]/,contains:[e.NUMBER_MODE,e.APOS_STRING_MODE,{className:\"string\",begin:/\"((\\\\\")|[^\"\\n])*(\"|\\n)/},{className:\"variable\",begin:/[bwtglsav]:[\\w\\d_]*/},{className:\"function\",beginKeywords:\"function function!\",end:\"$\",relevance:0,contains:[e.TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\"}]}]}}),e.registerLanguage(\"x86asm\",function(e){return{case_insensitive:!0,lexemes:\"\\\\.?\"+e.IDENT_RE,keywords:{keyword:\"lock rep repe repz repne repnz xaquire xrelease bnd nobnd aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63\",\nliteral:\"ip eip rip al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 cs ds es fs gs ss st st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0  xmm1  xmm2  xmm3  xmm4  xmm5  xmm6  xmm7  xmm8  xmm9 xmm10  xmm11 xmm12 xmm13 xmm14 xmm15 xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ymm0  ymm1  ymm2  ymm3  ymm4  ymm5  ymm6  ymm7  ymm8  ymm9 ymm10  ymm11 ymm12 ymm13 ymm14 ymm15 ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 zmm0  zmm1  zmm2  zmm3  zmm4  zmm5  zmm6  zmm7  zmm8  zmm9 zmm10  zmm11 zmm12 zmm13 zmm14 zmm15 zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 k0 k1 k2 k3 k4 k5 k6 k7 bnd0 bnd1 bnd2 bnd3 cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d r0h r1h r2h r3h r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l\",pseudo:\"db dw dd dq dt ddq do dy dz resb resw resd resq rest resdq reso resy resz incbin equ times\",preprocessor:\"%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif %ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep %endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment .nolist byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr __FILE__ __LINE__ __SECT__  __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ __UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__  __PASS__ struc endstruc istruc at iend align alignb sectalign daz nodaz up down zero default option assume public \",built_in:\"bits use16 use32 use64 default section segment absolute extern global common cpu float __utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ __float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ __Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__\"},contains:[e.COMMENT(\";\",\"$\",{relevance:0}),{className:\"number\",variants:[{begin:\"\\\\b(?:([0-9][0-9_]*)?\\\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|(0[Xx])?[0-9][0-9_]*\\\\.?[0-9_]*(?:[pP](?:[+-]?[0-9_]+)?)?)\\\\b\",relevance:0},{begin:\"\\\\$[0-9][0-9A-Fa-f]*\",relevance:0},{begin:\"\\\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[Hh]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\\\b\"},{begin:\"\\\\b(?:0[Xx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\\\b\"}]},e.QUOTE_STRING_MODE,{className:\"string\",variants:[{begin:\"'\",end:\"[^\\\\\\\\]'\"},{begin:\"`\",end:\"[^\\\\\\\\]`\"},{begin:\"\\\\.[A-Za-z0-9]+\"}],relevance:0},{className:\"label\",variants:[{begin:\"^\\\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\\\s+label)\"},{begin:\"^\\\\s*%%[A-Za-z0-9_$#@~.?]*:\"}],relevance:0},{className:\"argument\",begin:\"%[0-9]+\",relevance:0},{className:\"built_in\",begin:\"%!S+\",relevance:0}]}}),e.registerLanguage(\"xl\",function(e){var t=\"ObjectLoader Animate MovieCredits Slides Filters Shading Materials LensFlare Mapping VLCAudioVideo StereoDecoder PointCloud NetworkAccess RemoteControl RegExp ChromaKey Snowfall NodeJS Speech Charts\",n={keyword:\"if then else do while until for loop import with is as where when by data constant\",literal:\"true false nil\",type:\"integer real text name boolean symbol infix prefix postfix block tree\",built_in:\"in mod rem and or xor not abs sign floor ceil sqrt sin cos tan asin acos atan exp expm1 log log2 log10 log1p pi at\",module:t,id:\"text_length text_range text_find text_replace contains page slide basic_slide title_slide title subtitle fade_in fade_out fade_at clear_color color line_color line_width texture_wrap texture_transform texture scale_?x scale_?y scale_?z? translate_?x translate_?y translate_?z? rotate_?x rotate_?y rotate_?z? rectangle circle ellipse sphere path line_to move_to quad_to curve_to theme background contents locally time mouse_?x mouse_?y mouse_buttons\"},i={className:\"constant\",begin:\"[A-Z][A-Z_0-9]+\",relevance:0},r={className:\"variable\",begin:\"([A-Z][a-z_0-9]+)+\",relevance:0},a={className:\"id\",begin:\"[a-z][a-z_0-9]+\",relevance:0},o={className:\"string\",begin:'\"',end:'\"',illegal:\"\\\\n\"},s={className:\"string\",begin:\"'\",end:\"'\",illegal:\"\\\\n\"},l={className:\"string\",begin:\"<<\",end:\">>\"},c={className:\"number\",begin:\"[0-9]+#[0-9A-Z_]+(\\\\.[0-9-A-Z_]+)?#?([Ee][+-]?[0-9]+)?\",relevance:10},d={className:\"import\",beginKeywords:\"import\",end:\"$\",keywords:{keyword:\"import\",module:t},relevance:0,contains:[o]},u={className:\"function\",begin:\"[a-z].*->\"};return{aliases:[\"tao\"],lexemes:/[a-zA-Z][a-zA-Z0-9_?]*/,keywords:n,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,o,s,l,u,d,i,r,a,c,e.NUMBER_MODE]}}),e.registerLanguage(\"xquery\",function(e){var t=\"for let if while then else return where group by xquery encoding versionmodule namespace boundary-space preserve strip default collation base-uri orderingcopy-namespaces order declare import schema namespace function option in allowing emptyat tumbling window sliding window start when only end when previous next stable ascendingdescending empty greatest least some every satisfies switch case typeswitch try catch andor to union intersect instance of treat as castable cast map array delete insert intoreplace value rename copy modify update\",n=\"false true xs:string xs:integer element item xs:date xs:datetime xs:float xs:double xs:decimal QName xs:anyURI xs:long xs:int xs:short xs:byte attribute\",i={className:\"variable\",begin:/\\$[a-zA-Z0-9\\-]+/,relevance:5},r={className:\"number\",begin:\"(\\\\b0[0-7_]+)|(\\\\b0x[0-9a-fA-F_]+)|(\\\\b[1-9][0-9_]*(\\\\.[0-9_]+)?)|[0_]\\\\b\",relevance:0},a={className:\"string\",variants:[{begin:/\"/,end:/\"/,contains:[{begin:/\"\"/,relevance:0}]},{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]}]},o={className:\"decorator\",begin:\"%\\\\w+\"},s={className:\"comment\",begin:\"\\\\(:\",end:\":\\\\)\",relevance:10,contains:[{className:\"doc\",begin:\"@\\\\w+\"}]},l={begin:\"{\",end:\"}\"},c=[i,a,r,s,o,l];return l.contains=c,{aliases:[\"xpath\",\"xq\"],case_insensitive:!1,lexemes:/[a-zA-Z\\$][a-zA-Z0-9_:\\-]*/,illegal:/(proc)|(abstract)|(extends)|(until)|(#)/,keywords:{keyword:t,literal:n},contains:c}}),e.registerLanguage(\"zephir\",function(e){var t={className:\"string\",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:'b\"',end:'\"'},{begin:\"b'\",end:\"'\"},e.inherit(e.APOS_STRING_MODE,{illegal:null}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null})]},n={variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]};return{aliases:[\"zep\"],case_insensitive:!0,keywords:\"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var let while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally int uint long ulong char uchar double float bool boolean stringlikely unlikely\",contains:[e.C_LINE_COMMENT_MODE,e.HASH_COMMENT_MODE,e.COMMENT(\"/\\\\*\",\"\\\\*/\",{contains:[{className:\"doctag\",begin:\"@[A-Za-z]+\"}]}),e.COMMENT(\"__halt_compiler.+?;\",!1,{endsWithParent:!0,keywords:\"__halt_compiler\",lexemes:e.UNDERSCORE_IDENT_RE}),{className:\"string\",begin:\"<<<['\\\"]?\\\\w+['\\\"]?$\",end:\"^\\\\w+;\",contains:[e.BACKSLASH_ESCAPE]},{begin:/(::|->)+[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*/},{className:\"function\",beginKeywords:\"function\",end:/[;{]/,excludeEnd:!0,illegal:\"\\\\$|\\\\[|%\",contains:[e.UNDERSCORE_TITLE_MODE,{className:\"params\",begin:\"\\\\(\",end:\"\\\\)\",contains:[\"self\",e.C_BLOCK_COMMENT_MODE,t,n]}]},{className:\"class\",beginKeywords:\"class interface\",end:\"{\",excludeEnd:!0,illegal:/[:\\(\\$\"]/,contains:[{beginKeywords:\"extends implements\"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:\"namespace\",end:\";\",illegal:/[\\.']/,contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:\"use\",end:\";\",contains:[e.UNDERSCORE_TITLE_MODE]},{begin:\"=>\"},t,n]}}),e}),function(){function e(e){this.tokens=[],this.tokens.links={},this.options=e||c.defaults,this.rules=d.normal,this.options.gfm&&(this.options.tables?this.rules=d.tables:this.rules=d.gfm)}function t(e,t){if(this.options=t||c.defaults,this.links=e,this.rules=u.normal,this.renderer=this.options.renderer||new n,this.renderer.options=this.options,!this.links)throw new Error(\"Tokens array requires a `links` property.\");this.options.gfm?this.options.breaks?this.rules=u.breaks:this.rules=u.gfm:this.options.pedantic&&(this.rules=u.pedantic)}function n(e){this.options=e||{}}function i(e){this.tokens=[],this.token=null,this.options=e||c.defaults,this.options.renderer=this.options.renderer||new n,this.renderer=this.options.renderer,this.renderer.options=this.options}function r(e,t){return e.replace(t?/&/g:/&(?!#?\\w+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")}function a(e){return e.replace(/&([#\\w]+);/g,function(e,t){return t=t.toLowerCase(),\"colon\"===t?\":\":\"#\"===t.charAt(0)?\"x\"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):\"\"})}function o(e,t){return e=e.source,t=t||\"\",function n(i,r){return i?(r=r.source||r,r=r.replace(/(^|[^\\[])\\^/g,\"$1\"),e=e.replace(i,r),n):new RegExp(e,t)}}function s(){}function l(e){for(var t,n,i=1;i<arguments.length;i++){t=arguments[i];for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e}function c(t,n,a){if(a||\"function\"==typeof n){a||(a=n,n=null),n=l({},c.defaults,n||{});var o,s,d=n.highlight,u=0;try{o=e.lex(t,n)}catch(p){return a(p)}s=o.length;var m=function(e){if(e)return n.highlight=d,a(e);var t;try{t=i.parse(o,n)}catch(r){e=r}return n.highlight=d,e?a(e):a(null,t)};if(!d||d.length<3)return m();if(delete n.highlight,!s)return m();for(;u<o.length;u++)!function(e){return\"code\"!==e.type?--s||m():d(e.text,e.lang,function(t,n){return t?m(t):null==n||n===e.text?--s||m():(e.text=n,e.escaped=!0,void(--s||m()))})}(o[u])}else try{return n&&(n=l({},c.defaults,n)),i.parse(e.lex(t,n),n)}catch(p){if(p.message+=\"\\nPlease report this to https://github.com/chjj/marked.\",(n||c.defaults).silent)return\"<p>An error occured:</p><pre>\"+r(p.message+\"\",!0)+\"</pre>\";throw p}}var d={newline:/^\\n+/,code:/^( {4}[^\\n]+\\n*)+/,fences:s,hr:/^( *[-*_]){3,} *(?:\\n+|$)/,heading:/^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)/,nptable:s,lheading:/^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,blockquote:/^( *>[^\\n]+(\\n(?!def)[^\\n]+)*\\n*)+/,list:/^( *)(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,html:/^ *(?:comment *(?:\\n|\\s*$)|closed *(?:\\n{2,}|\\s*$)|closing *(?:\\n{2,}|\\s*$))/,def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)/,table:s,paragraph:/^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*/,text:/^[^\\n]+/};d.bullet=/(?:[*+-]|\\d+\\.)/,d.item=/^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*/,d.item=o(d.item,\"gm\")(/bull/g,d.bullet)(),d.list=o(d.list)(/bull/g,d.bullet)(\"hr\",\"\\\\n+(?=\\\\1?(?:[-*_] *){3,}(?:\\\\n+|$))\")(\"def\",\"\\\\n+(?=\"+d.def.source+\")\")(),d.blockquote=o(d.blockquote)(\"def\",d.def)(),d._tag=\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:/|[^\\\\w\\\\s@]*@)\\\\b\",d.html=o(d.html)(\"comment\",/<!--[\\s\\S]*?-->/)(\"closed\",/<(tag)[\\s\\S]+?<\\/\\1>/)(\"closing\",/<tag(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/)(/tag/g,d._tag)(),d.paragraph=o(d.paragraph)(\"hr\",d.hr)(\"heading\",d.heading)(\"lheading\",d.lheading)(\"blockquote\",d.blockquote)(\"tag\",\"<\"+d._tag)(\"def\",d.def)(),d.normal=l({},d),d.gfm=l({},d.normal,{fences:/^ *(`{3,}|~{3,})[ \\.]*(\\S+)? *\\n([\\s\\S]*?)\\s*\\1 *(?:\\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\\n]+?) *#* *(?:\\n+|$)/}),d.gfm.paragraph=o(d.paragraph)(\"(?!\",\"(?!\"+d.gfm.fences.source.replace(\"\\\\1\",\"\\\\2\")+\"|\"+d.list.source.replace(\"\\\\1\",\"\\\\3\")+\"|\")(),d.tables=l({},d.gfm,{nptable:/^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*/,table:/^ *\\|(.+)\\n *\\|( *[-:]+[-| :]*)\\n((?: *\\|.*(?:\\n|$))*)\\n*/}),e.rules=d,e.lex=function(t,n){var i=new e(n);return i.lex(t)},e.prototype.lex=function(e){return e=e.replace(/\\r\\n|\\r/g,\"\\n\").replace(/\\t/g,\"    \").replace(/\\u00a0/g,\" \").replace(/\\u2424/g,\"\\n\"),this.token(e,!0)},e.prototype.token=function(e,t,n){for(var i,r,a,o,s,l,c,u,p,e=e.replace(/^ +$/gm,\"\");e;)if((a=this.rules.newline.exec(e))&&(e=e.substring(a[0].length),a[0].length>1&&this.tokens.push({type:\"space\"})),a=this.rules.code.exec(e))e=e.substring(a[0].length),a=a[0].replace(/^ {4}/gm,\"\"),this.tokens.push({type:\"code\",text:this.options.pedantic?a:a.replace(/\\n+$/,\"\")});else if(a=this.rules.fences.exec(e))e=e.substring(a[0].length),this.tokens.push({type:\"code\",lang:a[2],text:a[3]||\"\"});else if(a=this.rules.heading.exec(e))e=e.substring(a[0].length),this.tokens.push({type:\"heading\",depth:a[1].length,text:a[2]});else if(t&&(a=this.rules.nptable.exec(e))){for(e=e.substring(a[0].length),l={type:\"table\",header:a[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:a[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:a[3].replace(/\\n$/,\"\").split(\"\\n\")},u=0;u<l.align.length;u++)/^ *-+: *$/.test(l.align[u])?l.align[u]=\"right\":/^ *:-+: *$/.test(l.align[u])?l.align[u]=\"center\":/^ *:-+ *$/.test(l.align[u])?l.align[u]=\"left\":l.align[u]=null;for(u=0;u<l.cells.length;u++)l.cells[u]=l.cells[u].split(/ *\\| */);this.tokens.push(l)}else if(a=this.rules.lheading.exec(e))e=e.substring(a[0].length),this.tokens.push({type:\"heading\",depth:\"=\"===a[2]?1:2,text:a[1]});else if(a=this.rules.hr.exec(e))e=e.substring(a[0].length),this.tokens.push({type:\"hr\"});else if(a=this.rules.blockquote.exec(e))e=e.substring(a[0].length),this.tokens.push({type:\"blockquote_start\"}),a=a[0].replace(/^ *> ?/gm,\"\"),this.token(a,t,!0),this.tokens.push({type:\"blockquote_end\"});else if(a=this.rules.list.exec(e)){for(e=e.substring(a[0].length),o=a[2],this.tokens.push({type:\"list_start\",ordered:o.length>1}),a=a[0].match(this.rules.item),i=!1,p=a.length,u=0;p>u;u++)l=a[u],c=l.length,l=l.replace(/^ *([*+-]|\\d+\\.) +/,\"\"),~l.indexOf(\"\\n \")&&(c-=l.length,l=this.options.pedantic?l.replace(/^ {1,4}/gm,\"\"):l.replace(new RegExp(\"^ {1,\"+c+\"}\",\"gm\"),\"\")),this.options.smartLists&&u!==p-1&&(s=d.bullet.exec(a[u+1])[0],o===s||o.length>1&&s.length>1||(e=a.slice(u+1).join(\"\\n\")+e,u=p-1)),r=i||/\\n\\n(?!\\s*$)/.test(l),u!==p-1&&(i=\"\\n\"===l.charAt(l.length-1),r||(r=i)),this.tokens.push({type:r?\"loose_item_start\":\"list_item_start\"}),this.token(l,!1,n),this.tokens.push({type:\"list_item_end\"});this.tokens.push({type:\"list_end\"})}else if(a=this.rules.html.exec(e))e=e.substring(a[0].length),this.tokens.push({type:this.options.sanitize?\"paragraph\":\"html\",pre:!this.options.sanitizer&&(\"pre\"===a[1]||\"script\"===a[1]||\"style\"===a[1]),text:a[0]});else if(!n&&t&&(a=this.rules.def.exec(e)))e=e.substring(a[0].length),this.tokens.links[a[1].toLowerCase()]={href:a[2],title:a[3]};else if(t&&(a=this.rules.table.exec(e))){for(e=e.substring(a[0].length),l={type:\"table\",header:a[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:a[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:a[3].replace(/(?: *\\| *)?\\n$/,\"\").split(\"\\n\")},u=0;u<l.align.length;u++)/^ *-+: *$/.test(l.align[u])?l.align[u]=\"right\":/^ *:-+: *$/.test(l.align[u])?l.align[u]=\"center\":/^ *:-+ *$/.test(l.align[u])?l.align[u]=\"left\":l.align[u]=null;for(u=0;u<l.cells.length;u++)l.cells[u]=l.cells[u].replace(/^ *\\| *| *\\| *$/g,\"\").split(/ *\\| */);this.tokens.push(l)}else if(t&&(a=this.rules.paragraph.exec(e)))e=e.substring(a[0].length),this.tokens.push({type:\"paragraph\",text:\"\\n\"===a[1].charAt(a[1].length-1)?a[1].slice(0,-1):a[1]});else if(a=this.rules.text.exec(e))e=e.substring(a[0].length),this.tokens.push({type:\"text\",text:a[0]});else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0));return this.tokens};var u={escape:/^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])/,autolink:/^<([^ >]+(@|:\\/)[^ >]+)>/,url:s,tag:/^<!--[\\s\\S]*?-->|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/,link:/^!?\\[(inside)\\]\\(href\\)/,reflink:/^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]/,nolink:/^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]/,strong:/^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)/,em:/^\\b_((?:[^_]|__)+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/,code:/^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)/,br:/^ {2,}\\n(?!\\s*$)/,del:s,text:/^[\\s\\S]+?(?=[\\\\<!\\[_*`]| {2,}\\n|$)/};u._inside=/(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*/,u._href=/\\s*<?([\\s\\S]*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*/,u.link=o(u.link)(\"inside\",u._inside)(\"href\",u._href)(),u.reflink=o(u.reflink)(\"inside\",u._inside)(),u.normal=l({},u),u.pedantic=l({},u.normal,{strong:/^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,em:/^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/}),u.gfm=l({},u.normal,{escape:o(u.escape)(\"])\",\"~|])\")(),url:/^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/,del:/^~~(?=\\S)([\\s\\S]*?\\S)~~/,text:o(u.text)(\"]|\",\"~]|\")(\"|\",\"|https?://|\")()}),u.breaks=l({},u.gfm,{br:o(u.br)(\"{2,}\",\"*\")(),text:o(u.gfm.text)(\"{2,}\",\"*\")()}),t.rules=u,t.output=function(e,n,i){var r=new t(n,i);return r.output(e)},t.prototype.output=function(e){for(var t,n,i,a,o=\"\";e;)if(a=this.rules.escape.exec(e))e=e.substring(a[0].length),o+=a[1];else if(a=this.rules.autolink.exec(e))e=e.substring(a[0].length),\"@\"===a[2]?(n=\":\"===a[1].charAt(6)?this.mangle(a[1].substring(7)):this.mangle(a[1]),i=this.mangle(\"mailto:\")+n):(n=r(a[1]),i=n),o+=this.renderer.link(i,null,n);else if(this.inLink||!(a=this.rules.url.exec(e))){if(a=this.rules.tag.exec(e))!this.inLink&&/^<a /i.test(a[0])?this.inLink=!0:this.inLink&&/^<\\/a>/i.test(a[0])&&(this.inLink=!1),e=e.substring(a[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(a[0]):r(a[0]):a[0];else if(a=this.rules.link.exec(e))e=e.substring(a[0].length),this.inLink=!0,o+=this.outputLink(a,{href:a[2],title:a[3]}),this.inLink=!1;else if((a=this.rules.reflink.exec(e))||(a=this.rules.nolink.exec(e))){if(e=e.substring(a[0].length),t=(a[2]||a[1]).replace(/\\s+/g,\" \"),t=this.links[t.toLowerCase()],!t||!t.href){o+=a[0].charAt(0),e=a[0].substring(1)+e;continue}this.inLink=!0,o+=this.outputLink(a,t),this.inLink=!1}else if(a=this.rules.strong.exec(e))e=e.substring(a[0].length),o+=this.renderer.strong(this.output(a[2]||a[1]));else if(a=this.rules.em.exec(e))e=e.substring(a[0].length),o+=this.renderer.em(this.output(a[2]||a[1]));else if(a=this.rules.code.exec(e))e=e.substring(a[0].length),o+=this.renderer.codespan(r(a[2],!0));else if(a=this.rules.br.exec(e))e=e.substring(a[0].length),o+=this.renderer.br();else if(a=this.rules.del.exec(e))e=e.substring(a[0].length),o+=this.renderer.del(this.output(a[1]));else if(a=this.rules.text.exec(e))e=e.substring(a[0].length),o+=this.renderer.text(r(this.smartypants(a[0])));else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0))}else e=e.substring(a[0].length),n=r(a[1]),i=n,o+=this.renderer.link(i,null,n);return o},t.prototype.outputLink=function(e,t){var n=r(t.href),i=t.title?r(t.title):null;return\"!\"!==e[0].charAt(0)?this.renderer.link(n,i,this.output(e[1])):this.renderer.image(n,i,r(e[1]))},t.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,\"—\").replace(/--/g,\"–\").replace(/(^|[-\\u2014\\/(\\[{\"\\s])'/g,\"$1‘\").replace(/'/g,\"’\").replace(/(^|[-\\u2014\\/(\\[{\\u2018\\s])\"/g,\"$1“\").replace(/\"/g,\"”\").replace(/\\.{3}/g,\"…\"):e},t.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n=\"\",i=e.length,r=0;i>r;r++)t=e.charCodeAt(r),Math.random()>.5&&(t=\"x\"+t.toString(16)),n+=\"&#\"+t+\";\";return n},n.prototype.code=function(e,t,n){if(this.options.highlight){var i=this.options.highlight(e,t);null!=i&&i!==e&&(n=!0,e=i)}return t?'<pre><code class=\"'+this.options.langPrefix+r(t,!0)+'\">'+(n?e:r(e,!0))+\"\\n</code></pre>\\n\":\"<pre><code>\"+(n?e:r(e,!0))+\"\\n</code></pre>\"},n.prototype.blockquote=function(e){return\"<blockquote>\\n\"+e+\"</blockquote>\\n\"},n.prototype.html=function(e){return e},n.prototype.heading=function(e,t,n){return\"<h\"+t+' id=\"'+this.options.headerPrefix+n.toLowerCase().replace(/[^\\w]+/g,\"-\")+'\">'+e+\"</h\"+t+\">\\n\"},n.prototype.hr=function(){return this.options.xhtml?\"<hr/>\\n\":\"<hr>\\n\"},n.prototype.list=function(e,t){var n=t?\"ol\":\"ul\";return\"<\"+n+\">\\n\"+e+\"</\"+n+\">\\n\"},n.prototype.listitem=function(e){return\"<li>\"+e+\"</li>\\n\"},n.prototype.paragraph=function(e){return\"<p>\"+e+\"</p>\\n\"},n.prototype.table=function(e,t){return\"<table>\\n<thead>\\n\"+e+\"</thead>\\n<tbody>\\n\"+t+\"</tbody>\\n</table>\\n\"},n.prototype.tablerow=function(e){return\"<tr>\\n\"+e+\"</tr>\\n\"},n.prototype.tablecell=function(e,t){var n=t.header?\"th\":\"td\",i=t.align?\"<\"+n+' style=\"text-align:'+t.align+'\">':\"<\"+n+\">\";return i+e+\"</\"+n+\">\\n\"},n.prototype.strong=function(e){return\"<strong>\"+e+\"</strong>\"},n.prototype.em=function(e){return\"<em>\"+e+\"</em>\"},n.prototype.codespan=function(e){return\"<code>\"+e+\"</code>\"},n.prototype.br=function(){return this.options.xhtml?\"<br/>\":\"<br>\"},n.prototype.del=function(e){return\"<del>\"+e+\"</del>\"},n.prototype.link=function(e,t,n){if(this.options.sanitize){try{var i=decodeURIComponent(a(e)).replace(/[^\\w:]/g,\"\").toLowerCase()}catch(r){return\"\"}if(0===i.indexOf(\"javascript:\")||0===i.indexOf(\"vbscript:\"))return\"\"}var o='<a href=\"'+e+'\"';return t&&(o+=' title=\"'+t+'\"'),o+=\">\"+n+\"</a>\"},n.prototype.image=function(e,t,n){var i='<img src=\"'+e+'\" alt=\"'+n+'\"';return t&&(i+=' title=\"'+t+'\"'),i+=this.options.xhtml?\"/>\":\">\"},n.prototype.text=function(e){return e},i.parse=function(e,t,n){var r=new i(t,n);return r.parse(e)},i.prototype.parse=function(e){this.inline=new t(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var n=\"\";this.next();)n+=this.tok();return n},i.prototype.next=function(){return this.token=this.tokens.pop()},i.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},i.prototype.parseText=function(){for(var e=this.token.text;\"text\"===this.peek().type;)e+=\"\\n\"+this.next().text;return this.inline.output(e)},i.prototype.tok=function(){switch(this.token.type){case\"space\":return\"\";case\"hr\":return this.renderer.hr();case\"heading\":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case\"code\":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case\"table\":var e,t,n,i,r,a=\"\",o=\"\";for(n=\"\",e=0;e<this.token.header.length;e++)i={header:!0,align:this.token.align[e]},n+=this.renderer.tablecell(this.inline.output(this.token.header[e]),{header:!0,align:this.token.align[e]});for(a+=this.renderer.tablerow(n),e=0;e<this.token.cells.length;e++){for(t=this.token.cells[e],n=\"\",r=0;r<t.length;r++)n+=this.renderer.tablecell(this.inline.output(t[r]),{header:!1,align:this.token.align[r]});o+=this.renderer.tablerow(n)}return this.renderer.table(a,o);case\"blockquote_start\":for(var o=\"\";\"blockquote_end\"!==this.next().type;)o+=this.tok();return this.renderer.blockquote(o);case\"list_start\":for(var o=\"\",s=this.token.ordered;\"list_end\"!==this.next().type;)o+=this.tok();return this.renderer.list(o,s);case\"list_item_start\":for(var o=\"\";\"list_item_end\"!==this.next().type;)o+=\"text\"===this.token.type?this.parseText():this.tok();return this.renderer.listitem(o);case\"loose_item_start\":for(var o=\"\";\"list_item_end\"!==this.next().type;)o+=this.tok();return this.renderer.listitem(o);case\"html\":var l=this.token.pre||this.options.pedantic?this.token.text:this.inline.output(this.token.text);return this.renderer.html(l);case\"paragraph\":return this.renderer.paragraph(this.inline.output(this.token.text));case\"text\":return this.renderer.paragraph(this.parseText())}},s.exec=s,c.options=c.setOptions=function(e){return l(c.defaults,e),c},c.defaults={gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!1,sanitizer:null,mangle:!0,smartLists:!1,silent:!1,highlight:null,langPrefix:\"lang-\",smartypants:!1,headerPrefix:\"\",renderer:new n,xhtml:!1},c.Parser=i,c.parser=i.parse,c.Renderer=n,c.Lexer=e,c.lexer=e.lex,c.InlineLexer=t,c.inlineLexer=t.output,c.parse=c,\"undefined\"!=typeof module&&\"object\"==typeof exports?module.exports=c:\"function\"==typeof define&&define.amd?define(function(){return c}):this.marked=c}.call(function(){return this||(\"undefined\"!=typeof window?window:global)}()),function(){var e={};e.init=function(){this._bind=function(e,t){return function(){return e.apply(t,arguments)}},this.registerGlobals(),this.addListeners(),this.handleTextareas(),this.manipulateUi(),hljs.initHighlightingOnLoad()},e.registerGlobals=function(){window.csrfToken=$('meta[name=\"csrf-token\"]').attr(\"content\"),window.routeName=$('meta[name=\"route\"]').attr(\"content\"),$.ajaxSetup({headers:{\"X-CSRF-TOKEN\":window.csrfToken}})},e.addListeners=function(){$(\"#back-to-top\").on(\"click\",function(){return $(\"body,html\").animate({scrollTop:0},800),!1}),$(\"#md-caller\").on(\"click\",function(e){return e.preventDefault(),$(\"#md-modal\").modal(),!1}),$(\"div.nav__forum > a\").on(\"click\",function(){$(\".sidebar__forum\").slideToggle(\"fast\"),$(\"body,html\").animate({scrollTop:0},\"fast\")}),$(\"div.nav__lessons > a\").on(\"click\",function(){$(\".sidebar__lessons\").slideToggle(\"fast\"),$(\"body,html\").animate({scrollTop:0},\"fast\")}),$(window).on(\"load\",function(){FastClick.attach(document.body)}),$(window).on(\"scroll\",function(){var e=$(window).scrollTop(),t=$(\".box__landing\");if(e>50?$(\"#back-to-top\").fadeIn():$(\"#back-to-top\").fadeOut(),t.length){var n=t.height();t.css({opacity:1-e/n/4})}})},e.handleTextareas=function(){var e=$(\"textarea\");e.length&&(e.tabby({tabString:\"    \"}),autosize(e),e.on(\"focus\",function(e){var t=$(this).siblings(\"div.preview__forum\").first();t.html().length||t.html(\"Preview will be shown here...\"),t.show()}),e.on(\"keyup\",function(e){var t=$(this),n=t.val(),i=t.siblings(\"div.preview__forum\").first(),r=marked(n,{renderer:new marked.Renderer,gfm:!0,tables:!0,breaks:!0,pedantic:!1,sanitize:!0,smartLists:!0,smartypants:!1});i.html(r),i.find(\"pre code\").each(function(e,t){hljs.highlightBlock(t)})}).trigger(\"keyup\"))},e.manipulateUi=function(){$(\".flash-message\")&&$(\".flash-message\").delay(5e3).fadeOut(),$(\"#flash-overlay-modal\")&&$(\"#flash-overlay-modal\").modal(),$(\".container__forum article>p>img, .container__lessons article>p>img\").closest(\"p\").addClass(\"text-center\")},$(function(){return e.init()})}.apply(this);"
  },
  {
    "path": "public/build/rev-manifest.json",
    "content": "{\n  \"css/app.css\": \"css/app-4cd4d601dd.css\",\n  \"js/app.js\": \"js/app-6c3ef62a70.js\"\n}"
  },
  {
    "path": "public/index.php",
    "content": "<?php\n\n/**\n * Laravel - A PHP Framework For Web Artisans\n *\n * @package  Laravel\n * @author   Taylor Otwell <taylorotwell@gmail.com>\n */\n\n/*\n|--------------------------------------------------------------------------\n| Register The Auto Loader\n|--------------------------------------------------------------------------\n|\n| Composer provides a convenient, automatically generated class loader for\n| our application. We just need to utilize it! We'll simply require it\n| into the script here so that we don't have to worry about manual\n| loading any of our classes later on. It feels nice to relax.\n|\n*/\n\nrequire __DIR__.'/../bootstrap/autoload.php';\n\n/*\n|--------------------------------------------------------------------------\n| Turn On The Lights\n|--------------------------------------------------------------------------\n|\n| We need to illuminate PHP development, so let us turn on the lights.\n| This bootstraps the framework and gets it ready for use, then it\n| will load up this application so that we can run it and send\n| the responses back to the browser and delight our users.\n|\n*/\n\n$app = require_once __DIR__.'/../bootstrap/app.php';\n\n/*\n|--------------------------------------------------------------------------\n| Run The Application\n|--------------------------------------------------------------------------\n|\n| Once we have the application, we can handle the incoming request\n| through the kernel, and send the associated response back to\n| the client's browser allowing them to enjoy the creative\n| and wonderful application we have prepared for them.\n|\n*/\n\n$kernel = $app->make(Illuminate\\Contracts\\Http\\Kernel::class);\n\n$response = $kernel->handle(\n    $request = Illuminate\\Http\\Request::capture()\n);\n\n$response->send();\n\n$kernel->terminate($request, $response);\n"
  },
  {
    "path": "public/robots.txt",
    "content": "User-agent: *\nDisallow:\n"
  },
  {
    "path": "readme.md",
    "content": "# 라라벨 (Laravel) 5 입문 및 실전 강좌\n\n[![Build Status](https://travis-ci.org/appkr/l5essential.svg)](https://travis-ci.org/appkr/l5essential)\n\n라라벨은 PHP 언어로 개발된 풀스택 MVC 웹 어플리케이션 프레임웍이다.\n\n## 종이책 출간 안내\n\n[http://blog.appkr.dev/work-n-play/laravel-paper-book-published/](http://blog.appkr.dev/work-n-play/laravel-paper-book-published/)\n\n## 이 강좌를 처음 시작하시는 분들께\n\n2016년 4월 현재 `laravel/framework` 프로젝트에는 13,000개가 넘는 이슈와 거의 13,000개에 육박하는 커밋이 등록되어 있다. 곧 라라벨 탄생 5주기가 되는데, 5년 동안의 행적치고는 엄청나다. 라라벨이 살아 있다는 증거다. 이 강좌는 1월 말에 다썼다. 불과 3달 남짓 동안 또 엄청난 변화가 있었다. 이 강좌를 읽기 전에, [https://github.com/appkr/l5essential/issues/10](https://github.com/appkr/l5essential/issues/10) 를 꼭 읽고 시작하시기 바란다. 이 강좌에서 수정 적용할 부분을 기록해 두었다.\n\n## 라이브 데모 사이트\n\n클라우드 비용이 꽤 나와서 라이브 데모 사이트는 폐지했다. 대신 강의 내용만 모아 댓글이 가능한 정적 사이트([http://l5.appkr.dev](http://l5.appkr.dev))로 오픈해 두었다.\n\n## 목적\n\n1.  라라벨 입문을 돕는다.\n2.  실전 강좌를 통해 중급 이상의 개발자로 성장할 수 있도록 돕는다.\n3.  모던 개발 방법론과 베스트 프랙티스를 전파하여, 국내 PHP 개발자 생태계가 진화할 수 있도록 일조한다. \n \n## 목표\n\n1.  8 시간 정도에 라라벨의 기본기를 모두 마스터하는 것을 목표로 한다. (1강 ~ 25강)\n2.  제시된 실전 프로젝트를 통해 중급 이상의 라라벨 개발자로 성장하도록 한다. (26강 ~ 계속 연재 중)\n\n## 다루지 않는 것들\n\n강좌를 진행하기 위해 사용하지만, 설명하지 않는 것들이다.\n\n1.  PHP 문법\n2.  웹 프로그래밍 일반론\n3.  객체 지향 프로그래밍(OOP) 일반론\n4.  프론트엔드 프로그래밍 일반론\n\n## 같이 배워 볼 주제들\n\n### **[입문코스]** 라라벨 프레임 입문\n\n라라벨 입문자들이 꼭 알아야 하는 내용만 추렸다 (고 생각한다). \n\n-   [1강 - 처음 만나는 라라벨](lessons/01-welcome.md)\n-   [2강 - 라라벨 5 설치하기](lessons/02-hello-laravel.md)\n-   [2강 - 라라벨 5 설치하기 (on Windows)](lessons/02-install-on-windows.md)\n-   [3강 - 글로벌 설정 살펴보기](lessons/03-configuration.md)\n-   [4강 - Routing 기본기](lessons/04-routing-basics.md)\n-   [5강 - 뷰에 데이터 바인딩하기](lessons/05-pass-data-to-view.md)\n-   [6강 - 블레이드 101](lessons/06-blade-101.md)\n-   [7강 - 블레이드 201](lessons/07-blade-201.md)\n-   [8강 - 날 쿼리 :(](lessons/08-raw-queries.md)\n-   [9강 - 쿼리 빌더](lessons/09-query-builder.md)\n-   [10강 - 엘로퀀트 ORM](lessons/10-eloquent.md)\n-   [11강 - DB 마이그레이션](lessons/11-migration.md)\n-   [12강 - 컨트롤러](lessons/12-controller.md)\n-   [13강 - RESTful 리소스 컨트롤러](lessons/13-restful-resource-controller.md)\n-   [14강 - 이름 있는 Route](lessons/14-named-routes.md)\n-   [15강 - 중첩된 리소스](lessons/15-nested-resources.md)\n-   [16강 - 사용자 인증 기본기](lessons/16-authentication.md)\n-   [17강 - 라라벨에 내장된 사용자 인증](lessons/17-authentication-201.md)\n-   [18강 - 모델간 관계 맺기](lessons/18-eloquent-relationships.md)\n-   [19강 - 데이터 심기](lessons/19-seeder.md)\n-   [20강 - Eager 로딩](lessons/20-eager-loading.md)\n-   [추가 - 페이징](lessons/20-1-pagination.md)\n-   [21강 - 메일 보내기](lessons/21-mail.md)\n-   [22강 - 이벤트](lessons/22-events.md)\n-   [23강 - 입력 값 유효성 검사](lessons/23-validation.md)\n-   [24강 - 예외 처리](lessons/24-exception-handling.md)\n-   [25강 - 컴포저](lessons/25-composer.md)\n\n### **[중급코스]** 실전 프로젝트\n\n총 3개의 실전 프로젝트를 같이 만들어 본다.\n\n#### 1. Markdown Viewer\n\n마크다운으로 작성된 이 강좌들을 HTML 뷰로 나이스하게 보여주는 기능을 구현해 본다. 이를 통해 Filesystem, Custom Helper, Cache, Elixir 등의 라라벨 기능을 살펴볼 예정이다.\n\n-   [26강 - Document 모델](lessons/26-document-model.md)\n-   [27강 - Document 컨트롤러](lessons/27-document-controller.md)\n-   [28강 - Cache](lessons/28-cache.md)\n-   [29강 - Elixir, 만병통치약?](lessons/29-elixir.md)\n-   [30강 - Debug & Final Touch](lessons/30-final-touch.md)\n\n#### 2. Forum\n\nStackOverflow 처럼 댓글이 가능한 포럼을 구현해 본다. 이를 통해 HTTP Request &amp; Response 에 대한 이해를 높인다. 뿐만 아니라, 라라벨을 이용한 CRUD, Event, File/Image Upload, 인증과 권한부여 등에 대해 배워볼 예정이다.\n\n-   [31강 - 포럼 요구사항 기획](lessons/31-forum-features.md)\n-   [32강 - 사용자 로그인](lessons/32-login.md)\n-   [33강 - 소셜 로그인](lessons/33-social-login.md)\n-   [34강 - 사용자 역할](lessons/34-role.md)\n-   [35강 - 다국어 지원](lessons/35-locale.md)\n-   [36강 - 마이그레이션과 모델](lessons/36-models.md)\n-   [37강 - Article 기능 구현](lessons/37-articles.md)\n-   [38강 - Tag 기능 구현](lessons/38-tags.md)\n-   [39강 - Attachment 기능 구현](lessons/39-attachments.md)\n-   [32/33 보충 - 인증 리팩토링](lessons/32n33-auth-refactoring.md)\n-   [40강 - Comment 기능 구현](lessons/40-comments.md)\n-   [41강 - UI 개선](lessons/41-ui-makeup.md)\n-   [42강 - 서버 사이드 개선](lessons/42-be-makeup.md)\n-   [43강 - 변경 사항 알림](lessons/43-change-note.md)\n\n#### 3. RESTful API\n\nForum 에서 생성된 게시글/댓글을 JSON API 로 외부에 노출하여, 외부 앱들이 Forum 서비스와 상호 작용할 수 있도록 해 본다. 실험을 위해 프론트엔드 프레임웍을 이용한 간단한 모바일 앱도 만들어 볼 것이다.\n \n-   [44강 - API 기본기 및 기획](lessons/44-api-basic.md)\n-   [45강 - 기본 구조 잡기](lessons/45-api-big-picture.md)\n-   [46강 - JWT 를 이용한 인증](lessons/46-jwt.md)\n-   [47강 - 중복 제거 리팩토링](lessons/47-dry-refactoring.md)\n-   [48강 - all() is bad](lessons/48-all-is-bad.md)\n-   [49강 - API Rate Limit](lessons/49-rate-limit.md)\n-   [50강 - 리소스 id 난독화](lessons/50-id-obfuscation.md)\n-   [51강 - CORS](lessons/51-cors.md)\n-   [52강 - Caching](lessons/52-caching.md)\n-   [53강 - Partial Response](lessons/53-partial-response.md)\n-   [54강 - API Documents](lessons/54-api-docs.md)\n\n#### 번외. 기타 알면 좋은 내용들\n\n-   [Homestead 설치 (on Mac)](lessons/02-install-homestead-osx.md)\n-   [Homestead 설치 (on Windows)](lessons/02-install-homestead-windows.md)\n-   [코드 배포](lessons/999-code-release.md)\n\n## 이 강좌를 보는 방법\n\n강좌들은 Markdown 문법으로 작성되어 있으므로 Github에서 보는 것이 좋다. 이미 PHP 언어와 라라벨을 좀 아는 분이라면, 강좌를 눈으로 읽고 머리로 이해하는 것도 도움이 된다. 강좌의 내용과 더불어, [Github Commit 로그](https://github.com/appkr/l5essential/commits/master) 를 이용해서 이전 강좌 대비 달라진 부분들을 보는 것도 좋은 방법이다. \n\n**그런데 필자는 이미 만들어진 소스코드를 눈으로 읽는 것 보다, 한 문장, 한 단락씩 따라하면서 실제 실습해 볼 것을 적극 권장한다.** 강좌의 단계별 소스코드는 Git Tag 로 저장되어 있다. 먼저 이 프로젝트를 클론하고, 원하는 강좌로 체크아웃하자. \n\n```bash\n$ git clone git@github.com:appkr/l5essential.git myProject\n$ cd myProject\n$ composer install # composer가 설치되어 있지 않다면 2강을 참조해서 설치하자.\n$ git checkout 03(tab & enter)\n```\n\n**`참고`** 학생들과 만나보면, 콘솔을 쓸 줄 모르는 분들이 많다. 문서에 나온 코드 블럭 중에서 `$` (윈도우즈의 경우 `\\>`) 로 시작하는 명령들은 콘솔에서 실행하라는 의미이다. 가령, `$ ls -al` 이라 써 있으면, 콘솔에서 `ls -al (enter)` 를 하라는 의미이다. 콘솔 명령 블럭에서 `# ...` 은 주석이다.\n\n## Contributors / Sponsors\n\n[기여 가이드](CONTRIBUTING.md) 를 따라 주세요.\n\n-   오탈자/오류 신고 - dosirak 님, [이현석 님](https://www.facebook.com/leehs), [ibin79 ](https://github.com/ibin79), [AidenJeon 님](https://github.com/AidenJeon), [smartyunhui 님](https://github.com/smartyunhui), [찬스냅 님](https://www.facebook.com/chansnapit), [김종운 님](https://www.facebook.com/profile.php?id=100001411952158), [richellin 님](https://github.com/richellin), [jicjjang 님](https://github.com/jicjjang), [jongguheo 님](https://github.com/jongguheo), [desty 님](https://github.com/desty), [백창현 님](https://github.com/paikwiki), SeungHyun Kang(selene)님, [younglai lee님](https://disqus.com/by/younglai_lee/)\n-   감수 - [이종웅 님](https://www.facebook.com/jongwoong.lee.71)\n-   [Pull Request 를 통한 기여자 분들](https://github.com/appkr/l5essential/graphs/contributors)\n-   [정광섭님](https://github.com/lesstif) - 라이브 데모 서버\n-   [JetBrains](https://www.jetbrains.com/)에서 phpStorm IDE를 지원해 주셨습니다.\n\n![](icon_PhpStorm.png)\n\n\"모두 모두 감사합니다.\"\n\n## 라이센스\n\n- 강좌에 사용된 코드는 [MIT](https://raw.githubusercontent.com/appkr/l5essential/master/LICENSE) 라이센스를 따른다.\n- 강좌 자체는 [CC BY-NC](https://creativecommons.org/licenses/by-nc/4.0/) 라이센스를 따른다.\n"
  },
  {
    "path": "resources/assets/js/app.js",
    "content": "(function() {\n\n  var App = {};\n\n  App.init = function() {\n    this._bind = function(fn, me) {\n      return function() {\n        return fn.apply(me, arguments);\n      };\n    };\n\n    this.registerGlobals();\n    this.addListeners();\n    this.handleTextareas();\n    this.manipulateUi();\n\n    /* Activate syntax highlight.\n     This will affect code blocks right after the page renders */\n    hljs.initHighlightingOnLoad();\n  };\n\n  App.registerGlobals = function() {\n    window.csrfToken = $('meta[name=\"csrf-token\"]').attr('content');\n    window.routeName = $('meta[name=\"route\"]').attr('content');\n\n    /* Set Ajax request header.\n     Document can be found at http://laravel.com/docs/5.1/routing#csrf-x-csrf-token */\n    $.ajaxSetup({\n      headers: {\n        'X-CSRF-TOKEN': window.csrfToken\n      }\n    });\n  };\n\n  App.addListeners = function() {\n    $('#back-to-top').on(\"click\", function () {\n      $('body,html').animate({\n        scrollTop: 0\n      }, 800);\n\n      return false;\n    });\n\n    /* Modal window for Markdown Cheatsheet */\n    $(\"#md-caller\").on(\"click\", function(e) {\n      e.preventDefault();\n      $(\"#md-modal\").modal();\n\n      return false;\n    });\n\n    /* Slide menu effect on a small device */\n    $(\"div.nav__forum > a\").on(\"click\", function() {\n      $(\".sidebar__forum\").slideToggle(\"fast\");\n      $('body,html').animate({ scrollTop: 0 }, \"fast\");\n    });\n\n    $(\"div.nav__lessons > a\").on(\"click\", function() {\n      $(\".sidebar__lessons\").slideToggle(\"fast\");\n      $('body,html').animate({ scrollTop: 0 }, \"fast\");\n    });\n\n    /* Activate Fastclick */\n    $(window).on(\"load\", function() {\n      FastClick.attach(document.body);\n    });\n\n    /* \"Back to top\" button */\n    $(window).on(\"scroll\", function () {\n      var scrollPos = $(window).scrollTop();\n      var boxLanding = $('.box__landing');\n\n      if (scrollPos > 50) {\n        $('#back-to-top').fadeIn();\n      } else {\n        $('#back-to-top').fadeOut();\n      }\n\n      if (boxLanding.length) {\n        var objHeight = boxLanding.height();\n\n        boxLanding.css({\n          'opacity': 1 - (scrollPos / objHeight / 4)\n        });\n      }\n    });\n  };\n\n  App.handleTextareas = function() {\n    var textAreas = $('textarea');\n\n    if (textAreas.length) {\n      /* Activate Tabby on every textarea element */\n      textAreas.tabby({tabString: '    '});\n\n      /* Auto expand textarea size */\n      autosize(textAreas);\n\n      textAreas.on(\"focus\", function (e) {\n        // Show preview pane when a textarea is in focus\n        var el = $(this).siblings(\"div.preview__forum\").first();\n\n        if (! el.html().length) {\n          el.html(\"Preview will be shown here...\");\n        }\n\n        el.show();\n      });\n\n      textAreas.on(\"keyup\", function(e) {\n        // Register 'keyup' event handler\n        var self = $(this),\n            content = self.val(),\n            previewEl = self.siblings(\"div.preview__forum\").first();\n\n        // Compile textarea content\n        var compiled = marked(content, {\n          renderer: new marked.Renderer(),\n          gfm: true,\n          tables: true,\n          breaks: true,\n          pedantic: false,\n          sanitize: true,\n          smartLists: true,\n          smartypants: false\n        });\n\n        // Fill preview container with compiled content\n        previewEl.html(compiled);\n        // Add syntax highlight on the preview content\n        previewEl.find('pre code').each(function(i, block) {\n          hljs.highlightBlock(block)\n        });\n      }).trigger(\"keyup\");\n    }\n  };\n\n  App.manipulateUi = function() {\n    /* At the time of page loading, remove any element having flash-message class in 5 secs */\n    if($(\".flash-message\")) {\n      $(\".flash-message\").delay(5000).fadeOut();\n    }\n\n    if ($(\"#flash-overlay-modal\")) {\n      $(\"#flash-overlay-modal\").modal();\n    }\n\n    /* Center image in the html which was compiled from markdown */\n    $(\".container__forum article>p>img, .container__lessons article>p>img\").closest(\"p\").addClass(\"text-center\");\n\n  };\n\n  $(function() {\n    return App.init();\n  });\n\n}).apply(this);\n\n/* Global Helper Functions */\n\n/* Generate flash message from javascript */\nfunction flash(type, msg, delay) {\n  var el = $(\"div.js-flash-message\");\n\n  if (el) {\n    el.remove();\n  }\n\n  $(\"<div></div>\", {\n    \"class\": \"alert alert-\" + type + \" alert-dismissible js-flash-message\",\n    \"html\": '<button type=\"button\" class=\"close\" data-dismiss=\"alert\">'\n    + '<span aria-hidden=\"true\">&times;</span>'\n    + '<span class=\"sr-only\">Close</span></button>' + msg\n  }).appendTo($(\".container\").first());\n\n  $(\"div.js-flash-message\").fadeIn(\"fast\").delay(delay || 5000).fadeOut(\"fast\");\n}\n\n/* Reload page */\nfunction reload(interval) {\n  setTimeout(function () {\n    window.location.reload(true);\n  }, interval || 5000);\n}\n\n/* Random background image for landing page to give fun to visitors */\n//var images = [\"459033.jpg\", \"378663.jpg\", \"413890.jpg\", \"419042.jpg\", \"510930.jpg\"],\n//    randomIndex = Math.floor(Math.random() * images.length),\n//    pickedImage = images[randomIndex];\n//$(\"#laracroft\").css({\"background-image\": \"url(/images/\" + pickedImage + \")\"});\n//$(\".credit\").find(\"a\").first().attr(\"href\", \"http://wall.alphacoders.com/big.php?i=\" + pickedImage.substring(0, 6));\n"
  },
  {
    "path": "resources/assets/sass/_auth.scss",
    "content": ".form-auth {\n  max-width: 330px;\n  width: 100%;\n  padding: 15px;\n  margin: 0 auto;\n\n  .form-signin-heading,\n  .checkbox {\n    margin-bottom: 1rem;\n  }\n\n  .checkbox {\n    font-weight: normal;\n  }\n\n  .form-control {\n    position: relative;\n    height: auto;\n    box-sizing: border-box;\n    padding: 0.6rem;\n  }\n\n  .form-control:focus {\n    z-index: 2;\n  }\n\n  input {\n    margin-bottom: 10px;\n  }\n}"
  },
  {
    "path": "resources/assets/sass/_commons.scss",
    "content": "/* variables*/\n$font-size-base: 16px;\n$font-size-large: ceil(($font-size-base * 1.25));\n$font-size-small: ceil(($font-size-base * 0.85));\n\n$baseline: $font-size-base * 1.5;\n\n$margin-multiplier: 2;\n$margin-base: $baseline * $margin-multiplier;\n\n$screen-xs: 480px;\n$screen-sm: 768px;\n$screen-md: 992px;\n$screen-lg: 1200px;\n$screen-xs-max: ($screen-sm - 1);\n$screen-sm-max: ($screen-md - 1);\n$screen-md-max: ($screen-lg - 1);\n\n$color-gray: #98978B;\n$color-text1: #444;\n$color-text2: #fff;\n$color-background: #f5f5f5;\n$color-hr: #e9e9e9;\n$color-selection: #fff7a8;\n$color-link: #2f7dc8;\n$color-link-hover: #000;\n\n$brand-primary: #325D88;\n$brand-success: #93C54B;\n$brand-info: #29ABE0;\n$brand-warning: #F47C3C;\n$brand-danger: #d9534f;\n\n/* common */\nhtml,\nbody {\n  width: 100%;\n  color: $color-text1;\n  font-size: $font-size-base;\n  font-weight: 400;\n  -webkit-font-smoothing: antialiased;\n  line-height: $baseline;\n  background: $color-background;\n  overflow-x: hidden;\n  box-sizing: border-box;\n}\n\nhr {\n  display: block;\n  height: 1px;\n  border: 0;\n  border-top: 1px solid $color-hr;\n  margin: 1em 0;\n  padding: 0;\n}\n\n::selection {\n  background: $color-selection;\n  color: $color-text1;\n  text-shadow: none;\n}\n\n::-moz-selection {\n  background: $color-selection;\n  color: $color-text1;\n  text-shadow: none;\n}\n\nbody>div.container{\n  margin-top: 5rem;\n}\n\n.navbar-brand {\n  padding: 10px 15px;\n}\n\n.flash-message,\n.js-flash-message {\n  display: inline-block;\n  position: fixed;\n  bottom: 50px;\n  right: 15px;\n  max-width: 450px;\n  opacity: .8;\n  z-index: 9999;\n}\n\n.page-header {\n  margin: 20px 0 20px;\n}\n\n.footer {\n  min-height: 60px;\n  padding: 1rem 1rem;\n  margin-top: $margin-base;\n  margin-bottom: $baseline;\n  border-top: 1px solid $color-hr;\n  color: $color-gray;\n  font-size: $font-size-small;\n\n  a {\n    color: $color-gray;\n\n    &:hover {\n      color: $color-text1;\n    }\n  }\n\n  .locale li.active {\n    background-color: $color-hr;\n    a {\n      color: $color-text1;\n    }\n  }\n}\n\ni.icon {\n  display: inline-block;\n  width: 10px;\n  margin-right: 10px;\n}\n\nspan.form-error {\n  margin-top: 5px;\n  display: block;\n  font-size: .8em;\n  color: $brand-danger;\n  font-style: italic;\n  font-weight: 100\n}\n\n.divider {\n  display: block;\n  margin: 1rem auto;\n  width: 100%;\n}\n\n.back-to-top {\n  cursor: pointer;\n  position: fixed;\n  bottom: 1px;\n  right: 1px;\n  display: none;\n  z-index: 9998;\n  transition: all 0.5s ease-in-out;\n  padding: 8px 10px;\n}\n\n/*\n.btn-default,\n.badge-default {\n  color: $color_text1;\n  background-color: $color_text2;\n  border-color: $color_hr !important;\n\n  &:hover,\n  &:focus,\n  &:active,\n  .active {\n    color: $color_text1;\n    background-color: $color_hr;\n    border-color: $color_text2;\n  }\n\n  &:active,\n  .active {\n    background-image: none;\n  }\n\n  .badge {\n    color: $color_text1;\n    background-color: $color_text2;\n  }\n\n  .disabled {\n    &:hover,\n    &:focus,\n    &:active,\n    .active {\n      background-color: $color_text2;\n      border-color: $color_text1;\n    }\n  }\n\n  &[disabled]{\n    &:hover,\n    &:focus,\n    &:active,\n    .active,\n    {\n      background-color: $color_text2;\n      border-color: $color_text1;\n    }\n  }\n}\n*/\n"
  },
  {
    "path": "resources/assets/sass/_forum.scss",
    "content": "/* forum */\n.container__forum {\n  margin-top: 1rem;\n\n  .form__forum,\n  article {\n    background-color: #fff;\n    padding: 1rem;\n  }\n\n  .media {\n    margin: $baseline 0;\n  }\n\n  aside {\n    li {\n      display: block;\n    }\n\n    li a {\n      display: block;\n      padding: 0.5rem 1rem;\n    }\n\n    li.active {\n      background-color: $color-hr;\n\n      a, a:hover, a:active, a:focus {\n        color: $color-text1;\n      }\n    }\n  }\n\n  img {\n    display: inline-block;\n    height: auto;\n    max-width: 100%;\n    padding: 4px;\n    margin: 0 auto;\n    line-height: 1rem;\n    background-color: #fff;\n    transition: all .2s ease-in-out\n  }\n\n  table {\n    width: 100%;\n    max-width: 100%;\n    overflow-y: hidden;\n    overflow-x: auto;\n    border-radius: 2px;\n    background-color: transparent;\n    margin: $baseline auto;\n\n    & > thead > tr > th,\n    & > tbody > tr > th,\n    & > tfoot > tr > th,\n    & > thead > tr > td,\n    & > tbody > tr > td,\n    & > tfoot > tr > td {\n      padding: 0.5rem;\n      border-top: 1px solid #eee;\n    }\n\n    & > tbody > tr:nth-child(odd) > td,\n    & > tbody > tr:nth-child(odd) > th {\n      background-color: #efefef;\n    }\n  }\n}\n\n.sidebar__forum aside {\n  &>ul>li {\n    margin-bottom: 1rem;\n  }\n\n  form {\n    padding-left: 1rem;\n    margin-bottom: 1rem;\n  }\n\n  p.lead {\n    margin: 0;\n    padding: 1rem;\n  }\n\n  ul {\n    padding-left: 1rem;\n  }\n}\n\n.tags__forum {\n  display: inline-block;\n  padding: 0;\n\n  li {\n    cursor:  pointer;\n\n    a {\n      color: $color-text1;\n    }\n\n    a:hover, a:active, a:focus {\n      color: $color-text2;\n    }\n\n    &:hover, &:focus, &.active {\n      background-color: $color-link;\n      color: $color-text2;\n      transition: all 0.3s ease;\n    }\n  }\n\n  .label {\n    display: inline-block;\n    margin-left: 0 !important;\n    margin-right: 5px;\n    margin-bottom: 5px;\n    padding: 5px 7px;\n    font-weight: 100;\n    border-radius: 1px;\n    background-color: $color-hr;\n    color: $color-text1;\n  }\n}\n\ndiv.preview__forum {\n  display: none;\n  @extend .form-control;\n  margin-top: $baseline;\n  height: auto;\n}\n\ndiv.dropzone {\n  @extend .form-control;\n  display: none;\n  height: auto;\n}\n\ntextarea.forum__content {\n  width: 100%;\n  padding: 1rem;\n}\n\npre {\n  padding: 0;\n  border: none;\n  border-radius: 0;\n  &>code.hljs {\n    padding: 1rem;\n  }\n}\n\ndiv.nav__forum {\n  display: none;\n}\n\n.login__forum {\n  padding: 1rem;\n  border-radius: 3px;\n  border: 1px solid $color-hr;\n  width: 100%;\n}\n\n.border__item {\n  padding: 1rem;\n  border-radius: 3px;\n  position: relative;\n  overflow: visible;\n  float: right;\n  width: calc(100% - 80px);\n  border: 1px solid $color-hr;\n\n  &:before {\n    content: \"\";\n    display: block;\n    position: absolute;\n    top: 21px;\n    left: -6px;\n    width: 10px;\n    height: 10px;\n    background: #fff;\n    border-left: 1px solid $color-hr;\n    border-top: 1px solid $color-hr;\n    -moz-transform: rotate(-45deg);\n    -webkit-transform: rotate(-45deg);\n  }\n}"
  },
  {
    "path": "resources/assets/sass/_landing.scss",
    "content": ".landing {\n  margin-top: 50px;\n\n  hr {\n    margin: 4rem;\n  }\n\n  #laracroft {\n    background-color: $color-background;\n    background: url(\"/images/459033.jpg\") 50% 0 no-repeat fixed;\n    background-position: center 50px;\n    background-size: cover;\n    position: relative;\n    transition: all 0.5s ease;\n\n    .container-fluid {\n      color: $color-text2;\n      padding: calc(100% / 4 - 125px) 0;\n\n      .row {\n        background: rgba(0,0,0,0.5);\n        text-align: center;\n        padding-bottom: 20px;\n      }\n    }\n\n    margin-bottom: 5rem;\n\n    span.selection {\n      background: $color-selection;\n      color: $color-text1;\n      text-shadow: none;\n    }\n\n    .credit {\n      position: absolute;\n      right: 2rem;\n      bottom: 1rem;\n      color: $color-text2;\n      font-weight: bold;\n      font-size: 0.8rem;\n      a {\n        color: $color-text2;\n        text-decoration: underline;\n      }\n    }\n  }\n\n  #story,\n  #feature {\n    h1 {\n      margin-bottom: 2rem;\n    }\n  }\n\n  #story blockquote,\n  #feature blockquote {\n    margin: 2rem auto;\n  }\n\n  #feature pre {\n    width: 95%;\n    margin: 2rem auto;\n  }\n\n  #courses {\n    img {\n      width: 8rem;\n      max-width: 50%;\n      display: block;\n      margin: 2rem auto;\n    }\n\n    h1,h2,h3,h4,p {\n      margin: 1rem auto;\n    }\n\n    .btn {\n      display: inline-block;\n      margin: 1rem auto;\n    }\n  }\n\n  #mailing-list {\n    form {\n      display: block;\n      margin-left: auto;\n      margin-right: auto;\n    }\n  }\n}"
  },
  {
    "path": "resources/assets/sass/_lessons.scss",
    "content": "/* lessons */\n.container__lessons {\n  margin-top: 1rem;\n\n  article {\n    background-color: #fff;\n    padding: 1rem;\n  }\n\n  .media {\n    margin: $baseline 0;\n  }\n\n  aside {\n    li {\n      display: block;\n    }\n\n    li a {\n      display: block;\n      padding: 0.5rem 1rem;\n    }\n\n    li.active {\n      background-color: $color-hr;\n\n      a, a:hover, a:active, a:focus {\n        color: $color-text1;\n      }\n    }\n  }\n\n  aside,\n  .article__lessons article {\n    ul {\n      list-style: none;\n      padding-left: 1rem;\n    }\n  }\n\n  dl {\n    width: auto;\n    margin: 1rem auto;\n    font-weight: 300;\n  }\n\n  dt,\n  dd {\n    padding: 0.5rem;\n  }\n}\n\n.tags__lessons {\n  display: inline-block;\n  padding: 0;\n\n  li {\n    cursor: pointer;\n\n    a {\n      color: $color-text1;\n    }\n\n    a:hover, a:active, a:focus {\n      color: $color-text2;\n    }\n\n    &:hover, &:focus, &.active {\n      background-color: $color-link;\n      color: $color-text2;\n      transition: all 0.3s ease;\n    }\n  }\n\n  .label {\n    display: inline-block;\n    margin-left: 0 !important;\n    margin-right: 5px;\n    margin-bottom: 5px;\n    padding: 5px 7px;\n    font-weight: 100;\n    border-radius: 1px;\n    background-color: $color-hr;\n    color: $color-text1;\n  }\n}\n\n.sidebar__lessons aside {\n  &>ul>li>ul>li:first-child {\n    margin-top: 0.5rem;\n  }\n\n  &>ul>li {\n    padding: 0 0 1rem 0;\n    margin-bottom: $baseline;\n    border-bottom: 1px solid $color-hr;\n  }\n\n  &>ul>li:last-child {\n    border-bottom: none;\n  }\n}\n\n/* markdown styling */\n.article__lessons article:first-child {\n  line-height: 1.6rem;\n\n  li {\n    padding: 0.5rem 0;\n  }\n\n  ul li {\n    &:before {\n      content: \"# \";\n      color: $color-link;\n      padding-right: 5px;\n      opacity: 0.4;\n    }\n  }\n\n  pre {\n    margin-bottom: $baseline;\n  }\n\n  h1 {\n    margin-bottom: .8rem;\n    margin-top: .5rem;\n  }\n\n  h2 {\n    margin-top: 1rem;\n    margin-bottom: $baseline;\n    padding-top: $margin-base;\n    border-top: 1px solid $color-hr;\n  }\n\n  h4 {\n    font-size: 1.2rem;\n  }\n\n  h2, h3, h4, h5, h6 {\n    &:before {\n      color: $color-link;\n      content: \"# \";\n      padding-right: 5px;\n      opacity: .4;\n    }\n    a {\n      transition: 250ms linear all;\n      &:active,\n      &:focus,\n      &:hover {\n        outline: 0;\n      }\n    }\n  }\n\n  p {\n    margin-bottom: $baseline;\n  }\n\n  blockquote {\n    background-color: $color-hr;\n    font-size: 1rem;\n    border-radius: 2px;\n    box-sizing: border-box;\n    margin-bottom: $baseline;\n    max-width: 100%;\n    padding: 1rem;\n    opacity: 0.7;\n\n    p {\n      margin-bottom: 0;\n    }\n  }\n\n  p>img {\n    display: inline-block;\n    height: auto;\n    max-width: 100%;\n    padding: 4px;\n    margin: 0 auto;\n    line-height: 1rem;\n    background-color: #fff;\n    transition: all .2s ease-in-out\n  }\n\n  table {\n    width: 100%;\n    max-width: 100%;\n    overflow-y: hidden;\n    overflow-x: auto;\n    border-radius: 2px;\n    background-color: transparent;\n    margin: $baseline auto;\n\n    & > thead > tr > th,\n    & > tbody > tr > th,\n    & > tfoot > tr > th,\n    & > thead > tr > td,\n    & > tbody > tr > td,\n    & > tfoot > tr > td {\n      padding: 0.5rem;\n      border-top: 1px solid #eee;\n    }\n\n    & > tbody > tr:nth-child(odd) > td,\n    & > tbody > tr:nth-child(odd) > th {\n      background-color: #efefef;\n    }\n  }\n\n  ul.pager li {\n    &:before {\n      content: \"\" !important;\n      color: $color-link;\n      padding-right: 5px;\n      opacity: 0;\n    }\n  }\n}\n\ndiv.nav__lessons {\n  display: none;\n}\n"
  },
  {
    "path": "resources/assets/sass/_mediaquery.scss",
    "content": "/* media queries */\n@media screen and (max-width: $screen-sm-max) {\n  /* MD 991px */\n  .landing {\n    h1 {\n      font-size: ceil(($font-size-base * 2));\n    }\n    h2 {\n      font-size: ceil(($font-size-base * 1.6));\n    }\n    p.lead {\n      font-size: $font-size-base;\n    }\n\n    hr {\n      margin: 2rem auto;\n    }\n  }\n\n  .sidebar__lessons,\n  .sidebar__forum {\n    display: none;\n    overflow: hidden;\n    margin-bottom: $baseline;\n\n    li a {\n      display: block;\n    }\n\n    li a:hover {\n      background-color: $brand-info;\n      color: $color-text2;\n    }\n  }\n\n  div.sort__forum {\n    display: none;\n  }\n\n  div.nav__forum,\n  div.nav__lessons {\n    position: fixed;\n    bottom: 1px;\n    left: 1px;\n    z-index: 9999;\n    display: block;\n    transition: all 0.5s ease-in-out;\n  }\n\n  .border__item {\n    width: 100%;\n    &:before {\n      content: none;\n    }\n  }\n}\n\n@media screen and (max-width: $screen-xs-max) {\n  .landing {\n    h1 {\n      font-size: ceil(($font-size-base * 1.8));\n    }\n    h2 {\n      font-size: ceil(($font-size-base * 1.4));\n    }\n    p.lead {\n      font-size: ceil(($font-size-base * 0.8));\n    }\n\n    #laracroft {\n      //background-image: none;\n      background-size: contain;\n\n      .container-fluid {\n        padding: 4rem 0;\n      }\n    }\n\n    button {\n      white-space: normal !important;\n      word-wrap: break-word !important;\n      padding: 6px 12px !important;\n      line-height: 1.42 !important;\n      border-radius: 4px !important;\n    }\n\n    #feature pre {\n      width: 100%;\n    }\n  }\n}\n\n@media screen and (max-width: 540px) {\n  .landing {\n    #laracroft {\n      background-size: 540px 342px;\n    }\n  }\n}\n\n@media screen and (max-width: $screen-xs) {\n  /* Phone Device */\n  .landing {\n    h1 {\n      font-size: ceil(($font-size-base * 1.6));\n    }\n    h2 {\n      font-size: ceil(($font-size-base * 1.2));\n    }\n    p.lead {\n      font-size: ceil(($font-size-base * 0.7));\n    }\n\n    #laracroft {\n      background-size: 480px 300px;\n    }\n  }\n\n  article {\n    img {\n      display: block;\n      width: 100%;\n      max-width: 100%;\n      height: auto;\n    }\n  }\n}"
  },
  {
    "path": "resources/assets/sass/app.scss",
    "content": "@import \"../vendor/bootstrap-sass/assets/stylesheets/bootstrap\";\n@import \"../vendor/font-awesome/scss/font-awesome\";\n@import \"../vendor/select2/src/scss/core\";\n@import \"../vendor/select2-bootstrap-theme/src/select2-bootstrap\";\n\n@import \"commons\";\n@import \"landing\";\n@import \"auth\";\n@import \"lessons\";\n@import \"forum\";\n@import \"mediaquery\";\n"
  },
  {
    "path": "resources/lang/en/auth.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used during authentication for various\n    | messages that we need to display to the user. You are free to modify\n    | these language lines according to your application's requirements.\n    |\n    */\n\n    'failed'                      => 'These credentials do not match our records.',\n    'throttle'                    => 'Too many login attempts. Please try again in :seconds seconds.',\n\n    /* Project specific dictionary */\n\n    'title_login'                 => 'Login',\n    'title_login_help'            => 'We love Github ^^/.',\n    'login_with_github'           => 'Login with Github',\n    'email_address'               => 'Email address',\n    'password'                    => 'Password',\n    'remember_me'                 => 'Remember me',\n    'button_login'                => 'Get me in~',\n    'recommend_signup'            => 'Not a member?',\n    'btutton_signup'              => 'Sign up',\n    'button_remind_password'      => 'Remind my password',\n    'button_remind_password_help' => '(For non-Github user only...)',\n\n    'title_password_remind'       => 'Password Remind',\n    'title_password_remind_help'  => \"Provide the same email address that you've registered and check your email inbox to reset the password.\",\n    'button_send_reminder'        => 'Send reminder',\n\n    'title_signup'                => 'Sign Up',\n    'title_signup_help'           => 'We love Github ^^/. Please <a href=\":url\">login via Github</a> if you have an account. Otherwise proceed the following~',\n    'name'                        => 'Full name',\n    'password_confirmation'       => 'Confirm password',\n    'button_signup'               => 'Sign me up~',\n\n    'title_reset_password'        => 'Reset Password',\n    'title_reset_password_help'   => 'Provide your email address and NEW PASSWORD.',\n    'new_password'                => 'New password',\n    'button_reset_password'       => 'Reset my password~',\n\n    'title_logout'                => 'Log Out',\n\n    'welcome'                     => 'Welcome back :name',\n    'goodbye'                     => 'See you soon~',\n\n    'email_password_reset_title'  => 'Your Password Reset Link',\n\n    'social_only'                 => 'You are a social login user.',\n    'no_password'                 => 'Password is not required for social login.'\n\n];\n"
  },
  {
    "path": "resources/lang/en/common.php",
    "content": "<?php\n\nreturn [\n\n    'reset'            => 'Reset',\n    'post'             => 'Post',\n    'edit'             => 'Edit',\n    'delete'           => 'Delete',\n    'reply'            => 'Reply',\n    'sort_by'          => 'Sort by',\n    'notice'           => 'Notice',\n    'cheat_sheet'      => 'Markdown Cheatsheet',\n    'markdown_preview' => 'Converted preview will be shown here.',\n    'search'           => 'Search',\n    'confirm_delete'   => 'Are you sure to delete this article?',\n    'msg_reload'       => 'The page will reload.',\n    'created'          => 'Saved !',\n    'updated'          => 'Updated !',\n    'deleted'          => 'Deleted !',\n    'msg_whoops'       => 'Whoops! What is happening here?',\n\n];"
  },
  {
    "path": "resources/lang/en/errors.php",
    "content": "<?php\n\nreturn [\n\n    'not_found'             => 'Page Not Found',\n    'not_found_description' => 'Sorry, the page or resource you are trying to view does not exist.',\n    'forbidden'             => 'Forbidden',\n    'forbidden_description' => 'Sorry, you are not allowed to access this resource.',\n    'server_error'          => 'Server Error',\n    'msg_form_error'        => 'Some errors found in the form. Please review and correct them and retry !',\n\n];"
  },
  {
    "path": "resources/lang/en/forum.php",
    "content": "<?php\n\nreturn [\n\n    'title_forum'        => 'Forum',\n    'create'             => 'New Forum',\n    'button_toc'         => 'Forum Tags',\n    'solved'             => 'Solved',\n    'title'              => 'Title',\n    'content'            => 'Content',\n    'tags'               => 'Tags',\n    'notification'       => 'Email me when somebody leaves a comment',\n    'tags_help'          => 'Choose tags (max to 3)',\n    'comment_add'        => 'Your comment attached !',\n    'comment_edit'       => 'Your comment updated !',\n    'title_comments'     => 'Comments',\n    'pin'                => 'Pin this article ?',\n    'msg_dropfile'       => 'Drop files to upload !',\n    'msg_dropfile_sub'   => '(or Click to choose...)',\n    'msg_pick_best'      => \"Are you sure to select this comment as the 'Best'?\",\n    'msg_pick_help'      => 'Pick as the Best Answer',\n    'deleted_comment'    => 'This comment has been deleted by the author!!!',\n    'msg_ask_login'      => 'to leave a comment.',\n    'msg_delete_comment' => 'Are you sure to delete this comment?',\n    'age'                => 'Age',\n    'view_count'         => 'View',\n\n];"
  },
  {
    "path": "resources/lang/en/lessons.php",
    "content": "<?php\n\nreturn [\n\n    'title_lessons' => 'Lessons',\n    'button_toc'    => 'Lessons Index',\n\n];"
  },
  {
    "path": "resources/lang/en/pagination.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Pagination Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used by the paginator library to build\n    | the simple pagination links. You are free to change them to anything\n    | you want to customize your views to better match your application.\n    |\n    */\n\n    'previous' => '&laquo; Previous',\n    'next'     => 'Next &raquo;',\n\n];\n"
  },
  {
    "path": "resources/lang/en/passwords.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Password Reminder Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are the default lines which match reasons\n    | that are given by the password broker for a password update attempt\n    | has failed, such as for an invalid token or invalid new password.\n    |\n    */\n\n    'password' => 'Passwords must be at least six characters and match the confirmation.',\n    'reset'    => 'Your password has been reset!',\n    'sent'     => 'We have e-mailed your password reset link!',\n    'token'    => 'This password reset token is invalid.',\n    'user'     => \"We can't find a user with that e-mail address.\",\n\n];\n"
  },
  {
    "path": "resources/lang/en/validation.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Validation Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines contain the default error messages used by\n    | the validator class. Some of these rules have multiple versions such\n    | as the size rules. Feel free to tweak each of these messages here.\n    |\n    */\n\n    'accepted'             => 'The :attribute must be accepted.',\n    'active_url'           => 'The :attribute is not a valid URL.',\n    'after'                => 'The :attribute must be a date after :date.',\n    'alpha'                => 'The :attribute may only contain letters.',\n    'alpha_dash'           => 'The :attribute may only contain letters, numbers, and dashes.',\n    'alpha_num'            => 'The :attribute may only contain letters and numbers.',\n    'array'                => 'The :attribute must be an array.',\n    'before'               => 'The :attribute must be a date before :date.',\n    'between'              => [\n        'numeric' => 'The :attribute must be between :min and :max.',\n        'file'    => 'The :attribute must be between :min and :max kilobytes.',\n        'string'  => 'The :attribute must be between :min and :max characters.',\n        'array'   => 'The :attribute must have between :min and :max items.',\n    ],\n    'boolean'              => 'The :attribute field must be true or false.',\n    'confirmed'            => 'The :attribute confirmation does not match.',\n    'date'                 => 'The :attribute is not a valid date.',\n    'date_format'          => 'The :attribute does not match the format :format.',\n    'different'            => 'The :attribute and :other must be different.',\n    'digits'               => 'The :attribute must be :digits digits.',\n    'digits_between'       => 'The :attribute must be between :min and :max digits.',\n    'email'                => 'The :attribute must be a valid email address.',\n    'exists'               => 'The selected :attribute is invalid.',\n    'filled'               => 'The :attribute field is required.',\n    'image'                => 'The :attribute must be an image.',\n    'in'                   => 'The selected :attribute is invalid.',\n    'integer'              => 'The :attribute must be an integer.',\n    'ip'                   => 'The :attribute must be a valid IP address.',\n    'json'                 => 'The :attribute must be a valid JSON string.',\n    'max'                  => [\n        'numeric' => 'The :attribute may not be greater than :max.',\n        'file'    => 'The :attribute may not be greater than :max kilobytes.',\n        'string'  => 'The :attribute may not be greater than :max characters.',\n        'array'   => 'The :attribute may not have more than :max items.',\n    ],\n    'mimes'                => 'The :attribute must be a file of type: :values.',\n    'min'                  => [\n        'numeric' => 'The :attribute must be at least :min.',\n        'file'    => 'The :attribute must be at least :min kilobytes.',\n        'string'  => 'The :attribute must be at least :min characters.',\n        'array'   => 'The :attribute must have at least :min items.',\n    ],\n    'not_in'               => 'The selected :attribute is invalid.',\n    'numeric'              => 'The :attribute must be a number.',\n    'regex'                => 'The :attribute format is invalid.',\n    'required'             => 'The :attribute field is required.',\n    'required_if'          => 'The :attribute field is required when :other is :value.',\n    'required_unless'      => 'The :attribute field is required unless :other is in :values.',\n    'required_with'        => 'The :attribute field is required when :values is present.',\n    'required_with_all'    => 'The :attribute field is required when :values is present.',\n    'required_without'     => 'The :attribute field is required when :values is not present.',\n    'required_without_all' => 'The :attribute field is required when none of :values are present.',\n    'same'                 => 'The :attribute and :other must match.',\n    'size'                 => [\n        'numeric' => 'The :attribute must be :size.',\n        'file'    => 'The :attribute must be :size kilobytes.',\n        'string'  => 'The :attribute must be :size characters.',\n        'array'   => 'The :attribute must contain :size items.',\n    ],\n    'string'               => 'The :attribute must be a string.',\n    'timezone'             => 'The :attribute must be a valid zone.',\n    'unique'               => 'The :attribute has already been taken.',\n    'url'                  => 'The :attribute format is invalid.',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Custom Validation Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify custom validation messages for attributes using the\n    | convention \"attribute.rule\" to name the lines. This makes it quick to\n    | specify a specific custom language line for a given attribute rule.\n    |\n    */\n\n    'custom' => [\n        'attribute-name' => [\n            'rule-name' => 'custom-message',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Custom Validation Attributes\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used to swap attribute place-holders\n    | with something more reader friendly such as E-Mail Address instead\n    | of \"email\". This simply helps us make messages a little cleaner.\n    |\n    */\n\n    'attributes' => [],\n\n];\n"
  },
  {
    "path": "resources/lang/ko/auth.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Authentication Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used during authentication for various\n    | messages that we need to display to the user. You are free to modify\n    | these language lines according to your application's requirements.\n    |\n    */\n\n    'failed'                      => '로그인 정보가 정확하지 않습니다.',\n    'throttle'                    => '로그인 한도를 초과했습니다. :seconds 초 후에 다시 시도해주세요.',\n\n    /* Project specific dictionary */\n\n    'title_login'                 => '로그인',\n    'title_login_help'            => '개발자라면 Github ^^/.',\n    'login_with_github'           => 'Github 계정으로 로그인하기',\n    'email_address'               => '이메일 주소',\n    'password'                    => '비밀번호',\n    'remember_me'                 => '로그인 기억하기',\n    'button_login'                => '드러간다~',\n    'recommend_signup'            => '회원이 아니라면?',\n    'btutton_signup'              => '가입할껴~',\n    'button_remind_password'      => '비밀번호가 기억나지 않으면?',\n    'button_remind_password_help' => '(Github 로그인만 사용하시는 분은 비밀번호가 없어요.)',\n\n    'title_password_remind'       => '비밀번호 초기화 신청',\n    'title_password_remind_help'  => \"등록한 이메일을 입력하여 신청하고, 메일박스를 확인해 보세요~\",\n    'button_send_reminder'        => '비밀번호 초기화 신청하기',\n\n    'title_signup'                => '가입하기',\n    'title_signup_help'           => '개발자라면 Github ^^/. <a href=\":url\">Github로 로그인</a>해 주세요. Github 로그인이 싫다면 아래 양식을 채우고 가입해 주세요.',\n    'name'                        => '이름',\n    'password_confirmation'       => '비밀번호 확인',\n    'button_signup'               => '가입시켜줘~',\n\n    'title_reset_password'        => '비밀번호 초기화',\n    'title_reset_password_help'   => '가입했던 이메일을 입력하고 새로 사용할 비밀번호를 입력하세요.',\n    'new_password'                => '새로운 비밀번호',\n    'button_reset_password'       => '초기화 =3=3=3',\n\n    'title_logout'                => '로그아웃',\n\n    'welcome'                     => ':name님 반갑습니다.',\n    'goodbye'                     => '또 오세요~',\n\n    'email_password_reset_title'  => '비밀번호 재설정 이메일',\n\n    'social_only'                 => '님은 소셜 로그인 사용자입니다.',\n    'no_password'                 => '소셜 로그인은 비밀번호가 필요없습니다.'\n\n\n];\n"
  },
  {
    "path": "resources/lang/ko/common.php",
    "content": "<?php\n\nreturn [\n\n    'reset'            => '초기화',\n    'post'             => '저장하기',\n    'edit'             => '수정하기',\n    'delete'           => '삭제하기',\n    'reply'            => '답글하기',\n    'sort_by'          => '정렬하기',\n    'notice'           => '공지사항',\n    'cheat_sheet'      => '마크다운 도우미',\n    'markdown_preview' => '여기에 변환된 미리보기가 표시됩니다.',\n    'search'           => '검색',\n    'confirm_delete'   => '삭제할까요?',\n    'msg_reload'       => '페이지를 다시 읽어 옵니다.',\n    'created'          => '새 글이 저장되었습니다.',\n    'updated'          => '수정 되었습니다.',\n    'deleted'          => '삭제 되었습니다.',\n    'msg_whoops'       => '알수 없는 에러가 발생했습니다.',\n\n];"
  },
  {
    "path": "resources/lang/ko/errors.php",
    "content": "<?php\n\nreturn [\n\n    'not_found'             => '찾을 수 없습니다.',\n    'not_found_description' => '죄송합니다! 요청하신 페이지가 없습니다.',\n    'forbidden'             => '접근 제한',\n    'forbidden_description' => '죄송합니다! 접근이 불가능한 페이지입니다.',\n    'server_error'          => '이런 :(',\n    'msg_form_error'        => '작성하신 내용에 오류를 확인하시고 다시 시도해 주세요.',\n\n];"
  },
  {
    "path": "resources/lang/ko/forum.php",
    "content": "<?php\n\nreturn [\n\n    'title_forum'        => '포럼',\n    'create'             => '새 포럼 쓰기',\n    'button_toc'         => '포럼 메뉴',\n    'solved'             => '답변됨',\n    'title'              => '제목',\n    'content'            => '내용',\n    'tags'               => '태그',\n    'notification'       => '댓글이 달리면 이메일을 받겠습니다.',\n    'tags_help'          => '태그를 선택하세요 (최대 3개)',\n    'comment_add'        => '댓글이 작성되었습니다.',\n    'comment_edit'       => '댓글이 수정되었습니다.',\n    'title_comments'     => '댓글',\n    'pin'                => '게시물 상단 고정 (공지사항)',\n    'msg_dropfile'       => '업로드할 파일을 끌어다 놓으세요.',\n    'msg_dropfile_sub'   => '(또는 여기를 클릭하세요.)',\n    'msg_pick_best'      => '베스트 댓글로 선택할까요?',\n    'msg_pick_help'      => '베스트 댓글로 선택하기',\n    'deleted_comment'    => '삭제된 댓글입니다!!!',\n    'msg_ask_login'      => '하면 댓글을 쓸 수 있습니다.',\n    'msg_delete_comment' => '댓글을 삭제할까요?',\n    'age'                => '작성일',\n    'view_count'         => '조회수',\n\n];"
  },
  {
    "path": "resources/lang/ko/lessons.php",
    "content": "<?php\n\nreturn [\n\n    'title_lessons' => '강좌',\n    'button_toc'    => '강좌 목록',\n\n];"
  },
  {
    "path": "resources/lang/ko/pagination.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Pagination Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are used by the paginator library to build\n    | the simple pagination links. You are free to change them to anything\n    | you want to customize your views to better match your application.\n    |\n    */\n\n    'previous' => '&laquo; 이전',\n    'next'     => '다음 &raquo;',\n\n];\n"
  },
  {
    "path": "resources/lang/ko/passwords.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Password Reminder Language Lines\n    |--------------------------------------------------------------------------\n    |\n    | The following language lines are the default lines which match reasons\n    | that are given by the password broker for a password update attempt\n    | has failed, such as for an invalid token or invalid new password.\n    |\n    */\n\n    'password' => '비밀번호를 확인해 주세요. (6문자 이상)',\n    'reset'    => '비밀번호가 재설정되었습니다!',\n    'sent'     => '비밀번호 재설정을 위한 링크를 이메일로 전송했습니다!',\n    'token'    => '비밀번호 재설정을 위한 토큰이 정확하지 않습니다.',\n    'user'     => \"누구세요?\",\n\n];\n"
  },
  {
    "path": "resources/lang/ko/validation.php",
    "content": "<?php\n\nreturn [\n\n/*\n|--------------------------------------------------------------------------\n| Validation Language Lines\n|--------------------------------------------------------------------------\n|\n| The following language lines contain the default error messages used by\n| the validator class. Some of these rules have multiple versions such\n| as the size rules. Feel free to tweak each of these messages here.\n|\n*/\n\n\"accepted\"             => \":attribute 에 동의해 주세요\",\n\"active_url\"           => \":attribute 은(는) 유효한 URL이 아닙니다.\",\n\"after\"                => \":attribute 은(는) :date 이후만 허용합니다.\",\n\"alpha\"                => \":attribute 은(는) 영문자만 허용합니다.\",\n\"alpha_dash\"           => \":attribute 은(는) 영문자, 숫자, 대시(-)만 허용합니다.\",\n\"alpha_num\"            => \":attribute 은(는) 영문자와 숫자만 허용합니다.\",\n\"array\"                => \":attribute 은(는) 배열 형태만 허용 합니다.\",\n\"before\"               => \":attribute 은(는) :date 이전만 허용합니다.\",\n\"between\"              => array(\n\"numeric\" => \":attribute 은(는) :min 보다 크고 :max 보다 작아야 합니다.\",\n\"file\"    => \":attribute 은(는) :min kilobytes보다 크고 :max 보다 작아야 합니다.\",\n\"string\"  => \":attribute 은(는) :min 문자 보다 길고 :max 문자를 넘지 않아야 합니다. \",\n\"array\"   => \":attribute 은(는) 최소 :min 개, 최대 :max 개의 배열 요소만 허용합니다.\",\n),\n\"boolean\"              => \":attribute 은(는) true/false 만 허용됩니다.\",\n\"confirmed\"            => \":attribute 확인란이 일치하지 않습니다.\",\n\"date\"                 => \":attribute 은(는) 유효한 날짜 형식이 아닙니다.\",\n\"date_format\"          => \":attribute 은(는) 유효한 날짜 형식(:format)이 아닙니다.\",\n\"different\"            => \":attribute 은(는) :other 와 같을 수 없습니다.\",\n\"digits\"               => \":attribute 은(는) :digits 자리 숫자여야 합니다.\",\n\"digits_between\"       => \":attribute 은(는) 최소 :min 최대 :max 자리 숫자여야 합니다.\",\n\"email\"                => \":attribute 은(는) 유효한 이메일 주소가 아닙니다.\",\n\"exists\"               => \":attribute 은(는) 유효하지 않습니다.\",\n\"image\"                => \":attribute 은(는) 이미지 형식의 파일만 허용합니다.\",\n\"in\"                   => \":attribute 은(는) 유효하지 않습니다.\",\n\"integer\"              => \":attribute 은(는) 정수만 허용됩니다.\",\n\"ip\"                   => \":attribute 은(는) 유효한 IP 주소가 아닙니다.\",\n\"max\"                  => array(\n\"numeric\" => \":attribute 은(는) 최대 :max 까지만 허용됩니다.\",\n\"file\"    => \":attribute 은(는) 최대 :max 킬로바이트 까지만 허용됩니다.\",\n\"string\"  => \":attribute 은(는) 최대 :max 글자까지만 허용됩니다.\",\n\"array\"   => \":attribute 은(는) 최대 :max 개의 배열요소까지만 허용됩니다. \",\n),\n\"mimes\"                => \":attribute 은(는) type: :values 형식만 허용됩니다.\",\n\"min\"                  => array(\n\"numeric\" => \":attribute 은(는) 최소 :min 이상이어야 합니다.\",\n\"file\"    => \":attribute 은(는) 최소 :min kilobytes 이상이어야 합니다.\",\n\"string\"  => \":attribute 은(는) 최소 :min 글자 이상이어야 합니다.\",\n\"array\"   => \":attribute 은(는) 최소 :min 배열요소 이상이어야 합니다.\",\n),\n\"not_in\"               => \":attribute 은(는) 유효하지 않습니다.\",\n\"numeric\"              => \":attribute 은(는) 숫자 형태만 허용합니다.\",\n\"regex\"                => \":attribute 은(는) 올바른 형식이 아닙니다.\",\n\"required\"             => \":attribute 은(는) 필수 입력 항목 입니다.\",\n\"required_if\"          => \":attribute 은(는) :other 값이 :value 일때 필수 입력 항목 입니다.\",\n\"required_with\"        => \":attribute 은(는) :values 값이 있을 때 필수 입력 항목 입니다.\",\n\"required_with_all\"    => \":attribute 은(는) :values 값이 있을 때 필수 입력 항목 입니다.\",\n\"required_without\"     => \":attribute 은(는) :values 값이 없을 때 필수 입력 항목 입니다.\",\n\"required_without_all\" => \":attribute 은(는) :values 값이 없을 때 필수 입력 항목 입니다.\",\n\"same\"                 => \":attribute 은(는) :other 와 입력값이 일치해야 합니다.\",\n\"size\"                 => array(\n\"numeric\" => \":attribute 은(는) :size 여야 합니다.\",\n\"file\"    => \":attribute 은(는) :size kilobytes 여야 합니다.\",\n\"string\"  => \":attribute 은(는) :size 문자여야 합니다.\",\n\"array\"   => \":attribute 은(는) :size 배열 요소를 담고 있어야 합니다.\",\n),\n\"unique\"               => \":attribute 은(는) 이미 사용 중입니다.\",\n\"url\"                  => \":attribute 은(는) 유효하지 않은 Url 입니다.\",\n\n/*\n|--------------------------------------------------------------------------\n| Custom Validation Language Lines\n|--------------------------------------------------------------------------\n|\n| Here you may specify custom validation messages for attributes using the\n| convention \"attribute.rule\" to name the lines. This makes it quick to\n| specify a specific custom language line for a given attribute rule.\n|\n*/\n\n'custom'               => array(\n'attribute-name' => array(\n'rule-name' => 'custom-message',\n),\n),\n\n/*\n|--------------------------------------------------------------------------\n| Custom Validation Attributes\n|--------------------------------------------------------------------------\n|\n| The following language lines are used to swap attribute place-holders\n| with something more reader friendly such as E-Mail Address instead\n| of \"email\". This simply helps us make messages a little cleaner.\n|\n*/\n\n'attributes'           => array(),\n\n];\n"
  },
  {
    "path": "resources/views/articles/create.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    <h4>\n      {!! icon('forum', null, 'margin-right:1rem') !!}\n      <a href=\"{{ route('articles.index') }}\">\n        {{ trans('forum.title_forum') }}\n      </a>\n      <small> / </small>\n      {{ trans('forum.create') }}\n    </h4>\n  </div>\n\n  <div class=\"container__forum\">\n    <form action=\"{{ route('articles.store') }}\" method=\"POST\" role=\"form\" class=\"form__forum\">\n      {!! csrf_field() !!}\n\n      @include('articles.partial.form')\n\n      <div class=\"form-group\">\n        <p class=\"text-center\">\n          <a href=\"{{ route('articles.create') }}\" class=\"btn btn-default\">\n            {!! icon('reset') !!} {{ trans('common.reset') }}\n          </a>\n          <button type=\"submit\" class=\"btn btn-primary\">\n            {!! icon('plane') !!} {{ trans('common.post') }}\n          </button>\n        </p>\n      </div>\n    </form>\n  </div>\n@stop\n\n\n\n"
  },
  {
    "path": "resources/views/articles/edit.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    <h4>\n      {!! icon('forum', null, 'margin-right:1rem') !!}\n      <a href=\"{{ route('articles.index') }}\">\n        {{ trans('forum.title_forum') }}\n      </a>\n      <small> / </small>\n      <a href=\"{{ route('articles.edit', $article->id) }}\">{{ $article->title }}</a>\n      <small> / </small>\n      Edit\n    </h4>\n  </div>\n\n  <div class=\"container__forum\">\n    <form action=\"{{ route('articles.update', $article->id) }}\" method=\"POST\" role=\"form\" class=\"form__forum\">\n      {!! csrf_field() !!}\n      {!! method_field('PUT') !!}\n\n      @include('articles.partial.form')\n\n      <div class=\"form-group\">\n        <p class=\"text-center\">\n          <a href=\"{{ route('articles.edit', $article->id) }}\" class=\"btn btn-default\">\n            {!! icon('reset') !!} {{ trans('common.reset') }}\n          </a>\n          <button type=\"submit\" class=\"btn btn-primary\">\n            {!! icon('plane') !!} {{ trans('common.edit') }}\n          </button>\n        </p>\n      </div>\n    </form>\n  </div>\n@stop\n"
  },
  {
    "path": "resources/views/articles/index.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header clearfix\">\n    <a class=\"btn btn-primary pull-right\" href=\"{{ route('articles.create') }}\">\n      {!! icon('new') !!} {{ trans('forum.create') }}\n    </a>\n\n    <div class=\"btn-group pull-right sort__forum hidden-xs\">\n      <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n        {!! icon('sort') !!} {{ trans('common.sort_by') }} <span class=\"caret\"></span>\n      </button>\n      <ul class=\"dropdown-menu\" role=\"menu\">\n        @foreach(['created_at' => trans('forum.age'), 'view_count' => trans('forum.view_count')] as $column => $name)\n          <li class=\"{{ Request::input('s') == $column ? 'active' : '' }}\">\n            {!! link_for_sort($column, $name) !!}\n          </li>\n        @endforeach\n      </ul>\n    </div>\n\n    <h4>\n      {!! icon('forum', null, 'margin-right:1rem') !!}\n      <a href=\"{{ route('articles.index') }}\">\n        {{ trans('forum.title_forum') }}\n      </a>\n    </h4>\n  </div>\n\n  <div class=\"row container__forum\">\n    <div class=\"col-md-3 sidebar__forum\">\n      <aside>\n        @include('articles.partial.search')\n        @include('tags.partial.index')\n      </aside>\n    </div>\n\n    <div class=\"col-md-9\">\n      <article>\n        @forelse($articles as $article)\n          @include('articles.partial.article', ['article' => $article])\n        @empty\n          <p class=\"text-center text-danger\">{{ trans('errors.not_found_description') }}</p>\n        @endforelse\n\n        <div class=\"text-center\">\n          {!! $articles->appends(Request::except('page'))->render() !!}\n        </div>\n      </article>\n    </div>\n\n  </div>\n\n  <div class=\"nav__forum\">\n    <a type=\"button\" role=\"button\" class=\"btn btn-sm btn-danger\">{{ trans('forum.button_toc') }}</a>\n  </div>\n@stop\n"
  },
  {
    "path": "resources/views/articles/partial/article.blade.php",
    "content": "<div class=\"media\">\n  @include('users.partial.avatar', ['user' => $article->author, 'size' => 64])\n\n  <div class=\"media-body\">\n    <h4 class=\"media-heading\">\n      @if ($article->isNotice())\n        <span style=\"margin-right: 1rem;\" title=\"{{ trans('common.notice') }}\">\n          {!! icon('pin', false) !!}\n        </span>\n      @endif\n\n      <a href=\"{{ route('articles.show', $article->id) }}\">\n        {{ $article->title }}\n\n        @if ($commentCount = $article->comments->count())\n          <span class=\"badge pull-right\">\n            {!! icon('comments') !!} {{ $commentCount }}\n          </span>\n        @endif\n\n        @if ($article->solution_id)\n          <span class=\"badge pull-right\" title=\"{{ trans('forum.solved') }}\">\n            {!! icon('check', false) !!}\n          </span>\n        @endif\n\n        @if ($attachmentsCount = $article->attachments->count())\n          <span class=\"badge pull-right\">\n            {!! icon('clip') !!} {{ $attachmentsCount }}\n          </span>\n        @endif\n      </a>\n    </h4>\n\n    <p class=\"text-muted\">\n      <a href=\"{{ gravatar_profile_url($article->author->email) }}\" style=\"margin-right: 1rem;\">\n        {!! icon('user') !!} {{ $article->author->name }}\n      </a>\n\n      <span style=\"margin-right: 1rem;\">\n        {!! icon('clock') !!} {{ $article->created_at->diffForHumans() }}\n      </span>\n\n      <span style=\"margin-right: 1rem;\">\n        {!! icon('view_count') !!} {{ number_format($article->view_count) }}\n      </span>\n    </p>\n\n    @include('tags.partial.list', ['tags' => $article->tags])\n  </div>\n</div>"
  },
  {
    "path": "resources/views/articles/partial/form.blade.php",
    "content": "<div class=\"form-group {{ $errors->has('title') ? 'has-error' : '' }}\">\n  <label for=\"title\">{{ trans('forum.title') }}</label>\n  <input type=\"text\" name=\"title\" id=\"title\" class=\"form-control\" value=\"{{ old('title', $article->title) }}\"/>\n  {!! $errors->first('title', '<span class=\"form-error\">:message</span>') !!}\n</div>\n\n<div class=\"form-group {{ $errors->has('tags') ? 'has-error' : '' }}\">\n  <label for=\"tags\">{{ trans('forum.tags') }}</label>\n  <select class=\"form-control select2-multiple\" name=\"tags[]\" id=\"tags\" multiple=\"multiple\">\n    @foreach($allTags as $tag)\n      <option value=\"{{ $tag->id }}\" {{ in_array($tag->id, $article->tags->lists('id')->toArray()) ? 'selected=\"selected\"' : '' }}>{{ $tag->name }}</option>\n    @endforeach\n  </select>\n  {!! $errors->first('tags', '<span class=\"form-error\">:message</span>') !!}\n</div>\n\n<div class=\"form-group {{ $errors->has('content') ? 'has-error' : '' }}\">\n  <a href=\"#\" class=\"help-block pull-right hidden-xs\" id=\"md-caller\">\n    <small>{!! icon('preview') !!} {{ trans('common.cheat_sheet') }}</small>\n  </a>\n  <label for=\"content\">{{ trans('forum.content') }}</label>\n  <textarea name=\"content\" id=\"content\" class=\"form-control forum__content\" rows=\"10\">{{ old('content', $article->content) }}</textarea>\n  {!! $errors->first('content', '<span class=\"form-error\">:message</span>') !!}\n  <div class=\"preview__forum\">{{ markdown(old('content', trans('common.markdown_preview'))) }}</div>\n</div>\n\n<div class=\"form-group\">\n  <label for=\"my-dropzone\">\n    Files\n    <small class=\"text-muted\">\n      Click to attach files <i class=\"fa fa-chevron-down\"></i>\n    </small>\n    <small class=\"text-muted\" style=\"display: none;\">\n      Click to close pane <i class=\"fa fa-chevron-up\"></i>\n    </small>\n  </label>\n  <div id=\"my-dropzone\" class=\"dropzone\"></div>\n</div>\n\n<div class=\"form-group\">\n  <div class=\"checkbox\">\n    <label>\n      <input type=\"checkbox\" name=\"notification\" {{ $article->notification ? 'checked=\"checked\"': ''}}>\n      {{ trans('forum.notification') }}\n    </label>\n  </div>\n</div>\n\n@if ($currentUser and $currentUser->isAdmin())\n  <div class=\"form-group\">\n    <div class=\"checkbox\">\n      <label>\n        <input type=\"checkbox\" name=\"pin\" {{ $article->pin ? 'checked=\"checked\"': ''}}>\n        {{ trans('forum.pin') }}\n      </label>\n    </div>\n  </div>\n@endif\n\n@include('layouts.partial.markdown')\n\n@section('script')\n  <script>\n    var form = $(\"form.form__forum\").first(),\n        dropzone  = $(\"div.dropzone\"),\n        dzControl = $(\"label[for=my-dropzone]>small\");\n\n    dzControl.on(\"click\", function(e) {\n      dropzone.fadeToggle(0);\n      dzControl.fadeToggle(0);\n    });\n\n    /* Activate select2 for a nicer tag selector UI */\n    $(\"select#tags\").select2({\n      placeholder: \"{{ trans('forum.tags_help') }}\",\n      maximumSelectionLength: 3,\n      theme: \"bootstrap\"\n    });\n\n    /* Dropzone Related */\n    Dropzone.autoDiscover = false;\n\n    /* Instantiate Dropzone for a nicer attachment upload UI */\n    var myDropzone = new Dropzone(\"div#my-dropzone\", {\n      url: \"/files\",\n      params: {\n        _token: window.csrfToken,\n        articleId: \"{{ $article->id }}\"\n      },\n      dictDefaultMessage: \"<div class=\\\"text-center text-muted\\\">\" +\n      \"<h2>{{ trans('forum.msg_dropfile') }}</h2>\" +\n      \"<p>{{ trans('forum.msg_dropfile_sub') }}</p></div>\",\n      addRemoveLinks: true\n    });\n\n    var handleImage = function(objId, imgUrl, remove) {\n      var caretPos = document.getElementById(objId).selectionStart;\n      var textAreaTxt = $(\"#\" + objId).val();\n      var txtToAdd = \"![](\" + imgUrl + \")\";\n\n      if (remove) {\n// Todo write remove logic\n//        var pattern = new RegExp(txtToAdd);\n//\n//        if (pattern.test(textAreaTxt)) {\n//          textAreaTxt.match(pattern);\n//        }\n        return;\n      }\n\n      $(\"#\" + objId).val(\n        textAreaTxt.substring(0, caretPos) +\n        txtToAdd +\n        textAreaTxt.substring(caretPos)\n      );\n    };\n\n    myDropzone.on(\"success\", function(file, data) {\n      // File upload success handler\n      // 1. make a hidden input to give hint to the server side what has been attached\n      // 2. if the attached file was image type, call handleImage();\n      file._id = data.id;\n      file._name = data.name;\n      file._url = data.url;\n\n      $(\"<input>\", {\n        type: \"hidden\",\n        name: \"attachments[]\",\n        class: \"attachments\",\n        value: data.id\n      }).appendTo(form);\n\n      if (/^image/.test(data.type)) {\n        handleImage('content', data.url);\n      }\n    });\n\n    myDropzone.on(\"removedfile\", function(file) {\n      // When user removed a file from the Dropzone UI,\n      // the image will be disappear in DOM level, but not in the service\n      // The following code send ajax request to the server to handle that situation\n      $.ajax({\n        type: \"POST\",\n        url: \"/files/\" + file._id,\n        data: {\n          _method: \"DELETE\"\n        }\n      }).success(function(file, data) {\n        handleImage('content', file._url, true);\n      })\n    });\n  </script>\n@stop\n"
  },
  {
    "path": "resources/views/articles/partial/search.blade.php",
    "content": "<form action=\"{{ route('articles.index') }}\" method=\"get\" role=\"search\" id=\"search__forum\">\n  <input type=\"text\" name=\"q\" value=\"{{ Request::input('q') }}\" class=\"form-control\" placeholder=\"{{ trans('common.search') }}\"/>\n</form>\n"
  },
  {
    "path": "resources/views/articles/show.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    <h4>\n      {!! icon('forum', null, 'margin-right:1rem') !!}\n      <a href=\"{{ route('articles.index') }}\">\n        {{ trans('forum.title_forum') }}\n      </a>\n      <small> / </small>\n      {{ $article->title }}\n    </h4>\n  </div>\n\n  <div class=\"row container__forum\">\n    <div class=\"col-md-3 sidebar__forum\">\n      <aside>\n        @include('articles.partial.search')\n        @include('tags.partial.index')\n      </aside>\n    </div>\n\n    <div class=\"col-md-9\">\n      <article id=\"article__article\" data-id=\"{{ $article->id }}\">\n        @include('articles.partial.article', ['article' => $article])\n\n        @include('attachments.partial.list', ['attachments' => $article->attachments])\n\n        <p>\n          {!! markdown($article->content) !!}\n        </p>\n\n        <div class=\"divider\">&nbsp;</div>\n\n        @if ($article->solution)\n          @include('comments.partial.best', ['comment' => $article->solution])\n        @endif\n\n        @if ($currentUser and ($currentUser->isAdmin() or $article->isAuthor()))\n        <div class=\"text-center\">\n            <button type=\"button\" class=\"btn btn-danger btn__delete\">\n              {!! icon('delete') !!} {{ trans('common.delete') }}\n            </button>\n            <a href=\"{{route('articles.edit', $article->id)}}\" class=\"btn btn-info\">\n              {!! icon('pencil') !!} {{ trans('common.edit') }}\n            </a>\n          </form>\n        </div>\n        @endif\n      </article>\n\n      <hr class=\"divider\"/>\n\n      <article>\n        @include('comments.index', [\n          'solved' => $article->solution,\n          'owner'  => $currentUser && $article->isAuthor()\n        ])\n      </article>\n    </div>\n\n    @include('layouts.partial.markdown')\n  </div>\n@stop\n\n@section('script')\n  <script>\n    $(\"button.btn__delete\").on(\"click\", function(e) {\n      var articleId = $(\"#article__article\").data(\"id\");\n\n      if (confirm(\"{{ trans('common.confirm_delete') }}\")) {\n        $.ajax({\n          type: \"POST\",\n          url: \"/articles/\" + articleId,\n          data: {\n            _method: \"DELETE\"\n          }\n        }).success(function() {\n          flash(\"success\", \"{{ trans('common.deleted') }} {{ trans('common.msg_reload') }}\", 1500);\n\n          var timer = setTimeout(function () {\n            window.location.href = '/articles';\n          }, 2000);\n        });\n      }\n    });\n  </script>\n@stop"
  },
  {
    "path": "resources/views/attachments/partial/list.blade.php",
    "content": "@if ($attachments->count())\n  <ul class=\"tags__forum\">\n    @foreach ($attachments as $attachment)\n      <li class=\"label label-default\">\n        {!! icon('download') !!}\n        <a href=\"/attachments/{{ $attachment->name }}\">{{ $attachment->name }}</a>\n        @if ($currentUser and ($currentUser->isAdmin() or $article->isAuthor()))\n          <form action=\"{{ route('files.destroy', $attachment->id) }}\" method=\"post\" style=\"display: inline;\">\n            {!! csrf_field() !!}\n            {!! method_field('DELETE') !!}\n            <button type=\"submit\">x</button>\n          </form>\n        @endif\n      </li>\n    @endforeach\n  </ul>\n@endif"
  },
  {
    "path": "resources/views/comments/index.blade.php",
    "content": "<div class=\"container__forum\">\n  <a href=\"#\" class=\"help-block pull-right hidden-xs\" id=\"md-caller\">\n    <small>{!! icon('preview') !!} {{ trans('common.cheat_sheet') }}</small>\n  </a>\n  <h4>{!! icon('comments') !!} {{ trans('forum.title_comments') }}</h4>\n\n  @if($currentUser)\n    @include('comments.partial.create')\n  @else\n    @include('comments.partial.login')\n  @endif\n\n  @forelse($comments as $comment)\n    @include('comments.partial.comment', [\n      'parentId'  => $comment->id,\n      'isReply'   => false,\n      'hasChild'  => count($comment->replies),\n      'isTrashed' => $comment->trashed()\n    ])\n  @empty\n  @endforelse\n</div>\n\n@section('style')\n  <style>\n    div.media__create:not(:first-child),\n    div.media__edit {\n      display: none;\n    }\n  </style>\n@stop\n\n@section('script')\n  @parent\n  <script>\n    $(\"button.btn__reply\").on(\"click\", function(e) {\n      // Toggle reply form\n      var el__create = $(this).closest(\".media__item\").find(\".media__create\").first(),\n          el__edit = $(this).closest(\".media__item\").find(\".media__edit\").first();\n\n      el__edit.hide(\"fast\");\n      el__create.toggle(\"fast\").end().find('textarea').focus();\n    });\n\n    $(\"a.btn__edit\").on(\"click\", function(e) {\n      // Toggle edit form\n      var el__create = $(this).closest(\".media__item\").find(\".media__create\").first(),\n          el__edit = $(this).closest(\".media__item\").find(\".media__edit\").first();\n\n      el__create.hide(\"fast\");\n      el__edit.toggle(\"fast\").end().find('textarea').first().focus();\n    });\n\n    $(\"a.btn__delete\").on(\"click\", function(e) {\n      // Make a delete request to the server\n      var commentId = $(this).closest(\".media__item\").data(\"id\");\n\n      if (confirm(\"{{ trans('forum.msg_delete_comment') }}\")) {\n        $.ajax({\n          type: \"POST\",\n          url: \"/comments/\" + commentId,\n          data: {\n            _method: \"DELETE\"\n          }\n        }).success(function() {\n          flash(\"success\", \"{{ trans('common.deleted') }} {{ trans('common.msg_reload') }}\", 1500);\n          reload(2000);\n        });\n      }\n    });\n\n    $(\"button.btn__vote\").on(\"click\", function(e) {\n      var self = $(this),\n          commentId = $(this).closest(\".media__item\").data(\"id\");\n\n      $.ajax({\n        type: \"POST\",\n        url: \"/comments/\" + commentId + \"/vote\",\n        data: {\n          vote: self.data(\"vote\")\n        }\n      }).success(function(data) {\n        self.find(\"span\").html(data.value);\n        self.attr(\"disabled\", \"disabled\");\n        self.siblings().attr(\"disabled\", \"disabled\");\n      }).error(function() {\n        flash(\"danger\", \"{{ trans('common.msg_whoops') }}\", 2500);\n      });\n    });\n\n    $(\"button.btn__pick\").on(\"click\", function(e) {\n      // Update Best Answer against the Article model\n      var articleId = $(\"#article__article\").data(\"id\"),\n          commentId = $(this).closest(\".media__item\").data(\"id\");\n\n      if (confirm(\"{{ trans('forum.msg_pick_best') }}\")) {\n        $.ajax({\n          type: \"POST\",\n          url: \"/articles/\" + articleId + \"/pick\",\n          data: {\n            _method: \"PUT\",\n            solution_id: commentId\n          }\n        }).success(function() {\n          flash(\"success\", \"{{ trans('common.updated') }} {{ trans('common.msg_reload') }}\", 1500);\n          reload(2000);\n        });\n      }\n    });\n\n    $(\"#md-modal\").on(\"click\", function(e) {\n      // Make an overlay, explaining markdown syntax\n      e.preventDefault();\n      $(\"#md-modal\").modal();\n      return false;\n    });\n  </script>\n@stop"
  },
  {
    "path": "resources/views/comments/partial/best.blade.php",
    "content": "<div class=\"panel panel-info\">\n  <div class=\"panel-heading\">Best Answer</div>\n  <div class=\"panel-body\">\n    <div class=\"media\" data-id=\"{{ $comment->id }}\">\n\n      @include('users.partial.avatar', ['user' =>  $comment->author])\n\n      <div class=\"media-body\">\n        <h4 class=\"media-heading\">\n          <a href=\"{{ gravatar_profile_url($comment->author->email) }}\">\n            {{ $comment->author->name }}\n          </a>\n          <small>\n            {{ $comment->created_at->diffForHumans() }}\n          </small>\n        </h4>\n        <p>{!! markdown($comment->content) !!}</p>\n      </div>\n    </div>\n  </div>\n</div>"
  },
  {
    "path": "resources/views/comments/partial/comment.blade.php",
    "content": "@if ($isTrashed and ! $hasChild)\n  <!-- A trashed item but has no child -->\n@elseif ($isTrashed and $hasChild)\n  <div class=\"media media__item\" data-id=\"{{ $comment->id }}\" style=\"{{ $isReply ? 'margin-bottom:0;' : '' }}\">\n    @include('users.partial.avatar')\n\n    <div class=\"media-body @if (! $isReply) {{\"border__item\"}} @endif\">\n      <h4 class=\"media-heading\">\n        <span class=\"text-muted\">???</span>\n        <small>\n          {{ $comment->deleted_at->diffForHumans() }}\n        </small>\n      </h4>\n      <p class=\"text-danger\">{{ trans('forum.deleted_comment') }}</p>\n\n      @forelse ($comment->replies as $reply)\n        @include('comments.partial.comment', [\n          'comment'   => $reply,\n          'isReply'   => true,\n          'hasChild'  => count($reply->replies),\n          'isTrashed' => $reply->trashed()\n        ])\n      @empty\n      @endforelse\n    </div>\n  </div>\n@else\n  <div class=\"media media__item\" data-id=\"{{ $comment->id }}\" style=\"{{ $isReply ? 'margin-bottom:0;' : '' }}\">\n    @include('users.partial.avatar', ['user' =>  $comment->author])\n\n    <div class=\"media-body @if (! $isReply) {{\"border__item\"}} @endif\">\n\n      @if($currentUser and ($comment->isAuthor() or $currentUser->isAdmin()))\n        @include('comments.partial.control')\n      @endif\n\n      <h4 class=\"media-heading\">\n        <a href=\"{{ gravatar_profile_url($comment->author->email) }}\">\n          {{ $comment->author->name }}\n        </a>\n        <small>\n          {{ $comment->created_at->diffForHumans() }}\n        </small>\n      </h4>\n\n      <p>{!! markdown($comment->content) !!}</p>\n\n      @if ($currentUser)\n        <div class=\"row\">\n          <div class=\"col-xs-6\">\n            <div class=\"btn-group\" role=\"group\">\n              <?php $voted = $comment->votes->contains('user_id', $currentUser->id); ?>\n              <button type=\"button\" class=\"btn btn-default btn-sm btn__vote\" data-vote=\"up\" title=\"Vote up\" @if ($voted) {{ 'disabled=\"disabled\"' }} @endif>\n                {!! icon('up', false) !!} <span>{{ $comment->up_count }}</span>\n              </button>\n              <button type=\"button\" class=\"btn btn-default btn-sm btn__vote\" data-vote=\"down\" title=\"Vote down\" @if ($voted) {{ 'disabled=\"disabled\"' }} @endif>\n                {!! icon('down', false) !!} <span>{{ $comment->down_count }}</span>\n              </button>\n            </div>\n          </div>\n          <div class=\"col-xs-6 text-right\">\n            @if (! $solved && $owner)\n              <button type=\"button\" class=\"btn btn-default btn-sm btn__pick\" title=\"{{ trans('forum.msg_pick_help') }}\">\n                {!! icon('check', false) !!}\n              </button>\n            @endif\n            <button type=\"button\" class=\"btn btn-info btn-sm btn__reply\">\n              {!! icon('reply') !!} {{ trans('common.reply') }}\n            </button>\n          </div>\n        </div>\n      @endif\n\n      @if($currentUser and ($comment->isAuthor() or $currentUser->isAdmin()))\n        @include('comments.partial.edit')\n      @endif\n\n      @if($currentUser)\n        @include('comments.partial.create', ['parentId' => $comment->id])\n      @endif\n\n      @forelse ($comment->replies as $reply)\n        @include('comments.partial.comment', [\n          'comment'   => $reply,\n          'isReply'   => true,\n          'hasChild'  => count($reply->replies),\n          'isTrashed' => $reply->trashed()\n        ])\n      @empty\n      @endforelse\n    </div>\n  </div>\n@endif"
  },
  {
    "path": "resources/views/comments/partial/control.blade.php",
    "content": "<div class=\"dropdown pull-right\">\n  <span class=\"dropdown-toggle btn btn-default btn-xs\" type=\"button\" data-toggle=\"dropdown\">\n    {!! icon('dropdown', null) !!}\n  </span>\n  <ul class=\"dropdown-menu\" role=\"menu\">\n    <li role=\"presentation\">\n      <a role=\"menuitem\" tabindex=\"-1\" alt=\"edit\" class=\"btn__edit\">\n        {!! icon('update') !!} {{ trans('common.edit') }}\n      </a>\n    </li>\n    <li role=\"presentation\">\n      <a role=\"menuitem\" tabindex=\"-1\" alt=\"delete\" class=\"btn__delete\">\n        {!! icon('delete') !!} {{ trans('common.delete') }}\n      </a>\n    </li>\n  </ul>\n</div>"
  },
  {
    "path": "resources/views/comments/partial/create.blade.php",
    "content": "<div class=\"media media__create\" style=\"{{ isset($parentId) ? 'display:none;' : 'display:block;' }}\">\n\n  @include('users.partial.avatar', ['user' => $currentUser])\n\n  <div class=\"media-body\">\n    <form action=\"{{ route('comments.store') }}\" method=\"POST\" role=\"form\" class=\"form-horizontal\">\n      {!! csrf_field() !!}\n      <input type=\"hidden\" name=\"commentable_type\" value=\"{{ $commentableType }}\">\n      <input type=\"hidden\" name=\"commentable_id\" value=\"{{ $commentableId }}\">\n      @if(isset($parentId))\n        <input type=\"hidden\" name=\"parent_id\" value=\"{{ $parentId }}\">\n      @endif\n\n      <div class=\"form-group {{ $errors->has('content') ? 'has-error' : '' }}\" style=\"width:100%; margin: auto;\">\n        <textarea name=\"content\" class=\"form-control forum__content\">{{ old('content') }}</textarea>\n        {!! $errors->first('content', '<span class=\"form-error\">:message</span>') !!}\n        <div class=\"preview__forum\">{{ markdown(old('content', trans('common.markdown_preview'))) }}</div>\n      </div>\n\n      <p class=\"text-right\" style=\"margin:0;\">\n        <button type=\"submit\" class=\"btn btn-primary btn-sm\" style=\"margin-top: 1rem;\">\n          {!! icon('plane') !!} {{ trans('common.post') }}\n        </button>\n      </p>\n    </form>\n  </div>\n</div>"
  },
  {
    "path": "resources/views/comments/partial/edit.blade.php",
    "content": "<div class=\"media media__edit\">\n  <div class=\"media-body\">\n    <form action=\"{{ route('comments.update', $comment->id) }}\" method=\"POST\" role=\"form\" class=\"form-horizontal\">\n      {!! csrf_field() !!}\n      {!! method_field('PUT') !!}\n\n      <div class=\"form-group {{ $errors->has('content') ? 'has-error' : '' }}\" style=\"width:100%; margin: auto;\">\n        <textarea name=\"content\" class=\"form-control forum__content\">{{ old('content', $comment->content) }}</textarea>\n        {!! $errors->first('content', '<span class=\"form-error\">:message</span>') !!}\n        <div class=\"preview__forum\">{{ markdown(old('content', trans('common.markdown_preview'))) }}</div>\n      </div>\n\n      <p class=\"text-right\" style=\"margin:0;\">\n        <button type=\"submit\" class=\"btn btn-primary btn-sm\" style=\"margin-top: 1rem;\">\n          {!! icon('plane') !!} {{ trans('common.edit') }}\n        </button>\n      </p>\n    </form>\n  </div>\n</div>"
  },
  {
    "path": "resources/views/comments/partial/login.blade.php",
    "content": "<div class=\"media login__forum\">\n  <div class=\"media-body\">\n    <h4 class=\"media-heading text-center\">\n      <a href=\"{{ route('sessions.create', ['return' => urlencode($currentUrl)]) }}\">\n        {{ trans('auth.title_login') }}</a>\n      {{ trans('forum.msg_ask_login') }}\n    </h4>\n  </div>\n</div>"
  },
  {
    "path": "resources/views/emails/new-comment.blade.php",
    "content": "<h1>A new comment created <small>(or updated)</small></h1>\n\n<hr/>\n\n<ul style=\"list-style: none;\">\n  <li>{{ $comment->author->name }} <{{ $comment->author->email }}></li>\n  <li>{{ $comment->created_at }}</li>\n</ul>\n\n<hr/>\n\n<article>\n  {!! markdown($comment->content) !!}\n</article>"
  },
  {
    "path": "resources/views/emails/password.blade.php",
    "content": "Click here to reset your password: {{ route('reset.create', $token) }}"
  },
  {
    "path": "resources/views/errors/503.blade.php",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n        <title>Be right back.</title>\n\n        <link href=\"https://fonts.googleapis.com/css?family=Lato:100\" rel=\"stylesheet\" type=\"text/css\">\n\n        <style>\n            html, body {\n                height: 100%;\n            }\n\n            body {\n                margin: 0;\n                padding: 0;\n                width: 100%;\n                color: #B0BEC5;\n                display: table;\n                font-weight: 100;\n                font-family: 'Lato';\n            }\n\n            .container {\n                text-align: center;\n                display: table-cell;\n                vertical-align: middle;\n            }\n\n            .content {\n                text-align: center;\n                display: inline-block;\n            }\n\n            .title {\n                font-size: 72px;\n                margin-bottom: 40px;\n            }\n        </style>\n    </head>\n    <body>\n        <div class=\"container\">\n            <div class=\"content\">\n                <div class=\"title\">Be right back.</div>\n            </div>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "resources/views/errors/notice.blade.php",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>{{ $title }}</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\">\n    <style>\n        * { line-height: 1.5; margin: 0; }\n        html { color: #888; font-family: sans-serif; text-align: center; }\n        body { left: 50%; margin: -43px 0 0 -150px; position: absolute; top: 50%; width: 300px; }\n        h1 { color: #555; font-size: 2em; font-weight: 400; }\n        p { line-height: 1.2; }\n        @media only screen and (max-width: 270px) {\n            body { margin: 10px auto; position: static; width: 95%; }\n            h1 { font-size: 1.5em; }\n        }\n    </style>\n</head>\n<body>\n<h1>{{ $title }}</h1>\n\n<p>{{ $description }}</p>\n</body>\n</html>"
  },
  {
    "path": "resources/views/home.blade.php",
    "content": "@extends('layouts.master')\n\n@section('style')\n  @parent\n  <style>\n    .navbar.transparent.navbar-inverse .navbar-inner {\n      background: rgba(0,0,0,0.4);\n    }\n  </style>\n@stop\n\n@section('content')\n  <section id=\"laracroft\">\n    <div class=\"container-fluid box__landing\">\n      <div class=\"row\">\n        <h1>\n          <strong>라라벨</strong>\n        </h1>\n        <h2>\n          PHP 월드에서 가장 <span class=\"selection\">섹시한 웹 프레임웍</span>\n        </h2>\n        <p class=\"lead\">\n          웹 장인 <sup>Web Artisan</sup> 이 만든 웹 장인을 위한 프레임웍\n        </p>\n        <a href=\"{{ route('lessons.show') }}\" class=\"btn btn-primary\">\n          강좌 바로가기\n        </a>\n        <a href=\"{{ route('articles.index') }}\" class=\"btn btn-default\">\n          포럼 바로가기\n        </a>\n      </div>\n    </div>\n\n    <div class=\"credit\">\n      Image from <a href=\"http://wall.alphacoders.com/big.php?i=459033\">Alpha Coders</a>\n    </div>\n  </section>\n\n  <section class=\"container\" id=\"story\">\n    <div class=\"row\">\n      <div class=\"col-md-12\">\n        <h1 class=\"text-center\">\n          왜 섹시하다고 하는가? 왜 라라크로프트 인가?\n        </h1>\n\n        <p>\n          테일러 <sup><a href=\"http://taylorotwell.com/\" target=\"_blank\">Taylor Otwell - The Creator of Laravel</a></sup> 는 나니아연대기의 배경이되는 프라벨 <sup><a\n              href=\"https://en.wikipedia.org/wiki/Cair_Paravel\" target=\"_blank\">Pravel</a></sup> 이란 가상의 왕국 이름에서 라라벨이란 이름을 따왔다고 얘기하지만... 누가 봐도 그건 마케팅 스토리다. 라라벨 작명에 대한 비하인드 스토리는 제이슨 <sup>Jason Lewis - A Core Member</sup> 의\n          <a href=\"http://jasonlewis.me/article/laravel-the-story-behind-the-name\" target=\"_blank\">블로그 포스트</a>에 공개되어 있다.\n        </p>\n\n        <blockquote>\n          <p>\n            ... when during a Skiing holiday with Lara Croft, an unfortunate tumble led to me becoming Enveloped within her ample bosom. I had become <span style=\"text-decoration: underline;\">Laraveloped</span> ...\n          </p>\n          <footer>Dayle Lees</footer>\n        </blockquote>\n\n        <p>\n          라라벨 4 프로젝트 이름으로 사용했었고, 지금은 라라벨 코어 콤포넌트들의 네임스페이스로도 사용하고 있는 <code>Illumination</code> 도 툼레이더 <sup>Tomb Raider</sup> 에서 등장하는 비밀결사 조직인 Illuminati 에서 따온 것으로 추정된다. 여러가지 정황상 라라벨의 라라는 툼레이더의 주인공인 라라크로프트 <sup>Lara Croft</sup> 일 가능성이 높다. 역시 동서고금을 막론하고, 남자들이 모이면 <span style=\"text-decoration: underline;\">기-승-전-여자</span> 인가 보다 ^^/. 어쨌든...\n        </p>\n\n        <p>\n          라라벨은 여성 이름으로도 사용되기도 하는데, 이 이름을 가진 이들의 공통 특징은 침착함, 우아함, 준비됨의 성격을 가진다고 알려져 있다. 라라벨에 입문하고, 프로젝트를 진행해 보면, 쓰면 쓸수록 참 매력적인 프레임웍인 것을 몸소 체험하게 될 것이다.\n        </p>\n      </div>\n    </div>\n  </section>\n\n  <hr/>\n\n  <section class=\"container\" id=\"feature\">\n    <div class=\"row\">\n      <div class=\"col-md-12\">\n        <h1 class=\"text-center\">\n          라라벨을 배워야 하는 이유? 그것도 오늘 당장?\n        </h1>\n        <p>\n          라라벨은 표현력이 풍부한 API 와 우아한 문법, 무한한 확장성을 제공한다. 그 이유는 PSR <sup>PHP Standard Recommendations</sup>, 컴포저 <sup><a\n              href=\"https://getcomposer.org/\" target=\"_blank\"></a>Composer</sup> 에 의한  의존성 관리 등 PHP 생태계에서 제공하는 개발 표준을 준수하기 때문이다.\n        </p>\n\n        <p class=\"snippets\">\n          <pre><code class=\"hljs language-bash\"># PHP 에서 Image 조작을 위해서 아래 컴포넌트를 composer 로 설치한다.\n$ composer require \"intervention/image:2.3.*\"</code></pre>\n        </p>\n\n        <p class=\"snippets\">\n          <pre><code class=\"hljs language-php\">// 웹 서버 Document Root 디렉토리 밖에 있는 이미지를 요청하기 위한 Route 정의이다.\n// app/Http/routes.php\nRoute::get('lessons/{file}', 'LessonsController@image');</code></pre>\n        </p>\n\n        <p class=\"snippets\">\n          <pre><code class=\"hljs language-php\">// 좀 전에 Composer 로 설치한 intervention/image 컴포넌트를 이용해서 image/png 응답을 한다.\n// app/Http/Controllers/LessonsController.php\n<\\?php\n\nnamespace App\\Http\\Controllers;\n\nclass LessonsController extends Controller {\n    public function image($file)\n    {\n        $image = \\Image::make('images/' . $file);\n        return response($image->encode('png'), 200, ['Content-Type'  => 'image/png']);\n    }\n}</code></pre>\n        </p>\n\n        <p style=\"margin-top: 2rem;\">\n          또, IoC 컨테이너 <sup><a\n              href=\"https://en.wikipedia.org/wiki/Inversion_of_control\" target=\"_blank\">Inversion of Control</a></sup>, ORM <sup><a\n              href=\"https://en.wikipedia.org/wiki/Object-relational_mapping\" target=\"_blank\">Object Relational Mapping</a></sup> 등 객체지향 프로그래밍의 베스트 프랙티스들을 실천한다. <em class=\"help-block\">용어들에 절대 겁먹을 필요없다. 몰라도 이 강좌를 따라가는데 아무런 지장이 없고, 강좌를 진행하면서 저절로 익히게 될 것이다.</em>\n        </p>\n\n        <p>\n          라라벨은 프론트엔드 프레임웍 <sup><code>jQuery</code>, <code>VueJs</code>, <code>ReactJs</code>, <code>...</code></sup> 의 선택에는 관여하지 않지만, 클라이언트 사이드를 위한 기능들도 포함하고 있는 풀 스택 프레임웍이다. MVC <sup>Model View Controller</sup> 웹 프레임웍이 가진 기본 기능이라 할 수 있는 자체 템플릿 문법을 이용한 서버사이드 뷰 렌더링을 제공할 뿐 아니라, 프론트엔드 빌드 자동화를 위한 엘릭서 <sup><code>Elixir</code> - a Gulp Task Runner</sup> 기능도 제공한다. 엘릭서에는 <code>Babel</code>, <code>BrowserSync</code>, <code>Cache Bursting</code>, <code>...</code> 거의 모든 최신 빌드 레시피가 기본 포함되어 있다. 그 뿐인가? 팀 협업 및 개발 환경의 단일화를 위한 홈스테드 <sup><code>Homestead</code> - Ubuntu VM powered by Vagrant</sup>, 원격 서버로의 코드 배포 등을 자동화할 수 있는 엔보이 <sup><code>Envoy</code> - SSH Task Runner</sup> 까지 제공되니, 그 세심한 배려에 감동하지 않을 수 없다.\n        </p>\n\n        <blockquote>\n          <p>\n            Laravel continues its path toward <span style=\"text-decoration: underline;\">world conquest</span> with Lumen, a new (and well-done) PHP micro framework\n          </p>\n          <footer>\n            <a href=\"https://twitter.com/codeguy/status/587979729430519808\">\n              Josh Lockhart, April 2015\n            </a>\n          </footer>\n        </blockquote>\n\n        <p>\n          <a href=\"http://www.yes24.com/24/goods/22380599\" target=\"_blank\">Modern PHP</a>, <a href=\"http://modernpug.github.io/php-the-right-way/\" target=\"_blank\">PHP The Right Way</a> 를 쓰면서 PHP 사용자 커뮤니티에서 위대한 리더로 자리 잡고 있는 조시 <sup>Josh Lockhart - Modern PHP Evangelist</sup> 도, 라라벨의 간결하고 우아함에 감탄하며, 자신이 개발하고 유지하던 <a href=\"http://www.slimframework.com/\" target=\"_blank\">Slim Framework</a> 에서 잠시 손을 놓았다가 최근에 3.0 업데이트를 내 놓기도 했다. 가장 <a href=\"http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/\" target=\"_blank\">일관성이 없는 언어라는 비난을 받던 PHP</a> 가, 조시와 같은 선구자 및 라라벨의 등장으로 인해 그 위상이 굉장히 많이 높아졌다고 필자는 평가한다.\n        </p>\n\n        <p>\n          PHP 개발자라면 지금 당장 라라벨 우주선에 올라타야 한다. 조시의 말대로, 해외에서는 라라벨과 루멘 <sup><a href=\"http://lumen.laravel.com/\">Lumen - A Micro Framework based on Laravel</a></sup> 으로 대동단결하는 추세다, 마치 <code>Java/Spring</code>, <code>Ruby on Rails</code>, <code>python/Django</code>, 각 언어별로 하나의 프레임웍이 사용자들의 사랑을 받는 것 처럼. 과거의 절차 지향 방식의 PHP 개발방법론은 대형 프로젝트에 사용이 어렵다. 물론, 토이 프로젝트에 프레임웍을 사용할 필요는 없다. 하지만, <span style=\"text-decoration: underline;\">개발자 본인 스스로와 PHP 개발자 그룹 전체의 몸값을 높이기 위해서</span>, 꼭 라라벨이 아니더라도 <code>CodeIgniter</code>, <code>CakePHP</code>, <code>Slim</code> 과 같은 PHP 프레임웍을 공부할 것을 권장한다.\n        </p>\n\n        <p>\n          이유야 어떻든 PHP 를 배우려는 분이라면, 라라벨을 선택할 것을 강력히 추천한다. 필자도 <code>Ruby On Rails</code> 를 쓰다가 2013년 경에 라라벨 3 버전을 때 넘어 왔다. 각 프레임웍들이 가지고 있는 기능들의 많고 적음 및 언어 고유의 특성에 의한 약간의 차이가 있지만, 각 기능들의 사용법은 크게 다르지 않다고 생각한다. 하나의 프레임웍을 자유자재로 쓸 수 있다면, <span style=\"text-decoration: underline;\">다른 언어/프레임웍으로 전향할 때 학습속도는 말도 못하게 빨라진다</span>. 필자도 그랬으니까...\n        </p>\n      </div>\n    </div>\n  </section>\n\n  <hr/>\n\n  <section class=\"container\" id=\"courses\">\n    <div class=\"row\">\n      <div class=\"col-md-12\">\n        <h1 class=\"text-center\">\n          코스 소개\n        </h1>\n        <p>\n          입문 코스는 완성되었고 내용이 더 변경될 것이 없을 것 같다. 중급 및 실전 코스는 강좌를 계속 작성하고 있다. 중급 이상 강좌를 쓰는 중에 느낀 점은, 라라벨 고유의 기능보다는 프로그래밍 일반적인 것들이 많다는 것인데, 문맥상 설명에 필요하지 않는 부분들은 과감히 생략되었으니 독자들의 양해를 부탁드린다.\n        </p>\n      </div>\n    </div>\n\n    <div class=\"row\">\n      <div class=\"col-md-4\">\n        <h3 class=\"text-center\">입문 코스</h3>\n\n        <img src=\"images/icon_beginner_course.svg\" alt=\"\">\n\n        <p>\n          입문자가 꼭 알아야 할 내용만을 추렸다. 이 정도만 익혀도 실전에 투입할 수 있다고 생각한다.\n        </p>\n\n        <p>\n          라라벨 설치 및 Hello World 출력, 환경 변수 설정, 라우팅, 블레이드 템플릿 문법, 데이터베이스 연결, 테이블 마이그레이션, 데이터 씨딩, 데이터베이스 쿼리, 엘로퀀트 <sup><code>Eloquent</code> - 라라벨의 ORM</sup>, 모델과 컨트롤러, 사용자 인증, 메일보내기, 이벤트 트리거 및 처리, 사용자 입력갑 유효성 검사, 컴포저 사용법 등 을 배운다.\n        </p>\n\n        <p class=\"text-center\">\n          <a class=\"btn btn-default\" href=\"{{ route('lessons.show', '01-welcome.md') }}\" role=\"button\">\n            바로가기 &raquo;\n          </a>\n        </p>\n      </div>\n\n      <div class=\"col-md-4\">\n        <h3 class=\"text-center\">중급 코스</h3>\n\n        <img src=\"images/icon_intermediate_course.svg\" alt=\"\">\n\n        <p>\n          중급 코스와 실전 프로젝트는 별도로 분리되어 있지는 않지만, 실전 프로젝트를 진행하는 과정에서 입문 코스에서 배우지 못한 라라벨의 다양한 기능을 익히게 될 것이다.\n        </p>\n\n        <p>\n          실전 프로젝트를 진행하는 과정에서 컴포저를 이용한 콤포넌트 설치와 사용법을 다시 한번 살펴보고, 엘로퀀트가 제공하는 다양한 관계 클래스의 사용법, 파일 시스템, 언어 현지화, 고급 이벤트 핸들링, 콘솔 코맨드 등등 의 내용을 배울 것이다.\n        </p>\n\n        <p class=\"text-center\">\n          <a class=\"btn btn-default\" href=\"{{ route('lessons.show', '26-document-model.md') }}\" role=\"button\">\n            바로가기 &raquo;\n          </a>\n        </p>\n      </div>\n\n      <div class=\"col-md-4\">\n        <h3 class=\"text-center\">실전 코스</h3>\n\n        <img src=\"images/icon_realworld_course.svg\" alt=\"\">\n\n        <p>\n          실전 프로젝트를 통해서, 서비스를 기획하고, 구현 방안 및 구조에 대한 디자인 의사결정을 하는 과정을 같이 공부해 보고 싶었다.\n        </p>\n\n        <p>\n          이 강좌를 웹 페이지에서 볼 수 있도록 하는 Markdown Viewer 를 먼저 만들어 볼 것이다. 커뮤니티에서 주로 사용하는 댓글이 가능한 포럼을 만들어 볼 것이며, 이 포럼을 다른 디바이스에서도 사용할 수 있도록 RESTful API 서비스로 포장하는 과정을 진행해 볼 것이다.\n        </p>\n\n        <p class=\"text-center\">\n          <a class=\"btn btn-default\" href=\"{{ route('lessons.show', '26-document-model.md') }}\" role=\"button\">\n            바로가기 &raquo;\n          </a>\n        </p>\n      </div>\n    </div>\n  </section>\n\n  {{--<hr/>\n\n  <section class=\"container\" id=\"mailing-list\">\n    <div class=\"row\">\n      <div class=\"col-sm-6\">\n        <h3>새로운 소식을 메일로 알려 드립니다.</h3>\n        <p>새로운 강좌 등록, 라라벨 관련한 소식 등 유용한 정보를 메일로 받아 보세요.</p>\n      </div>\n      <div class=\"col-sm-6\">\n        <form action=\"{{ route('mail-list.subscribe') }}\" method=\"POST\" class=\"form-horizontal\">\n          {!! csrf_field() !!}\n          <div class=\"form-group col-sm-8 {{ $errors->has('email') ? 'has-error' : '' }}\">\n            <input type=\"email\" class=\"form-control\" id=\"email\" placeholder=\"signup@example.com\">\n          </div>\n          <div class=\"form-group col-sm-4\">\n            <button type=\"submit\" class=\"btn btn-primary btn-block\">가입하기</button>\n          </div>\n        </form>\n      </div>\n    </div>\n  </section>--}}\n@stop"
  },
  {
    "path": "resources/views/layouts/master.blade.php",
    "content": "<!DOCTYPE html>\n<html>\n\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, user-scalable=no\">\n\n  <meta name=\"description\" content=\"\">\n  <meta name=\"msapplication-tap-highlight\" content=\"no\">\n  <meta name=\"google-site-verification\" content=\"{{ config('project.seo.google_site_key') }}\" />\n  <meta name=\"naver-site-verification\" content=\"{{ config('project.seo.naver_site_key') }}\"/>\n  <meta property=\"og:site_name\" content=\"{{ config('project.description') }}\" />\n  <meta property=\"og:image\" content=\"//{{ config('project.app_domain') }}/images/logo_laravel.png\" />\n  <meta property=\"og:type\" content=\"Website\" />\n  <meta property=\"article:author\" content=\"{{ config('project.contacts.author.name') }} ({{ config('project.contacts.author.email') }})\" />\n\n  <meta name=\"csrf-token\" content=\"{{ csrf_token() }}\" />\n  <meta name=\"route\" content=\"{{ $currentRouteName }}\" />\n\n  <title>{{ config('project.description') }}</title>\n\n  <link href=\"{{ elixir(\"css/app.css\") }}\" rel=\"stylesheet\">\n  @yield('style')\n\n  <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n  <!--[if lt IE 9]>\n  <script src=\"//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js\"></script>\n  <script src=\"//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js\"></script>\n  <![endif]-->\n</head>\n\n<body>\n  @include('layouts.partial.navigation')\n\n  @include('layouts.partial.flash_message')\n\n  <div class=\"{{ $isLandingPage ? 'landing' : 'container' }}\">\n    @yield('content')\n  </div>\n\n  @include('layouts.partial.footer')\n\n  <script src=\"{{ elixir(\"js/app.js\") }}\"></script>\n  @yield('script')\n  @include('layouts.partial.tracker')\n</body>\n\n</html>"
  },
  {
    "path": "resources/views/layouts/partial/flash_message.blade.php",
    "content": "@if (session()->has('flash_notification'))\n  @if (session()->has('flash_notification.overlay'))\n    @include('layouts.partial.flash_modal', ['modalClass' => 'flash-modal', 'title' => session('flash_notification.title'), 'body' => session('flash_notification.message')])\n  @else\n    <div class=\"alert alert-{{ session('flash_notification.level') }} alert-dismissible flash-message\" role=\"alert\">\n      <button type=\"button\" class=\"close\" data-dismiss=\"alert\">\n        <span aria-hidden=\"true\">&times;</span>\n        <span class=\"sr-only\">Close</span>\n      </button>\n      {{ session('flash_notification.message') }}\n    </div>\n  @endif\n@endif\n\n{{--@if ($errors->has())\n  <div class=\"alert alert-danger alert-dismissible flash-message\" role=\"alert\">\n    <button type=\"button\" class=\"close\" data-dismiss=\"alert\">\n      <span aria-hidden=\"true\">&times;</span>\n      <span class=\"sr-only\">Close</span>\n    </button>\n    {{ trans('errors.msg_form_error') }}\n  </div>\n@endif--}}\n"
  },
  {
    "path": "resources/views/layouts/partial/flash_modal.blade.php",
    "content": "<div id=\"flash-overlay-modal\" class=\"modal fade {{ $modalClass or '' }}\">\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\n                <h4 class=\"modal-title\">{{ $title }}</h4>\n            </div>\n\n            <div class=\"modal-body\">\n                <p>{!! $body !!}</p>\n            </div>\n\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/layouts/partial/footer.blade.php",
    "content": "<footer class=\"footer\">\n  <ul class=\"list-inline pull-right locale\">\n    <li>{!! icon('locale') !!}</li>\n    @foreach (['en' => 'English', 'ko' => '한국어'] as $locale => $language)\n      <li class=\"{{ ($locale == $currentLocale) ? 'active' : '' }}\">\n        <a href=\"{{ route('locale', ['locale' => $locale, 'return' => urlencode($currentUrl)]) }}\">\n          {{ $language }}\n        </a>\n      </li>\n    @endforeach\n  </ul>\n\n  <div>\n    &copy; {{ date('Y') }} &nbsp; <a href=\"https://github.com/appkr-studio\">Appkr Studio</a>\n  </div>\n</footer>\n\n<div>\n  <a type=\"button\" id=\"back-to-top\" href=\"#\" class=\"btn btn-sm btn-danger back-to-top\" title=\"Top\">\n    <i class=\"fa fa-chevron-up\"></i>\n  </a>\n</div>\n"
  },
  {
    "path": "resources/views/layouts/partial/markdown.blade.php",
    "content": "<div class=\"modal fade\" id=\"md-modal\" tabindex=\"-1\" role=\"dialog\">\n  <div class=\"modal-dialog modal-lg\">\n    <div class=\"modal-content\">\n      <div class=\"modal-header\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"modal\">\n          <span aria-hidden=\"true\">&times;</span>\n          <span class=\"sr-only\">Close</span>\n        </button>\n        <h4 class=\"modal-title\">{{ trans('common.cheat_sheet') }}</h4>\n      </div>\n\n      <div class=\"modal-body table-responsive\">\n        <table class=\"table\">\n          <tr>\n            <th>Markdown</th>\n            <th>Compiled HTML</th>\n          </tr>\n          <tr>\n            <td># heading 1</td>\n            <td>{!! markdown('# heading 1') !!}</td>\n          </tr>\n          <tr>\n            <td>## heading 2</td>\n            <td>{!! markdown('## heading 2') !!}</td>\n          </tr>\n          <tr>\n            <td>###### heading 6</td>\n            <td>{!! markdown('###### heading 6') !!}</td>\n          </tr>\n          <tr>\n            <td>Paragraphs are separated<br/><br/>by a blank line.</td>\n            <td>{!! markdown('Paragraphs are separated\n\nby a blank line.') !!}</td>\n          </tr>\n          <tr>\n            <td>Let 2 spaces at the end of a line to do a&nbsp;&nbsp;<br/>\nline break</td>\n            <td>{!! markdown('Let 2 spaces at the end of a line to do a\nline break') !!}</td>\n          </tr>\n          <tr>\n            <td>*emphasis*, _emphasis_, **strong**, __strong__, ~~strike~~, `inline code`</td>\n            <td>{!! markdown('*emphasis*, _emphasis_, **strong**, __strong__, ~~strike~~, `inline code`') !!}</td>\n          </tr>\n          <tr>\n            <td>[Link Text](http://example.com)</td>\n            <td>{!! markdown('[Link Text](http://example.com)') !!}</td>\n          </tr>\n          <tr>\n            <td>![Alt Text](http://lorempixel.com/100/100/)</td>\n            <td>{!! markdown('![Alt Text](http://lorempixel.com/100/100/)') !!}</td>\n          </tr>\n          <tr>\n            <td>- apples<br/>- oranges<br/>- pears</td>\n            <td>{!! markdown('- apples\n- oranges\n- pears') !!}</td>\n          </tr>\n          <tr>\n            <td>1. apples<br/>2. oranges<br/>3. pears</td>\n            <td>{!! markdown('1. apples\n2. oranges\n3. pears') !!}</td>\n          </tr>\n          <tr>\n            <td>```<br/>\n              public function clear(key) {<br/>\n&nbsp;&nbsp;&nbsp;&nbsp;return this.cache.flush(key);<br/>\n}<br/>\n```<br/>\n              <small class=\"text-muted\">3 tilde(~~~) is also possible.</small>\n            </td>\n            <td>{!! markdown('```\npublic function clear(key) {\n    return this.cache.flush(key);\n}\n```') !!}</td>\n            </td>\n          </tr>\n          <tr>\n            <td>Markdown | Less | Pretty<br/> --- | --- | --:<br/> *Still* | `renders` | **nicely**<br/> 1 | 2 | 3<br/>\n              <small class=\"text-muted\">Colons(:) can be used to align columns.</small>\n            </td>\n            <td>{!! markdown('Markdown | Less | Pretty\n--- | --- | --:\n*Still* | `renders` | **nicely**\n1 | 2 | 3') !!}</td>\n          </tr>\n          <tr>\n            <td>>Blockquotes are very handy in email to emulate reply text.<br/> > This line is part of the same\n              quote.<br/> <br/> Quote break.<br/> <br/> > This is a very long line that will still be quoted properly\n              when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone.\n              Oh, you can *put* **Markdown** into a blockquote.\n            </td>\n            <td>{!! markdown('>Blockquotes are very handy in email to emulate reply text.\n>This line is part of the same quote.\n\nQuote break.\n> This is a very long line that will still be quoted properly when it wraps. Oh boy let\\'s keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote.') !!}</td>\n          </tr>\n          <tr>\n            <td>---</td>\n            <td>{!! markdown('---') !!}</td>\n          </tr>\n          <tr>\n            <td>[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/dhI9bsQwFRw/1.jpg)](http://www.youtube.com/watch?v=dhI9bsQwFRw)\n            </td>\n            <td>{!! markdown('[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/dhI9bsQwFRw/1.jpg)](http://www.youtube.com/watch?v=dhI9bsQwFRw)') !!}</td>\n          </tr>\n          <tr>\n            <td>That's some text with a footnote.[^1]<br/>[^1]: And that's the footnote.</td>\n            <td>{!! markdown('That\\'s some text with a footnote.[^1]\n\n[^1]: And that\\'s the footnote.') !!}</td>\n          </tr>\n          <tr>\n            <td>\\_Markdown tries to translate paired underscores as an emphasis. Use back slash to escape_</td>\n            <td>{!! markdown('\\_Markdown tries to translate paired underscores as an emphasis. Use back slash to escape_') !!}</td>\n          </tr>\n        </table>\n      </div>\n\n      <div class=\"modal-footer\">\n        <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n      </div>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "resources/views/layouts/partial/navigation.blade.php",
    "content": "<nav class=\"navbar navbar-fixed-top {{ $isLandingPage ? 'transparent navbar-inverse' : 'navbar-default' }}\" role=\"navigation\">\n\n  <div class=\"container-fluid\">\n    <div class=\"navbar-header\">\n      <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-responsive-collapse\">\n        <span class=\"sr-only\">Toggle Navigation</span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n        <span class=\"icon-bar\"></span>\n      </button>\n\n      <a href=\"{{ $currentUser ? route('home') : route('index') }}\" class=\"navbar-brand\">\n        <img src=\"/images/logo_laravel.png\" style=\"display: inline-block; height: 30px;\"/>\n      </a>\n    </div>\n\n    <div class=\"collapse navbar-collapse navbar-responsive-collapse\">\n      <ul class=\"nav navbar-nav navbar-right\">\n        <li>\n          <a href=\"{{ route('lessons.show') }}\">\n            {!! icon('book') !!} {{ trans('lessons.title_lessons') }}\n          </a>\n        </li>\n        <li>\n          <a href=\"{{ route('articles.index') }}\">\n            {!! icon('forum') !!} {{ trans('forum.title_forum') }}\n          </a>\n        </li>\n\n        @if(! auth()->check())\n          <li>\n            <a href=\"{{ route('sessions.create', ['return' => urlencode($currentUrl)]) }}\">\n              {!! icon('login') !!} {{ trans('auth.title_login') }}\n            </a>\n          </li>\n          <li>\n            <a href=\"{{ route('users.create', ['return' => urlencode($currentUrl)]) }}\">\n              {!! icon('certificate') !!} {{ trans('auth.title_signup') }}\n            </a>\n          </li>\n        @else\n          <li>\n            <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">\n              {!! icon('user') !!} {{ $currentUser->name }} <b class=\"caret\"></b>\n            </a>\n            <ul class=\"dropdown-menu\">\n              <li>\n                <a href=\"{{ route('sessions.destroy') }}\">\n                  {!! icon('logout') !!} {{ trans('auth.title_logout') }}\n                </a>\n              </li>\n            </ul>\n          </li>\n        @endif\n      </ul>\n    </div>\n  </div>\n</nav>"
  },
  {
    "path": "resources/views/layouts/partial/tracker.blade.php",
    "content": "<script>\n  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n  ga('create', 'UA-71112324-1', 'auto');\n  ga('send', 'pageview');\n</script>"
  },
  {
    "path": "resources/views/lessons/partial/pager.blade.php",
    "content": "<nav>\n  <ul class=\"pager\">\n    <li class=\"previous {{ $prev === false ? 'disabled' : ''}}\">\n      <a href=\"{{ $prev !== false ? route('lessons.show', $prev) : '#'}}\">\n        {{ trans('pagination.previous') }}\n      </a>\n    </li>\n    <li class=\"next {{ $next === false ? 'disabled' : ''}}\">\n      <a href=\"{{ $next !== false ? route('lessons.show', $next) : '#' }}\">\n        {{ trans('pagination.next') }}\n      </a>\n    </li>\n  </ul>\n</nav>"
  },
  {
    "path": "resources/views/lessons/show.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <div class=\"page-header\">\n    <h4>\n      {!! icon('book', null, 'margin-right:1rem') !!}\n      <a href=\"{{ route('lessons.show') }}\">\n        {{ trans('lessons.title_lessons') }}\n      </a>\n    </h4>\n  </div>\n\n  <div class=\"row container__lessons\">\n    <div class=\"col-md-3 sidebar__lessons\">\n      <aside>\n        {!! markdown($index->content) !!}\n      </aside>\n    </div>\n\n    <div class=\"col-md-9 article__lessons\">\n      <article>\n        @include('lessons.partial.pager')\n\n        <hr/>\n\n        {!! markdown($lesson->content) !!}\n\n        <hr/>\n\n        @include('lessons.partial.pager')\n      </article>\n\n      <hr class=\"divider\"/>\n\n      <article>\n        @include('comments.index', [\n          'solved' => false,\n          'owner'  => $currentUser && $lesson->isAuthor()\n        ])\n      </article>\n    </div>\n  </div>\n\n  <div class=\"nav__lessons\">\n    <a type=\"button\" role=\"button\" class=\"btn btn-sm btn-danger\">{{ trans('lessons.button_toc') }}</a>\n  </div>\n\n  @include('layouts.partial.markdown')\n@stop"
  },
  {
    "path": "resources/views/passwords/remind.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <form action=\"{{ route('remind.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n\n    <div class=\"page-header\">\n      <h4>{{ trans('auth.title_password_remind') }}</h4>\n      <p class=\"text-muted\">\n        {{ trans('auth.title_password_remind_help') }}\n      </p>\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"{{ trans('auth.email_address') }}\" value=\"{{ old('email') }}\" autofocus>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <button class=\"btn btn-primary btn-lg btn-block\" type=\"submit\">\n      {{ trans('auth.button_send_reminder') }}\n    </button>\n\n  </form>\n@stop"
  },
  {
    "path": "resources/views/passwords/reset.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <form action=\"{{ route('reset.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n\n    <input type=\"hidden\" name=\"token\" value=\"{{ $token }}\">\n\n    <div class=\"page-header\">\n      <h4>{{ trans('auth.title_reset_password') }}</h4>\n      <p class=\"text-muted\">\n        {{ trans('auth.title_reset_password_help') }}\n      </p>\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"{{ trans('auth.email_address') }}\" value=\"{{ old('email') }}\" autofocus>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"password\" name=\"password\" class=\"form-control\" placeholder=\"{{ trans('auth.new_password') }}\">\n      {!! $errors->first('password', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <input type=\"password\" name=\"password_confirmation\" class=\"form-control\" placeholder=\"{{ trans('auth.password_confirmation') }}\">\n      {!! $errors->first('password_confirmation', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <button class=\"btn btn-primary btn-lg btn-block\" type=\"submit\">\n      {{ trans('auth.button_reset_password') }}\n    </button>\n\n  </form>\n@stop"
  },
  {
    "path": "resources/views/sessions/create.blade.php",
    "content": "@extends('layouts.master')\n\n@section('style')\n  <style>\n    .login-or {\n      position: relative;\n      font-size: 16px;\n      color: #aaa;\n      margin-top: 20px;\n      margin-bottom: 20px;\n      padding-top: 15px;\n      padding-bottom: 15px;\n    }\n    .span-or {\n      display: block;\n      position: absolute;\n      left: 50%;\n      top: -2px;\n      margin-left: -25px;\n      background-color: #f5f5f5;\n      width: 50px;\n      text-align: center;\n    }\n    .hr-or {\n      background-color: #cdcdcd;\n      height: 1px;\n      margin-top: 0px !important;\n      margin-bottom: 0px !important;\n    }\n  </style>\n@stop\n\n@section('content')\n  <form action=\"{{ route('sessions.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n    @if ($return = Request::input('return'))\n      <input type=\"hidden\" name=\"return\" value=\"{{ $return }}\">\n    @endif\n\n    <div class=\"page-header\">\n      <h4>{{ trans('auth.title_login') }}</h4>\n      <p class=\"text-muted\">\n        {{ trans('auth.title_login_help') }}\n      </p>\n    </div>\n\n    <div class=\"form-group\">\n      <a class=\"btn btn-default btn-lg btn-block\" href=\"{{ route('social.login', ['github']) }}\">\n        <strong>{!! icon('github') !!} {{ trans('auth.login_with_github') }}</strong>\n      </a>\n    </div>\n\n    <div class=\"login-or\">\n      <hr class=\"hr-or\">\n      <span class=\"span-or\">or</span>\n    </div>\n\n    <div class=\"form-group {{ $errors->has('email') ? 'has-error' : '' }}\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"{{ trans('auth.email_address') }}\" value=\"{{ old('email') }}\" autofocus/>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group {{ $errors->has('password') ? 'has-error' : '' }}\">\n      <input type=\"password\" name=\"password\" class=\"form-control\" placeholder=\"{{ trans('auth.password') }}\">\n      {!! $errors->first('password', '<span class=\"form-error\">:message</span>')!!}\n    </div>\n\n    <div class=\"form-group\">\n      <div class=\"checkbox\">\n        <label>\n          <input type=\"checkbox\" name=\"remember\" value=\"{{ old('remember', 1) }}\" checked>\n          {{ trans('auth.remember_me') }}\n        </label>\n      </div>\n    </div>\n\n    <div class=\"form-group\">\n      <button class=\"btn btn-primary btn-lg btn-block\" type=\"submit\">\n        {{ trans('auth.button_login') }}\n      </button>\n    </div>\n\n    <div class=\"description\">\n      <p>&nbsp;</p>\n      <p class=\"text-center\">{{ trans('auth.recommend_signup') }}\n        <a href=\"{{ route('users.create', ['return' => urlencode($currentUrl)]) }}\">\n          {{ trans('auth.button_signup') }}\n        </a>\n      </p>\n      <p class=\"text-center\">\n        <a href=\"{{ route('remind.create')}}\">\n          {{ trans('auth.button_remind_password') }}\n        </a>\n        <br>\n        <small class=\"text-center text-muted\">\n            {{ trans('auth.button_remind_password_help') }}\n        </small>\n      </p>\n    </div>\n\n  </form>\n@stop\n"
  },
  {
    "path": "resources/views/tags/partial/index.blade.php",
    "content": "<p class=\"lead\">\n  {!! icon('filter') !!} Filters\n</p>\n\n<ul class=\"list-unstyled\">\n  @foreach(config('project.filters.article') as $filter => $name)\n    <li class=\"{{ (Request::input(config('project.params.filter')) == $filter) ? 'active' : '' }}\">\n      <a href=\"{{ route('articles.index', [config('project.params.filter') => $filter]) }}\">\n        {{ $name }}\n      </a>\n    </li>\n  @endforeach\n</ul>\n\n<p class=\"lead\">\n  {!! icon('tags') !!} Tags\n</p>\n\n<ul class=\"list-unstyled\">\n  @foreach($allTags as $tag)\n    <li class=\"{{ (Route::current()->parameter('slug') == $tag->slug) ? 'active' : '' }}\">\n      <a href=\"{{ route('tags.articles.index', $tag->slug) }}\">\n        {{ $tag->name }}\n        @if ($tagCount = $tag->articles->count())\n          <span class=\"badge badge-default\">{{ $tagCount }}</span>\n        @endif\n      </a>\n    </li>\n  @endforeach\n</ul>"
  },
  {
    "path": "resources/views/tags/partial/list.blade.php",
    "content": "@if ($tags->count())\n  <span class=\"text-muted\">{!! icon('tags') !!}</span>\n\n  <ul class=\"tags__forum\">\n    @foreach ($tags as $tag)\n      <li class=\"label label-default\">\n        <a href=\"{{ route('tags.articles.index', $tag->slug) }}\">{{ $tag->name }}</a>\n      </li>\n    @endforeach\n  </ul>\n@endif"
  },
  {
    "path": "resources/views/users/create.blade.php",
    "content": "@extends('layouts.master')\n\n@section('content')\n  <form action=\"{{ route('users.store') }}\" method=\"POST\" role=\"form\" class=\"form-auth\">\n\n    {!! csrf_field() !!}\n    @if ($return = Request::input('return'))\n      <input type=\"hidden\" name=\"return\" value=\"{{ $return }}\">\n    @endif\n\n    <div class=\"page-header\">\n      <h4>{{ trans('auth.title_signup') }}</h4>\n      <p class=\"text-muted\">\n        {!!  trans('auth.title_signup_help', ['url' => route('sessions.create')]) !!}\n      </p>\n    </div>\n\n    <div class=\"form-group {{ $errors->has('name') ? 'has-error' : '' }}\">\n      <input type=\"text\" name=\"name\" class=\"form-control\" placeholder=\"{{ trans('auth.name') }}\" value=\"{{ old('name') }}\" autofocus/>\n      {!! $errors->first('name', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group {{ $errors->has('email') ? 'has-error' : '' }}\">\n      <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"{{ trans('auth.email_address') }}\" value=\"{{ old('email') }}\"/>\n      {!! $errors->first('email', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group {{ $errors->has('password') ? 'has-error' : '' }}\">\n      <input type=\"password\" name=\"password\" class=\"form-control\" placeholder=\"{{ trans('auth.password') }}\"/>\n      {!! $errors->first('password', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group {{ $errors->has('password') ? 'has-error' : '' }}\">\n      <input type=\"password\" name=\"password_confirmation\" class=\"form-control\" placeholder=\"{{ trans('auth.password_confirmation') }}\" />\n      {!! $errors->first('password_confirmation', '<span class=\"form-error\">:message</span>') !!}\n    </div>\n\n    <div class=\"form-group\">\n      <button class=\"btn btn-primary btn-lg btn-block\" type=\"submit\">\n        {{ trans('auth.button_signup') }}\n      </button>\n    </div>\n\n  </form>\n@stop\n\n"
  },
  {
    "path": "resources/views/users/partial/avatar.blade.php",
    "content": "<?php $size = isset($size) ? $size : 48; ?>\n\n@if (isset($user) and $user)\n  <a class=\"pull-left hidden-xs hidden-sm\" href=\"{{ gravatar_profile_url($user->email) }}\">\n    <img class=\"media-object img-thumbnail\" src=\"{{ gravatar_url($user->email, $size) }}\" alt=\"{{ $user->name }}\">\n  </a>\n@else\n  <a class=\"pull-left hidden-xs hidden-sm\" href=\"{{ gravatar_profile_url('john@example.com') }}\">\n    <img class=\"media-object img-thumbnail\" src=\"{{ gravatar_url('john@example.com', $size) }}\" alt=\"Unknown User\">\n  </a>\n@endif"
  },
  {
    "path": "resources/views/vendor/.gitkeep",
    "content": ""
  },
  {
    "path": "resources/views/vendor/flash/message.blade.php",
    "content": "@if (Session::has('flash_notification.message'))\n    @if (Session::has('flash_notification.overlay'))\n        @include('flash::modal', ['modalClass' => 'flash-modal', 'title' => Session::get('flash_notification.title'), 'body' => Session::get('flash_notification.message')])\n    @else\n        <div class=\"alert alert-{{ Session::get('flash_notification.level') }}\">\n            <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>\n\n            {!! Session::get('flash_notification.message') !!}\n        </div>\n    @endif\n@endif\n"
  },
  {
    "path": "resources/views/vendor/flash/modal.blade.php",
    "content": "<div id=\"flash-overlay-modal\" class=\"modal fade {{ $modalClass or '' }}\">\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\n                <h4 class=\"modal-title\">{{ $title }}</h4>\n            </div>\n\n            <div class=\"modal-body\">\n                <p>{!! $body !!}</p>\n            </div>\n\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">Close</button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "server.php",
    "content": "<?php\n\n/**\n * Laravel - A PHP Framework For Web Artisans\n *\n * @package  Laravel\n * @author   Taylor Otwell <taylorotwell@gmail.com>\n */\n\n$uri = urldecode(\n    parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)\n);\n\n// This file allows us to emulate Apache's \"mod_rewrite\" functionality from the\n// built-in PHP web server. This provides a convenient way to test a Laravel\n// application without having installed a \"real\" web server software here.\nif ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {\n    return false;\n}\n\nrequire_once __DIR__.'/public/index.php';\n"
  },
  {
    "path": "storage/app/.gitignore",
    "content": "*\n!.gitignore"
  },
  {
    "path": "storage/backup/.gitignore",
    "content": "*\n!.gitignore"
  },
  {
    "path": "storage/framework/.gitignore",
    "content": "config.php\nroutes.php\ncompiled.php\nservices.json\nevents.scanned.php\nroutes.scanned.php\ndown\n"
  },
  {
    "path": "storage/framework/cache/.gitignore",
    "content": "*\n!.gitignore"
  },
  {
    "path": "storage/framework/sessions/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/framework/views/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "storage/logs/.gitignore",
    "content": "*\n!.gitignore\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nclass TestCase extends Illuminate\\Foundation\\Testing\\TestCase\n{\n    /**\n     * The base URL to use while testing the application.\n     *\n     * @var string\n     */\n    protected $baseUrl = 'http://localhost';\n\n    /**\n     * Creates the application.\n     *\n     * @return \\Illuminate\\Foundation\\Application\n     */\n    public function createApplication()\n    {\n        $app = require __DIR__.'/../bootstrap/app.php';\n\n        $app->make(Illuminate\\Contracts\\Console\\Kernel::class)->bootstrap();\n\n        return $app;\n    }\n}\n"
  },
  {
    "path": "tests/integration/Http/Controllers/Api/ApiTest.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers\\Api;\n\nuse App\\Article;\nuse App\\Attachment;\nuse App\\Comment;\nuse App\\User;\nuse Bican\\Roles\\Models\\Role;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\n\nclass ApiTest extends \\TestCase\n{\n    use DatabaseTransactions;\n\n    /**\n     * The base URL to use while testing the application.\n     *\n     * @var string\n     */\n    protected $baseUrl;\n\n    /**\n     * @var User\n     */\n    protected $user;\n\n    /**\n     * @var Article\n     */\n    protected $article;\n\n    /**\n     * @var array\n     */\n    protected $userPayload = [\n        'name'     => 'foo',\n        'email'    => 'foo@bar.com',\n        'password' => 'password',\n    ];\n\n    /**\n     * @var string\n     */\n    protected $jwtToken;\n\n    /**\n     * Set up.\n     */\n    public function setUp()\n    {\n        parent::setUp();\n        $this->baseUrl = 'http://' . config('project.api_domain');\n    }\n\n    /**\n     * Mimic the login attempt.\n     *\n     * @param array $overrides\n     * @param array $headers\n     * @return $this\n     */\n    public function login($overrides = [], $headers = [])\n    {\n        return $this->post(\n            route('api.sessions.store'),\n            array_merge([\n                'email'    => $this->user->email,\n                'password' => 'password',\n            ], $overrides),\n            $this->httpHeaders($headers)\n        )->parseJwtToken();\n    }\n\n    /**\n     * Mimic the user registration attempt.\n     *\n     * @param array $overrides\n     * @param array $headers\n     * @return $this\n     */\n    public function register($overrides = [], $headers = [])\n    {\n        return $this->post(\n            route('api.users.store'),\n            array_merge(\n                $this->userPayload,\n                ['password_confirmation' => $this->userPayload['password']],\n                $overrides\n            ),\n            $this->httpHeaders($headers)\n        )->parseJwtToken();\n    }\n\n    /**\n     * Mimic the password remind attempt.\n     *\n     * @param array $overrides\n     * @param array $headers\n     * @return $this\n     */\n    public function remind($overrides = [], $headers = [])\n    {\n        return $this->post(\n            route('api.remind.store'),\n            [\n                'email' => array_key_exists('email', $overrides)\n                    ? $overrides['email']\n                    : $this->user->email\n            ],\n            $this->httpHeaders($headers)\n        );\n    }\n\n    /**\n     * Create User.\n     *\n     * @param array $overrides\n     * @return $this\n     */\n    protected function createUserStub($overrides = [])\n    {\n        $this->user = empty($overrides)\n            ? factory(User::class)->create()\n            : factory(User::class)->create($overrides);\n\n        $this->user->attachRole(Role::find(2));\n\n        return $this;\n    }\n\n    /**\n     * Create Article.\n     *\n     * @param array $overrides\n     * @return $this\n     */\n    protected function createArticleStub($overrides = [])\n    {\n        $payload = array_merge([\n            'title'     => 'foo',\n            // user 1 is safe, because we already seeded.\n            'author_id' => is_null($this->user) ? 1 : $this->user->id,\n            'content'   => 'bar',\n        ], $overrides);\n\n        $this->article = factory(Article::class)->create($payload);\n\n        return $this;\n    }\n\n    /**\n     * Create Comment.\n     *\n     * @param array $overrides\n     * @return $this\n     */\n    protected function createCommentStub($overrides = [])\n    {\n        $article = is_null($this->article) ? $this->createArticleStub() : $this->article;\n\n        $article->comments()->save(\n            factory(Comment::class)->make([\n                'author_id' => is_null($this->user) ? 1 : $this->user->id,\n            ])\n        );\n\n        return $this;\n    }\n\n    /**\n     * Create Tag.\n     *\n     * @return $this\n     */\n    protected function createTagStub()\n    {\n        $article = is_null($this->article) ? $this->createArticleStub() : $this->article;\n        $article->tags()->attach(1);\n\n        return $this;\n    }\n\n    /**\n     * Create Attachment.\n     *\n     * @return $this\n     */\n    protected function createAttachmentStub()\n    {\n        $article = is_null($this->article) ? $this->createArticleStub() : $this->article;\n        $article->attachments()->save(factory(Attachment::class)->make());\n\n        return $this;\n    }\n\n    /**\n     * Stubbing all test data.\n     *\n     * @param array $userOverrides\n     * @param array $articleOverrides\n     * @param array $commentOverrides\n     * @return $this\n     */\n    protected function createTestStub($userOverrides = [], $articleOverrides = [], $commentOverrides = [])\n    {\n        return $this->createUserStub($userOverrides)\n            ->createArticleStub($articleOverrides)\n            ->createCommentStub($commentOverrides)\n            ->createTagStub()\n            ->createAttachmentStub();\n    }\n\n    /**\n     * Set or Get http request header.\n     *\n     * @param array $append\n     *\n     * @return array\n     */\n    protected function httpHeaders($append = [])\n    {\n        return array_merge([\n            'Accept' => 'application/json'\n        ], $append);\n    }\n\n    /**\n     * Parse jwt token out of the login or register request.\n     *\n     * @return $this\n     */\n    protected function parseJwtToken()\n    {\n        $json = json_decode($this->response->getContent());\n\n        if (isset($json->meta->token)) {\n            $this->jwtToken = $json->meta->token;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Build Authorization header with jwt token.\n     *\n     * @param null $overrides\n     * @return array\n     */\n    protected function jwtHeader($overrides = null)\n    {\n        $jwtToken = $overrides ?: $this->jwtToken;\n        return ['HTTP_Authorization' => 'Bearer ' . $jwtToken];\n    }\n}"
  },
  {
    "path": "tests/integration/Http/Controllers/Api/PasswordsController.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers\\Api;\n\nuse Teapot\\StatusCode\\All as StatusCode;\n\nclass PasswordsController extends ApiTest\n{\n    /** @test */\n    public function it_can_remind_password()\n    {\n        $this->createUserStub()\n            ->remind()\n            ->seeStatusCode(StatusCode::OK)\n            ->seeJsonContains(['message' => 'Success']);\n    }\n\n    /** @test */\n    public function it_guides_social_user_password_reset_impossible()\n    {\n        $this->createUserStub(['password' => null])\n            ->remind(['password' => null])\n            ->seeStatusCode(StatusCode::BAD_REQUEST);\n    }\n\n    /** @test */\n    public function it_fails_when_user_not_found()\n    {\n        $this->remind(['email' => 'not.existing@bar.com'])\n            ->seeStatusCode(StatusCode::NOT_FOUND);\n    }\n}"
  },
  {
    "path": "tests/integration/Http/Controllers/Api/SessionsController.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers\\Api;\n\nuse Teapot\\StatusCode\\All as StatusCode;\n\nclass SessionsController extends ApiTest\n{\n    /** @test */\n    public function it_respond_token_when_user_login()\n    {\n        $this->createUserStub()\n            ->login()\n            ->seeStatusCode(StatusCode::CREATED)\n            ->seeJsonStructure(['success' => ['code', 'message'], 'meta' => ['token']]);\n    }\n\n    /** @test */\n    public function it_fails_login_when_credentials_malformed()\n    {\n        $this->createUserStub()\n            ->login(['email' => 'malformed.email', 'password' => 'short'])\n            ->seeStatusCode(StatusCode::UNPROCESSABLE_ENTITY)\n            ->seeJsonStructure(['error' => ['code', 'message' => [0, 1]]]);\n    }\n\n    /** @test */\n    public function it_fails_login_when_credential_invalid()\n    {\n        $this->createUserStub()\n            ->login(['password' => 'wrong.password'])\n            ->seeStatusCode(StatusCode::UNAUTHORIZED)\n            ->seeJsonContains(['message' => 'invalid_credentials']);\n    }\n}"
  },
  {
    "path": "tests/integration/Http/Controllers/Api/UsersController.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers\\Api;\n\nuse Teapot\\StatusCode\\All as StatusCode;\n\nclass UsersController extends ApiTest\n{\n    /** @test */\n    public function it_respond_token_when_user_login()\n    {\n        $this->register()\n            ->seeStatusCode(StatusCode::CREATED)\n            ->seeJsonStructure(['success' => ['code', 'message'], 'meta' => ['token']]);\n    }\n\n    /** @test */\n    public function it_fails_login_when_payload_malformed()\n    {\n        $this->register(['name' => '', 'email' => 'malformed.email', 'password' => 'short'])\n            ->seeStatusCode(StatusCode::UNPROCESSABLE_ENTITY)\n            ->seeJsonStructure(['error' => ['code', 'message' => [0, 1, 2]]]);\n    }\n}"
  },
  {
    "path": "tests/integration/Http/Controllers/Api/V1/ArticlesController.php",
    "content": "<?php\n\n// Todo write test for Comment, Tag, Attachment.\n\nnamespace Test\\Http\\Controllers\\Api\\V1;\n\nuse Teapot\\StatusCode\\All as StatusCode;\nuse Test\\Http\\Controllers\\Api\\ApiTest;\n\nclass ArticlesController extends ApiTest\n{\n    /** @test */\n    public function it_fetches_collection_of_articles()\n    {\n        $this->get(\n                route('api.v1.articles.index'),\n                $this->httpHeaders()\n            )\n            ->seeStatusCode(StatusCode::OK)\n            ->seeJson();\n    }\n\n    /** @test */\n    public function it_fails_fetching_collection_when_querystrings_not_valid()\n    {\n        $this->get(\n                route('api.v1.articles.index', [config('project.params.filter') => 'abc']),\n                $this->httpHeaders()\n            )\n            ->seeStatusCode(StatusCode::UNPROCESSABLE_ENTITY);\n    }\n\n    /** @test */\n    public function it_fetches_single_article()\n    {\n        // Create obfuscated id\n        $id = optimus(1);\n\n        $this->get(\n            // 1 is safe, because it's in the seeding\n                route('api.v1.articles.show', $id),\n                $this->httpHeaders()\n            )\n            ->seeStatusCode(StatusCode::OK)\n            ->seeJson();\n    }\n\n    /** @test */\n    public function it_fails_fetching_article_when_model_not_exist()\n    {\n        $this->get(\n                route('api.v1.articles.show', 10000),\n                $this->httpHeaders()\n            )\n            ->seeStatusCode(StatusCode::NOT_FOUND)\n            ->seeJson();\n    }\n\n    /** @test */\n    public function it_creates_new_article()\n    {\n\n        $this->createUserStub()\n            ->login()\n            ->post(\n                route('api.v1.articles.store'),\n                [\n                    'title' => 'foo',\n                    'content' => 'bar',\n                    'tags' => [1]\n                ],\n                $this->httpHeaders($this->jwtHeader())\n            )\n            ->seeStatusCode(StatusCode::CREATED)\n            ->seeJson()\n            ->seeInDatabase('articles', ['title' => 'foo']);\n    }\n\n    /** @test */\n    public function it_fails_creating_new_article_if_given_jwt_token_is_not_valid()\n    {\n        $this->createUserStub()\n            ->login()\n            ->post(\n                route('api.v1.articles.store'),\n                [\n                    'title' => 'foo',\n                    'content' => 'bar',\n                    'tags' => [1]\n                ],\n                $this->httpHeaders($this->jwtHeader('malformed.jwt.token'))\n            )\n            ->seeStatusCode(StatusCode::BAD_REQUEST)\n            ->seeJsonContains(['message' => 'token_invalid']);\n    }\n\n    /** @test */\n    public function it_fails_creating_new_article_if_request_payload_not_valid()\n    {\n        $this->createUserStub()\n            ->login()\n            ->post(\n                route('api.v1.articles.store'),\n                ['title' => 'foo',],\n                $this->httpHeaders($this->jwtHeader())\n            )\n            ->seeStatusCode(StatusCode::UNPROCESSABLE_ENTITY)\n            ->seeJson();\n    }\n\n    /** @test */\n    public function it_updates_article()\n    {\n        $this->createUserStub()\n            ->login()\n            ->createArticleStub(['title' => 'foo'])\n            ->put(\n                route('api.v1.articles.update', optimus($this->article->id)),\n                ['title' => 'bar',],\n                $this->httpHeaders($this->jwtHeader())\n            )\n            ->seeStatusCode(StatusCode::OK)\n            ->seeJson()\n            ->seeInDatabase('articles', ['title' => 'bar']);\n    }\n\n    /** @test */\n    public function it_fails_updating_article_when_not_owner()\n    {\n        $this->createUserStub()\n            ->login()\n            ->put(\n                // Assumes that article 1 exists by seeding.\n                route('api.v1.articles.update', 1),\n                ['title' => 'bar',],\n                $this->httpHeaders($this->jwtHeader())\n            )\n            ->seeStatusCode(StatusCode::FORBIDDEN)\n            ->seeJson();\n    }\n\n    /** @test */\n    public function it_update_best_solution()\n    {\n        // Todo\n    }\n\n    /** @test */\n    public function it_fails_update_best_when_request_payload_not_valid()\n    {\n        // Todo\n    }\n\n    /** @test */\n    public function it_deletes_article()\n    {\n        $this->createUserStub()\n            ->login()\n            ->createArticleStub(['title' => 'foo'])\n            ->delete(\n                route('api.v1.articles.destroy', optimus($this->article->id)),\n                [],\n                $this->httpHeaders($this->jwtHeader())\n            )\n            ->seeStatusCode(StatusCode::NO_CONTENT);\n    }\n}"
  },
  {
    "path": "tests/integration/Http/Controllers/AuthTest.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers;\n\nuse App\\Article;\nuse App\\Attachment;\nuse App\\Comment;\nuse App\\User;\nuse Bican\\Roles\\Models\\Role;\nuse Illuminate\\Foundation\\Testing\\DatabaseTransactions;\n\nclass AuthTest extends \\TestCase\n{\n    use DatabaseTransactions;\n\n    /**\n     * The base URL to use while testing the application.\n     *\n     * @var string\n     */\n    protected $baseUrl;\n\n    /**\n     * @var User\n     */\n    protected $user;\n\n    /**\n     * @var Article\n     */\n    protected $article;\n\n    /**\n     * @var array\n     */\n    protected $userPayload = [\n        'name' => 'foo',\n        'email' => 'foo@bar.com',\n        'password' => 'password',\n    ];\n\n    /**\n     * Set up.\n     */\n    public function setUp()\n    {\n        parent::setUp();\n        $this->baseUrl = 'http://' . config('project.app_domain');\n    }\n\n    /**\n     * Visit login page and attempt login.\n     *\n     * @param array $overrides\n     * @return mixed\n     */\n    public function login($overrides = [])\n    {\n        return $this->visit(route('sessions.create'))\n            ->submitForm(\n                trans('auth.button_login'),\n                array_merge([\n                    'email' => $this->user->email,\n                    'password' => 'password',\n                ], $overrides)\n            );\n    }\n\n    /**\n     * Visit login route.\n     *\n     * @return mixed\n     */\n    public function logout()\n    {\n        return $this->visit(route('sessions.destroy'));\n    }\n\n    /**\n     * Visit signup page and attempt user registration.\n     *\n     * @param array $overrides\n     * @return $this\n     */\n    public function register($overrides = [])\n    {\n        return $this->visit(route('users.create'))\n            ->submitForm(\n                trans('auth.button_signup'),\n                array_merge(\n                    $this->userPayload,\n                    ['password_confirmation' => $this->userPayload['password']],\n                    $overrides\n                )\n            );\n    }\n\n    /**\n     * Visit password remind page and attempt the password remind.\n     *\n     * @param array $overrides\n     * @return $this\n     */\n    public function remind($overrides = [])\n    {\n        return $this->visit(route('remind.create'))\n            ->submitForm(\n                trans('auth.button_send_reminder'),\n                [\n                    'email' => array_key_exists('email', $overrides)\n                        ? $overrides['email']\n                        : $this->user->email\n                ]\n            );\n    }\n\n    /**\n     * Stubbing test data.\n     *\n     * @param array $overrides\n     */\n    protected function createTestStub($overrides = [])\n    {\n        $this->user = ! empty($overrides)\n            ? factory(User::class)->create()\n            : factory(User::class)->create($overrides);\n\n        $this->user->attachRole(Role::find(2));\n\n        $this->article = factory(Article::class)->create([\n            'title'     => 'title',\n            'author_id' => $this->user->id,\n            'content'   => 'description',\n        ]);\n\n        $this->article->comments()->save(\n            factory(Comment::class)->make([\n                'author_id' => $this->user->id\n            ])\n        );\n\n        $this->article->tags()->attach(1);\n\n        $this->article->attachments()->save(\n            factory(Attachment::class)->make()\n        );\n    }\n}"
  },
  {
    "path": "tests/integration/Http/Controllers/SessionsController.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers;\n\nclass SessionsController extends AuthTest\n{\n    public function setUp()\n    {\n        parent::setUp();\n        $this->createTestStub();\n    }\n\n    /** @test */\n    public function it_logs_a_user_in()\n    {\n        $this->login()\n            ->see(trans('auth.welcome', ['name' => $this->user->name]));\n    }\n\n    /** @test */\n    public function it_fails_login_when_validation_fails()\n    {\n        $this->login(['email' => 'malformed.email', 'password' => 'short'])\n            ->see(trans('validation.email', ['attribute' => 'email']))\n            ->see(trans('validation.min.string', ['attribute' => 'password', 'min' => 6]))\n            ->seePageIs(route('sessions.create'));\n    }\n\n    /** @test */\n    public function it_fails_login_when_credentials_not_match()\n    {\n        $this->login(['password' => 'wrong.password'])\n            ->see(trans('auth.failed'))\n            ->seePageIs(route('sessions.create'));\n    }\n\n    /** @test */\n    public function it_logs_a_user_out()\n    {\n        $this->actingAs($this->user)\n            ->logout()\n            ->seePageIs(route('index'));\n    }\n}"
  },
  {
    "path": "tests/integration/Http/Controllers/UsersController.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers;\n\nclass UsersController extends AuthTest\n{\n    /** @test */\n    public function it_registers_a_user()\n    {\n        return $this->register(['name' => 'foo'])\n            ->seePageIs(route('home'))\n            ->seeInDatabase('users', ['name' => 'foo']);\n    }\n\n    /** @test */\n    public function it_fails_registration_when_validation_fails()\n    {\n        $this->register([\n                'name' => null,\n                'email' => 'malformed.email',\n                'password'  => 'short',\n                'password_confirmation' => 'not.matching.password',\n            ])\n            ->see(trans('validation.required', ['attribute' => 'name']))\n            ->see(trans('validation.email', ['attribute' => 'email']))\n            ->see(trans('validation.confirmed', ['attribute' => 'password']))\n            ->seePageIs(route('users.create'));\n    }\n}\n"
  },
  {
    "path": "tests/integration/Http/Controllers/WelcomeController.php",
    "content": "<?php\n\nnamespace Test\\Http\\Controllers;\n\nclass WelcomeController extends \\TestCase\n{\n    /** @test */\n    public function it_loads_welcome_page()\n    {\n        $this->visit(route('index'))\n            ->see('Hello');\n    }\n\n    /** @test */\n    public function it_redirect_to_login_page_without_login()\n    {\n        $this->visit(route('home'))\n            ->seePageIs(\\Request::fullUrl());\n    }\n}\n"
  }
]