diff --git a/.editorconfig b/.editorconfig index bf094abefc..b2e4603bf0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,6 +4,7 @@ root = true insert_final_newline = false charset = utf-8 indent_style = tab +indent_size = 4 [tests/languages/**.test] end_of_line = crlf diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..4a96cb856e --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,224 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + plugins: ['jsdoc', 'regexp'], + extends: 'eslint:recommended', + rules: { + 'no-use-before-define': ['error', { 'functions': false, 'classes': false }], + + // stylistic rules + 'brace-style': ['warn', '1tbs', { allowSingleLine: true }], + 'curly': ['warn', 'all'], + 'eol-last': 'warn', + 'no-multiple-empty-lines': ['warn', { max: 2, maxBOF: 0, maxEOF: 0 }], + 'no-tabs': ['warn', { allowIndentationTabs: true }], + 'no-var': 'error', + 'one-var': ['warn', 'never'], + 'quotes': ['warn', 'single', { avoidEscape: true, allowTemplateLiterals: true }], + 'semi': 'warn', + 'wrap-iife': 'warn', + + // spaces and indentation + 'arrow-spacing': 'warn', + 'block-spacing': 'warn', + 'comma-spacing': 'warn', + 'computed-property-spacing': 'warn', + 'func-call-spacing': 'warn', + 'generator-star-spacing': 'warn', + 'indent': ['warn', 'tab', { SwitchCase: 1 }], + 'key-spacing': 'warn', + 'keyword-spacing': 'warn', + 'no-multi-spaces': ['warn', { ignoreEOLComments: true }], + 'no-trailing-spaces': 'warn', + 'no-whitespace-before-property': 'warn', + 'object-curly-spacing': ['warn', 'always'], + 'rest-spread-spacing': 'warn', + 'semi-spacing': 'warn', + 'space-before-blocks': 'warn', + 'space-before-function-paren': ['warn', { named: 'never' }], + 'space-in-parens': 'warn', + 'space-infix-ops': ['warn', { int32Hint: true }], + 'space-unary-ops': 'warn', + 'switch-colon-spacing': 'warn', + 'template-curly-spacing': 'warn', + 'yield-star-spacing': 'warn', + + // JSDoc + 'jsdoc/check-alignment': 'warn', + 'jsdoc/check-syntax': 'warn', + 'jsdoc/check-param-names': 'warn', + 'jsdoc/require-hyphen-before-param-description': ['warn', 'never'], + 'jsdoc/check-tag-names': 'warn', + 'jsdoc/check-types': 'warn', + 'jsdoc/empty-tags': 'warn', + 'jsdoc/newline-after-description': 'warn', + 'jsdoc/require-param-name': 'warn', + 'jsdoc/require-property-name': 'warn', + + // regexp + 'regexp/no-dupe-disjunctions': 'error', + 'regexp/no-empty-alternative': 'error', + 'regexp/no-empty-capturing-group': 'error', + 'regexp/no-empty-lookarounds-assertion': 'error', + 'regexp/no-lazy-ends': 'error', + 'regexp/no-obscure-range': 'error', + 'regexp/no-optional-assertion': 'error', + 'regexp/no-standalone-backslash': 'error', + 'regexp/no-super-linear-backtracking': 'error', + 'regexp/no-unused-capturing-group': 'error', + 'regexp/no-zero-quantifier': 'error', + 'regexp/optimal-lookaround-quantifier': 'error', + + 'regexp/match-any': 'warn', + 'regexp/negation': 'warn', + 'regexp/no-dupe-characters-character-class': 'warn', + 'regexp/no-trivially-nested-assertion': 'warn', + 'regexp/no-trivially-nested-quantifier': 'warn', + 'regexp/no-useless-character-class': 'warn', + 'regexp/no-useless-flag': 'warn', + 'regexp/no-useless-lazy': 'warn', + 'regexp/no-useless-range': 'warn', + 'regexp/prefer-d': ['warn', { insideCharacterClass: 'ignore' }], + 'regexp/prefer-plus-quantifier': 'warn', + 'regexp/prefer-question-quantifier': 'warn', + 'regexp/prefer-star-quantifier': 'warn', + 'regexp/prefer-w': 'warn', + 'regexp/sort-alternatives': 'warn', + 'regexp/sort-flags': 'warn', + 'regexp/strict': 'warn', + + // I turned this rule off because we use `hasOwnProperty` in a lot of places + // TODO: Think about re-enabling this rule + 'no-prototype-builtins': 'off', + // TODO: Think about re-enabling this rule + 'no-inner-declarations': 'off', + // TODO: Think about re-enabling this rule + 'no-sparse-arrays': 'off', + + // turning off some regex rules + // these are supposed to protect against accidental use but we need those quite often + 'no-control-regex': 'off', + 'no-empty-character-class': 'off', + 'no-useless-escape': 'off' + }, + settings: { + jsdoc: { mode: 'typescript' }, + regexp: { + // allow alphanumeric and cyrillic ranges + allowedCharacterRanges: ['alphanumeric', 'а-я', 'А-Я'] + } + }, + ignorePatterns: [ + '*.min.js', + 'vendor/', + 'docs/', + 'components.js', + 'prism.js', + 'node_modules' + ], + + overrides: [ + { + // Languages and plugins + files: [ + 'components/*.js', + 'plugins/*/prism-*.js' + ], + excludedFiles: 'components/index.js', + env: { + browser: true, + node: true, + worker: true + }, + globals: { + 'Prism': true, + // Allow Set and Map. They are partially supported by IE11 + 'Set': true, + 'Map': true + }, + rules: { + 'no-var': 'off' + } + }, + { + // `loadLanguages` function for Node.js + files: 'components/index.js', + env: { + es6: true, + node: true + }, + parserOptions: { + ecmaVersion: 6 + }, + globals: { + 'Prism': true + } + }, + { + // Gulp and Danger + files: 'dependencies.js', + env: { + browser: true, + node: true + }, + rules: { + 'no-var': 'off' + } + }, + { + // The scripts that run on our website + files: 'assets/*.js', + env: { + browser: true + }, + globals: { + 'components': true, + 'getLoader': true, + 'PrefixFree': true, + 'Prism': true, + 'Promise': true, + 'saveAs': true, + '$': true, + '$$': true, + '$u': true + }, + rules: { + 'no-var': 'off' + } + }, + { + // Test files + files: 'tests/**', + env: { + es6: true, + mocha: true, + node: true + }, + parserOptions: { + ecmaVersion: 2018 + } + }, + { + // Gulp, Danger, and benchmark + files: [ + 'gulpfile.js/**', + 'dangerfile.js', + 'benchmark/**', + ], + env: { + es6: true, + node: true + }, + parserOptions: { + ecmaVersion: 2018 + } + }, + { + // This file + files: '.eslintrc.js', + env: { + node: true + } + }, + ] +}; diff --git a/.gitattributes b/.gitattributes index 1d598bdc92..176a458f94 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1 @@ * text=auto - -# Test files should not have their line endings modified by git -/tests/languages/**/*.test binary \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..556c3df877 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,26 @@ +--- +name: Bug report +about: Create a report to help us improve. +title: '' +labels: '' +assignees: '' + +--- + +**Information:** +- Prism version: [e.g. 1.14, latest from the download page, etc.] +- Plugins: [a list of plugins you are using or 'none'] +- Environment: [e.g. Browser, Node, Webpack] + + + +**Description** +A clear and concise description of what the bug is and how to reproduce it. +If applicable, add screenshots to help explain your problem. + +**Example** +An example which reproduces the bug. This can be a link to a website, a [JSFiddle](https://jsfiddle.net/), an attached example project, etc. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..5987d5973a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,4 @@ +contact_links: + - name: Questions and Help + url: https://github.com/PrismJS/prism/discussions/categories/q-a + about: This issue tracker is not for support questions. Please refer to the Prism's Discussion tab. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..a077152dd0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest a new feature for Prism. +title: '' +labels: enhancement +assignees: '' + +--- + +**Motivation** +Please explain the problem you're having/why you propose this feature. Ex. I'm always frustrated when [...] + +**Description** +A clear and concise description of what you want to happen. + +**Alternatives** +A clear and concise description of any alternative solutions or features you've considered, if applicable. diff --git a/.github/ISSUE_TEMPLATE/highlighting-bug-report.md b/.github/ISSUE_TEMPLATE/highlighting-bug-report.md new file mode 100644 index 0000000000..1e8c5e6fde --- /dev/null +++ b/.github/ISSUE_TEMPLATE/highlighting-bug-report.md @@ -0,0 +1,38 @@ +--- +name: Highlighting bug report +about: Does Prism highlight parts of your code incorrectly or is a language feature + not supported? +title: '' +labels: language-definitions +assignees: '' + +--- + +**Information** +- Language: [e.g. C++, JavaScript, YAML, etc.] +- Plugins: [a list of plugins you are using or 'none'] + + + +**Description** +A clear and concise description of what is being highlighted incorrectly and how it should be highlighted instead. Add screenshots to illustrate the problem. + +**Code snippet** + + +[Test page]() + +
+The code being highlighted incorrectly. + +``` +Your code goes here +``` + +
diff --git a/.github/ISSUE_TEMPLATE/new-language-request.md b/.github/ISSUE_TEMPLATE/new-language-request.md new file mode 100644 index 0000000000..8b9b8ff70d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new-language-request.md @@ -0,0 +1,14 @@ +--- +name: New language request +about: Suggest a new language Prism should support. +title: '' +labels: language-definitions, new language +assignees: '' + +--- + +**Language** +A short description of the language. + +**Additional resources** +E.g. The official website, documentation or language specification. diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml new file mode 100644 index 0000000000..eda9686de4 --- /dev/null +++ b/.github/workflows/danger.yml @@ -0,0 +1,24 @@ +name: Danger + +on: + pull_request_target: + +jobs: + run: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 0 + # create a new branch called pr from the remote PR branch + - run: git remote add pr_repo $PR_URL && git fetch pr_repo $PR_REF && git branch pr pr_repo/$PR_REF + env: + PR_URL: ${{github.event.pull_request.head.repo.clone_url}} + PR_REF: ${{github.event.pull_request.head.ref}} + - run: npm ci + - name: Danger + run: npx danger ci + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000..f8f4941b8b --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,72 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + tests: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [10.x, 12.x, 14.x, 16.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm test + + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [10.x, 12.x, 14.x, 16.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm run build + - run: | + git add --all && \ + git diff-index --cached HEAD --stat --exit-code || \ + (echo && echo "The above files changed because the build is not up to date." && echo "Please rebuild Prism." && exit 1) + + lint: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14.x + uses: actions/setup-node@v1 + with: + node-version: 14.x + - run: npm ci + - run: npm run lint:ci + + coverage: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14.x + uses: actions/setup-node@v1 + with: + node-version: 14.x + - run: npm ci + - run: npm run regex-coverage diff --git a/.gitignore b/.gitignore index 3b16b7d30c..f3e4015150 100755 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ hide-*.js node_modules .idea/ .DS_Store +.eslintcache + +benchmark/remotes/ +benchmark/downloads/ diff --git a/.jsdoc.json b/.jsdoc.json new file mode 100644 index 0000000000..3d27a4582f --- /dev/null +++ b/.jsdoc.json @@ -0,0 +1,66 @@ +{ + "plugins": [ + "plugins/markdown", + "./gulpfile.js/docs.js" + ], + "opts": { + "destination": "./docs", + "encoding": "utf8", + "template": "./node_modules/docdash", + "access": [ + "public", + "protected" + ] + }, + "recurseDepth": 10, + "source": { + "includePattern": "\\.js$", + "excludePattern": "\\.min\\.js$" + }, + "tags": { + "allowUnknownTags": true, + "dictionaries": [ + "jsdoc", + "closure" + ] + }, + "templates": { + "cleverLinks": true, + "monospaceLinks": true, + "default": { + "includeDate": false + } + }, + "docdash": { + "static": true, + "sort": true, + "search": true, + "collapse": false, + "wrap": false, + "typedefs": true, + "private": false, + "scripts": [ + "styles/overwrites.css" + ], + "openGraph": { + "title": "Prism generated API documentation", + "type": "website", + "image": "/logo.svg", + "site_name": "Prism", + "url": "https://prismjs.com" + }, + "menu": { + "PrismJS": { + "href": "https://prismjs.com", + "class": "menu-item", + "id": "website_link" + }, + "GitHub": { + "href": "https://github.com/PrismJS/prism", + "target": "_blank", + "class": "menu-item", + "id": "github_link" + } + } + } +} diff --git a/.npmignore b/.npmignore index 2ff075c95b..aa4fd97e43 100644 --- a/.npmignore +++ b/.npmignore @@ -2,26 +2,24 @@ *.iml hide-*.js - +.DS_Store CNAME +.github/ +benchmark/ +assets/ +docs/ examples/ -img/ -templates/ tests/ -vendor/ *.tgz *.html -style.css -favicon.png -logo.svg +*.svg bower.json composer.json -download.js -examples.js +dangerfile.js gulpfile.js -prefixfree.min.js -utopia.js -code.js .editorconfig .gitattributes -.travis.yml \ No newline at end of file +.travis.yml +.eslintrc.js +.eslintcache +.jsdoc.json diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3d0c7d1643..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: node_js -node_js: -- '4' -- '6' -- '8' -- '9' -# Build all branches -branches: - only: - - gh-pages - - /.*/ -before_script: -- npm install -g gulp -- gulp -script: npm test -deploy: - provider: npm - email: lea@verou.me - api_key: - secure: TjRcXEr7Y/9KRJ4EOEQbd2Ij8hxKj8c/yOpEROy2lTYv6QH9x46nFDgZEE3VHfp/nnBUYpC47dRaSxiUj8H5rtkMNCZrREZu1n1zahmzP6dI6kCj+H3GiY7yw/Jhdx3uvQZHwknW2TJ/YRsLeQsmMSG2HnJobY9Zn4REX5ccP2E= - on: - tags: true - repo: PrismJS/prism diff --git a/CHANGELOG.md b/CHANGELOG.md index eb11cf858e..6329ab4686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,79 +1,1729 @@ # Prism Changelog + +## 1.27.0 (2022-02-17) + +### New components + +* __UO Razor Script__ (#3309) [`3f8cc5a0`](https://github.com/PrismJS/prism/commit/3f8cc5a0) + +### Updated components + +* __AutoIt__ + * Allow hyphen in directive (#3308) [`bcb2e2c8`](https://github.com/PrismJS/prism/commit/bcb2e2c8) +* __EditorConfig__ + * Change alias of `section` from `keyword` to `selector` (#3305) [`e46501b9`](https://github.com/PrismJS/prism/commit/e46501b9) +* __Ini__ + * Swap out `header` for `section` (#3304) [`deb3a97f`](https://github.com/PrismJS/prism/commit/deb3a97f) +* __MongoDB__ + * Added v5 support (#3297) [`8458c41f`](https://github.com/PrismJS/prism/commit/8458c41f) +* __PureBasic__ + * Added missing keyword and fixed constants ending with `$` (#3320) [`d6c53726`](https://github.com/PrismJS/prism/commit/d6c53726) +* __Scala__ + * Added support for interpolated strings (#3293) [`441a1422`](https://github.com/PrismJS/prism/commit/441a1422) +* __Systemd configuration file__ + * Swap out `operator` for `punctuation` (#3306) [`2eb89e15`](https://github.com/PrismJS/prism/commit/2eb89e15) + +### Updated plugins + +* __Command Line__ + * Escape markup in command line output (#3341) [`e002e78c`](https://github.com/PrismJS/prism/commit/e002e78c) + * Add support for line continuation and improved colors (#3326) [`1784b175`](https://github.com/PrismJS/prism/commit/1784b175) + * Added span around command and output (#3312) [`82d0ca15`](https://github.com/PrismJS/prism/commit/82d0ca15) + +### Other + +* __Core__ + * Added better error message for missing grammars (#3311) [`2cc4660b`](https://github.com/PrismJS/prism/commit/2cc4660b) + +## 1.26.0 (2022-01-06) + +### New components + +* __Atmel AVR Assembly__ ([#2078](https://github.com/PrismJS/prism/issues/2078)) [`b5a70e4c`](https://github.com/PrismJS/prism/commit/b5a70e4c) +* __Go module__ ([#3209](https://github.com/PrismJS/prism/issues/3209)) [`8476a9ab`](https://github.com/PrismJS/prism/commit/8476a9ab) +* __Keepalived Configure__ ([#2417](https://github.com/PrismJS/prism/issues/2417)) [`d908e457`](https://github.com/PrismJS/prism/commit/d908e457) +* __Tremor__ & __Trickle__ & __Troy__ ([#3087](https://github.com/PrismJS/prism/issues/3087)) [`ec25ba65`](https://github.com/PrismJS/prism/commit/ec25ba65) +* __Web IDL__ ([#3107](https://github.com/PrismJS/prism/issues/3107)) [`ef53f021`](https://github.com/PrismJS/prism/commit/ef53f021) + +### Updated components + +* Use `\d` for `[0-9]` ([#3097](https://github.com/PrismJS/prism/issues/3097)) [`9fe2f93e`](https://github.com/PrismJS/prism/commit/9fe2f93e) +* __6502 Assembly__ + * Use standard tokens and minor improvements ([#3184](https://github.com/PrismJS/prism/issues/3184)) [`929c33e0`](https://github.com/PrismJS/prism/commit/929c33e0) +* __AppleScript__ + * Use `class-name` standard token ([#3182](https://github.com/PrismJS/prism/issues/3182)) [`9f5e511d`](https://github.com/PrismJS/prism/commit/9f5e511d) +* __AQL__ + * Differentiate between strings and identifiers ([#3183](https://github.com/PrismJS/prism/issues/3183)) [`fa540ab7`](https://github.com/PrismJS/prism/commit/fa540ab7) +* __Arduino__ + * Added `ino` alias ([#2990](https://github.com/PrismJS/prism/issues/2990)) [`5b7ce5e4`](https://github.com/PrismJS/prism/commit/5b7ce5e4) +* __Avro IDL__ + * Removed char syntax ([#3185](https://github.com/PrismJS/prism/issues/3185)) [`c7809285`](https://github.com/PrismJS/prism/commit/c7809285) +* __Bash__ + * Added `node` to known commands ([#3291](https://github.com/PrismJS/prism/issues/3291)) [`4b19b502`](https://github.com/PrismJS/prism/commit/4b19b502) + * Added `vcpkg` command ([#3282](https://github.com/PrismJS/prism/issues/3282)) [`b351bc69`](https://github.com/PrismJS/prism/commit/b351bc69) + * Added `docker` and `podman` commands ([#3237](https://github.com/PrismJS/prism/issues/3237)) [`8c5ed251`](https://github.com/PrismJS/prism/commit/8c5ed251) +* __Birb__ + * Fixed class name false positives ([#3111](https://github.com/PrismJS/prism/issues/3111)) [`d7017beb`](https://github.com/PrismJS/prism/commit/d7017beb) +* __Bro__ + * Removed `variable` and minor improvements ([#3186](https://github.com/PrismJS/prism/issues/3186)) [`4cebf34c`](https://github.com/PrismJS/prism/commit/4cebf34c) +* __BSL (1C:Enterprise)__ + * Made `directive` greedy ([#3112](https://github.com/PrismJS/prism/issues/3112)) [`5c412cbb`](https://github.com/PrismJS/prism/commit/5c412cbb) +* __C__ + * Added `char` token ([#3207](https://github.com/PrismJS/prism/issues/3207)) [`d85a64ae`](https://github.com/PrismJS/prism/commit/d85a64ae) +* __C#__ + * Added `char` token ([#3270](https://github.com/PrismJS/prism/issues/3270)) [`220bc40f`](https://github.com/PrismJS/prism/commit/220bc40f) + * Move everything into the IIFE ([#3077](https://github.com/PrismJS/prism/issues/3077)) [`9ed4cf6e`](https://github.com/PrismJS/prism/commit/9ed4cf6e) +* __Clojure__ + * Added `char` token ([#3188](https://github.com/PrismJS/prism/issues/3188)) [`1c88c7da`](https://github.com/PrismJS/prism/commit/1c88c7da) +* __Concurnas__ + * Improved tokenization ([#3189](https://github.com/PrismJS/prism/issues/3189)) [`7b34e65d`](https://github.com/PrismJS/prism/commit/7b34e65d) +* __Content-Security-Policy__ + * Improved tokenization ([#3276](https://github.com/PrismJS/prism/issues/3276)) [`a943f2bb`](https://github.com/PrismJS/prism/commit/a943f2bb) +* __Coq__ + * Improved attribute pattern performance ([#3085](https://github.com/PrismJS/prism/issues/3085)) [`2f9672aa`](https://github.com/PrismJS/prism/commit/2f9672aa) +* __Crystal__ + * Improved tokenization ([#3194](https://github.com/PrismJS/prism/issues/3194)) [`51e3ecc0`](https://github.com/PrismJS/prism/commit/51e3ecc0) +* __Cypher__ + * Removed non-standard use of `symbol` token name ([#3195](https://github.com/PrismJS/prism/issues/3195)) [`6af8a644`](https://github.com/PrismJS/prism/commit/6af8a644) +* __D__ + * Added standard char token ([#3196](https://github.com/PrismJS/prism/issues/3196)) [`dafdbdec`](https://github.com/PrismJS/prism/commit/dafdbdec) +* __Dart__ + * Added string interpolation and improved metadata ([#3197](https://github.com/PrismJS/prism/issues/3197)) [`e1370357`](https://github.com/PrismJS/prism/commit/e1370357) +* __DataWeave__ + * Fixed keywords being highlighted as functions ([#3113](https://github.com/PrismJS/prism/issues/3113)) [`532212b2`](https://github.com/PrismJS/prism/commit/532212b2) +* __EditorConfig__ + * Swap out `property` for `key`; alias with `attr-name` ([#3272](https://github.com/PrismJS/prism/issues/3272)) [`bee6ad56`](https://github.com/PrismJS/prism/commit/bee6ad56) +* __Eiffel__ + * Removed non-standard use of `builtin` name ([#3198](https://github.com/PrismJS/prism/issues/3198)) [`6add768b`](https://github.com/PrismJS/prism/commit/6add768b) +* __Elm__ + * Recognize unicode escapes as valid Char ([#3105](https://github.com/PrismJS/prism/issues/3105)) [`736c581d`](https://github.com/PrismJS/prism/commit/736c581d) +* __ERB__ + * Better embedding of Ruby ([#3192](https://github.com/PrismJS/prism/issues/3192)) [`336edeea`](https://github.com/PrismJS/prism/commit/336edeea) +* __F#__ + * Added `char` token ([#3271](https://github.com/PrismJS/prism/issues/3271)) [`b58cd722`](https://github.com/PrismJS/prism/commit/b58cd722) +* __G-code__ + * Use standard-conforming alias for checksum ([#3205](https://github.com/PrismJS/prism/issues/3205)) [`ee7ab563`](https://github.com/PrismJS/prism/commit/ee7ab563) +* __GameMaker Language__ + * Fixed `operator` token and added tests ([#3114](https://github.com/PrismJS/prism/issues/3114)) [`d359eeae`](https://github.com/PrismJS/prism/commit/d359eeae) +* __Go__ + * Added `char` token and improved `string` and `number` tokens ([#3208](https://github.com/PrismJS/prism/issues/3208)) [`f11b86e2`](https://github.com/PrismJS/prism/commit/f11b86e2) +* __GraphQL__ + * Optimized regexes ([#3136](https://github.com/PrismJS/prism/issues/3136)) [`8494519e`](https://github.com/PrismJS/prism/commit/8494519e) +* __Haml__ + * Use `symbol` alias for filter names ([#3210](https://github.com/PrismJS/prism/issues/3210)) [`3d410670`](https://github.com/PrismJS/prism/commit/3d410670) + * Improved filter and interpolation tokenization ([#3191](https://github.com/PrismJS/prism/issues/3191)) [`005ba469`](https://github.com/PrismJS/prism/commit/005ba469) +* __Haxe__ + * Improved tokenization ([#3211](https://github.com/PrismJS/prism/issues/3211)) [`f41bcf23`](https://github.com/PrismJS/prism/commit/f41bcf23) +* __Hoon__ + * Simplified the language definition a little ([#3212](https://github.com/PrismJS/prism/issues/3212)) [`81920b62`](https://github.com/PrismJS/prism/commit/81920b62) +* __HTTP__ + * Added support for special header value tokenization ([#3275](https://github.com/PrismJS/prism/issues/3275)) [`3362fc79`](https://github.com/PrismJS/prism/commit/3362fc79) + * Relax pattern for body ([#3169](https://github.com/PrismJS/prism/issues/3169)) [`22d0c6ba`](https://github.com/PrismJS/prism/commit/22d0c6ba) +* __HTTP Public-Key-Pins__ + * Improved tokenization ([#3278](https://github.com/PrismJS/prism/issues/3278)) [`0f1b5810`](https://github.com/PrismJS/prism/commit/0f1b5810) +* __HTTP Strict-Transport-Security__ + * Improved tokenization ([#3277](https://github.com/PrismJS/prism/issues/3277)) [`3d708b97`](https://github.com/PrismJS/prism/commit/3d708b97) +* __Idris__ + * Fixed import statements ([#3115](https://github.com/PrismJS/prism/issues/3115)) [`15cb3b78`](https://github.com/PrismJS/prism/commit/15cb3b78) +* __Io__ + * Simplified comment token ([#3214](https://github.com/PrismJS/prism/issues/3214)) [`c2afa59b`](https://github.com/PrismJS/prism/commit/c2afa59b) +* __J__ + * Made comments greedy ([#3215](https://github.com/PrismJS/prism/issues/3215)) [`5af16014`](https://github.com/PrismJS/prism/commit/5af16014) +* __Java__ + * Added `char` token ([#3217](https://github.com/PrismJS/prism/issues/3217)) [`0a9f909c`](https://github.com/PrismJS/prism/commit/0a9f909c) +* __Java stack trace__ + * Removed unreachable parts of regexes ([#3219](https://github.com/PrismJS/prism/issues/3219)) [`fa55492b`](https://github.com/PrismJS/prism/commit/fa55492b) + * Added missing lookbehinds ([#3116](https://github.com/PrismJS/prism/issues/3116)) [`cfb2e782`](https://github.com/PrismJS/prism/commit/cfb2e782) +* __JavaScript__ + * Improved `number` pattern ([#3149](https://github.com/PrismJS/prism/issues/3149)) [`5a24cbff`](https://github.com/PrismJS/prism/commit/5a24cbff) + * Added properties ([#3099](https://github.com/PrismJS/prism/issues/3099)) [`3b2238fa`](https://github.com/PrismJS/prism/commit/3b2238fa) +* __Jolie__ + * Improved tokenization ([#3221](https://github.com/PrismJS/prism/issues/3221)) [`dfbb2020`](https://github.com/PrismJS/prism/commit/dfbb2020) +* __JQ__ + * Improved performance of strings ([#3084](https://github.com/PrismJS/prism/issues/3084)) [`233415b8`](https://github.com/PrismJS/prism/commit/233415b8) +* __JS stack trace__ + * Added missing boundary assertion ([#3117](https://github.com/PrismJS/prism/issues/3117)) [`23d9aec1`](https://github.com/PrismJS/prism/commit/23d9aec1) +* __Julia__ + * Added `char` token ([#3223](https://github.com/PrismJS/prism/issues/3223)) [`3a876df0`](https://github.com/PrismJS/prism/commit/3a876df0) +* __Keyman__ + * Improved tokenization ([#3224](https://github.com/PrismJS/prism/issues/3224)) [`baa95cab`](https://github.com/PrismJS/prism/commit/baa95cab) +* __Kotlin__ + * Added `char` token and improved string interpolation ([#3225](https://github.com/PrismJS/prism/issues/3225)) [`563cd73e`](https://github.com/PrismJS/prism/commit/563cd73e) +* __Latte__ + * Use standard token names and combined delimiter tokens ([#3226](https://github.com/PrismJS/prism/issues/3226)) [`6b168a3b`](https://github.com/PrismJS/prism/commit/6b168a3b) +* __Liquid__ + * Removed unmatchable object variants ([#3135](https://github.com/PrismJS/prism/issues/3135)) [`05e7ab04`](https://github.com/PrismJS/prism/commit/05e7ab04) +* __Lisp__ + * Improved `defun` ([#3130](https://github.com/PrismJS/prism/issues/3130)) [`e8f84a6c`](https://github.com/PrismJS/prism/commit/e8f84a6c) +* __Makefile__ + * Use standard token names correctly ([#3227](https://github.com/PrismJS/prism/issues/3227)) [`21a3c2d7`](https://github.com/PrismJS/prism/commit/21a3c2d7) +* __Markdown__ + * Fixed typo in token name ([#3101](https://github.com/PrismJS/prism/issues/3101)) [`00f77a2c`](https://github.com/PrismJS/prism/commit/00f77a2c) +* __MAXScript__ + * Various improvements ([#3181](https://github.com/PrismJS/prism/issues/3181)) [`e9b856c8`](https://github.com/PrismJS/prism/commit/e9b856c8) + * Fixed booleans not being highlighted ([#3134](https://github.com/PrismJS/prism/issues/3134)) [`c6574e6b`](https://github.com/PrismJS/prism/commit/c6574e6b) +* __Monkey__ + * Use standard tokens correctly ([#3228](https://github.com/PrismJS/prism/issues/3228)) [`c1025aa6`](https://github.com/PrismJS/prism/commit/c1025aa6) +* __N1QL__ + * Updated keywords + minor improvements ([#3229](https://github.com/PrismJS/prism/issues/3229)) [`642d93ec`](https://github.com/PrismJS/prism/commit/642d93ec) +* __nginx__ + * Made some patterns greedy ([#3230](https://github.com/PrismJS/prism/issues/3230)) [`7b72e0ad`](https://github.com/PrismJS/prism/commit/7b72e0ad) +* __Nim__ + * Added `char` token and made some tokens greedy ([#3231](https://github.com/PrismJS/prism/issues/3231)) [`2334b4b6`](https://github.com/PrismJS/prism/commit/2334b4b6) + * Fixed backtick identifier ([#3118](https://github.com/PrismJS/prism/issues/3118)) [`75331bea`](https://github.com/PrismJS/prism/commit/75331bea) +* __Nix__ + * Use standard token name correctly ([#3232](https://github.com/PrismJS/prism/issues/3232)) [`5bf6e35f`](https://github.com/PrismJS/prism/commit/5bf6e35f) + * Removed unmatchable token ([#3119](https://github.com/PrismJS/prism/issues/3119)) [`dc1e808f`](https://github.com/PrismJS/prism/commit/dc1e808f) +* __NSIS__ + * Made `comment` greedy ([#3234](https://github.com/PrismJS/prism/issues/3234)) [`969f152a`](https://github.com/PrismJS/prism/commit/969f152a) + * Update regex pattern for variables ([#3266](https://github.com/PrismJS/prism/issues/3266)) [`adcc8784`](https://github.com/PrismJS/prism/commit/adcc8784) + * Update regex for constants pattern ([#3267](https://github.com/PrismJS/prism/issues/3267)) [`55583fb2`](https://github.com/PrismJS/prism/commit/55583fb2) +* __Objective-C__ + * Improved `string` token ([#3235](https://github.com/PrismJS/prism/issues/3235)) [`8e0e95f3`](https://github.com/PrismJS/prism/commit/8e0e95f3) +* __OCaml__ + * Improved tokenization ([#3269](https://github.com/PrismJS/prism/issues/3269)) [`7bcc5da0`](https://github.com/PrismJS/prism/commit/7bcc5da0) + * Removed unmatchable punctuation variant ([#3120](https://github.com/PrismJS/prism/issues/3120)) [`314d6994`](https://github.com/PrismJS/prism/commit/314d6994) +* __Oz__ + * Improved tokenization ([#3240](https://github.com/PrismJS/prism/issues/3240)) [`a3905c04`](https://github.com/PrismJS/prism/commit/a3905c04) +* __Pascal__ + * Added support for asm and directives ([#2653](https://github.com/PrismJS/prism/issues/2653)) [`f053af13`](https://github.com/PrismJS/prism/commit/f053af13) +* __PATROL Scripting Language__ + * Added `boolean` token ([#3248](https://github.com/PrismJS/prism/issues/3248)) [`a5b6c5eb`](https://github.com/PrismJS/prism/commit/a5b6c5eb) +* __Perl__ + * Improved tokenization ([#3241](https://github.com/PrismJS/prism/issues/3241)) [`f22ea9f9`](https://github.com/PrismJS/prism/commit/f22ea9f9) +* __PHP__ + * Removed useless keyword tokens ([#3121](https://github.com/PrismJS/prism/issues/3121)) [`ee62a080`](https://github.com/PrismJS/prism/commit/ee62a080) +* __PHP Extras__ + * Improved `scope` and `this` ([#3243](https://github.com/PrismJS/prism/issues/3243)) [`59ef51db`](https://github.com/PrismJS/prism/commit/59ef51db) +* __PL/SQL__ + * Updated keywords + other improvements ([#3109](https://github.com/PrismJS/prism/issues/3109)) [`e7ba877b`](https://github.com/PrismJS/prism/commit/e7ba877b) +* __PowerQuery__ + * Improved tokenization and use standard tokens correctly ([#3244](https://github.com/PrismJS/prism/issues/3244)) [`5688f487`](https://github.com/PrismJS/prism/commit/5688f487) + * Removed useless `data-type` alternative ([#3122](https://github.com/PrismJS/prism/issues/3122)) [`eeb13996`](https://github.com/PrismJS/prism/commit/eeb13996) +* __PowerShell__ + * Fixed lookbehind + refactoring ([#3245](https://github.com/PrismJS/prism/issues/3245)) [`d30a2da6`](https://github.com/PrismJS/prism/commit/d30a2da6) +* __Processing__ + * Use standard tokens correctly ([#3246](https://github.com/PrismJS/prism/issues/3246)) [`5ee8c557`](https://github.com/PrismJS/prism/commit/5ee8c557) +* __Prolog__ + * Removed variable token + minor improvements ([#3247](https://github.com/PrismJS/prism/issues/3247)) [`bacf9ae3`](https://github.com/PrismJS/prism/commit/bacf9ae3) +* __Pug__ + * Improved filter tokenization ([#3258](https://github.com/PrismJS/prism/issues/3258)) [`0390e644`](https://github.com/PrismJS/prism/commit/0390e644) +* __PureBasic__ + * Fixed token order inside `asm` token ([#3123](https://github.com/PrismJS/prism/issues/3123)) [`f3b25786`](https://github.com/PrismJS/prism/commit/f3b25786) +* __Python__ + * Made `comment` greedy ([#3249](https://github.com/PrismJS/prism/issues/3249)) [`8ecef306`](https://github.com/PrismJS/prism/commit/8ecef306) + * Add `match` and `case` (soft) keywords ([#3142](https://github.com/PrismJS/prism/issues/3142)) [`3f24dc72`](https://github.com/PrismJS/prism/commit/3f24dc72) + * Recognize walrus operator ([#3126](https://github.com/PrismJS/prism/issues/3126)) [`18bd101c`](https://github.com/PrismJS/prism/commit/18bd101c) + * Fixed numbers ending with a dot ([#3106](https://github.com/PrismJS/prism/issues/3106)) [`2c63efa6`](https://github.com/PrismJS/prism/commit/2c63efa6) +* __QML__ + * Made `string` greedy ([#3250](https://github.com/PrismJS/prism/issues/3250)) [`1e6dcb51`](https://github.com/PrismJS/prism/commit/1e6dcb51) +* __React JSX__ + * Move alias property ([#3222](https://github.com/PrismJS/prism/issues/3222)) [`18c92048`](https://github.com/PrismJS/prism/commit/18c92048) +* __React TSX__ + * Removed `parameter` token ([#3090](https://github.com/PrismJS/prism/issues/3090)) [`0a313f4f`](https://github.com/PrismJS/prism/commit/0a313f4f) +* __Reason__ + * Use standard tokens correctly ([#3251](https://github.com/PrismJS/prism/issues/3251)) [`809af0d9`](https://github.com/PrismJS/prism/commit/809af0d9) +* __Regex__ + * Fixed char-class/char-set confusion ([#3124](https://github.com/PrismJS/prism/issues/3124)) [`4dde2e20`](https://github.com/PrismJS/prism/commit/4dde2e20) +* __Ren'py__ + * Improved language + added tests ([#3125](https://github.com/PrismJS/prism/issues/3125)) [`ede55b2c`](https://github.com/PrismJS/prism/commit/ede55b2c) +* __Rip__ + * Use standard `char` token ([#3252](https://github.com/PrismJS/prism/issues/3252)) [`2069ab0c`](https://github.com/PrismJS/prism/commit/2069ab0c) +* __Ruby__ + * Improved tokenization ([#3193](https://github.com/PrismJS/prism/issues/3193)) [`86028adb`](https://github.com/PrismJS/prism/commit/86028adb) +* __Rust__ + * Improved `type-definition` and use standard tokens correctly ([#3253](https://github.com/PrismJS/prism/issues/3253)) [`4049e5c6`](https://github.com/PrismJS/prism/commit/4049e5c6) +* __Scheme__ + * Use standard `char` token ([#3254](https://github.com/PrismJS/prism/issues/3254)) [`7d740c45`](https://github.com/PrismJS/prism/commit/7d740c45) + * Updates syntax for reals ([#3159](https://github.com/PrismJS/prism/issues/3159)) [`4eb81fa1`](https://github.com/PrismJS/prism/commit/4eb81fa1) +* __Smalltalk__ + * Use standard `char` token ([#3255](https://github.com/PrismJS/prism/issues/3255)) [`a7bb3001`](https://github.com/PrismJS/prism/commit/a7bb3001) + * Added `boolean` token ([#3100](https://github.com/PrismJS/prism/issues/3100)) [`51382524`](https://github.com/PrismJS/prism/commit/51382524) +* __Smarty__ + * Improved tokenization ([#3268](https://github.com/PrismJS/prism/issues/3268)) [`acc0bc09`](https://github.com/PrismJS/prism/commit/acc0bc09) +* __SQL__ + * Added identifier token ([#3141](https://github.com/PrismJS/prism/issues/3141)) [`4e00cddd`](https://github.com/PrismJS/prism/commit/4e00cddd) +* __Squirrel__ + * Use standard `char` token ([#3256](https://github.com/PrismJS/prism/issues/3256)) [`58a65bfd`](https://github.com/PrismJS/prism/commit/58a65bfd) +* __Stan__ + * Added missing keywords and HOFs ([#3238](https://github.com/PrismJS/prism/issues/3238)) [`afd77ed1`](https://github.com/PrismJS/prism/commit/afd77ed1) +* __Structured Text (IEC 61131-3)__ + * Structured text: Improved tokenization ([#3213](https://github.com/PrismJS/prism/issues/3213)) [`d04d166d`](https://github.com/PrismJS/prism/commit/d04d166d) +* __Swift__ + * Added support for `isolated` keyword ([#3174](https://github.com/PrismJS/prism/issues/3174)) [`18c828a6`](https://github.com/PrismJS/prism/commit/18c828a6) +* __TAP__ + * Conform to quoted-properties style ([#3127](https://github.com/PrismJS/prism/issues/3127)) [`3ef71533`](https://github.com/PrismJS/prism/commit/3ef71533) +* __Tremor__ + * Use standard `regex` token ([#3257](https://github.com/PrismJS/prism/issues/3257)) [`c56e4bf5`](https://github.com/PrismJS/prism/commit/c56e4bf5) +* __Twig__ + * Improved tokenization ([#3259](https://github.com/PrismJS/prism/issues/3259)) [`e03a7c24`](https://github.com/PrismJS/prism/commit/e03a7c24) +* __TypeScript__ + * Removed duplicate keywords ([#3132](https://github.com/PrismJS/prism/issues/3132)) [`91060fd6`](https://github.com/PrismJS/prism/commit/91060fd6) +* __URI__ + * Fixed IPv4 regex ([#3128](https://github.com/PrismJS/prism/issues/3128)) [`599e30ee`](https://github.com/PrismJS/prism/commit/599e30ee) +* __V__ + * Use standard `char` token ([#3260](https://github.com/PrismJS/prism/issues/3260)) [`e4373256`](https://github.com/PrismJS/prism/commit/e4373256) +* __Verilog__ + * Use standard tokens correctly ([#3261](https://github.com/PrismJS/prism/issues/3261)) [`43124129`](https://github.com/PrismJS/prism/commit/43124129) +* __Visual Basic__ + * Simplify regexes and use more common aliases ([#3262](https://github.com/PrismJS/prism/issues/3262)) [`aa73d448`](https://github.com/PrismJS/prism/commit/aa73d448) +* __Wolfram language__ + * Removed unmatchable punctuation variant ([#3133](https://github.com/PrismJS/prism/issues/3133)) [`a28a86ad`](https://github.com/PrismJS/prism/commit/a28a86ad) +* __Xojo (REALbasic)__ + * Proper token name for directives ([#3263](https://github.com/PrismJS/prism/issues/3263)) [`ffd8343f`](https://github.com/PrismJS/prism/commit/ffd8343f) +* __Zig__ + * Added missing keywords ([#3279](https://github.com/PrismJS/prism/issues/3279)) [`deed35e3`](https://github.com/PrismJS/prism/commit/deed35e3) + * Use standard `char` token ([#3264](https://github.com/PrismJS/prism/issues/3264)) [`c3f9fb70`](https://github.com/PrismJS/prism/commit/c3f9fb70) + * Fixed module comments and astral chars ([#3129](https://github.com/PrismJS/prism/issues/3129)) [`09a0e2ba`](https://github.com/PrismJS/prism/commit/09a0e2ba) + +### Updated plugins + +* __File Highlight__ + * File highlight+data range ([#1813](https://github.com/PrismJS/prism/issues/1813)) [`d38592c5`](https://github.com/PrismJS/prism/commit/d38592c5) +* __Keep Markup__ + * Added `drop-tokens` option class ([#3166](https://github.com/PrismJS/prism/issues/3166)) [`b679cfe6`](https://github.com/PrismJS/prism/commit/b679cfe6) +* __Line Highlight__ + * Expose `highlightLines` function as `Prism.plugins.highlightLines` ([#3086](https://github.com/PrismJS/prism/issues/3086)) [`9f4c0e74`](https://github.com/PrismJS/prism/commit/9f4c0e74) +* __Toolbar__ + * Set `z-index` of `.toolbar` to 10 ([#3163](https://github.com/PrismJS/prism/issues/3163)) [`1cac3559`](https://github.com/PrismJS/prism/commit/1cac3559) + +### Updated themes + +* Coy: Set `z-index` to make shadows visible in colored table cells ([#3161](https://github.com/PrismJS/prism/issues/3161)) [`79f250f3`](https://github.com/PrismJS/prism/commit/79f250f3) +* Coy: Added padding to account for box shadow ([#3143](https://github.com/PrismJS/prism/issues/3143)) [`a6a4ce7e`](https://github.com/PrismJS/prism/commit/a6a4ce7e) + +### Other + +* __Core__ + * Added `setLanguage` util function ([#3167](https://github.com/PrismJS/prism/issues/3167)) [`b631949a`](https://github.com/PrismJS/prism/commit/b631949a) + * Fixed type error on null ([#3057](https://github.com/PrismJS/prism/issues/3057)) [`a80a68ba`](https://github.com/PrismJS/prism/commit/a80a68ba) + * Document `disableWorkerMessageHandler` ([#3088](https://github.com/PrismJS/prism/issues/3088)) [`213cf7be`](https://github.com/PrismJS/prism/commit/213cf7be) +* __Infrastructure__ + * Tests: Added `.html.test` files for replace `.js` language tests ([#3148](https://github.com/PrismJS/prism/issues/3148)) [`2e834c8c`](https://github.com/PrismJS/prism/commit/2e834c8c) + * Added regex coverage ([#3138](https://github.com/PrismJS/prism/issues/3138)) [`5333e281`](https://github.com/PrismJS/prism/commit/5333e281) + * Tests: Added `TestCaseFile` class and generalized `runTestCase` ([#3147](https://github.com/PrismJS/prism/issues/3147)) [`ae8888a0`](https://github.com/PrismJS/prism/commit/ae8888a0) + * Added even more language tests ([#3137](https://github.com/PrismJS/prism/issues/3137)) [`344d0b27`](https://github.com/PrismJS/prism/commit/344d0b27) + * Added more plugin tests ([#1969](https://github.com/PrismJS/prism/issues/1969)) [`a394a14d`](https://github.com/PrismJS/prism/commit/a394a14d) + * Added more language tests ([#3131](https://github.com/PrismJS/prism/issues/3131)) [`2f7f7364`](https://github.com/PrismJS/prism/commit/2f7f7364) + * `package.json`: Added `engines.node` field ([#3108](https://github.com/PrismJS/prism/issues/3108)) [`798ee4f6`](https://github.com/PrismJS/prism/commit/798ee4f6) + * Use tabs in `package(-lock).json` ([#3098](https://github.com/PrismJS/prism/issues/3098)) [`8daebb4a`](https://github.com/PrismJS/prism/commit/8daebb4a) + * Update `eslint-plugin-regexp@1.2.0` ([#3091](https://github.com/PrismJS/prism/issues/3091)) [`e6e1d5ae`](https://github.com/PrismJS/prism/commit/e6e1d5ae) + * Added minified CSS ([#3073](https://github.com/PrismJS/prism/issues/3073)) [`d63d6c0e`](https://github.com/PrismJS/prism/commit/d63d6c0e) +* __Website__ + * Readme: Clarify usage of our build system ([#3239](https://github.com/PrismJS/prism/issues/3239)) [`6f1d904a`](https://github.com/PrismJS/prism/commit/6f1d904a) + * Improved CDN usage URLs ([#3285](https://github.com/PrismJS/prism/issues/3285)) [`6c21b2f7`](https://github.com/PrismJS/prism/commit/6c21b2f7) + * Update download.html [`9d5424b6`](https://github.com/PrismJS/prism/commit/9d5424b6) + * Autoloader: Mention how to load grammars from URLs ([#3218](https://github.com/PrismJS/prism/issues/3218)) [`cefccdd1`](https://github.com/PrismJS/prism/commit/cefccdd1) + * Added PrismJS React and HTML tutorial link ([#3190](https://github.com/PrismJS/prism/issues/3190)) [`0ecdbdce`](https://github.com/PrismJS/prism/commit/0ecdbdce) + * Improved readability ([#3177](https://github.com/PrismJS/prism/issues/3177)) [`4433d7fe`](https://github.com/PrismJS/prism/commit/4433d7fe) + * Fixed red highlighting in Firefox ([#3178](https://github.com/PrismJS/prism/issues/3178)) [`746da79b`](https://github.com/PrismJS/prism/commit/746da79b) + * Use Keep markup to highlight code section ([#3164](https://github.com/PrismJS/prism/issues/3164)) [`ebd59e32`](https://github.com/PrismJS/prism/commit/ebd59e32) + * Document standard tokens and provide examples ([#3104](https://github.com/PrismJS/prism/issues/3104)) [`37551200`](https://github.com/PrismJS/prism/commit/37551200) + * Fixed dead link to third-party tutorial [#3155](https://github.com/PrismJS/prism/issues/3155) ([#3156](https://github.com/PrismJS/prism/issues/3156)) [`31b4c1b8`](https://github.com/PrismJS/prism/commit/31b4c1b8) + * Repositioned theme selector ([#3146](https://github.com/PrismJS/prism/issues/3146)) [`ea361e5a`](https://github.com/PrismJS/prism/commit/ea361e5a) + * Adjusted TOC's line height for better readability ([#3145](https://github.com/PrismJS/prism/issues/3145)) [`c5629706`](https://github.com/PrismJS/prism/commit/c5629706) + * Updated plugin header template ([#3144](https://github.com/PrismJS/prism/issues/3144)) [`faedfe85`](https://github.com/PrismJS/prism/commit/faedfe85) + * Update test and example pages to use Autoloader ([#1936](https://github.com/PrismJS/prism/issues/1936)) [`3d96eedc`](https://github.com/PrismJS/prism/commit/3d96eedc) + +## 1.25.0 (2021-09-16) + +### New components + +* __AviSynth__ ([#3071](https://github.com/PrismJS/prism/issues/3071)) [`746a4b1a`](https://github.com/PrismJS/prism/commit/746a4b1a) +* __Avro IDL__ ([#3051](https://github.com/PrismJS/prism/issues/3051)) [`87e5a376`](https://github.com/PrismJS/prism/commit/87e5a376) +* __Bicep__ ([#3027](https://github.com/PrismJS/prism/issues/3027)) [`c1dce998`](https://github.com/PrismJS/prism/commit/c1dce998) +* __GAP (CAS)__ ([#3054](https://github.com/PrismJS/prism/issues/3054)) [`23cd9b65`](https://github.com/PrismJS/prism/commit/23cd9b65) +* __GN__ ([#3062](https://github.com/PrismJS/prism/issues/3062)) [`4f97b82b`](https://github.com/PrismJS/prism/commit/4f97b82b) +* __Hoon__ ([#2978](https://github.com/PrismJS/prism/issues/2978)) [`ea776756`](https://github.com/PrismJS/prism/commit/ea776756) +* __Kusto__ ([#3068](https://github.com/PrismJS/prism/issues/3068)) [`e008ea05`](https://github.com/PrismJS/prism/commit/e008ea05) +* __Magma (CAS)__ ([#3055](https://github.com/PrismJS/prism/issues/3055)) [`a1b67ce3`](https://github.com/PrismJS/prism/commit/a1b67ce3) +* __MAXScript__ ([#3060](https://github.com/PrismJS/prism/issues/3060)) [`4fbdd2f8`](https://github.com/PrismJS/prism/commit/4fbdd2f8) +* __Mermaid__ ([#3050](https://github.com/PrismJS/prism/issues/3050)) [`148c1eca`](https://github.com/PrismJS/prism/commit/148c1eca) +* __Razor C#__ ([#3064](https://github.com/PrismJS/prism/issues/3064)) [`4433ccfc`](https://github.com/PrismJS/prism/commit/4433ccfc) +* __Systemd configuration file__ ([#3053](https://github.com/PrismJS/prism/issues/3053)) [`8df825e0`](https://github.com/PrismJS/prism/commit/8df825e0) +* __Wren__ ([#3063](https://github.com/PrismJS/prism/issues/3063)) [`6a356d25`](https://github.com/PrismJS/prism/commit/6a356d25) + +### Updated components + +* __Bicep__ + * Added support for multiline and interpolated strings and other improvements ([#3028](https://github.com/PrismJS/prism/issues/3028)) [`748bb9ac`](https://github.com/PrismJS/prism/commit/748bb9ac) +* __C#__ + * Added `with` keyword & improved record support ([#2993](https://github.com/PrismJS/prism/issues/2993)) [`fdd291c0`](https://github.com/PrismJS/prism/commit/fdd291c0) + * Added `record`, `init`, and `nullable` keyword ([#2991](https://github.com/PrismJS/prism/issues/2991)) [`9b561565`](https://github.com/PrismJS/prism/commit/9b561565) + * Added context check for `from` keyword ([#2970](https://github.com/PrismJS/prism/issues/2970)) [`158f25d4`](https://github.com/PrismJS/prism/commit/158f25d4) +* __C++__ + * Fixed generic function false positive ([#3043](https://github.com/PrismJS/prism/issues/3043)) [`5de8947f`](https://github.com/PrismJS/prism/commit/5de8947f) +* __Clojure__ + * Improved tokenization ([#3056](https://github.com/PrismJS/prism/issues/3056)) [`8d0b74b5`](https://github.com/PrismJS/prism/commit/8d0b74b5) +* __Hoon__ + * Fixed mixed-case aura tokenization ([#3002](https://github.com/PrismJS/prism/issues/3002)) [`9c8911bd`](https://github.com/PrismJS/prism/commit/9c8911bd) +* __Liquid__ + * Added all objects from Shopify reference ([#2998](https://github.com/PrismJS/prism/issues/2998)) [`693b7433`](https://github.com/PrismJS/prism/commit/693b7433) + * Added `empty` keyword ([#2997](https://github.com/PrismJS/prism/issues/2997)) [`fe3bc526`](https://github.com/PrismJS/prism/commit/fe3bc526) +* __Log file__ + * Added support for Java stack traces ([#3003](https://github.com/PrismJS/prism/issues/3003)) [`b0365e70`](https://github.com/PrismJS/prism/commit/b0365e70) +* __Markup__ + * Made most patterns greedy ([#3065](https://github.com/PrismJS/prism/issues/3065)) [`52e8cee9`](https://github.com/PrismJS/prism/commit/52e8cee9) + * Fixed ReDoS ([#3078](https://github.com/PrismJS/prism/issues/3078)) [`0ff371bb`](https://github.com/PrismJS/prism/commit/0ff371bb) +* __PureScript__ + * Made `∀` a keyword (alias for `forall`) ([#3005](https://github.com/PrismJS/prism/issues/3005)) [`b38fc89a`](https://github.com/PrismJS/prism/commit/b38fc89a) + * Improved Haskell and PureScript ([#3020](https://github.com/PrismJS/prism/issues/3020)) [`679539ec`](https://github.com/PrismJS/prism/commit/679539ec) +* __Python__ + * Support for underscores in numbers ([#3039](https://github.com/PrismJS/prism/issues/3039)) [`6f5d68f7`](https://github.com/PrismJS/prism/commit/6f5d68f7) +* __Sass__ + * Fixed issues with CSS Extras ([#2994](https://github.com/PrismJS/prism/issues/2994)) [`14fdfe32`](https://github.com/PrismJS/prism/commit/14fdfe32) +* __Shell session__ + * Fixed command false positives ([#3048](https://github.com/PrismJS/prism/issues/3048)) [`35b88fcf`](https://github.com/PrismJS/prism/commit/35b88fcf) + * Added support for the percent sign as shell symbol ([#3010](https://github.com/PrismJS/prism/issues/3010)) [`4492b62b`](https://github.com/PrismJS/prism/commit/4492b62b) +* __Swift__ + * Major improvements ([#3022](https://github.com/PrismJS/prism/issues/3022)) [`8541db2e`](https://github.com/PrismJS/prism/commit/8541db2e) + * Added support for `@propertyWrapper`, `@MainActor`, and `@globalActor` ([#3009](https://github.com/PrismJS/prism/issues/3009)) [`ce5e0f01`](https://github.com/PrismJS/prism/commit/ce5e0f01) + * Added support for new Swift 5.5 keywords ([#2988](https://github.com/PrismJS/prism/issues/2988)) [`bb93fac0`](https://github.com/PrismJS/prism/commit/bb93fac0) +* __TypeScript__ + * Fixed keyword false positives ([#3001](https://github.com/PrismJS/prism/issues/3001)) [`212e0ef2`](https://github.com/PrismJS/prism/commit/212e0ef2) + +### Updated plugins + +* __JSONP Highlight__ + * Refactored JSONP logic ([#3018](https://github.com/PrismJS/prism/issues/3018)) [`5126d1e1`](https://github.com/PrismJS/prism/commit/5126d1e1) +* __Line Highlight__ + * Extend highlight to full line width inside scroll container ([#3011](https://github.com/PrismJS/prism/issues/3011)) [`e289ec60`](https://github.com/PrismJS/prism/commit/e289ec60) +* __Normalize Whitespace__ + * Removed unnecessary checks ([#3017](https://github.com/PrismJS/prism/issues/3017)) [`63edf14c`](https://github.com/PrismJS/prism/commit/63edf14c) +* __Previewers__ + * Ensure popup is visible across themes ([#3080](https://github.com/PrismJS/prism/issues/3080)) [`c7b6a7f6`](https://github.com/PrismJS/prism/commit/c7b6a7f6) + +### Updated themes + +* __Twilight__ + * Increase selector specificities of plugin overrides ([#3081](https://github.com/PrismJS/prism/issues/3081)) [`ffb20439`](https://github.com/PrismJS/prism/commit/ffb20439) + +### Other + +* __Infrastructure__ + * Added benchmark suite ([#2153](https://github.com/PrismJS/prism/issues/2153)) [`44456b21`](https://github.com/PrismJS/prism/commit/44456b21) + * Tests: Insert expected JSON by Default ([#2960](https://github.com/PrismJS/prism/issues/2960)) [`e997dd35`](https://github.com/PrismJS/prism/commit/e997dd35) + * Tests: Improved dection of empty patterns ([#3058](https://github.com/PrismJS/prism/issues/3058)) [`d216e602`](https://github.com/PrismJS/prism/commit/d216e602) +* __Website__ + * Highlight Keywords: More documentation ([#3049](https://github.com/PrismJS/prism/issues/3049)) [`247fd9a3`](https://github.com/PrismJS/prism/commit/247fd9a3) + + +## 1.24.1 (2021-07-03) + +### Updated components + +* __Markdown__ + * Fixed Markdown not working in NodeJS ([#2977](https://github.com/PrismJS/prism/issues/2977)) [`151121cd`](https://github.com/PrismJS/prism/commit/151121cd) + +### Updated plugins + +* __Toolbar__ + * Fixed styles being applies to nested elements ([#2980](https://github.com/PrismJS/prism/issues/2980)) [`748ecddc`](https://github.com/PrismJS/prism/commit/748ecddc) + + +## 1.24.0 (2021-06-27) + +### New components + +* __CFScript__ ([#2771](https://github.com/PrismJS/prism/issues/2771)) [`b0a6ec85`](https://github.com/PrismJS/prism/commit/b0a6ec85) +* __ChaiScript__ ([#2706](https://github.com/PrismJS/prism/issues/2706)) [`3f7d7453`](https://github.com/PrismJS/prism/commit/3f7d7453) +* __COBOL__ ([#2800](https://github.com/PrismJS/prism/issues/2800)) [`7e5f78ff`](https://github.com/PrismJS/prism/commit/7e5f78ff) +* __Coq__ ([#2803](https://github.com/PrismJS/prism/issues/2803)) [`41e25d3c`](https://github.com/PrismJS/prism/commit/41e25d3c) +* __CSV__ ([#2794](https://github.com/PrismJS/prism/issues/2794)) [`f9b69528`](https://github.com/PrismJS/prism/commit/f9b69528) +* __DOT (Graphviz)__ ([#2690](https://github.com/PrismJS/prism/issues/2690)) [`1f91868e`](https://github.com/PrismJS/prism/commit/1f91868e) +* __False__ ([#2802](https://github.com/PrismJS/prism/issues/2802)) [`99a21dc5`](https://github.com/PrismJS/prism/commit/99a21dc5) +* __ICU Message Format__ ([#2745](https://github.com/PrismJS/prism/issues/2745)) [`bf4e7ba9`](https://github.com/PrismJS/prism/commit/bf4e7ba9) +* __Idris__ ([#2755](https://github.com/PrismJS/prism/issues/2755)) [`e9314415`](https://github.com/PrismJS/prism/commit/e9314415) +* __Jexl__ ([#2764](https://github.com/PrismJS/prism/issues/2764)) [`7e51b99c`](https://github.com/PrismJS/prism/commit/7e51b99c) +* __KuMir (КуМир)__ ([#2760](https://github.com/PrismJS/prism/issues/2760)) [`3419fb77`](https://github.com/PrismJS/prism/commit/3419fb77) +* __Log file__ ([#2796](https://github.com/PrismJS/prism/issues/2796)) [`2bc6475b`](https://github.com/PrismJS/prism/commit/2bc6475b) +* __Nevod__ ([#2798](https://github.com/PrismJS/prism/issues/2798)) [`f84c49c5`](https://github.com/PrismJS/prism/commit/f84c49c5) +* __OpenQasm__ ([#2797](https://github.com/PrismJS/prism/issues/2797)) [`1a2347a3`](https://github.com/PrismJS/prism/commit/1a2347a3) +* __PATROL Scripting Language__ ([#2739](https://github.com/PrismJS/prism/issues/2739)) [`18c67b49`](https://github.com/PrismJS/prism/commit/18c67b49) +* __Q#__ ([#2804](https://github.com/PrismJS/prism/issues/2804)) [`1b63cd01`](https://github.com/PrismJS/prism/commit/1b63cd01) +* __Rego__ ([#2624](https://github.com/PrismJS/prism/issues/2624)) [`e38986f9`](https://github.com/PrismJS/prism/commit/e38986f9) +* __Squirrel__ ([#2721](https://github.com/PrismJS/prism/issues/2721)) [`fd1081d2`](https://github.com/PrismJS/prism/commit/fd1081d2) +* __URI__ ([#2708](https://github.com/PrismJS/prism/issues/2708)) [`bbc77d19`](https://github.com/PrismJS/prism/commit/bbc77d19) +* __V__ ([#2687](https://github.com/PrismJS/prism/issues/2687)) [`72962701`](https://github.com/PrismJS/prism/commit/72962701) +* __Wolfram language__ & __Mathematica__ & __Mathematica Notebook__ ([#2921](https://github.com/PrismJS/prism/issues/2921)) [`c4f6b2cc`](https://github.com/PrismJS/prism/commit/c4f6b2cc) + +### Updated components + +* Fixed problems reported by `regexp/no-dupe-disjunctions` ([#2952](https://github.com/PrismJS/prism/issues/2952)) [`f471d2d7`](https://github.com/PrismJS/prism/commit/f471d2d7) +* Fixed some cases of quadratic worst-case runtime ([#2922](https://github.com/PrismJS/prism/issues/2922)) [`79d22182`](https://github.com/PrismJS/prism/commit/79d22182) +* Fixed 2 cases of exponential backtracking ([#2774](https://github.com/PrismJS/prism/issues/2774)) [`d85e30da`](https://github.com/PrismJS/prism/commit/d85e30da) +* __AQL__ + * Update for ArangoDB 3.8 ([#2842](https://github.com/PrismJS/prism/issues/2842)) [`ea82478d`](https://github.com/PrismJS/prism/commit/ea82478d) +* __AutoHotkey__ + * Improved tag pattern ([#2920](https://github.com/PrismJS/prism/issues/2920)) [`fc2a3334`](https://github.com/PrismJS/prism/commit/fc2a3334) +* __Bash__ + * Accept hyphens in function names ([#2832](https://github.com/PrismJS/prism/issues/2832)) [`e4ad22ad`](https://github.com/PrismJS/prism/commit/e4ad22ad) + * Fixed single-quoted strings ([#2792](https://github.com/PrismJS/prism/issues/2792)) [`e5cfdb4a`](https://github.com/PrismJS/prism/commit/e5cfdb4a) +* __C++__ + * Added support for generic functions and made `::` punctuation ([#2814](https://github.com/PrismJS/prism/issues/2814)) [`3df62fd0`](https://github.com/PrismJS/prism/commit/3df62fd0) + * Added missing keywords and modules ([#2763](https://github.com/PrismJS/prism/issues/2763)) [`88fa72cf`](https://github.com/PrismJS/prism/commit/88fa72cf) +* __Dart__ + * Improved support for classes & generics ([#2810](https://github.com/PrismJS/prism/issues/2810)) [`d0bcd074`](https://github.com/PrismJS/prism/commit/d0bcd074) +* __Docker__ + * Improvements ([#2720](https://github.com/PrismJS/prism/issues/2720)) [`93dd83c2`](https://github.com/PrismJS/prism/commit/93dd83c2) +* __Elixir__ + * Added missing keywords ([#2958](https://github.com/PrismJS/prism/issues/2958)) [`114e4626`](https://github.com/PrismJS/prism/commit/114e4626) + * Added missing keyword and other improvements ([#2773](https://github.com/PrismJS/prism/issues/2773)) [`e6c0d298`](https://github.com/PrismJS/prism/commit/e6c0d298) + * Added `defdelagate` keyword and highlighting for function/module names ([#2709](https://github.com/PrismJS/prism/issues/2709)) [`59f725d7`](https://github.com/PrismJS/prism/commit/59f725d7) +* __F#__ + * Fixed comment false positive ([#2703](https://github.com/PrismJS/prism/issues/2703)) [`a5d7178c`](https://github.com/PrismJS/prism/commit/a5d7178c) +* __GraphQL__ + * Fixed `definition-query` and `definition-mutation` tokens ([#2964](https://github.com/PrismJS/prism/issues/2964)) [`bfd7fded`](https://github.com/PrismJS/prism/commit/bfd7fded) + * Added more detailed tokens ([#2939](https://github.com/PrismJS/prism/issues/2939)) [`34f24ac9`](https://github.com/PrismJS/prism/commit/34f24ac9) +* __Handlebars__ + * Added `hbs` alias ([#2874](https://github.com/PrismJS/prism/issues/2874)) [`43976351`](https://github.com/PrismJS/prism/commit/43976351) +* __HTTP__ + * Fixed body not being highlighted ([#2734](https://github.com/PrismJS/prism/issues/2734)) [`1dfc8271`](https://github.com/PrismJS/prism/commit/1dfc8271) + * More granular tokenization ([#2722](https://github.com/PrismJS/prism/issues/2722)) [`6183fd9b`](https://github.com/PrismJS/prism/commit/6183fd9b) + * Allow root path in request line ([#2711](https://github.com/PrismJS/prism/issues/2711)) [`4e7b2a82`](https://github.com/PrismJS/prism/commit/4e7b2a82) +* __Ini__ + * Consistently mimic Win32 INI parsing ([#2779](https://github.com/PrismJS/prism/issues/2779)) [`42d24fa2`](https://github.com/PrismJS/prism/commit/42d24fa2) +* __Java__ + * Improved generics ([#2812](https://github.com/PrismJS/prism/issues/2812)) [`4ec7535c`](https://github.com/PrismJS/prism/commit/4ec7535c) +* __JavaScript__ + * Added support for import assertions ([#2953](https://github.com/PrismJS/prism/issues/2953)) [`ab7c9953`](https://github.com/PrismJS/prism/commit/ab7c9953) + * Added support for RegExp Match Indices ([#2900](https://github.com/PrismJS/prism/issues/2900)) [`415651a0`](https://github.com/PrismJS/prism/commit/415651a0) + * Added hashbang and private getters/setters ([#2815](https://github.com/PrismJS/prism/issues/2815)) [`9c610ae6`](https://github.com/PrismJS/prism/commit/9c610ae6) + * Improved contextual keywords ([#2713](https://github.com/PrismJS/prism/issues/2713)) [`022f90a0`](https://github.com/PrismJS/prism/commit/022f90a0) +* __JS Templates__ + * Added SQL templates ([#2945](https://github.com/PrismJS/prism/issues/2945)) [`abab9104`](https://github.com/PrismJS/prism/commit/abab9104) +* __JSON__ + * Fixed backtracking issue in Safari ([#2691](https://github.com/PrismJS/prism/issues/2691)) [`cf28d1b2`](https://github.com/PrismJS/prism/commit/cf28d1b2) +* __Liquid__ + * Added Markup support, missing tokens, and other improvements ([#2950](https://github.com/PrismJS/prism/issues/2950)) [`ac1d12f9`](https://github.com/PrismJS/prism/commit/ac1d12f9) +* __Log file__ + * Minor improvements ([#2851](https://github.com/PrismJS/prism/issues/2851)) [`45ec4a88`](https://github.com/PrismJS/prism/commit/45ec4a88) +* __Markdown__ + * Improved code snippets ([#2967](https://github.com/PrismJS/prism/issues/2967)) [`e9477d83`](https://github.com/PrismJS/prism/commit/e9477d83) + * Workaround for incorrect highlighting due to double `wrap` hook ([#2719](https://github.com/PrismJS/prism/issues/2719)) [`2b355c98`](https://github.com/PrismJS/prism/commit/2b355c98) +* __Markup__ + * Added support for DOM event attributes ([#2702](https://github.com/PrismJS/prism/issues/2702)) [`8dbbbb35`](https://github.com/PrismJS/prism/commit/8dbbbb35) +* __nginx__ + * Complete rewrite ([#2793](https://github.com/PrismJS/prism/issues/2793)) [`5943f4cb`](https://github.com/PrismJS/prism/commit/5943f4cb) +* __PHP__ + * Fixed functions with namespaces ([#2889](https://github.com/PrismJS/prism/issues/2889)) [`87d79390`](https://github.com/PrismJS/prism/commit/87d79390) + * Fixed string interpolation ([#2864](https://github.com/PrismJS/prism/issues/2864)) [`cf3755cb`](https://github.com/PrismJS/prism/commit/cf3755cb) + * Added missing PHP 7.4 `fn` keyword ([#2858](https://github.com/PrismJS/prism/issues/2858)) [`e0ee93f1`](https://github.com/PrismJS/prism/commit/e0ee93f1) + * Fixed methods with keyword names + minor improvements ([#2818](https://github.com/PrismJS/prism/issues/2818)) [`7e8cd40d`](https://github.com/PrismJS/prism/commit/7e8cd40d) + * Improved constant support for PHP 8.1 enums ([#2770](https://github.com/PrismJS/prism/issues/2770)) [`8019e2f6`](https://github.com/PrismJS/prism/commit/8019e2f6) + * Added support for PHP 8.1 enums ([#2752](https://github.com/PrismJS/prism/issues/2752)) [`f79b0eef`](https://github.com/PrismJS/prism/commit/f79b0eef) + * Class names at the start of a string are now highlighted correctly ([#2731](https://github.com/PrismJS/prism/issues/2731)) [`04ef309c`](https://github.com/PrismJS/prism/commit/04ef309c) + * Numeral syntax improvements ([#2701](https://github.com/PrismJS/prism/issues/2701)) [`01af04ed`](https://github.com/PrismJS/prism/commit/01af04ed) +* __React JSX__ + * Added support for general spread expressions ([#2754](https://github.com/PrismJS/prism/issues/2754)) [`9f59f52d`](https://github.com/PrismJS/prism/commit/9f59f52d) + * Added support for comments inside tags ([#2728](https://github.com/PrismJS/prism/issues/2728)) [`30b0444f`](https://github.com/PrismJS/prism/commit/30b0444f) +* __reST (reStructuredText)__ + * Fixed `inline` pattern ([#2946](https://github.com/PrismJS/prism/issues/2946)) [`a7656de6`](https://github.com/PrismJS/prism/commit/a7656de6) +* __Ruby__ + * Added heredoc literals ([#2885](https://github.com/PrismJS/prism/issues/2885)) [`20b77bff`](https://github.com/PrismJS/prism/commit/20b77bff) + * Added missing regex flags ([#2845](https://github.com/PrismJS/prism/issues/2845)) [`3786f396`](https://github.com/PrismJS/prism/commit/3786f396) + * Added missing regex interpolation ([#2841](https://github.com/PrismJS/prism/issues/2841)) [`f08c2f7f`](https://github.com/PrismJS/prism/commit/f08c2f7f) +* __Scheme__ + * Added support for high Unicode characters ([#2693](https://github.com/PrismJS/prism/issues/2693)) [`0e61a7e1`](https://github.com/PrismJS/prism/commit/0e61a7e1) + * Added bracket support ([#2813](https://github.com/PrismJS/prism/issues/2813)) [`1c6c0bf3`](https://github.com/PrismJS/prism/commit/1c6c0bf3) +* __Shell session__ + * Fixed multi-line commands ([#2872](https://github.com/PrismJS/prism/issues/2872)) [`cda976b1`](https://github.com/PrismJS/prism/commit/cda976b1) + * Commands prefixed with a path are now detected ([#2686](https://github.com/PrismJS/prism/issues/2686)) [`c83fd0b8`](https://github.com/PrismJS/prism/commit/c83fd0b8) +* __SQL__ + * Added `ILIKE` operator ([#2704](https://github.com/PrismJS/prism/issues/2704)) [`6e34771f`](https://github.com/PrismJS/prism/commit/6e34771f) +* __Swift__ + * Added `some` keyword ([#2756](https://github.com/PrismJS/prism/issues/2756)) [`cf354ef5`](https://github.com/PrismJS/prism/commit/cf354ef5) +* __TypeScript__ + * Updated keywords ([#2861](https://github.com/PrismJS/prism/issues/2861)) [`fe98d536`](https://github.com/PrismJS/prism/commit/fe98d536) + * Added support for decorators ([#2820](https://github.com/PrismJS/prism/issues/2820)) [`31cc2142`](https://github.com/PrismJS/prism/commit/31cc2142) +* __VB.Net__ + * Improved strings, comments, and punctuation ([#2782](https://github.com/PrismJS/prism/issues/2782)) [`a68f1fb6`](https://github.com/PrismJS/prism/commit/a68f1fb6) +* __Xojo (REALbasic)__ + * `REM` is no longer highlighted as a keyword in comments ([#2823](https://github.com/PrismJS/prism/issues/2823)) [`ebbbfd47`](https://github.com/PrismJS/prism/commit/ebbbfd47) + * Added last missing Keyword "Selector" ([#2807](https://github.com/PrismJS/prism/issues/2807)) [`e32e043b`](https://github.com/PrismJS/prism/commit/e32e043b) + * Added missing keywords ([#2805](https://github.com/PrismJS/prism/issues/2805)) [`459365ec`](https://github.com/PrismJS/prism/commit/459365ec) + +### Updated plugins + +* Made Match Braces and Custom Class compatible ([#2947](https://github.com/PrismJS/prism/issues/2947)) [`4b55bd6a`](https://github.com/PrismJS/prism/commit/4b55bd6a) +* Consistent Prism check ([#2788](https://github.com/PrismJS/prism/issues/2788)) [`96335642`](https://github.com/PrismJS/prism/commit/96335642) +* __Command Line__ + * Don't modify empty code blocks ([#2896](https://github.com/PrismJS/prism/issues/2896)) [`c81c3319`](https://github.com/PrismJS/prism/commit/c81c3319) +* __Copy to Clipboard__ + * Removed ClipboardJS dependency ([#2784](https://github.com/PrismJS/prism/issues/2784)) [`d5e14e1a`](https://github.com/PrismJS/prism/commit/d5e14e1a) + * Fixed `clipboard.writeText` not working inside iFrames ([#2826](https://github.com/PrismJS/prism/issues/2826)) [`01b7b6f7`](https://github.com/PrismJS/prism/commit/01b7b6f7) + * Added support for custom styles ([#2789](https://github.com/PrismJS/prism/issues/2789)) [`4d7f75b0`](https://github.com/PrismJS/prism/commit/4d7f75b0) + * Make copy-to-clipboard configurable with multiple attributes ([#2723](https://github.com/PrismJS/prism/issues/2723)) [`2cb909e1`](https://github.com/PrismJS/prism/commit/2cb909e1) +* __File Highlight__ + * Fixed Prism check ([#2827](https://github.com/PrismJS/prism/issues/2827)) [`53d34b22`](https://github.com/PrismJS/prism/commit/53d34b22) +* __Line Highlight__ + * Fixed linkable line numbers not being initialized ([#2732](https://github.com/PrismJS/prism/issues/2732)) [`ccc73ab7`](https://github.com/PrismJS/prism/commit/ccc73ab7) +* __Previewers__ + * Use `classList` instead of `className` ([#2787](https://github.com/PrismJS/prism/issues/2787)) [`d298d46e`](https://github.com/PrismJS/prism/commit/d298d46e) + +### Other + +* __Core__ + * Add `tabindex` to code blocks to enable keyboard navigation ([#2799](https://github.com/PrismJS/prism/issues/2799)) [`dbf70515`](https://github.com/PrismJS/prism/commit/dbf70515) + * Fixed greedy rematching reach bug ([#2705](https://github.com/PrismJS/prism/issues/2705)) [`b37987d3`](https://github.com/PrismJS/prism/commit/b37987d3) + * Added support for plaintext ([#2738](https://github.com/PrismJS/prism/issues/2738)) [`970674cf`](https://github.com/PrismJS/prism/commit/970674cf) +* __Infrastructure__ + * Added ESLint + * Added `npm-run-all` to clean up test command ([#2938](https://github.com/PrismJS/prism/issues/2938)) [`5d3d8088`](https://github.com/PrismJS/prism/commit/5d3d8088) + * Added link to Q&A to issue templates ([#2834](https://github.com/PrismJS/prism/issues/2834)) [`7cd9e794`](https://github.com/PrismJS/prism/commit/7cd9e794) + * CI: Run tests with NodeJS 16.x ([#2888](https://github.com/PrismJS/prism/issues/2888)) [`b77317c5`](https://github.com/PrismJS/prism/commit/b77317c5) + * Dangerfile: Trim merge base ([#2761](https://github.com/PrismJS/prism/issues/2761)) [`45b0e82a`](https://github.com/PrismJS/prism/commit/45b0e82a) + * Dangerfile: Fixed how changed files are determined ([#2757](https://github.com/PrismJS/prism/issues/2757)) [`0feb266f`](https://github.com/PrismJS/prism/commit/0feb266f) + * Deps: Updated regex tooling ([#2923](https://github.com/PrismJS/prism/issues/2923)) [`ad9878ad`](https://github.com/PrismJS/prism/commit/ad9878ad) + * Tests: Added `--language` for patterns tests ([#2929](https://github.com/PrismJS/prism/issues/2929)) [`a62ef796`](https://github.com/PrismJS/prism/commit/a62ef796) + * Tests: Fixed polynomial backtracking test ([#2891](https://github.com/PrismJS/prism/issues/2891)) [`8dbf1217`](https://github.com/PrismJS/prism/commit/8dbf1217) + * Tests: Fixed languages test discovery [`a9a199b6`](https://github.com/PrismJS/prism/commit/a9a199b6) + * Tests: Test discovery should ignore unsupported file extensions ([#2886](https://github.com/PrismJS/prism/issues/2886)) [`4492c5ce`](https://github.com/PrismJS/prism/commit/4492c5ce) + * Tests: Exhaustive pattern tests ([#2688](https://github.com/PrismJS/prism/issues/2688)) [`53151404`](https://github.com/PrismJS/prism/commit/53151404) + * Tests: Fixed pretty print incorrectly calculating print width ([#2821](https://github.com/PrismJS/prism/issues/2821)) [`5bc405e7`](https://github.com/PrismJS/prism/commit/5bc405e7) + * Tests: Automatically normalize line ends ([#2934](https://github.com/PrismJS/prism/issues/2934)) [`99f3ddcd`](https://github.com/PrismJS/prism/commit/99f3ddcd) + * Tests: Added `--insert` and `--update` parameters to language test ([#2809](https://github.com/PrismJS/prism/issues/2809)) [`4c8b855d`](https://github.com/PrismJS/prism/commit/4c8b855d) + * Tests: Stricter `components.json` tests ([#2758](https://github.com/PrismJS/prism/issues/2758)) [`933af805`](https://github.com/PrismJS/prism/commit/933af805) +* __Website__ + * Copy to clipboard: Fixed highlighting ([#2725](https://github.com/PrismJS/prism/issues/2725)) [`7a790bf9`](https://github.com/PrismJS/prism/commit/7a790bf9) + * Readme: Mention `npm ci` ([#2899](https://github.com/PrismJS/prism/issues/2899)) [`91f3aaed`](https://github.com/PrismJS/prism/commit/91f3aaed) + * Readme: Added Node and npm version requirements ([#2790](https://github.com/PrismJS/prism/issues/2790)) [`cb220168`](https://github.com/PrismJS/prism/commit/cb220168) + * Readme: Update link to Chinese translation ([#2749](https://github.com/PrismJS/prism/issues/2749)) [`266cc700`](https://github.com/PrismJS/prism/commit/266cc700) + * Replace `my.cdn` in code sample with Handlebars-like placeholder ([#2906](https://github.com/PrismJS/prism/issues/2906)) [`80471181`](https://github.com/PrismJS/prism/commit/80471181) + * Set dummy domain for CDN ([#2905](https://github.com/PrismJS/prism/issues/2905)) [`38f1d289`](https://github.com/PrismJS/prism/commit/38f1d289) + * Added MySQL to "Used by" section ([#2785](https://github.com/PrismJS/prism/issues/2785)) [`9b784ebf`](https://github.com/PrismJS/prism/commit/9b784ebf) + * Improved basic usage section ([#2777](https://github.com/PrismJS/prism/issues/2777)) [`a1209930`](https://github.com/PrismJS/prism/commit/a1209930) + * Updated URL in Autolinker example ([#2751](https://github.com/PrismJS/prism/issues/2751)) [`ec9767d6`](https://github.com/PrismJS/prism/commit/ec9767d6) + * Added React native tutorial ([#2683](https://github.com/PrismJS/prism/issues/2683)) [`1506f345`](https://github.com/PrismJS/prism/commit/1506f345) + + +## 1.23.0 (2020-12-31) + +### New components + +* __Apex__ ([#2622](https://github.com/PrismJS/prism/issues/2622)) [`f0e2b70e`](https://github.com/PrismJS/prism/commit/f0e2b70e) +* __DataWeave__ ([#2659](https://github.com/PrismJS/prism/issues/2659)) [`0803525b`](https://github.com/PrismJS/prism/commit/0803525b) +* __PromQL__ ([#2628](https://github.com/PrismJS/prism/issues/2628)) [`8831c706`](https://github.com/PrismJS/prism/commit/8831c706) + +### Updated components + +* Fixed multiple vulnerable regexes ([#2584](https://github.com/PrismJS/prism/issues/2584)) [`c2f6a644`](https://github.com/PrismJS/prism/commit/c2f6a644) +* __Apache Configuration__ + * Update directive-flag to match `=` ([#2612](https://github.com/PrismJS/prism/issues/2612)) [`00bf00e3`](https://github.com/PrismJS/prism/commit/00bf00e3) +* __C-like__ + * Made all comments greedy ([#2680](https://github.com/PrismJS/prism/issues/2680)) [`0a3932fe`](https://github.com/PrismJS/prism/commit/0a3932fe) +* __C__ + * Better class name and macro name detection ([#2585](https://github.com/PrismJS/prism/issues/2585)) [`129faf5c`](https://github.com/PrismJS/prism/commit/129faf5c) +* __Content-Security-Policy__ + * Added missing directives and keywords ([#2664](https://github.com/PrismJS/prism/issues/2664)) [`f1541342`](https://github.com/PrismJS/prism/commit/f1541342) + * Do not highlight directive names with adjacent hyphens ([#2662](https://github.com/PrismJS/prism/issues/2662)) [`a7ccc16d`](https://github.com/PrismJS/prism/commit/a7ccc16d) +* __CSS__ + * Better HTML `style` attribute tokenization ([#2569](https://github.com/PrismJS/prism/issues/2569)) [`b04cbafe`](https://github.com/PrismJS/prism/commit/b04cbafe) +* __Java__ + * Improved package and class name detection ([#2599](https://github.com/PrismJS/prism/issues/2599)) [`0889bc7c`](https://github.com/PrismJS/prism/commit/0889bc7c) + * Added Java 15 keywords ([#2567](https://github.com/PrismJS/prism/issues/2567)) [`73f81c89`](https://github.com/PrismJS/prism/commit/73f81c89) +* __Java stack trace__ + * Added support stack frame element class loaders and modules ([#2658](https://github.com/PrismJS/prism/issues/2658)) [`0bb4f096`](https://github.com/PrismJS/prism/commit/0bb4f096) +* __Julia__ + * Removed constants that are not exported by default ([#2601](https://github.com/PrismJS/prism/issues/2601)) [`093c8175`](https://github.com/PrismJS/prism/commit/093c8175) +* __Kotlin__ + * Added support for backticks in function names ([#2489](https://github.com/PrismJS/prism/issues/2489)) [`a5107d5c`](https://github.com/PrismJS/prism/commit/a5107d5c) +* __Latte__ + * Fixed exponential backtracking ([#2682](https://github.com/PrismJS/prism/issues/2682)) [`89f1e182`](https://github.com/PrismJS/prism/commit/89f1e182) +* __Markdown__ + * Improved URL tokenization ([#2678](https://github.com/PrismJS/prism/issues/2678)) [`2af3e2c2`](https://github.com/PrismJS/prism/commit/2af3e2c2) + * Added support for YAML front matter ([#2634](https://github.com/PrismJS/prism/issues/2634)) [`5cf9cfbc`](https://github.com/PrismJS/prism/commit/5cf9cfbc) +* __PHP__ + * Added support for PHP 7.4 + other major improvements ([#2566](https://github.com/PrismJS/prism/issues/2566)) [`38808e64`](https://github.com/PrismJS/prism/commit/38808e64) + * Added support for PHP 8.0 features ([#2591](https://github.com/PrismJS/prism/issues/2591)) [`df922d90`](https://github.com/PrismJS/prism/commit/df922d90) + * Removed C-like dependency ([#2619](https://github.com/PrismJS/prism/issues/2619)) [`89ebb0b7`](https://github.com/PrismJS/prism/commit/89ebb0b7) + * Fixed exponential backtracking ([#2684](https://github.com/PrismJS/prism/issues/2684)) [`37b9c9a1`](https://github.com/PrismJS/prism/commit/37b9c9a1) +* __Sass (Scss)__ + * Added support for Sass modules ([#2643](https://github.com/PrismJS/prism/issues/2643)) [`deb238a6`](https://github.com/PrismJS/prism/commit/deb238a6) +* __Scheme__ + * Fixed number pattern ([#2648](https://github.com/PrismJS/prism/issues/2648)) [`e01ecd00`](https://github.com/PrismJS/prism/commit/e01ecd00) + * Fixed function and function-like false positives ([#2611](https://github.com/PrismJS/prism/issues/2611)) [`7951ca24`](https://github.com/PrismJS/prism/commit/7951ca24) +* __Shell session__ + * Fixed false positives because of links in command output ([#2649](https://github.com/PrismJS/prism/issues/2649)) [`8e76a978`](https://github.com/PrismJS/prism/commit/8e76a978) +* __TSX__ + * Temporary fix for the collisions of JSX tags and TS generics ([#2596](https://github.com/PrismJS/prism/issues/2596)) [`25bdb494`](https://github.com/PrismJS/prism/commit/25bdb494) + +### Updated plugins + +* Made Autoloader and Diff Highlight compatible ([#2580](https://github.com/PrismJS/prism/issues/2580)) [`7a74497a`](https://github.com/PrismJS/prism/commit/7a74497a) +* __Copy to Clipboard Button__ + * Set `type="button"` attribute for copy to clipboard plugin ([#2593](https://github.com/PrismJS/prism/issues/2593)) [`f59a85f1`](https://github.com/PrismJS/prism/commit/f59a85f1) +* __File Highlight__ + * Fixed IE compatibility problem ([#2656](https://github.com/PrismJS/prism/issues/2656)) [`3f4ae00d`](https://github.com/PrismJS/prism/commit/3f4ae00d) +* __Line Highlight__ + * Fixed top offset in combination with Line numbers ([#2237](https://github.com/PrismJS/prism/issues/2237)) [`b40f8f4b`](https://github.com/PrismJS/prism/commit/b40f8f4b) + * Fixed print background color ([#2668](https://github.com/PrismJS/prism/issues/2668)) [`cdb24abe`](https://github.com/PrismJS/prism/commit/cdb24abe) +* __Line Numbers__ + * Fixed null reference ([#2605](https://github.com/PrismJS/prism/issues/2605)) [`7cdfe556`](https://github.com/PrismJS/prism/commit/7cdfe556) +* __Treeview__ + * Fixed icons on dark themes ([#2631](https://github.com/PrismJS/prism/issues/2631)) [`7266e32f`](https://github.com/PrismJS/prism/commit/7266e32f) +* __Unescaped Markup__ + * Refactoring ([#2445](https://github.com/PrismJS/prism/issues/2445)) [`fc602822`](https://github.com/PrismJS/prism/commit/fc602822) + +### Other + +* Readme: Added alternative link for Chinese translation [`071232b4`](https://github.com/PrismJS/prism/commit/071232b4) +* Readme: Removed broken icon for Chinese translation ([#2670](https://github.com/PrismJS/prism/issues/2670)) [`2ea202b9`](https://github.com/PrismJS/prism/commit/2ea202b9) +* Readme: Grammar adjustments ([#2629](https://github.com/PrismJS/prism/issues/2629)) [`f217ab75`](https://github.com/PrismJS/prism/commit/f217ab75) +* __Core__ + * Moved pattern matching + lookbehind logic into function ([#2633](https://github.com/PrismJS/prism/issues/2633)) [`24574406`](https://github.com/PrismJS/prism/commit/24574406) + * Fixed bug with greedy matching ([#2632](https://github.com/PrismJS/prism/issues/2632)) [`8fa8dd24`](https://github.com/PrismJS/prism/commit/8fa8dd24) +* __Infrastructure__ + * Migrate from TravisCI -> GitHub Actions ([#2606](https://github.com/PrismJS/prism/issues/2606)) [`69132045`](https://github.com/PrismJS/prism/commit/69132045) + * Added Dangerfile and provide bundle size info ([#2608](https://github.com/PrismJS/prism/issues/2608)) [`9df20c5e`](https://github.com/PrismJS/prism/commit/9df20c5e) + * New `start` script to start local server ([#2491](https://github.com/PrismJS/prism/issues/2491)) [`0604793c`](https://github.com/PrismJS/prism/commit/0604793c) + * Added test for exponential backtracking ([#2590](https://github.com/PrismJS/prism/issues/2590)) [`05afbb10`](https://github.com/PrismJS/prism/commit/05afbb10) + * Added test for polynomial backtracking ([#2597](https://github.com/PrismJS/prism/issues/2597)) [`e644178b`](https://github.com/PrismJS/prism/commit/e644178b) + * Tests: Better pretty print ([#2600](https://github.com/PrismJS/prism/issues/2600)) [`8bfcc819`](https://github.com/PrismJS/prism/commit/8bfcc819) + * Tests: Fixed sorted language list test ([#2623](https://github.com/PrismJS/prism/issues/2623)) [`2d3a1267`](https://github.com/PrismJS/prism/commit/2d3a1267) + * Tests: Stricter pattern for nice-token-names test ([#2588](https://github.com/PrismJS/prism/issues/2588)) [`0df60be1`](https://github.com/PrismJS/prism/commit/0df60be1) + * Tests: Added strict checks for `Prism.languages.extend` ([#2572](https://github.com/PrismJS/prism/issues/2572)) [`8828500e`](https://github.com/PrismJS/prism/commit/8828500e) +* __Website__ + * Test page: Added "Share" option ([#2575](https://github.com/PrismJS/prism/issues/2575)) [`b5f4f10e`](https://github.com/PrismJS/prism/commit/b5f4f10e) + * Test page: Don't trigger ad-blockers with class ([#2677](https://github.com/PrismJS/prism/issues/2677)) [`df0738e9`](https://github.com/PrismJS/prism/commit/df0738e9) + * Thousands -> millions [`9f82de50`](https://github.com/PrismJS/prism/commit/9f82de50) + * Unescaped Markup: More doc regarding comments ([#2652](https://github.com/PrismJS/prism/issues/2652)) [`add3736a`](https://github.com/PrismJS/prism/commit/add3736a) + * Website: Added and updated documentation ([#2654](https://github.com/PrismJS/prism/issues/2654)) [`8e660495`](https://github.com/PrismJS/prism/commit/8e660495) + * Website: Updated and improved guide on "Extending Prism" page ([#2586](https://github.com/PrismJS/prism/issues/2586)) [`8e1f38ff`](https://github.com/PrismJS/prism/commit/8e1f38ff) + +## 1.22.0 (2020-10-10) + +### New components + +* __Birb__ ([#2542](https://github.com/PrismJS/prism/issues/2542)) [`4d31e22a`](https://github.com/PrismJS/prism/commit/4d31e22a) +* __BSL (1C:Enterprise)__ & __OneScript__ ([#2520](https://github.com/PrismJS/prism/issues/2520)) [`5c33f0bb`](https://github.com/PrismJS/prism/commit/5c33f0bb) +* __MongoDB__ ([#2518](https://github.com/PrismJS/prism/issues/2518)) [`004eaa74`](https://github.com/PrismJS/prism/commit/004eaa74) +* __Naninovel Script__ ([#2494](https://github.com/PrismJS/prism/issues/2494)) [`388ad996`](https://github.com/PrismJS/prism/commit/388ad996) +* __PureScript__ ([#2526](https://github.com/PrismJS/prism/issues/2526)) [`ad748a00`](https://github.com/PrismJS/prism/commit/ad748a00) +* __SML__ & __SML/NJ__ ([#2537](https://github.com/PrismJS/prism/issues/2537)) [`cb75d9e2`](https://github.com/PrismJS/prism/commit/cb75d9e2) +* __Stan__ ([#2490](https://github.com/PrismJS/prism/issues/2490)) [`2da2beba`](https://github.com/PrismJS/prism/commit/2da2beba) +* __TypoScript__ & __TSConfig__ ([#2505](https://github.com/PrismJS/prism/issues/2505)) [`bf115f47`](https://github.com/PrismJS/prism/commit/bf115f47) + +### Updated components + +* Removed duplicate alternatives in various languages ([#2524](https://github.com/PrismJS/prism/issues/2524)) [`fa2225ff`](https://github.com/PrismJS/prism/commit/fa2225ff) +* __Haskell__ + * Improvements ([#2535](https://github.com/PrismJS/prism/issues/2535)) [`e023044c`](https://github.com/PrismJS/prism/commit/e023044c) +* __JS Extras__ + * Highlight import and export bindings ([#2533](https://github.com/PrismJS/prism/issues/2533)) [`c51ababb`](https://github.com/PrismJS/prism/commit/c51ababb) + * Added control-flow keywords ([#2529](https://github.com/PrismJS/prism/issues/2529)) [`bcef22af`](https://github.com/PrismJS/prism/commit/bcef22af) +* __PHP__ + * Added `match` keyword (PHP 8.0) ([#2574](https://github.com/PrismJS/prism/issues/2574)) [`1761513e`](https://github.com/PrismJS/prism/commit/1761513e) +* __Processing__ + * Fixed function pattern ([#2564](https://github.com/PrismJS/prism/issues/2564)) [`35cbc02f`](https://github.com/PrismJS/prism/commit/35cbc02f) +* __Regex__ + * Changed how languages embed regexes ([#2532](https://github.com/PrismJS/prism/issues/2532)) [`f62ca787`](https://github.com/PrismJS/prism/commit/f62ca787) +* __Rust__ + * Fixed Unicode char literals ([#2550](https://github.com/PrismJS/prism/issues/2550)) [`3b4f14ca`](https://github.com/PrismJS/prism/commit/3b4f14ca) +* __Scheme__ + * Added support for R7RS syntax ([#2525](https://github.com/PrismJS/prism/issues/2525)) [`e4f6ccac`](https://github.com/PrismJS/prism/commit/e4f6ccac) +* __Shell session__ + * Added aliases ([#2548](https://github.com/PrismJS/prism/issues/2548)) [`bfb36748`](https://github.com/PrismJS/prism/commit/bfb36748) + * Highlight all commands after the start of any Heredoc string ([#2509](https://github.com/PrismJS/prism/issues/2509)) [`6c921801`](https://github.com/PrismJS/prism/commit/6c921801) +* __YAML__ + * Improved key pattern ([#2561](https://github.com/PrismJS/prism/issues/2561)) [`59853a52`](https://github.com/PrismJS/prism/commit/59853a52) + +### Updated plugins + +* __Autoloader__ + * Fixed file detection regexes ([#2549](https://github.com/PrismJS/prism/issues/2549)) [`d36ea993`](https://github.com/PrismJS/prism/commit/d36ea993) +* __Match braces__ + * Fixed JS interpolation punctuation ([#2541](https://github.com/PrismJS/prism/issues/2541)) [`6b47133d`](https://github.com/PrismJS/prism/commit/6b47133d) +* __Show Language__ + * Added title for plain text ([#2555](https://github.com/PrismJS/prism/issues/2555)) [`a409245e`](https://github.com/PrismJS/prism/commit/a409245e) + +### Other + +* Tests: Added an option to accept the actual token stream ([#2515](https://github.com/PrismJS/prism/issues/2515)) [`bafab634`](https://github.com/PrismJS/prism/commit/bafab634) +* __Core__ + * Docs: Minor improvement ([#2513](https://github.com/PrismJS/prism/issues/2513)) [`206dc80f`](https://github.com/PrismJS/prism/commit/206dc80f) +* __Infrastructure__ + * JSDoc: Fixed line ends ([#2523](https://github.com/PrismJS/prism/issues/2523)) [`bf169e5f`](https://github.com/PrismJS/prism/commit/bf169e5f) +* __Website__ + * Website: Added new SB101 tutorial replacing the Crambler one ([#2576](https://github.com/PrismJS/prism/issues/2576)) [`655f985c`](https://github.com/PrismJS/prism/commit/655f985c) + * Website: Fix typo on homepage by adding missing word add ([#2570](https://github.com/PrismJS/prism/issues/2570)) [`8ae6a4ba`](https://github.com/PrismJS/prism/commit/8ae6a4ba) + * Custom class: Improved doc ([#2512](https://github.com/PrismJS/prism/issues/2512)) [`5ad6cb23`](https://github.com/PrismJS/prism/commit/5ad6cb23) + +## 1.21.0 (2020-08-06) + +### New components + +* __.ignore__ & __.gitignore__ & __.hgignore__ & __.npmignore__ ([#2481](https://github.com/PrismJS/prism/issues/2481)) [`3fcce6fe`](https://github.com/PrismJS/prism/commit/3fcce6fe) +* __Agda__ ([#2430](https://github.com/PrismJS/prism/issues/2430)) [`3a127c7d`](https://github.com/PrismJS/prism/commit/3a127c7d) +* __AL__ ([#2300](https://github.com/PrismJS/prism/issues/2300)) [`de21eb64`](https://github.com/PrismJS/prism/commit/de21eb64) +* __Cypher__ ([#2459](https://github.com/PrismJS/prism/issues/2459)) [`398e2943`](https://github.com/PrismJS/prism/commit/398e2943) +* __Dhall__ ([#2473](https://github.com/PrismJS/prism/issues/2473)) [`649e51e5`](https://github.com/PrismJS/prism/commit/649e51e5) +* __EditorConfig__ ([#2471](https://github.com/PrismJS/prism/issues/2471)) [`ed8fff91`](https://github.com/PrismJS/prism/commit/ed8fff91) +* __HLSL__ ([#2318](https://github.com/PrismJS/prism/issues/2318)) [`87a5c7ae`](https://github.com/PrismJS/prism/commit/87a5c7ae) +* __JS stack trace__ ([#2418](https://github.com/PrismJS/prism/issues/2418)) [`ae0327b3`](https://github.com/PrismJS/prism/commit/ae0327b3) +* __PeopleCode__ ([#2302](https://github.com/PrismJS/prism/issues/2302)) [`bd4d8165`](https://github.com/PrismJS/prism/commit/bd4d8165) +* __PureBasic__ ([#2369](https://github.com/PrismJS/prism/issues/2369)) [`d0c1c70d`](https://github.com/PrismJS/prism/commit/d0c1c70d) +* __Racket__ ([#2315](https://github.com/PrismJS/prism/issues/2315)) [`053016ef`](https://github.com/PrismJS/prism/commit/053016ef) +* __Smali__ ([#2419](https://github.com/PrismJS/prism/issues/2419)) [`22eb5cad`](https://github.com/PrismJS/prism/commit/22eb5cad) +* __Structured Text (IEC 61131-3)__ ([#2311](https://github.com/PrismJS/prism/issues/2311)) [`8704cdfb`](https://github.com/PrismJS/prism/commit/8704cdfb) +* __UnrealScript__ ([#2305](https://github.com/PrismJS/prism/issues/2305)) [`1093ceb3`](https://github.com/PrismJS/prism/commit/1093ceb3) +* __WarpScript__ ([#2307](https://github.com/PrismJS/prism/issues/2307)) [`cde5b0fa`](https://github.com/PrismJS/prism/commit/cde5b0fa) +* __XML doc (.net)__ ([#2340](https://github.com/PrismJS/prism/issues/2340)) [`caec5e30`](https://github.com/PrismJS/prism/commit/caec5e30) +* __YANG__ ([#2467](https://github.com/PrismJS/prism/issues/2467)) [`ed1df1e1`](https://github.com/PrismJS/prism/commit/ed1df1e1) + +### Updated components + +* Markup & JSON: Added new aliases ([#2390](https://github.com/PrismJS/prism/issues/2390)) [`9782cfe6`](https://github.com/PrismJS/prism/commit/9782cfe6) +* Fixed several cases of exponential backtracking ([#2268](https://github.com/PrismJS/prism/issues/2268)) [`7a554b5f`](https://github.com/PrismJS/prism/commit/7a554b5f) +* __APL__ + * Added `⍥` ([#2409](https://github.com/PrismJS/prism/issues/2409)) [`0255cb6a`](https://github.com/PrismJS/prism/commit/0255cb6a) +* __AutoHotkey__ + * Added missing `format` built-in ([#2450](https://github.com/PrismJS/prism/issues/2450)) [`7c66cfc4`](https://github.com/PrismJS/prism/commit/7c66cfc4) + * Improved comments and other improvements ([#2412](https://github.com/PrismJS/prism/issues/2412)) [`ddf3cc62`](https://github.com/PrismJS/prism/commit/ddf3cc62) + * Added missing definitions ([#2400](https://github.com/PrismJS/prism/issues/2400)) [`4fe03676`](https://github.com/PrismJS/prism/commit/4fe03676) +* __Bash__ + * Added `composer` command ([#2298](https://github.com/PrismJS/prism/issues/2298)) [`044dd271`](https://github.com/PrismJS/prism/commit/044dd271) +* __Batch__ + * Fix escaped double quote ([#2485](https://github.com/PrismJS/prism/issues/2485)) [`f0f8210c`](https://github.com/PrismJS/prism/commit/f0f8210c) +* __C__ + * Improved macros and expressions ([#2440](https://github.com/PrismJS/prism/issues/2440)) [`8a72fa6f`](https://github.com/PrismJS/prism/commit/8a72fa6f) + * Improved macros ([#2320](https://github.com/PrismJS/prism/issues/2320)) [`fdcf7ed2`](https://github.com/PrismJS/prism/commit/fdcf7ed2) +* __C#__ + * Improved pattern matching ([#2411](https://github.com/PrismJS/prism/issues/2411)) [`7f341fc1`](https://github.com/PrismJS/prism/commit/7f341fc1) + * Fixed adjacent string interpolations ([#2402](https://github.com/PrismJS/prism/issues/2402)) [`2a2e79ed`](https://github.com/PrismJS/prism/commit/2a2e79ed) +* __C++__ + * Added support for default comparison operator ([#2426](https://github.com/PrismJS/prism/issues/2426)) [`8e9d161c`](https://github.com/PrismJS/prism/commit/8e9d161c) + * Improved class name detection ([#2348](https://github.com/PrismJS/prism/issues/2348)) [`e3fe9040`](https://github.com/PrismJS/prism/commit/e3fe9040) + * Fixed `enum class` class names ([#2342](https://github.com/PrismJS/prism/issues/2342)) [`30b4e254`](https://github.com/PrismJS/prism/commit/30b4e254) +* __Content-Security-Policy__ + * Fixed directives ([#2461](https://github.com/PrismJS/prism/issues/2461)) [`537a9e80`](https://github.com/PrismJS/prism/commit/537a9e80) +* __CSS__ + * Improved url and added keywords ([#2432](https://github.com/PrismJS/prism/issues/2432)) [`964de5a1`](https://github.com/PrismJS/prism/commit/964de5a1) +* __CSS Extras__ + * Optimized `class` and `id` patterns ([#2359](https://github.com/PrismJS/prism/issues/2359)) [`fdbc4473`](https://github.com/PrismJS/prism/commit/fdbc4473) + * Renamed `attr-{name,value}` tokens and added tokens for combinators and selector lists ([#2373](https://github.com/PrismJS/prism/issues/2373)) [`e523f5d0`](https://github.com/PrismJS/prism/commit/e523f5d0) +* __Dart__ + * Added missing keywords ([#2355](https://github.com/PrismJS/prism/issues/2355)) [`4172ab6f`](https://github.com/PrismJS/prism/commit/4172ab6f) +* __Diff__ + * Added `prefix` token ([#2281](https://github.com/PrismJS/prism/issues/2281)) [`fd432a5b`](https://github.com/PrismJS/prism/commit/fd432a5b) +* __Docker__ + * Fixed strings inside comments ([#2428](https://github.com/PrismJS/prism/issues/2428)) [`37273a6f`](https://github.com/PrismJS/prism/commit/37273a6f) +* __EditorConfig__ + * Trim spaces before key and section title ([#2482](https://github.com/PrismJS/prism/issues/2482)) [`0c30c582`](https://github.com/PrismJS/prism/commit/0c30c582) +* __EJS__ + * Added `eta` alias ([#2282](https://github.com/PrismJS/prism/issues/2282)) [`0cfb6c5f`](https://github.com/PrismJS/prism/commit/0cfb6c5f) +* __GLSL__ + * Improvements ([#2321](https://github.com/PrismJS/prism/issues/2321)) [`33e49956`](https://github.com/PrismJS/prism/commit/33e49956) +* __GraphQL__ + * Added missing keywords ([#2407](https://github.com/PrismJS/prism/issues/2407)) [`de8ed16d`](https://github.com/PrismJS/prism/commit/de8ed16d) + * Added support for multi-line strings and descriptions ([#2406](https://github.com/PrismJS/prism/issues/2406)) [`9e64c62e`](https://github.com/PrismJS/prism/commit/9e64c62e) +* __Io__ + * Fixed operator pattern ([#2365](https://github.com/PrismJS/prism/issues/2365)) [`d6055771`](https://github.com/PrismJS/prism/commit/d6055771) +* __Java__ + * Fixed `namespace` token ([#2295](https://github.com/PrismJS/prism/issues/2295)) [`62e184bb`](https://github.com/PrismJS/prism/commit/62e184bb) +* __JavaDoc__ + * Improvements ([#2324](https://github.com/PrismJS/prism/issues/2324)) [`032910ba`](https://github.com/PrismJS/prism/commit/032910ba) +* __JavaScript__ + * Improved regex detection ([#2465](https://github.com/PrismJS/prism/issues/2465)) [`4f55052f`](https://github.com/PrismJS/prism/commit/4f55052f) + * Improved `get`/`set` and parameter detection ([#2387](https://github.com/PrismJS/prism/issues/2387)) [`ed715158`](https://github.com/PrismJS/prism/commit/ed715158) + * Added support for logical assignment operators ([#2378](https://github.com/PrismJS/prism/issues/2378)) [`b28f21b7`](https://github.com/PrismJS/prism/commit/b28f21b7) +* __JSDoc__ + * Improvements ([#2466](https://github.com/PrismJS/prism/issues/2466)) [`2805ae35`](https://github.com/PrismJS/prism/commit/2805ae35) +* __JSON__ + * Greedy comments ([#2479](https://github.com/PrismJS/prism/issues/2479)) [`158caf52`](https://github.com/PrismJS/prism/commit/158caf52) +* __Julia__ + * Improved strings, comments, and other patterns ([#2363](https://github.com/PrismJS/prism/issues/2363)) [`81cf2344`](https://github.com/PrismJS/prism/commit/81cf2344) +* __Kotlin__ + * Added `kt` and `kts` aliases ([#2474](https://github.com/PrismJS/prism/issues/2474)) [`67f97e2e`](https://github.com/PrismJS/prism/commit/67f97e2e) +* __Markup__ + * Added tokens inside DOCTYPE ([#2349](https://github.com/PrismJS/prism/issues/2349)) [`9c7bc820`](https://github.com/PrismJS/prism/commit/9c7bc820) + * Added `attr-equals` alias for the attribute `=` sign ([#2350](https://github.com/PrismJS/prism/issues/2350)) [`96a0116e`](https://github.com/PrismJS/prism/commit/96a0116e) + * Added alias for named entities ([#2351](https://github.com/PrismJS/prism/issues/2351)) [`ab1e34ae`](https://github.com/PrismJS/prism/commit/ab1e34ae) + * Added support for SSML ([#2306](https://github.com/PrismJS/prism/issues/2306)) [`eb70070d`](https://github.com/PrismJS/prism/commit/eb70070d) +* __Objective-C__ + * Added `objc` alias ([#2331](https://github.com/PrismJS/prism/issues/2331)) [`67c6b7af`](https://github.com/PrismJS/prism/commit/67c6b7af) +* __PowerShell__ + * New functions pattern bases on naming conventions ([#2301](https://github.com/PrismJS/prism/issues/2301)) [`fec39bcf`](https://github.com/PrismJS/prism/commit/fec39bcf) +* __Protocol Buffers__ + * Added support for RPC syntax ([#2414](https://github.com/PrismJS/prism/issues/2414)) [`939a17c4`](https://github.com/PrismJS/prism/commit/939a17c4) +* __Pug__ + * Improved class and id detection in tags ([#2358](https://github.com/PrismJS/prism/issues/2358)) [`7f948ecb`](https://github.com/PrismJS/prism/commit/7f948ecb) +* __Python__ + * Fixed empty multiline strings ([#2344](https://github.com/PrismJS/prism/issues/2344)) [`c9324476`](https://github.com/PrismJS/prism/commit/c9324476) +* __Regex__ + * Added aliases and minor improvements ([#2325](https://github.com/PrismJS/prism/issues/2325)) [`8a72830a`](https://github.com/PrismJS/prism/commit/8a72830a) +* __Ren'py__ + * Added `rpy` alias ([#2385](https://github.com/PrismJS/prism/issues/2385)) [`4935b5ca`](https://github.com/PrismJS/prism/commit/4935b5ca) +* __Ruby__ + * Optimized `regex` and `string` patterns ([#2354](https://github.com/PrismJS/prism/issues/2354)) [`b526e8c0`](https://github.com/PrismJS/prism/commit/b526e8c0) +* __Rust__ + * Improvements ([#2464](https://github.com/PrismJS/prism/issues/2464)) [`2ff40fe0`](https://github.com/PrismJS/prism/commit/2ff40fe0) + * Improvements ([#2332](https://github.com/PrismJS/prism/issues/2332)) [`194c5429`](https://github.com/PrismJS/prism/commit/194c5429) +* __SAS__ + * Improved macro string functions ([#2463](https://github.com/PrismJS/prism/issues/2463)) [`278316ca`](https://github.com/PrismJS/prism/commit/278316ca) + * Handle edge case of string macro functions ([#2451](https://github.com/PrismJS/prism/issues/2451)) [`a0a9f1ef`](https://github.com/PrismJS/prism/commit/a0a9f1ef) + * Improved comments in `proc groovy` and `proc lua` ([#2392](https://github.com/PrismJS/prism/issues/2392)) [`475a5903`](https://github.com/PrismJS/prism/commit/475a5903) +* __Scheme__ + * Adjusted lookbehind for literals ([#2396](https://github.com/PrismJS/prism/issues/2396)) [`1e3f542b`](https://github.com/PrismJS/prism/commit/1e3f542b) + * Improved lambda parameter ([#2346](https://github.com/PrismJS/prism/issues/2346)) [`1946918a`](https://github.com/PrismJS/prism/commit/1946918a) + * Consistent lookaheads ([#2322](https://github.com/PrismJS/prism/issues/2322)) [`d2541d54`](https://github.com/PrismJS/prism/commit/d2541d54) + * Improved boolean ([#2316](https://github.com/PrismJS/prism/issues/2316)) [`e27e65af`](https://github.com/PrismJS/prism/commit/e27e65af) + * Added missing special keywords ([#2304](https://github.com/PrismJS/prism/issues/2304)) [`ac297ba5`](https://github.com/PrismJS/prism/commit/ac297ba5) + * Improvements ([#2263](https://github.com/PrismJS/prism/issues/2263)) [`9a49f78f`](https://github.com/PrismJS/prism/commit/9a49f78f) +* __Solidity (Ethereum)__ + * Added `sol` alias ([#2382](https://github.com/PrismJS/prism/issues/2382)) [`6352213a`](https://github.com/PrismJS/prism/commit/6352213a) +* __SQL__ + * Added PostgreSQL `RETURNING` keyword ([#2476](https://github.com/PrismJS/prism/issues/2476)) [`bea7a585`](https://github.com/PrismJS/prism/commit/bea7a585) +* __Stylus__ + * Fixed comments breaking declarations + minor improvements ([#2372](https://github.com/PrismJS/prism/issues/2372)) [`6d663b6e`](https://github.com/PrismJS/prism/commit/6d663b6e) + * New tokens and other improvements ([#2368](https://github.com/PrismJS/prism/issues/2368)) [`2c10ef8a`](https://github.com/PrismJS/prism/commit/2c10ef8a) + * Fixed comments breaking strings and URLs ([#2361](https://github.com/PrismJS/prism/issues/2361)) [`0d65d6c9`](https://github.com/PrismJS/prism/commit/0d65d6c9) +* __T4 Text Templates (VB)__ + * Use the correct VB variant ([#2341](https://github.com/PrismJS/prism/issues/2341)) [`b6093339`](https://github.com/PrismJS/prism/commit/b6093339) +* __TypeScript__ + * Added `asserts` keyword and other improvements ([#2280](https://github.com/PrismJS/prism/issues/2280)) [`a197cfcd`](https://github.com/PrismJS/prism/commit/a197cfcd) +* __Visual Basic__ + * Added VBA alias ([#2469](https://github.com/PrismJS/prism/issues/2469)) [`78161d60`](https://github.com/PrismJS/prism/commit/78161d60) + * Added `until` keyword ([#2423](https://github.com/PrismJS/prism/issues/2423)) [`a13ee8d9`](https://github.com/PrismJS/prism/commit/a13ee8d9) + * Added missing keywords ([#2376](https://github.com/PrismJS/prism/issues/2376)) [`ba5ac1da`](https://github.com/PrismJS/prism/commit/ba5ac1da) + +### Updated plugins + +* File Highlight & JSONP Highlight update ([#1974](https://github.com/PrismJS/prism/issues/1974)) [`afea17d9`](https://github.com/PrismJS/prism/commit/afea17d9) +* Added general de/activation mechanism for plugins ([#2434](https://github.com/PrismJS/prism/issues/2434)) [`a36e96ab`](https://github.com/PrismJS/prism/commit/a36e96ab) +* __Autoloader__ + * Fixed bug breaking Autoloader ([#2449](https://github.com/PrismJS/prism/issues/2449)) [`a3416bf3`](https://github.com/PrismJS/prism/commit/a3416bf3) + * Fixed `data-dependencies` and extensions ([#2326](https://github.com/PrismJS/prism/issues/2326)) [`1654b25f`](https://github.com/PrismJS/prism/commit/1654b25f) + * Improved path detection and other minor improvements ([#2245](https://github.com/PrismJS/prism/issues/2245)) [`5cdc3251`](https://github.com/PrismJS/prism/commit/5cdc3251) +* __Command Line__ + * Some refactoring ([#2290](https://github.com/PrismJS/prism/issues/2290)) [`8c9c2896`](https://github.com/PrismJS/prism/commit/8c9c2896) + * Correctly rehighlight elements ([#2291](https://github.com/PrismJS/prism/issues/2291)) [`e6b2c6fc`](https://github.com/PrismJS/prism/commit/e6b2c6fc) +* __Line Highlight__ + * Added linkable line numbers ([#2328](https://github.com/PrismJS/prism/issues/2328)) [`eb82e804`](https://github.com/PrismJS/prism/commit/eb82e804) +* __Line Numbers__ + * Improved resize performance ([#2125](https://github.com/PrismJS/prism/issues/2125)) [`b96ed225`](https://github.com/PrismJS/prism/commit/b96ed225) + * Fixed TypeError when `lineNumberWrapper` is null ([#2337](https://github.com/PrismJS/prism/issues/2337)) [`4b61661d`](https://github.com/PrismJS/prism/commit/4b61661d) + * Exposed `_resizeElement` function ([#2288](https://github.com/PrismJS/prism/issues/2288)) [`893f2a79`](https://github.com/PrismJS/prism/commit/893f2a79) +* __Previewers__ + * Fixed XSS ([#2506](https://github.com/PrismJS/prism/issues/2506)) [`8bba4880`](https://github.com/PrismJS/prism/commit/8bba4880) +* __Unescaped Markup__ + * No longer requires `Prism.languages.markup` ([#2444](https://github.com/PrismJS/prism/issues/2444)) [`af132dd3`](https://github.com/PrismJS/prism/commit/af132dd3) + +### Updated themes + +* __Coy__ + * Minor improvements ([#2176](https://github.com/PrismJS/prism/issues/2176)) [`7109c18c`](https://github.com/PrismJS/prism/commit/7109c18c) +* __Default__ + * Added a comment that declares the background color of `operator` tokens as intentional ([#2309](https://github.com/PrismJS/prism/issues/2309)) [`937e2691`](https://github.com/PrismJS/prism/commit/937e2691) +* __Okaidia__ + * Update comment text color to meet WCAG contrast recommendations to AA level ([#2292](https://github.com/PrismJS/prism/issues/2292)) [`06495f90`](https://github.com/PrismJS/prism/commit/06495f90) + +### Other + +* Changelog: Fixed v1.20.0 release date [`cb6349e2`](https://github.com/PrismJS/prism/commit/cb6349e2) +* __Core__ + * Fixed greedy matching bug ([#2032](https://github.com/PrismJS/prism/issues/2032)) [`40285203`](https://github.com/PrismJS/prism/commit/40285203) + * Added JSDoc ([#1782](https://github.com/PrismJS/prism/issues/1782)) [`4ff555be`](https://github.com/PrismJS/prism/commit/4ff555be) +* __Infrastructure__ + * Update Git repo URL in package.json ([#2334](https://github.com/PrismJS/prism/issues/2334)) [`10f43275`](https://github.com/PrismJS/prism/commit/10f43275) + * Added docs to ignore files ([#2437](https://github.com/PrismJS/prism/issues/2437)) [`05c9f20b`](https://github.com/PrismJS/prism/commit/05c9f20b) + * Added `npm run build` command ([#2356](https://github.com/PrismJS/prism/issues/2356)) [`ff74a610`](https://github.com/PrismJS/prism/commit/ff74a610) + * gulp: Improved `inlineRegexSource` ([#2296](https://github.com/PrismJS/prism/issues/2296)) [`abb800dd`](https://github.com/PrismJS/prism/commit/abb800dd) + * gulp: Fixed language map ([#2283](https://github.com/PrismJS/prism/issues/2283)) [`11053193`](https://github.com/PrismJS/prism/commit/11053193) + * gulp: Removed `premerge` task ([#2357](https://github.com/PrismJS/prism/issues/2357)) [`5ff7932b`](https://github.com/PrismJS/prism/commit/5ff7932b) + * Tests are now faster ([#2165](https://github.com/PrismJS/prism/issues/2165)) [`e756be3f`](https://github.com/PrismJS/prism/commit/e756be3f) + * Tests: Added extra newlines in pretty token streams ([#2070](https://github.com/PrismJS/prism/issues/2070)) [`681adeef`](https://github.com/PrismJS/prism/commit/681adeef) + * Tests: Added test for identifier support across all languages ([#2371](https://github.com/PrismJS/prism/issues/2371)) [`48fac3b2`](https://github.com/PrismJS/prism/commit/48fac3b2) + * Tests: Added test to sort the language list ([#2222](https://github.com/PrismJS/prism/issues/2222)) [`a3758728`](https://github.com/PrismJS/prism/commit/a3758728) + * Tests: Always pretty-print token streams ([#2421](https://github.com/PrismJS/prism/issues/2421)) [`583e7eb5`](https://github.com/PrismJS/prism/commit/583e7eb5) + * Tests: Always use `components.json` ([#2370](https://github.com/PrismJS/prism/issues/2370)) [`e416341f`](https://github.com/PrismJS/prism/commit/e416341f) + * Tests: Better error messages for pattern tests ([#2364](https://github.com/PrismJS/prism/issues/2364)) [`10ca6433`](https://github.com/PrismJS/prism/commit/10ca6433) + * Tests: Included `console` in VM context ([#2353](https://github.com/PrismJS/prism/issues/2353)) [`b4ed5ded`](https://github.com/PrismJS/prism/commit/b4ed5ded) +* __Website__ + * Fixed typos "Prims" ([#2455](https://github.com/PrismJS/prism/issues/2455)) [`dfa5498a`](https://github.com/PrismJS/prism/commit/dfa5498a) + * New assets directory for all web-only files ([#2180](https://github.com/PrismJS/prism/issues/2180)) [`91fdd0b1`](https://github.com/PrismJS/prism/commit/91fdd0b1) + * Improvements ([#2053](https://github.com/PrismJS/prism/issues/2053)) [`ce0fa227`](https://github.com/PrismJS/prism/commit/ce0fa227) + * Fixed Treeview page ([#2484](https://github.com/PrismJS/prism/issues/2484)) [`a0efa40b`](https://github.com/PrismJS/prism/commit/a0efa40b) + * Line Numbers: Fixed class name on website [`453079bf`](https://github.com/PrismJS/prism/commit/453079bf) + * Line Numbers: Improved documentation ([#2456](https://github.com/PrismJS/prism/issues/2456)) [`447429f0`](https://github.com/PrismJS/prism/commit/447429f0) + * Line Numbers: Style inline code on website ([#2435](https://github.com/PrismJS/prism/issues/2435)) [`ad9c13e2`](https://github.com/PrismJS/prism/commit/ad9c13e2) + * Filter highlightAll: Fixed typo ([#2391](https://github.com/PrismJS/prism/issues/2391)) [`55bf7ec1`](https://github.com/PrismJS/prism/commit/55bf7ec1) + +## 1.20.0 (2020-04-04) + +### New components + +* __Concurnas__ ([#2206](https://github.com/PrismJS/prism/issues/2206)) [`b24f7348`](https://github.com/PrismJS/prism/commit/b24f7348) +* __DAX__ ([#2248](https://github.com/PrismJS/prism/issues/2248)) [`9227853f`](https://github.com/PrismJS/prism/commit/9227853f) +* __Excel Formula__ ([#2219](https://github.com/PrismJS/prism/issues/2219)) [`bf4f7bfa`](https://github.com/PrismJS/prism/commit/bf4f7bfa) +* __Factor__ ([#2203](https://github.com/PrismJS/prism/issues/2203)) [`f941102e`](https://github.com/PrismJS/prism/commit/f941102e) +* __LLVM IR__ ([#2221](https://github.com/PrismJS/prism/issues/2221)) [`43efde2e`](https://github.com/PrismJS/prism/commit/43efde2e) +* __PowerQuery__ ([#2250](https://github.com/PrismJS/prism/issues/2250)) [`8119e57b`](https://github.com/PrismJS/prism/commit/8119e57b) +* __Solution file__ ([#2213](https://github.com/PrismJS/prism/issues/2213)) [`15983d52`](https://github.com/PrismJS/prism/commit/15983d52) + +### Updated components + +* __Bash__ + * Added support for escaped quotes ([#2256](https://github.com/PrismJS/prism/issues/2256)) [`328d0e0e`](https://github.com/PrismJS/prism/commit/328d0e0e) +* __BBcode__ + * Added "shortcode" alias ([#2273](https://github.com/PrismJS/prism/issues/2273)) [`57eebced`](https://github.com/PrismJS/prism/commit/57eebced) +* __C/C++/OpenCL C__ + * Improvements ([#2196](https://github.com/PrismJS/prism/issues/2196)) [`674f4b35`](https://github.com/PrismJS/prism/commit/674f4b35) +* __C__ + * Improvemed `comment` pattern ([#2229](https://github.com/PrismJS/prism/issues/2229)) [`fa630726`](https://github.com/PrismJS/prism/commit/fa630726) +* __C#__ + * Fixed keywords in type lists blocking type names ([#2277](https://github.com/PrismJS/prism/issues/2277)) [`947a55bd`](https://github.com/PrismJS/prism/commit/947a55bd) + * C# improvements ([#1444](https://github.com/PrismJS/prism/issues/1444)) [`42b15463`](https://github.com/PrismJS/prism/commit/42b15463) +* __C++__ + * Added C++20 keywords ([#2236](https://github.com/PrismJS/prism/issues/2236)) [`462ad57e`](https://github.com/PrismJS/prism/commit/462ad57e) +* __CSS__ + * Fixed `url()` containing "@" ([#2272](https://github.com/PrismJS/prism/issues/2272)) [`504a63ba`](https://github.com/PrismJS/prism/commit/504a63ba) +* __CSS Extras__ + * Added support for the selector function ([#2201](https://github.com/PrismJS/prism/issues/2201)) [`2e0eff76`](https://github.com/PrismJS/prism/commit/2e0eff76) +* __Elixir__ + * Added support for attributes names ending with `?` ([#2182](https://github.com/PrismJS/prism/issues/2182)) [`5450e24c`](https://github.com/PrismJS/prism/commit/5450e24c) +* __Java__ + * Added `record` keyword ([#2185](https://github.com/PrismJS/prism/issues/2185)) [`47910b5c`](https://github.com/PrismJS/prism/commit/47910b5c) +* __Markdown__ + * Added support for nested lists ([#2228](https://github.com/PrismJS/prism/issues/2228)) [`73c8a376`](https://github.com/PrismJS/prism/commit/73c8a376) +* __OpenCL__ + * Require C ([#2231](https://github.com/PrismJS/prism/issues/2231)) [`26626ded`](https://github.com/PrismJS/prism/commit/26626ded) +* __PHPDoc__ + * Fixed exponential backtracking ([#2198](https://github.com/PrismJS/prism/issues/2198)) [`3b42536e`](https://github.com/PrismJS/prism/commit/3b42536e) +* __Ruby__ + * Fixed exponential backtracking ([#2225](https://github.com/PrismJS/prism/issues/2225)) [`c5de5aa8`](https://github.com/PrismJS/prism/commit/c5de5aa8) +* __SAS__ + * Fixed SAS' "peerDependencies" ([#2230](https://github.com/PrismJS/prism/issues/2230)) [`7d8ff7ea`](https://github.com/PrismJS/prism/commit/7d8ff7ea) +* __Shell session__ + * Improvements ([#2208](https://github.com/PrismJS/prism/issues/2208)) [`bd16bd57`](https://github.com/PrismJS/prism/commit/bd16bd57) +* __Visual Basic__ + * Added support for comments with line continuations ([#2195](https://github.com/PrismJS/prism/issues/2195)) [`a7d67ca3`](https://github.com/PrismJS/prism/commit/a7d67ca3) +* __YAML__ + * Improvements ([#2226](https://github.com/PrismJS/prism/issues/2226)) [`5362ba16`](https://github.com/PrismJS/prism/commit/5362ba16) + * Fixed highlighting of anchors and aliases ([#2217](https://github.com/PrismJS/prism/issues/2217)) [`6124c974`](https://github.com/PrismJS/prism/commit/6124c974) + +### New plugins + +* __Treeview__ ([#2265](https://github.com/PrismJS/prism/issues/2265)) [`be909b18`](https://github.com/PrismJS/prism/commit/be909b18) + +### Updated plugins + +* __Inline Color__ + * Support for (semi-)transparent colors and minor improvements ([#2223](https://github.com/PrismJS/prism/issues/2223)) [`8d2c5a3e`](https://github.com/PrismJS/prism/commit/8d2c5a3e) +* __Keep Markup__ + * Remove self & document from IIFE arguments ([#2258](https://github.com/PrismJS/prism/issues/2258)) [`3c043338`](https://github.com/PrismJS/prism/commit/3c043338) +* __Toolbar__ + * `data-toolbar-order` is now inherited ([#2205](https://github.com/PrismJS/prism/issues/2205)) [`238f1163`](https://github.com/PrismJS/prism/commit/238f1163) + +### Other + +* Updated all `String.propotype.replace` calls for literal strings [`5d7aab56`](https://github.com/PrismJS/prism/commit/5d7aab56) +* __Core__ + * Linked list implementation for `matchGrammar` ([#1909](https://github.com/PrismJS/prism/issues/1909)) [`2d4c94cd`](https://github.com/PrismJS/prism/commit/2d4c94cd) + * Faster `Token.stringify` ([#2171](https://github.com/PrismJS/prism/issues/2171)) [`f683972e`](https://github.com/PrismJS/prism/commit/f683972e) + * Fixed scope problem in script mode ([#2184](https://github.com/PrismJS/prism/issues/2184)) [`984e5d2e`](https://github.com/PrismJS/prism/commit/984e5d2e) +* __Infrastructure__ + * Travis: Updated NodeJS versions ([#2246](https://github.com/PrismJS/prism/issues/2246)) [`e635260b`](https://github.com/PrismJS/prism/commit/e635260b) + * gulp: Inline regex source improvement ([#2227](https://github.com/PrismJS/prism/issues/2227)) [`67afc5ad`](https://github.com/PrismJS/prism/commit/67afc5ad) + * Tests: Added new pattern check for octal escapes ([#2189](https://github.com/PrismJS/prism/issues/2189)) [`81e1c3dd`](https://github.com/PrismJS/prism/commit/81e1c3dd) + * Tests: Fixed optional dependencies in pattern tests ([#2242](https://github.com/PrismJS/prism/issues/2242)) [`1e3070a2`](https://github.com/PrismJS/prism/commit/1e3070a2) + * Tests: Added test for zero-width lookbehinds ([#2220](https://github.com/PrismJS/prism/issues/2220)) [`7d03ece4`](https://github.com/PrismJS/prism/commit/7d03ece4) + * Added tests for examples ([#2216](https://github.com/PrismJS/prism/issues/2216)) [`1f7a245c`](https://github.com/PrismJS/prism/commit/1f7a245c) +* __Website__ + * Removed invalid strings from C# example ([#2266](https://github.com/PrismJS/prism/issues/2266)) [`c917a8ca`](https://github.com/PrismJS/prism/commit/c917a8ca) + * Fixed Diff highlight plugin page title ([#2233](https://github.com/PrismJS/prism/issues/2233)) [`a82770f8`](https://github.com/PrismJS/prism/commit/a82770f8) + * Added link to `prism-liquibase` Bash language extension. ([#2191](https://github.com/PrismJS/prism/issues/2191)) [`0bf73dc7`](https://github.com/PrismJS/prism/commit/0bf73dc7) + * Examples: Updated content header ([#2232](https://github.com/PrismJS/prism/issues/2232)) [`6232878b`](https://github.com/PrismJS/prism/commit/6232878b) + * Website: Added Coy bug to the known failures page. ([#2170](https://github.com/PrismJS/prism/issues/2170)) [`e9dab85e`](https://github.com/PrismJS/prism/commit/e9dab85e) + +## 1.19.0 (2020-01-13) + +### New components + +* __Latte__ ([#2140](https://github.com/PrismJS/prism/issues/2140)) [`694a81b8`](https://github.com/PrismJS/prism/commit/694a81b8) +* __Neon__ ([#2140](https://github.com/PrismJS/prism/issues/2140)) [`694a81b8`](https://github.com/PrismJS/prism/commit/694a81b8) +* __QML__ ([#2139](https://github.com/PrismJS/prism/issues/2139)) [`c40d96c6`](https://github.com/PrismJS/prism/commit/c40d96c6) + +### Updated components + +* __Handlebars__ + * Added support for `:` and improved the `variable` pattern ([#2172](https://github.com/PrismJS/prism/issues/2172)) [`ef4d29d9`](https://github.com/PrismJS/prism/commit/ef4d29d9) +* __JavaScript__ + * Added support for keywords after a spread operator ([#2148](https://github.com/PrismJS/prism/issues/2148)) [`1f3f8929`](https://github.com/PrismJS/prism/commit/1f3f8929) + * Better regex detection ([#2158](https://github.com/PrismJS/prism/issues/2158)) [`a23d8f84`](https://github.com/PrismJS/prism/commit/a23d8f84) +* __Markdown__ + * Better language detection for code blocks ([#2114](https://github.com/PrismJS/prism/issues/2114)) [`d7ad48f9`](https://github.com/PrismJS/prism/commit/d7ad48f9) +* __OCaml__ + * Improvements ([#2179](https://github.com/PrismJS/prism/issues/2179)) [`2a570fd4`](https://github.com/PrismJS/prism/commit/2a570fd4) +* __PHP__ + * Fixed exponential runtime of a pattern ([#2157](https://github.com/PrismJS/prism/issues/2157)) [`24c8f833`](https://github.com/PrismJS/prism/commit/24c8f833) +* __React JSX__ + * Improved spread operator in tag attributes ([#2159](https://github.com/PrismJS/prism/issues/2159)) [`fd857e7b`](https://github.com/PrismJS/prism/commit/fd857e7b) + * Made `$` a valid character for attribute names ([#2144](https://github.com/PrismJS/prism/issues/2144)) [`f018cf04`](https://github.com/PrismJS/prism/commit/f018cf04) +* __Reason__ + * Added support for single line comments ([#2150](https://github.com/PrismJS/prism/issues/2150)) [`7f1c55b7`](https://github.com/PrismJS/prism/commit/7f1c55b7) +* __Ruby__ + * Override 'class-name' definition ([#2135](https://github.com/PrismJS/prism/issues/2135)) [`401d4b02`](https://github.com/PrismJS/prism/commit/401d4b02) +* __SAS__ + * Added CASL support ([#2112](https://github.com/PrismJS/prism/issues/2112)) [`99d979a0`](https://github.com/PrismJS/prism/commit/99d979a0) + +### Updated plugins + +* __Custom Class__ + * Fixed TypeError when mapper is undefined ([#2167](https://github.com/PrismJS/prism/issues/2167)) [`543f04d7`](https://github.com/PrismJS/prism/commit/543f04d7) + +### Updated themes + +* Added missing `.token` selector ([#2161](https://github.com/PrismJS/prism/issues/2161)) [`86780457`](https://github.com/PrismJS/prism/commit/86780457) + +### Other + +* Added a check for redundant dependency declarations ([#2142](https://github.com/PrismJS/prism/issues/2142)) [`a06aca06`](https://github.com/PrismJS/prism/commit/a06aca06) +* Added a check for examples ([#2128](https://github.com/PrismJS/prism/issues/2128)) [`0b539136`](https://github.com/PrismJS/prism/commit/0b539136) +* Added silent option to `loadLanguages` ([#2147](https://github.com/PrismJS/prism/issues/2147)) [`191b4116`](https://github.com/PrismJS/prism/commit/191b4116) +* __Infrastructure__ + * Dependencies: Improved `getLoader` ([#2151](https://github.com/PrismJS/prism/issues/2151)) [`199bdcae`](https://github.com/PrismJS/prism/commit/199bdcae) + * Updated gulp to v4.0.2 ([#2178](https://github.com/PrismJS/prism/issues/2178)) [`e5678a00`](https://github.com/PrismJS/prism/commit/e5678a00) +* __Website__ + * Custom Class: Fixed examples ([#2160](https://github.com/PrismJS/prism/issues/2160)) [`0c2fe405`](https://github.com/PrismJS/prism/commit/0c2fe405) + * Added documentation for new dependency API ([#2141](https://github.com/PrismJS/prism/issues/2141)) [`59068d67`](https://github.com/PrismJS/prism/commit/59068d67) + +## 1.18.0 (2020-01-04) + +### New components + +* __ANTLR4__ ([#2063](https://github.com/PrismJS/prism/issues/2063)) [`aaaa29a8`](https://github.com/PrismJS/prism/commit/aaaa29a8) +* __AQL__ ([#2025](https://github.com/PrismJS/prism/issues/2025)) [`3fdb7d55`](https://github.com/PrismJS/prism/commit/3fdb7d55) +* __BBcode__ ([#2095](https://github.com/PrismJS/prism/issues/2095)) [`aaf13aa6`](https://github.com/PrismJS/prism/commit/aaf13aa6) +* __BrightScript__ ([#2096](https://github.com/PrismJS/prism/issues/2096)) [`631f1e34`](https://github.com/PrismJS/prism/commit/631f1e34) +* __Embedded Lua templating__ ([#2050](https://github.com/PrismJS/prism/issues/2050)) [`0b771c90`](https://github.com/PrismJS/prism/commit/0b771c90) +* __Firestore security rules__ ([#2010](https://github.com/PrismJS/prism/issues/2010)) [`9f722586`](https://github.com/PrismJS/prism/commit/9f722586) +* __FreeMarker Template Language__ ([#2080](https://github.com/PrismJS/prism/issues/2080)) [`2f3da7e8`](https://github.com/PrismJS/prism/commit/2f3da7e8) +* __GDScript__ ([#2006](https://github.com/PrismJS/prism/issues/2006)) [`e2b99f40`](https://github.com/PrismJS/prism/commit/e2b99f40) +* __MoonScript__ ([#2100](https://github.com/PrismJS/prism/issues/2100)) [`f31946b3`](https://github.com/PrismJS/prism/commit/f31946b3) +* __Robot Framework__ (only the plain text format) ([#2034](https://github.com/PrismJS/prism/issues/2034)) [`f7eaa618`](https://github.com/PrismJS/prism/commit/f7eaa618) +* __Solidity (Ethereum)__ ([#2031](https://github.com/PrismJS/prism/issues/2031)) [`cc2cf3f7`](https://github.com/PrismJS/prism/commit/cc2cf3f7) +* __SPARQL__ ([#2033](https://github.com/PrismJS/prism/issues/2033)) [`c42f877d`](https://github.com/PrismJS/prism/commit/c42f877d) +* __SQF: Status Quo Function (Arma 3)__ ([#2079](https://github.com/PrismJS/prism/issues/2079)) [`cfac94ec`](https://github.com/PrismJS/prism/commit/cfac94ec) +* __Turtle__ & __TriG__ ([#2012](https://github.com/PrismJS/prism/issues/2012)) [`508d57ac`](https://github.com/PrismJS/prism/commit/508d57ac) +* __Zig__ ([#2019](https://github.com/PrismJS/prism/issues/2019)) [`a7cf56b7`](https://github.com/PrismJS/prism/commit/a7cf56b7) + +### Updated components + +* Minor improvements for C-like and Clojure ([#2064](https://github.com/PrismJS/prism/issues/2064)) [`7db0cab3`](https://github.com/PrismJS/prism/commit/7db0cab3) +* Inlined some unnecessary rest properties ([#2082](https://github.com/PrismJS/prism/issues/2082)) [`ad3fa443`](https://github.com/PrismJS/prism/commit/ad3fa443) +* __AQL__ + * Disallow unclosed multiline comments again ([#2089](https://github.com/PrismJS/prism/issues/2089)) [`717ace02`](https://github.com/PrismJS/prism/commit/717ace02) + * Allow unclosed multi-line comments ([#2058](https://github.com/PrismJS/prism/issues/2058)) [`f3c6ba59`](https://github.com/PrismJS/prism/commit/f3c6ba59) + * More pseudo keywords ([#2055](https://github.com/PrismJS/prism/issues/2055)) [`899574eb`](https://github.com/PrismJS/prism/commit/899574eb) + * Added missing keyword + minor improvements ([#2047](https://github.com/PrismJS/prism/issues/2047)) [`32a4c422`](https://github.com/PrismJS/prism/commit/32a4c422) +* __Clojure__ + * Added multiline strings (lisp style) ([#2061](https://github.com/PrismJS/prism/issues/2061)) [`8ea685b8`](https://github.com/PrismJS/prism/commit/8ea685b8) +* __CSS Extras__ + * CSS Extras & PHP: Fixed too greedy number token ([#2009](https://github.com/PrismJS/prism/issues/2009)) [`ebe363f4`](https://github.com/PrismJS/prism/commit/ebe363f4) +* __D__ + * Fixed strings ([#2029](https://github.com/PrismJS/prism/issues/2029)) [`010a0157`](https://github.com/PrismJS/prism/commit/010a0157) +* __Groovy__ + * Minor improvements ([#2036](https://github.com/PrismJS/prism/issues/2036)) [`fb618331`](https://github.com/PrismJS/prism/commit/fb618331) +* __Java__ + * Added missing `::` operator ([#2101](https://github.com/PrismJS/prism/issues/2101)) [`ee7fdbee`](https://github.com/PrismJS/prism/commit/ee7fdbee) + * Added support for new Java 13 syntax ([#2060](https://github.com/PrismJS/prism/issues/2060)) [`a7b95dd3`](https://github.com/PrismJS/prism/commit/a7b95dd3) +* __JavaScript__ + * Added Optional Chaining and Nullish Coalescing ([#2084](https://github.com/PrismJS/prism/issues/2084)) [`fdb7de0d`](https://github.com/PrismJS/prism/commit/fdb7de0d) + * Tokenize `:` as an operator ([#2073](https://github.com/PrismJS/prism/issues/2073)) [`0e5c48d1`](https://github.com/PrismJS/prism/commit/0e5c48d1) +* __Less__ + * Fixed exponential backtracking ([#2016](https://github.com/PrismJS/prism/issues/2016)) [`d03d19b4`](https://github.com/PrismJS/prism/commit/d03d19b4) +* __Markup__ + * Improved doctype pattern ([#2094](https://github.com/PrismJS/prism/issues/2094)) [`99994c58`](https://github.com/PrismJS/prism/commit/99994c58) +* __Python__ + * Fixed decorators ([#2018](https://github.com/PrismJS/prism/issues/2018)) [`5b8a16d9`](https://github.com/PrismJS/prism/commit/5b8a16d9) +* __Robot Framework__ + * Rename "robot-framework" to "robotframework" ([#2113](https://github.com/PrismJS/prism/issues/2113)) [`baa78774`](https://github.com/PrismJS/prism/commit/baa78774) +* __Ruby__ + * Made `true` and `false` booleans ([#2098](https://github.com/PrismJS/prism/issues/2098)) [`68d1c472`](https://github.com/PrismJS/prism/commit/68d1c472) + * Added missing keywords ([#2097](https://github.com/PrismJS/prism/issues/2097)) [`f460eafc`](https://github.com/PrismJS/prism/commit/f460eafc) +* __SAS__ + * Added support for embedded Groovy and Lua code ([#2091](https://github.com/PrismJS/prism/issues/2091)) [`3640b3f2`](https://github.com/PrismJS/prism/commit/3640b3f2) + * Minor improvements ([#2085](https://github.com/PrismJS/prism/issues/2085)) [`07020c7a`](https://github.com/PrismJS/prism/commit/07020c7a) + * Fixed `proc-args` token by removing backreferences from string pattern ([#2013](https://github.com/PrismJS/prism/issues/2013)) [`af5a36ae`](https://github.com/PrismJS/prism/commit/af5a36ae) + * Major improvements ([#1981](https://github.com/PrismJS/prism/issues/1981)) [`076f6155`](https://github.com/PrismJS/prism/commit/076f6155) +* __Smalltalk__ + * Fixed single quote character literal ([#2041](https://github.com/PrismJS/prism/issues/2041)) [`1aabcd17`](https://github.com/PrismJS/prism/commit/1aabcd17) +* __Turtle__ + * Minor improvements ([#2038](https://github.com/PrismJS/prism/issues/2038)) [`8ccd258b`](https://github.com/PrismJS/prism/commit/8ccd258b) +* __TypeScript__ + * Added missing keyword `undefined` ([#2088](https://github.com/PrismJS/prism/issues/2088)) [`c8b48b9f`](https://github.com/PrismJS/prism/commit/c8b48b9f) + +### Updated plugins + +* New Match Braces plugin ([#1944](https://github.com/PrismJS/prism/issues/1944)) [`365faade`](https://github.com/PrismJS/prism/commit/365faade) +* New Inline color plugin ([#2007](https://github.com/PrismJS/prism/issues/2007)) [`8403e453`](https://github.com/PrismJS/prism/commit/8403e453) +* New Filter highlightAll plugin ([#2074](https://github.com/PrismJS/prism/issues/2074)) [`a7f70090`](https://github.com/PrismJS/prism/commit/a7f70090) +* __Custom Class__ + * New class adder feature ([#2075](https://github.com/PrismJS/prism/issues/2075)) [`dab7998e`](https://github.com/PrismJS/prism/commit/dab7998e) +* __File Highlight__ + * Made the download button its own plugin ([#1840](https://github.com/PrismJS/prism/issues/1840)) [`c6c62a69`](https://github.com/PrismJS/prism/commit/c6c62a69) + +### Other + +* Issue template improvements ([#2069](https://github.com/PrismJS/prism/issues/2069)) [`53f07b1b`](https://github.com/PrismJS/prism/commit/53f07b1b) +* Readme: Links now use HTTPS if available ([#2045](https://github.com/PrismJS/prism/issues/2045)) [`6cd0738a`](https://github.com/PrismJS/prism/commit/6cd0738a) +* __Core__ + * Fixed null reference ([#2106](https://github.com/PrismJS/prism/issues/2106)) [`0fd062d5`](https://github.com/PrismJS/prism/commit/0fd062d5) + * Fixed race condition caused by deferring the script ([#2103](https://github.com/PrismJS/prism/issues/2103)) [`a3785ec9`](https://github.com/PrismJS/prism/commit/a3785ec9) + * Minor improvements ([#1973](https://github.com/PrismJS/prism/issues/1973)) [`2d858e0a`](https://github.com/PrismJS/prism/commit/2d858e0a) + * Fixed greedy partial lookbehinds not working ([#2030](https://github.com/PrismJS/prism/issues/2030)) [`174ed103`](https://github.com/PrismJS/prism/commit/174ed103) + * Fixed greedy targeting bug ([#1932](https://github.com/PrismJS/prism/issues/1932)) [`e864d518`](https://github.com/PrismJS/prism/commit/e864d518) + * Doubly check the `manual` flag ([#1957](https://github.com/PrismJS/prism/issues/1957)) [`d49f0f26`](https://github.com/PrismJS/prism/commit/d49f0f26) + * IE11 workaround for `currentScript` ([#2104](https://github.com/PrismJS/prism/issues/2104)) [`2108c60f`](https://github.com/PrismJS/prism/commit/2108c60f) +* __Infrastructure__ + * gulp: Fixed changes task [`2f495905`](https://github.com/PrismJS/prism/commit/2f495905) + * npm: Added `.github` folder to npm ignore ([#2052](https://github.com/PrismJS/prism/issues/2052)) [`1af89e06`](https://github.com/PrismJS/prism/commit/1af89e06) + * npm: Updated dependencies to fix 122 vulnerabilities ([#1997](https://github.com/PrismJS/prism/issues/1997)) [`3af5d744`](https://github.com/PrismJS/prism/commit/3af5d744) + * Tests: New test for unused capturing groups ([#1996](https://github.com/PrismJS/prism/issues/1996)) [`c187e229`](https://github.com/PrismJS/prism/commit/c187e229) + * Tests: Simplified error message format ([#2056](https://github.com/PrismJS/prism/issues/2056)) [`007c9af4`](https://github.com/PrismJS/prism/commit/007c9af4) + * Tests: New test for nice names ([#1911](https://github.com/PrismJS/prism/issues/1911)) [`3fda5c95`](https://github.com/PrismJS/prism/commit/3fda5c95) + * Standardized dependency logic implementation ([#1998](https://github.com/PrismJS/prism/issues/1998)) [`7a4a0c7c`](https://github.com/PrismJS/prism/commit/7a4a0c7c) +* __Website__ + * Added @mAAdhaTTah and @RunDevelopment to credits and footer [`5d07aa7c`](https://github.com/PrismJS/prism/commit/5d07aa7c) + * Added plugin descriptions to plugin list ([#2076](https://github.com/PrismJS/prism/issues/2076)) [`cdfa60ac`](https://github.com/PrismJS/prism/commit/cdfa60ac) + * Use HTTPS link to alistapart.com ([#2044](https://github.com/PrismJS/prism/issues/2044)) [`8bcc1b85`](https://github.com/PrismJS/prism/commit/8bcc1b85) + * Fixed the Toolbar plugin's overflow issue ([#1966](https://github.com/PrismJS/prism/issues/1966)) [`56a8711c`](https://github.com/PrismJS/prism/commit/56a8711c) + * FAQ update ([#1977](https://github.com/PrismJS/prism/issues/1977)) [`8a572af5`](https://github.com/PrismJS/prism/commit/8a572af5) + * Use modern JavaScript in the NodeJS usage section ([#1942](https://github.com/PrismJS/prism/issues/1942)) [`5c68a556`](https://github.com/PrismJS/prism/commit/5c68a556) + * Improved test page performance for Chromium ([#2020](https://github.com/PrismJS/prism/issues/2020)) [`3509f3e5`](https://github.com/PrismJS/prism/commit/3509f3e5) + * Fixed alias example in extending page ([#2011](https://github.com/PrismJS/prism/issues/2011)) [`7cb65eec`](https://github.com/PrismJS/prism/commit/7cb65eec) + * Robot Framework: Renamed example file ([#2126](https://github.com/PrismJS/prism/issues/2126)) [`9908ca69`](https://github.com/PrismJS/prism/commit/9908ca69) + +## 1.17.1 (2019-07-21) + +### Other + +* __Infrastructure__ + * Add .DS_Store to npmignore [`c2229ec2`](https://github.com/PrismJS/prism/commit/c2229ec2) + +## 1.17.0 (2019-07-21) + +### New components + +* __DNS zone file__ ([#1961](https://github.com/PrismJS/prism/issues/1961)) [`bb84f98c`](https://github.com/PrismJS/prism/commit/bb84f98c) +* __JQ__ ([#1896](https://github.com/PrismJS/prism/issues/1896)) [`73d964be`](https://github.com/PrismJS/prism/commit/73d964be) +* __JS Templates__: Syntax highlighting inside tagged template literals ([#1931](https://github.com/PrismJS/prism/issues/1931)) [`c8844286`](https://github.com/PrismJS/prism/commit/c8844286) +* __LilyPond__ ([#1967](https://github.com/PrismJS/prism/issues/1967)) [`5d992fc5`](https://github.com/PrismJS/prism/commit/5d992fc5) +* __PascaLIGO__ ([#1947](https://github.com/PrismJS/prism/issues/1947)) [`858201c7`](https://github.com/PrismJS/prism/commit/858201c7) +* __PC-Axis__ ([#1940](https://github.com/PrismJS/prism/issues/1940)) [`473f7fbd`](https://github.com/PrismJS/prism/commit/473f7fbd) +* __Shell session__ ([#1892](https://github.com/PrismJS/prism/issues/1892)) [`96044979`](https://github.com/PrismJS/prism/commit/96044979) +* __Splunk SPL__ ([#1962](https://github.com/PrismJS/prism/issues/1962)) [`c93c066b`](https://github.com/PrismJS/prism/commit/c93c066b) + +### New plugins + +* __Diff Highlight__: Syntax highlighting inside diff blocks ([#1889](https://github.com/PrismJS/prism/issues/1889)) [`e7702ae1`](https://github.com/PrismJS/prism/commit/e7702ae1) + +### Updated components + +* __Bash__ + * Major improvements ([#1443](https://github.com/PrismJS/prism/issues/1443)) [`363281b3`](https://github.com/PrismJS/prism/commit/363281b3) +* __C#__ + * Added `cs` alias ([#1899](https://github.com/PrismJS/prism/issues/1899)) [`a8164559`](https://github.com/PrismJS/prism/commit/a8164559) +* __C++__ + * Fixed number pattern ([#1887](https://github.com/PrismJS/prism/issues/1887)) [`3de29e72`](https://github.com/PrismJS/prism/commit/3de29e72) +* __CSS__ + * Extended `url` inside ([#1874](https://github.com/PrismJS/prism/issues/1874)) [`f0a10669`](https://github.com/PrismJS/prism/commit/f0a10669) + * Removed unnecessary flag and modifier ([#1875](https://github.com/PrismJS/prism/issues/1875)) [`74050c68`](https://github.com/PrismJS/prism/commit/74050c68) +* __CSS Extras__ + * Added `even` & `odd` keywords to `n-th` pattern ([#1872](https://github.com/PrismJS/prism/issues/1872)) [`5e5a3e00`](https://github.com/PrismJS/prism/commit/5e5a3e00) +* __F#__ + * Improved character literals ([#1956](https://github.com/PrismJS/prism/issues/1956)) [`d58d2aeb`](https://github.com/PrismJS/prism/commit/d58d2aeb) +* __JavaScript__ + * Fixed escaped template interpolation ([#1931](https://github.com/PrismJS/prism/issues/1931)) [`c8844286`](https://github.com/PrismJS/prism/commit/c8844286) + * Added support for private fields ([#1950](https://github.com/PrismJS/prism/issues/1950)) [`7bd08327`](https://github.com/PrismJS/prism/commit/7bd08327) + * Added support for numeric separators ([#1895](https://github.com/PrismJS/prism/issues/1895)) [`6068bf18`](https://github.com/PrismJS/prism/commit/6068bf18) + * Increased bracket count of interpolation expressions in template strings ([#1845](https://github.com/PrismJS/prism/issues/1845)) [`c13d6e7d`](https://github.com/PrismJS/prism/commit/c13d6e7d) + * Added support for the `s` regex flag ([#1846](https://github.com/PrismJS/prism/issues/1846)) [`9e164935`](https://github.com/PrismJS/prism/commit/9e164935) + * Formatting: Added missing semicolon ([#1856](https://github.com/PrismJS/prism/issues/1856)) [`e2683959`](https://github.com/PrismJS/prism/commit/e2683959) +* __JSON__ + * Kinda fixed comment issue ([#1853](https://github.com/PrismJS/prism/issues/1853)) [`cbe05ec3`](https://github.com/PrismJS/prism/commit/cbe05ec3) +* __Julia__ + * Added `struct` keyword ([#1941](https://github.com/PrismJS/prism/issues/1941)) [`feb1b6f5`](https://github.com/PrismJS/prism/commit/feb1b6f5) + * Highlight `Inf` and `NaN` as constants ([#1921](https://github.com/PrismJS/prism/issues/1921)) [`2141129f`](https://github.com/PrismJS/prism/commit/2141129f) + * Added `in` keyword ([#1918](https://github.com/PrismJS/prism/issues/1918)) [`feb3187f`](https://github.com/PrismJS/prism/commit/feb3187f) +* __LaTeX__ + * Added TeX and ConTeXt alias ([#1915](https://github.com/PrismJS/prism/issues/1915)) [`5ad58a75`](https://github.com/PrismJS/prism/commit/5ad58a75) + * Added support for $$ equations [`6f53f749`](https://github.com/PrismJS/prism/commit/6f53f749) +* __Markdown__ + * Markdown: Added support for auto-loading code block languages ([#1898](https://github.com/PrismJS/prism/issues/1898)) [`05823e88`](https://github.com/PrismJS/prism/commit/05823e88) + * Improved URLs ([#1955](https://github.com/PrismJS/prism/issues/1955)) [`b9ec6fd8`](https://github.com/PrismJS/prism/commit/b9ec6fd8) + * Added support for nested bold and italic expressions ([#1897](https://github.com/PrismJS/prism/issues/1897)) [`11903721`](https://github.com/PrismJS/prism/commit/11903721) + * Added support for tables ([#1848](https://github.com/PrismJS/prism/issues/1848)) [`cedb8e84`](https://github.com/PrismJS/prism/commit/cedb8e84) +* __Perl__ + * Added `return` keyword ([#1943](https://github.com/PrismJS/prism/issues/1943)) [`2f39de97`](https://github.com/PrismJS/prism/commit/2f39de97) +* __Protocol Buffers__ + * Full support for PB2 and PB3 syntax + numerous other improvements ([#1948](https://github.com/PrismJS/prism/issues/1948)) [`de10bd1d`](https://github.com/PrismJS/prism/commit/de10bd1d) +* __reST (reStructuredText)__ + * Fixed exponentially backtracking pattern ([#1986](https://github.com/PrismJS/prism/issues/1986)) [`8b5d67a3`](https://github.com/PrismJS/prism/commit/8b5d67a3) +* __Rust__ + * Added `async` and `await` keywords. ([#1882](https://github.com/PrismJS/prism/issues/1882)) [`4faa3314`](https://github.com/PrismJS/prism/commit/4faa3314) + * Improved punctuation and operators ([#1839](https://github.com/PrismJS/prism/issues/1839)) [`a42b1557`](https://github.com/PrismJS/prism/commit/a42b1557) +* __Sass (Scss)__ + * Fixed exponential url pattern ([#1938](https://github.com/PrismJS/prism/issues/1938)) [`4b6b6e8b`](https://github.com/PrismJS/prism/commit/4b6b6e8b) +* __Scheme__ + * Added support for rational number literals ([#1964](https://github.com/PrismJS/prism/issues/1964)) [`e8811d22`](https://github.com/PrismJS/prism/commit/e8811d22) +* __TOML__ + * Minor improvements ([#1917](https://github.com/PrismJS/prism/issues/1917)) [`3e181241`](https://github.com/PrismJS/prism/commit/3e181241) +* __Visual Basic__ + * Added support for interpolation strings ([#1971](https://github.com/PrismJS/prism/issues/1971)) [`4a2c90c1`](https://github.com/PrismJS/prism/commit/4a2c90c1) + +### Updated plugins + +* __Autolinker__ + * Improved component path guessing ([#1928](https://github.com/PrismJS/prism/issues/1928)) [`452d5c7d`](https://github.com/PrismJS/prism/commit/452d5c7d) + * Improved URL regex ([#1842](https://github.com/PrismJS/prism/issues/1842)) [`eb28b62b`](https://github.com/PrismJS/prism/commit/eb28b62b) +* __Autoloader__ + * Fixed and improved callbacks ([#1935](https://github.com/PrismJS/prism/issues/1935)) [`b19f512f`](https://github.com/PrismJS/prism/commit/b19f512f) +* __Command Line__ + * Fix for uncaught errors for empty 'commandLine' object. ([#1862](https://github.com/PrismJS/prism/issues/1862)) [`c24831b5`](https://github.com/PrismJS/prism/commit/c24831b5) +* __Copy to Clipboard Button__ + * Switch anchor to button ([#1926](https://github.com/PrismJS/prism/issues/1926)) [`79880197`](https://github.com/PrismJS/prism/commit/79880197) +* __Custom Class__ + * Added mapper functions for language specific transformations ([#1873](https://github.com/PrismJS/prism/issues/1873)) [`acceb3b5`](https://github.com/PrismJS/prism/commit/acceb3b5) +* __Line Highlight__ + * Batching DOM read/writes to avoid reflows ([#1865](https://github.com/PrismJS/prism/issues/1865)) [`632ce00c`](https://github.com/PrismJS/prism/commit/632ce00c) +* __Toolbar__ + * Added `className` option for toolbar items ([#1951](https://github.com/PrismJS/prism/issues/1951)) [`5ab28bbe`](https://github.com/PrismJS/prism/commit/5ab28bbe) + * Set opacity to 1 when focus is within ([#1927](https://github.com/PrismJS/prism/issues/1927)) [`0b1662dd`](https://github.com/PrismJS/prism/commit/0b1662dd) + +### Updated themes + +* __Funky__ + * Fixed typo ([#1960](https://github.com/PrismJS/prism/issues/1960)) [`7d056591`](https://github.com/PrismJS/prism/commit/7d056591) + +### Other + +* README: Added npm downloads badge ([#1934](https://github.com/PrismJS/prism/issues/1934)) [`d673d701`](https://github.com/PrismJS/prism/commit/d673d701) +* README: Minor changes ([#1857](https://github.com/PrismJS/prism/issues/1857)) [`77e403cb`](https://github.com/PrismJS/prism/commit/77e403cb) +* Clearer description for the highlighting bug report template ([#1850](https://github.com/PrismJS/prism/issues/1850)) [`2f9c9261`](https://github.com/PrismJS/prism/commit/2f9c9261) +* More language examples ([#1917](https://github.com/PrismJS/prism/issues/1917)) [`3e181241`](https://github.com/PrismJS/prism/commit/3e181241) +* __Core__ + * Removed `env.elements` from `before-highlightall` hook ([#1968](https://github.com/PrismJS/prism/issues/1968)) [`9d9e2ca4`](https://github.com/PrismJS/prism/commit/9d9e2ca4) + * Made `language-none` the default language ([#1858](https://github.com/PrismJS/prism/issues/1858)) [`fd691c52`](https://github.com/PrismJS/prism/commit/fd691c52) + * Removed `parent` from the `wrap` hook's environment ([#1837](https://github.com/PrismJS/prism/issues/1837)) [`65a4e894`](https://github.com/PrismJS/prism/commit/65a4e894) +* __Infrastructure__ + * gulp: Split `gulpfile.js` and expanded `changes` task ([#1835](https://github.com/PrismJS/prism/issues/1835)) [`033c5ad8`](https://github.com/PrismJS/prism/commit/033c5ad8) + * gulp: JSON formatting for partly generated files ([#1933](https://github.com/PrismJS/prism/issues/1933)) [`d4373f3a`](https://github.com/PrismJS/prism/commit/d4373f3a) + * gulp: Use `async` functions & drop testing on Node v6 ([#1783](https://github.com/PrismJS/prism/issues/1783)) [`0dd44d53`](https://github.com/PrismJS/prism/commit/0dd44d53) + * Tests: `lookbehind` test for patterns ([#1890](https://github.com/PrismJS/prism/issues/1890)) [`3ba786cd`](https://github.com/PrismJS/prism/commit/3ba786cd) + * Tests: Added test for empty regexes ([#1847](https://github.com/PrismJS/prism/issues/1847)) [`c1e6a7fd`](https://github.com/PrismJS/prism/commit/c1e6a7fd) +* __Website__ + * Added tutorial for using PrismJS with React ([#1979](https://github.com/PrismJS/prism/issues/1979)) [`f1e16c7b`](https://github.com/PrismJS/prism/commit/f1e16c7b) + * Update footer's GitHub repository URL and capitalisation of "GitHub" ([#1983](https://github.com/PrismJS/prism/issues/1983)) [`bab744a6`](https://github.com/PrismJS/prism/commit/bab744a6) + * Added known failures page ([#1876](https://github.com/PrismJS/prism/issues/1876)) [`36a5fa0e`](https://github.com/PrismJS/prism/commit/36a5fa0e) + * Added basic usage for CDNs ([#1924](https://github.com/PrismJS/prism/issues/1924)) [`922ec555`](https://github.com/PrismJS/prism/commit/922ec555) + * New tutorial for Drupal ([#1859](https://github.com/PrismJS/prism/issues/1859)) [`d2089d83`](https://github.com/PrismJS/prism/commit/d2089d83) + * Updated website page styles to not interfere with themes ([#1952](https://github.com/PrismJS/prism/issues/1952)) [`b6543853`](https://github.com/PrismJS/prism/commit/b6543853) + * Download page: Improved performance for Chromium-based browsers ([#1907](https://github.com/PrismJS/prism/issues/1907)) [`11f18e36`](https://github.com/PrismJS/prism/commit/11f18e36) + * Download page: Fixed Edge's word wrap ([#1920](https://github.com/PrismJS/prism/issues/1920)) [`5d191b92`](https://github.com/PrismJS/prism/commit/5d191b92) + * Examples page: Minor improvements ([#1919](https://github.com/PrismJS/prism/issues/1919)) [`a16d4a25`](https://github.com/PrismJS/prism/commit/a16d4a25) + * Extending page: Fixed typo + new alias section ([#1949](https://github.com/PrismJS/prism/issues/1949)) [`24c8e717`](https://github.com/PrismJS/prism/commit/24c8e717) + * Extending page: Added "Creating a new language definition" section ([#1925](https://github.com/PrismJS/prism/issues/1925)) [`ddf81233`](https://github.com/PrismJS/prism/commit/ddf81233) + * Test page: Use `prism-core.js` instead of `prism.js` ([#1908](https://github.com/PrismJS/prism/issues/1908)) [`0853e694`](https://github.com/PrismJS/prism/commit/0853e694) + * Copy to clipboard: Fixed typo ([#1869](https://github.com/PrismJS/prism/issues/1869)) [`59d4323f`](https://github.com/PrismJS/prism/commit/59d4323f) + * JSONP Highlight: Fixed examples ([#1877](https://github.com/PrismJS/prism/issues/1877)) [`f8ae465d`](https://github.com/PrismJS/prism/commit/f8ae465d) + * Line numbers: Fixed typo on webpage ([#1838](https://github.com/PrismJS/prism/issues/1838)) [`0f16eb87`](https://github.com/PrismJS/prism/commit/0f16eb87) + +## 1.16.0 (2019-03-24) + +### New components + +* __ANBF__ ([#1753](https://github.com/PrismJS/prism/issues/1753)) [`6d98f0e7`](https://github.com/PrismJS/prism/commit/6d98f0e7) +* __BNF__ & __RBNF__ ([#1754](https://github.com/PrismJS/prism/issues/1754)) [`1df96c55`](https://github.com/PrismJS/prism/commit/1df96c55) +* __CIL__ ([#1593](https://github.com/PrismJS/prism/issues/1593)) [`38def334`](https://github.com/PrismJS/prism/commit/38def334) +* __CMake__ ([#1820](https://github.com/PrismJS/prism/issues/1820)) [`30779976`](https://github.com/PrismJS/prism/commit/30779976) +* __Doc comment__ ([#1541](https://github.com/PrismJS/prism/issues/1541)) [`493d19ef`](https://github.com/PrismJS/prism/commit/493d19ef) +* __EBNF__ ([#1756](https://github.com/PrismJS/prism/issues/1756)) [`13e1c97d`](https://github.com/PrismJS/prism/commit/13e1c97d) +* __EJS__ ([#1769](https://github.com/PrismJS/prism/issues/1769)) [`c37c90df`](https://github.com/PrismJS/prism/commit/c37c90df) +* __G-code__ ([#1572](https://github.com/PrismJS/prism/issues/1572)) [`2288c25e`](https://github.com/PrismJS/prism/commit/2288c25e) +* __GameMaker Language__ ([#1551](https://github.com/PrismJS/prism/issues/1551)) [`e529edd8`](https://github.com/PrismJS/prism/commit/e529edd8) +* __HCL__ ([#1594](https://github.com/PrismJS/prism/issues/1594)) [`c939df8e`](https://github.com/PrismJS/prism/commit/c939df8e) +* __Java stack trace__ ([#1520](https://github.com/PrismJS/prism/issues/1520)) [`4a8219a4`](https://github.com/PrismJS/prism/commit/4a8219a4) +* __JavaScript Extras__ ([#1743](https://github.com/PrismJS/prism/issues/1743)) [`bb628606`](https://github.com/PrismJS/prism/commit/bb628606) +* __JSON5__ ([#1744](https://github.com/PrismJS/prism/issues/1744)) [`64dc049d`](https://github.com/PrismJS/prism/commit/64dc049d) +* __N1QL__ ([#1620](https://github.com/PrismJS/prism/issues/1620)) [`7def8f5c`](https://github.com/PrismJS/prism/commit/7def8f5c) +* __Nand To Tetris HDL__ ([#1710](https://github.com/PrismJS/prism/issues/1710)) [`b94b56c1`](https://github.com/PrismJS/prism/commit/b94b56c1) +* __Regex__ ([#1682](https://github.com/PrismJS/prism/issues/1682)) [`571704cb`](https://github.com/PrismJS/prism/commit/571704cb) +* __T4__ ([#1699](https://github.com/PrismJS/prism/issues/1699)) [`16f2ad06`](https://github.com/PrismJS/prism/commit/16f2ad06) +* __TOML__ ([#1488](https://github.com/PrismJS/prism/issues/1488)) [`5b6ad70d`](https://github.com/PrismJS/prism/commit/5b6ad70d) +* __Vala__ ([#1658](https://github.com/PrismJS/prism/issues/1658)) [`b48c012c`](https://github.com/PrismJS/prism/commit/b48c012c) + +### Updated components + +* Fixed dependencies of Pug and Pure ([#1759](https://github.com/PrismJS/prism/issues/1759)) [`c9a32674`](https://github.com/PrismJS/prism/commit/c9a32674) +* Add file extensions support for major languages ([#1478](https://github.com/PrismJS/prism/issues/1478)) [`0c8f6504`](https://github.com/PrismJS/prism/commit/0c8f6504) +* Fixed patterns which can match the empty string ([#1775](https://github.com/PrismJS/prism/issues/1775)) [`86dd3e42`](https://github.com/PrismJS/prism/commit/86dd3e42) +* More variables for better code compression ([#1489](https://github.com/PrismJS/prism/issues/1489)) [`bc53e093`](https://github.com/PrismJS/prism/commit/bc53e093) +* Added missing aliases ([#1830](https://github.com/PrismJS/prism/issues/1830)) [`8d28c74c`](https://github.com/PrismJS/prism/commit/8d28c74c) +* Replaced all occurrences of `new RegExp` with `RegExp` ([#1493](https://github.com/PrismJS/prism/issues/1493)) [`44fed4d3`](https://github.com/PrismJS/prism/commit/44fed4d3) +* Added missing aliases to components.json ([#1503](https://github.com/PrismJS/prism/issues/1503)) [`2fb66e04`](https://github.com/PrismJS/prism/commit/2fb66e04) +* __Apacheconf__ + * Apache config: Minor improvements + new keyword ([#1823](https://github.com/PrismJS/prism/issues/1823)) [`a91be7b2`](https://github.com/PrismJS/prism/commit/a91be7b2) +* __AsciiDoc__ + * Added `adoc` alias for AsciiDoc ([#1685](https://github.com/PrismJS/prism/issues/1685)) [`88434f7a`](https://github.com/PrismJS/prism/commit/88434f7a) +* __Bash__ + * Add additional commands to bash ([#1577](https://github.com/PrismJS/prism/issues/1577)) [`a2230c38`](https://github.com/PrismJS/prism/commit/a2230c38) + * Added `yarn add` to bash functions ([#1731](https://github.com/PrismJS/prism/issues/1731)) [`3a32cb75`](https://github.com/PrismJS/prism/commit/3a32cb75) + * Added `pnpm` function to Bash ([#1734](https://github.com/PrismJS/prism/issues/1734)) [`fccfb98d`](https://github.com/PrismJS/prism/commit/fccfb98d) +* __Batch__ + * Remove batch's shell alias ([#1543](https://github.com/PrismJS/prism/issues/1543)) [`7155e60f`](https://github.com/PrismJS/prism/commit/7155e60f) +* __C__ + * Improve C language ([#1697](https://github.com/PrismJS/prism/issues/1697)) [`7eccea5c`](https://github.com/PrismJS/prism/commit/7eccea5c) +* __C-like__ + * Simplify function pattern of C-like language ([#1552](https://github.com/PrismJS/prism/issues/1552)) [`b520e1b6`](https://github.com/PrismJS/prism/commit/b520e1b6) +* __C/C++/Java__ + * Operator fixes ([#1528](https://github.com/PrismJS/prism/issues/1528)) [`7af8f8be`](https://github.com/PrismJS/prism/commit/7af8f8be) +* __C#__ + * Improvements to C# operator and punctuation ([#1532](https://github.com/PrismJS/prism/issues/1532)) [`3b1e0916`](https://github.com/PrismJS/prism/commit/3b1e0916) +* __CSS__ + * Fix tokenizing !important ([#1585](https://github.com/PrismJS/prism/issues/1585)) [`c1d6cb85`](https://github.com/PrismJS/prism/commit/c1d6cb85) + * Added the comma to the list of CSS punctuation [`7ea2ff28`](https://github.com/PrismJS/prism/commit/7ea2ff28) + * CSS: Comma punctuation ([#1632](https://github.com/PrismJS/prism/issues/1632)) [`1b812386`](https://github.com/PrismJS/prism/commit/1b812386) + * Reuse CSS selector pattern in CSS Extras ([#1637](https://github.com/PrismJS/prism/issues/1637)) [`e2f2fd19`](https://github.com/PrismJS/prism/commit/e2f2fd19) + * Fixed CSS extra variable ([#1649](https://github.com/PrismJS/prism/issues/1649)) [`9de47d3a`](https://github.com/PrismJS/prism/commit/9de47d3a) + * Identify CSS units and variables ([#1450](https://github.com/PrismJS/prism/issues/1450)) [`5fcee966`](https://github.com/PrismJS/prism/commit/5fcee966) + * Allow multiline CSS at-rules ([#1676](https://github.com/PrismJS/prism/issues/1676)) [`4f6f3c7d`](https://github.com/PrismJS/prism/commit/4f6f3c7d) + * CSS: Highlight attribute selector ([#1671](https://github.com/PrismJS/prism/issues/1671)) [`245b59d4`](https://github.com/PrismJS/prism/commit/245b59d4) + * CSS: Selectors can contain any string ([#1638](https://github.com/PrismJS/prism/issues/1638)) [`a2d445d0`](https://github.com/PrismJS/prism/commit/a2d445d0) + * CSS extras: Highlighting for pseudo class arguments ([#1650](https://github.com/PrismJS/prism/issues/1650)) [`70a40414`](https://github.com/PrismJS/prism/commit/70a40414) +* __Django__ + * Django/Jinja2 improvements ([#1800](https://github.com/PrismJS/prism/issues/1800)) [`f2467488`](https://github.com/PrismJS/prism/commit/f2467488) +* __F#__ + * Chars can only contain one character ([#1570](https://github.com/PrismJS/prism/issues/1570)) [`f96b083a`](https://github.com/PrismJS/prism/commit/f96b083a) + * Improve F# ([#1573](https://github.com/PrismJS/prism/issues/1573)) [`00bfc969`](https://github.com/PrismJS/prism/commit/00bfc969) +* __GraphQL__ + * Improved field highlighting for GraphQL ([#1711](https://github.com/PrismJS/prism/issues/1711)) [`44aeffb9`](https://github.com/PrismJS/prism/commit/44aeffb9) + * Added GraphQL improvements and tests ([#1788](https://github.com/PrismJS/prism/issues/1788)) [`b2298b12`](https://github.com/PrismJS/prism/commit/b2298b12) +* __Haskell__ + * Added `hs` alias for Haskell ([#1831](https://github.com/PrismJS/prism/issues/1831)) [`64baec3c`](https://github.com/PrismJS/prism/commit/64baec3c) +* __HTTP__ + * Improved HTTP content highlighting ([#1598](https://github.com/PrismJS/prism/issues/1598)) [`1b75da90`](https://github.com/PrismJS/prism/commit/1b75da90) +* __Ini__ + * Add support for # comments to INI language ([#1730](https://github.com/PrismJS/prism/issues/1730)) [`baf6bb0c`](https://github.com/PrismJS/prism/commit/baf6bb0c) +* __Java__ + * Add Java 10 support ([#1549](https://github.com/PrismJS/prism/issues/1549)) [`8c981a22`](https://github.com/PrismJS/prism/commit/8c981a22) + * Added module keywords to Java. ([#1655](https://github.com/PrismJS/prism/issues/1655)) [`6e250a5f`](https://github.com/PrismJS/prism/commit/6e250a5f) + * Improve Java ([#1474](https://github.com/PrismJS/prism/issues/1474)) [`81bd8f0b`](https://github.com/PrismJS/prism/commit/81bd8f0b) +* __JavaScript__ + * Fix regex for `catch` and `finally` ([#1527](https://github.com/PrismJS/prism/issues/1527)) [`ebd1b9a6`](https://github.com/PrismJS/prism/commit/ebd1b9a6) + * Highlighting of supposed classes and functions ([#1482](https://github.com/PrismJS/prism/issues/1482)) [`c40f6047`](https://github.com/PrismJS/prism/commit/c40f6047) + * Added support for JS BigInt literals ([#1542](https://github.com/PrismJS/prism/issues/1542)) [`2b62e57b`](https://github.com/PrismJS/prism/commit/2b62e57b) + * Fixed lowercase supposed class names ([#1544](https://github.com/PrismJS/prism/issues/1544)) [`a47c05ad`](https://github.com/PrismJS/prism/commit/a47c05ad) + * Fixes regex for JS examples ([#1591](https://github.com/PrismJS/prism/issues/1591)) [`b41fb8f1`](https://github.com/PrismJS/prism/commit/b41fb8f1) + * Improve regex detection in JS ([#1473](https://github.com/PrismJS/prism/issues/1473)) [`2a4758ab`](https://github.com/PrismJS/prism/commit/2a4758ab) + * Identify JavaScript function parameters ([#1446](https://github.com/PrismJS/prism/issues/1446)) [`0cc8c56a`](https://github.com/PrismJS/prism/commit/0cc8c56a) + * Improved JavaScript parameter recognization ([#1722](https://github.com/PrismJS/prism/issues/1722)) [`57a92035`](https://github.com/PrismJS/prism/commit/57a92035) + * Make `undefined` a keyword in JS ([#1740](https://github.com/PrismJS/prism/issues/1740)) [`d9fa29a8`](https://github.com/PrismJS/prism/commit/d9fa29a8) + * Fix `function-variable` in JS ([#1739](https://github.com/PrismJS/prism/issues/1739)) [`bfbea4d6`](https://github.com/PrismJS/prism/commit/bfbea4d6) + * Improved JS constant pattern ([#1737](https://github.com/PrismJS/prism/issues/1737)) [`7bcec584`](https://github.com/PrismJS/prism/commit/7bcec584) + * Improved JS function pattern ([#1736](https://github.com/PrismJS/prism/issues/1736)) [`8378ac83`](https://github.com/PrismJS/prism/commit/8378ac83) + * JS: Fixed variables named "async" ([#1738](https://github.com/PrismJS/prism/issues/1738)) [`3560c643`](https://github.com/PrismJS/prism/commit/3560c643) + * JS: Keyword fix ([#1808](https://github.com/PrismJS/prism/issues/1808)) [`f2d8e1c7`](https://github.com/PrismJS/prism/commit/f2d8e1c7) +* __JSON__ / __JSONP__ + * Fix bugs in JSON language ([#1479](https://github.com/PrismJS/prism/issues/1479)) [`74fe81c6`](https://github.com/PrismJS/prism/commit/74fe81c6) + * Adds support for comments in JSON ([#1595](https://github.com/PrismJS/prism/issues/1595)) [`8720b3e6`](https://github.com/PrismJS/prism/commit/8720b3e6) + * Cleaned up JSON ([#1596](https://github.com/PrismJS/prism/issues/1596)) [`da474c77`](https://github.com/PrismJS/prism/commit/da474c77) + * Added `keyword` alias to JSON's `null` ([#1733](https://github.com/PrismJS/prism/issues/1733)) [`eee06649`](https://github.com/PrismJS/prism/commit/eee06649) + * Fix JSONP support ([#1745](https://github.com/PrismJS/prism/issues/1745)) [`b5041cf9`](https://github.com/PrismJS/prism/commit/b5041cf9) + * Fixed JSON/JSONP examples ([#1765](https://github.com/PrismJS/prism/issues/1765)) [`ae4842db`](https://github.com/PrismJS/prism/commit/ae4842db) +* __JSX__ + * React component tags are styled as classes in JSX ([#1519](https://github.com/PrismJS/prism/issues/1519)) [`3e1a9a3d`](https://github.com/PrismJS/prism/commit/3e1a9a3d) + * Support JSX/TSX class-name with dot ([#1725](https://github.com/PrismJS/prism/issues/1725)) [`4362e42c`](https://github.com/PrismJS/prism/commit/4362e42c) +* __Less__ + * Remove useless insertBefore in LESS ([#1629](https://github.com/PrismJS/prism/issues/1629)) [`86d31793`](https://github.com/PrismJS/prism/commit/86d31793) +* __Lisp__ + * Fix Lisp exponential string pattern ([#1763](https://github.com/PrismJS/prism/issues/1763)) [`5bd182c0`](https://github.com/PrismJS/prism/commit/5bd182c0)) +* __Markdown__ + * Added strike support to markdown ([#1563](https://github.com/PrismJS/prism/issues/1563)) [`9d2fddc2`](https://github.com/PrismJS/prism/commit/9d2fddc2) + * Fixed Markdown headers ([#1557](https://github.com/PrismJS/prism/issues/1557)) [`c6584290`](https://github.com/PrismJS/prism/commit/c6584290) + * Add support for code blocks in Markdown ([#1562](https://github.com/PrismJS/prism/issues/1562)) [`b0717e70`](https://github.com/PrismJS/prism/commit/b0717e70) + * Markdown: The 'md' alias is now recognized by hooks ([#1771](https://github.com/PrismJS/prism/issues/1771)) [`8ca3d65b`](https://github.com/PrismJS/prism/commit/8ca3d65b) +* __Markup__ + * Decouple XML from Markup ([#1603](https://github.com/PrismJS/prism/issues/1603)) [`0030a4ef`](https://github.com/PrismJS/prism/commit/0030a4ef) + * Fix for markup attributes ([#1752](https://github.com/PrismJS/prism/issues/1752)) [`c3862a24`](https://github.com/PrismJS/prism/commit/c3862a24) + * Markup: Added support for CSS and JS inside of CDATAs ([#1660](https://github.com/PrismJS/prism/issues/1660)) [`57127701`](https://github.com/PrismJS/prism/commit/57127701) + * Markup `addInline` improvements ([#1798](https://github.com/PrismJS/prism/issues/1798)) [`af67c32e`](https://github.com/PrismJS/prism/commit/af67c32e) +* __Markup Templating__ + * Markup-templating improvements ([#1653](https://github.com/PrismJS/prism/issues/1653)) [`b62e282b`](https://github.com/PrismJS/prism/commit/b62e282b) +* __nginx__ + * Add new keywords to nginx ([#1587](https://github.com/PrismJS/prism/issues/1587)) [`0d73f7f5`](https://github.com/PrismJS/prism/commit/0d73f7f5) +* __PHP__ + * Update PHP keywords ([#1690](https://github.com/PrismJS/prism/issues/1690)) [`55fb0f8e`](https://github.com/PrismJS/prism/commit/55fb0f8e) + * Improve recognition of constants in PHP ([#1688](https://github.com/PrismJS/prism/issues/1688)) [`f1026b4b`](https://github.com/PrismJS/prism/commit/f1026b4b) + * Made false, true, and null constants in PHP ([#1694](https://github.com/PrismJS/prism/issues/1694)) [`439e3bd7`](https://github.com/PrismJS/prism/commit/439e3bd7) + * PHP: Fixed closing tag issue ([#1652](https://github.com/PrismJS/prism/issues/1652)) [`289ddd9b`](https://github.com/PrismJS/prism/commit/289ddd9b) +* __Python__ + * Operator keywords are now keywords ([#1617](https://github.com/PrismJS/prism/issues/1617)) [`1d1fb800`](https://github.com/PrismJS/prism/commit/1d1fb800) + * Add decorator support to Python ([#1639](https://github.com/PrismJS/prism/issues/1639)) [`2577b6e6`](https://github.com/PrismJS/prism/commit/2577b6e6) + * Improvements to Python F-strings and string prefixes ([#1642](https://github.com/PrismJS/prism/issues/1642)) [`a69c2b62`](https://github.com/PrismJS/prism/commit/a69c2b62) +* __Reason__ + * Added additional operators to Reason ([#1648](https://github.com/PrismJS/prism/issues/1648)) [`8b1bb469`](https://github.com/PrismJS/prism/commit/8b1bb469) +* __Ruby__ + * Consistent Ruby method highlighting ([#1523](https://github.com/PrismJS/prism/issues/1523)) [`72775919`](https://github.com/PrismJS/prism/commit/72775919) + * Ruby/ERB: Fixed block comments ([#1768](https://github.com/PrismJS/prism/issues/1768)) [`c805f859`](https://github.com/PrismJS/prism/commit/c805f859) +* __Rust__ + * Add missing keywords ([#1634](https://github.com/PrismJS/prism/issues/1634)) [`3590edde`](https://github.com/PrismJS/prism/commit/3590edde) +* __SAS__ + * Added new SAS keywords ([#1784](https://github.com/PrismJS/prism/issues/1784)) [`3b396ef5`](https://github.com/PrismJS/prism/commit/3b396ef5) +* __Scheme__ + * Fix function without arguments in scheme language ([#1463](https://github.com/PrismJS/prism/issues/1463)) [`12a827e7`](https://github.com/PrismJS/prism/commit/12a827e7) + * Scheme improvements ([#1556](https://github.com/PrismJS/prism/issues/1556)) [`225dd3f7`](https://github.com/PrismJS/prism/commit/225dd3f7) + * Fixed operator-like functions in Scheme ([#1467](https://github.com/PrismJS/prism/issues/1467)) [`f8c8add2`](https://github.com/PrismJS/prism/commit/f8c8add2) + * Scheme: Minor improvements ([#1814](https://github.com/PrismJS/prism/issues/1814)) [`191830f2`](https://github.com/PrismJS/prism/commit/191830f2) +* __SCSS__ + * Fixed that selector pattern can take exponential time ([#1499](https://github.com/PrismJS/prism/issues/1499)) [`0f75d9d4`](https://github.com/PrismJS/prism/commit/0f75d9d4) + * Move SCSS `property` definition ([#1633](https://github.com/PrismJS/prism/issues/1633)) [`0536fb14`](https://github.com/PrismJS/prism/commit/0536fb14) + * Add `keyword` alias for SCSS' `null` ([#1735](https://github.com/PrismJS/prism/issues/1735)) [`bd0378f0`](https://github.com/PrismJS/prism/commit/bd0378f0) +* __Smalltalk__ + * Allowed empty strings and comments ([#1747](https://github.com/PrismJS/prism/issues/1747)) [`5fd7577a`](https://github.com/PrismJS/prism/commit/5fd7577a) +* __Smarty__ + * Removed useless `insertBefore` call in Smarty ([#1677](https://github.com/PrismJS/prism/issues/1677)) [`bc49c361`](https://github.com/PrismJS/prism/commit/bc49c361) +* __SQL__ + * Added support for quote escapes to SQL strings ([#1500](https://github.com/PrismJS/prism/issues/1500)) [`a59a7926`](https://github.com/PrismJS/prism/commit/a59a7926) + * SQL Quoted variables are now greedy ([#1510](https://github.com/PrismJS/prism/issues/1510)) [`42d119a2`](https://github.com/PrismJS/prism/commit/42d119a2) +* __TypeScript__ + * Enhance definitions in TypeScript component ([#1522](https://github.com/PrismJS/prism/issues/1522)) [`11695629`](https://github.com/PrismJS/prism/commit/11695629) +* __YAML__ + * Allow YAML strings to have trailing comments ([#1602](https://github.com/PrismJS/prism/issues/1602)) [`1c5f28a9`](https://github.com/PrismJS/prism/commit/1c5f28a9) + +### Updated plugins + +* Better class name detection for plugins ([#1772](https://github.com/PrismJS/prism/issues/1772)) [`c9762c6f`](https://github.com/PrismJS/prism/commit/c9762c6f) +* __Autolinker__ + * Fix Autolinker url-decoding all tokens ([#1723](https://github.com/PrismJS/prism/issues/1723)) [`8cf20d49`](https://github.com/PrismJS/prism/commit/8cf20d49) +* __Autoloader__ + * Resolved variable name clash ([#1568](https://github.com/PrismJS/prism/issues/1568)) [`bfa5a8d9`](https://github.com/PrismJS/prism/commit/bfa5a8d9) + * Autoloader: Fixed the directory of scripts ([#1828](https://github.com/PrismJS/prism/issues/1828)) [`fd4c764f`](https://github.com/PrismJS/prism/commit/fd4c764f) + * Autoloader: Added support for aliases ([#1829](https://github.com/PrismJS/prism/issues/1829)) [`52889b5b`](https://github.com/PrismJS/prism/commit/52889b5b) +* __Command Line__ + * Fixed class regex for Command Line plugin ([#1566](https://github.com/PrismJS/prism/issues/1566)) [`9f6e5026`](https://github.com/PrismJS/prism/commit/9f6e5026) +* __File Highlight__ + * Prevent double-loading & add scope to File Highlight ([#1586](https://github.com/PrismJS/prism/issues/1586)) [`10239c14`](https://github.com/PrismJS/prism/commit/10239c14) +* __JSONP Highlight__ + * Cleanup JSONP highlight code ([#1674](https://github.com/PrismJS/prism/issues/1674)) [`28489698`](https://github.com/PrismJS/prism/commit/28489698) + * Fix typos & other issues in JSONP docs ([#1672](https://github.com/PrismJS/prism/issues/1672)) [`cd058a91`](https://github.com/PrismJS/prism/commit/cd058a91) + * JSONP highlight: Fixed minified adapter names ([#1793](https://github.com/PrismJS/prism/issues/1793)) [`5dd8f916`](https://github.com/PrismJS/prism/commit/5dd8f916) +* __Keep Markup__ + * Add unit tests to the Keep Markup plugin ([#1646](https://github.com/PrismJS/prism/issues/1646)) [`a944c418`](https://github.com/PrismJS/prism/commit/a944c418) +* __Line Numbers__ + * Added inheritance for the `line-numbers` class ([#1799](https://github.com/PrismJS/prism/issues/1799)) [`14be7489`](https://github.com/PrismJS/prism/commit/14be7489) +* __Previewers__ + * Fixed Previewers bug [#1496](https://github.com/PrismJS/prism/issues/1496) ([#1497](https://github.com/PrismJS/prism/issues/1497)) [`4b56f3c1`](https://github.com/PrismJS/prism/commit/4b56f3c1) +* __Show Invisibles__ + * Updated styles of show invisibles ([#1607](https://github.com/PrismJS/prism/issues/1607)) [`2ba62268`](https://github.com/PrismJS/prism/commit/2ba62268) + * Corrected load order of Show Invisibles ([#1612](https://github.com/PrismJS/prism/issues/1612)) [`6e0c6e86`](https://github.com/PrismJS/prism/commit/6e0c6e86) + * Show invisibles inside tokens ([#1610](https://github.com/PrismJS/prism/issues/1610)) [`1090b253`](https://github.com/PrismJS/prism/commit/1090b253) +* __Show Language__ + * Show Language plugin alias support and improvements ([#1683](https://github.com/PrismJS/prism/issues/1683)) [`4c66d72c`](https://github.com/PrismJS/prism/commit/4c66d72c) +* __Toolbar__ + * Toolbar: Minor improvements ([#1818](https://github.com/PrismJS/prism/issues/1818)) [`3ad47047`](https://github.com/PrismJS/prism/commit/3ad47047) + +### Updated themes + +* Normalized the font-size of pre and code ([#1791](https://github.com/PrismJS/prism/issues/1791)) [`878ef295`](https://github.com/PrismJS/prism/commit/878ef295) +* __Coy__ + * Correct typo ([#1508](https://github.com/PrismJS/prism/issues/1508)) [`c322fc80`](https://github.com/PrismJS/prism/commit/c322fc80) + +### Other changes + +* __Core__ + * `insertBefore` now correctly updates references ([#1531](https://github.com/PrismJS/prism/issues/1531)) [`9dfec340`](https://github.com/PrismJS/prism/commit/9dfec340) + * Invoke `callback` after `after-highlight` hook ([#1588](https://github.com/PrismJS/prism/issues/1588)) [`bfbe4464`](https://github.com/PrismJS/prism/commit/bfbe4464) + * Improve `Prism.util.type` performance ([#1545](https://github.com/PrismJS/prism/issues/1545)) [`2864fe24`](https://github.com/PrismJS/prism/commit/2864fe24) + * Remove unused `insertBefore` overload ([#1631](https://github.com/PrismJS/prism/issues/1631)) [`39686e12`](https://github.com/PrismJS/prism/commit/39686e12) + * Ignore duplicates in insertBefore ([#1628](https://github.com/PrismJS/prism/issues/1628)) [`d33d259c`](https://github.com/PrismJS/prism/commit/d33d259c) + * Remove the Prism.tokenize language parameter ([#1654](https://github.com/PrismJS/prism/issues/1654)) [`fbf0b094`](https://github.com/PrismJS/prism/commit/fbf0b094) + * Call `insert-before` hook properly ([#1709](https://github.com/PrismJS/prism/issues/1709)) [`393ab164`](https://github.com/PrismJS/prism/commit/393ab164) + * Improved languages.DFS and util.clone ([#1506](https://github.com/PrismJS/prism/issues/1506)) [`152a68ef`](https://github.com/PrismJS/prism/commit/152a68ef) + * Core: Avoid redeclaring variables in util.clone ([#1778](https://github.com/PrismJS/prism/issues/1778)) [`b06f532f`](https://github.com/PrismJS/prism/commit/b06f532f) + * Made prism-core a little more editor friendly ([#1776](https://github.com/PrismJS/prism/issues/1776)) [`bac09f0a`](https://github.com/PrismJS/prism/commit/bac09f0a) + * Applied Array.isArray ([#1804](https://github.com/PrismJS/prism/issues/1804)) [`11d0f75e`](https://github.com/PrismJS/prism/commit/11d0f75e) +* __Infrastructure__ + * Linkify changelog more + add missing PR references [`2a100db7`](https://github.com/PrismJS/prism/commit/2a100db7) + * Set default indentation size ([#1516](https://github.com/PrismJS/prism/issues/1516)) [`e63d1597`](https://github.com/PrismJS/prism/commit/e63d1597) + * Add travis repo badge to readme ([#1561](https://github.com/PrismJS/prism/issues/1561)) [`716923f4`](https://github.com/PrismJS/prism/commit/716923f4) + * Update README.md ([#1553](https://github.com/PrismJS/prism/issues/1553)) [`6d1a2c61`](https://github.com/PrismJS/prism/commit/6d1a2c61) + * Mention Prism Themes in README ([#1625](https://github.com/PrismJS/prism/issues/1625)) [`5db04656`](https://github.com/PrismJS/prism/commit/5db04656) + * Fixed CHANGELOG.md ([#1707](https://github.com/PrismJS/prism/issues/1707)) [`b1f8a65d`](https://github.com/PrismJS/prism/commit/b1f8a65d) ([#1704](https://github.com/PrismJS/prism/issues/1704)) [`66d2104a`](https://github.com/PrismJS/prism/commit/66d2104a) + * Change tested NodeJS versions ([#1651](https://github.com/PrismJS/prism/issues/1651)) [`6ec71e0b`](https://github.com/PrismJS/prism/commit/6ec71e0b) + * Inline regex source with gulp ([#1537](https://github.com/PrismJS/prism/issues/1537)) [`e894fc89`](https://github.com/PrismJS/prism/commit/e894fc89) ([#1716](https://github.com/PrismJS/prism/issues/1716)) [`217a6ea4`](https://github.com/PrismJS/prism/commit/217a6ea4) + * Improve gulp error messages with pump ([#1741](https://github.com/PrismJS/prism/issues/1741)) [`671f4ca0`](https://github.com/PrismJS/prism/commit/671f4ca0) + * Update gulp to version 4.0.0 ([#1779](https://github.com/PrismJS/prism/issues/1779)) [`06627f6a`](https://github.com/PrismJS/prism/commit/06627f6a) + * gulp: Refactoring ([#1780](https://github.com/PrismJS/prism/issues/1780)) [`6c9fe257`](https://github.com/PrismJS/prism/commit/6c9fe257) + * npm: Updated all dependencies ([#1742](https://github.com/PrismJS/prism/issues/1742)) [`9d908d5a`](https://github.com/PrismJS/prism/commit/9d908d5a) + * Tests: Pretty-printed token stream ([#1801](https://github.com/PrismJS/prism/issues/1801)) [`9ea6d600`](https://github.com/PrismJS/prism/commit/9ea6d600) + * Refactored tests ([#1795](https://github.com/PrismJS/prism/issues/1795)) [`832a9643`](https://github.com/PrismJS/prism/commit/832a9643) + * Added issue templates ([#1805](https://github.com/PrismJS/prism/issues/1805)) [`dedb475f`](https://github.com/PrismJS/prism/commit/dedb475f) + * npm: Fixed `test` script ([#1809](https://github.com/PrismJS/prism/issues/1809)) [`bc649dfa`](https://github.com/PrismJS/prism/commit/bc649dfa) + * Add command to generate CHANGELOG [`212666d3`](https://github.com/PrismJS/prism/commit/212666d3) + * Name in composer.json set to lowercase ([#1824](https://github.com/PrismJS/prism/issues/1824)) [`4f78f1d6`](https://github.com/PrismJS/prism/commit/4f78f1d6) + * Added alias tests ([#1832](https://github.com/PrismJS/prism/issues/1832)) [`5c1a6fb2`](https://github.com/PrismJS/prism/commit/5c1a6fb2) + * Travis: Fail when changed files are detected ([#1819](https://github.com/PrismJS/prism/issues/1819)) [`66b44e3b`](https://github.com/PrismJS/prism/commit/66b44e3b) + * Tests: Additional checks for Prism functions ([#1803](https://github.com/PrismJS/prism/issues/1803)) [`c3e74ea3`](https://github.com/PrismJS/prism/commit/c3e74ea3) + * Adjusted .npmignore ([#1834](https://github.com/PrismJS/prism/issues/1834)) [`29a30c62`](https://github.com/PrismJS/prism/commit/29a30c62) +* __Website__ + * Add Python triple-quoted strings "known failure" ([#1449](https://github.com/PrismJS/prism/issues/1449)) [`334c7bca`](https://github.com/PrismJS/prism/commit/334c7bca) + * Updated index.html to fix broken instructions ([#1462](https://github.com/PrismJS/prism/issues/1462)) [`7418dfdd`](https://github.com/PrismJS/prism/commit/7418dfdd) + * Improve download page typography ([#1484](https://github.com/PrismJS/prism/issues/1484)) [`b1c2f4df`](https://github.com/PrismJS/prism/commit/b1c2f4df) + * Fixed peer dependencies in download page ([#1491](https://github.com/PrismJS/prism/issues/1491)) [`9d15ff6e`](https://github.com/PrismJS/prism/commit/9d15ff6e) + * Fixed empty link in extending ([#1507](https://github.com/PrismJS/prism/issues/1507)) [`74916d48`](https://github.com/PrismJS/prism/commit/74916d48) + * Display language aliases ([#1626](https://github.com/PrismJS/prism/issues/1626)) [`654b527b`](https://github.com/PrismJS/prism/commit/654b527b) + * Clean up Previewers' page ([#1630](https://github.com/PrismJS/prism/issues/1630)) [`b0d1823c`](https://github.com/PrismJS/prism/commit/b0d1823c) + * Updated website table of contents styles ([#1681](https://github.com/PrismJS/prism/issues/1681)) [`efdd96c3`](https://github.com/PrismJS/prism/commit/efdd96c3) + * Added new third-party tutorial for using Prism in Gutenberg ([#1701](https://github.com/PrismJS/prism/issues/1701)) [`ff9ccbe5`](https://github.com/PrismJS/prism/commit/ff9ccbe5) + * Remove dead tutorial ([#1702](https://github.com/PrismJS/prism/issues/1702)) [`e2d3bc7e`](https://github.com/PrismJS/prism/commit/e2d3bc7e) + * Fix downloads page fetching from GitHub([#1684](https://github.com/PrismJS/prism/issues/1684)) [`dbd3555e`](https://github.com/PrismJS/prism/commit/dbd3555e) + * Remove parentheses from download page ([#1627](https://github.com/PrismJS/prism/issues/1627)) [`2ce0666d`](https://github.com/PrismJS/prism/commit/2ce0666d) + * Line Numbers plugin instructions clarifications ([#1719](https://github.com/PrismJS/prism/issues/1719)) [`00f4f04f`](https://github.com/PrismJS/prism/commit/00f4f04f) + * Fixed Toolbar plugin example ([#1726](https://github.com/PrismJS/prism/issues/1726)) [`5311ca32`](https://github.com/PrismJS/prism/commit/5311ca32) + * Test page: Show tokens option ([#1757](https://github.com/PrismJS/prism/issues/1757)) [`729cb28b`](https://github.com/PrismJS/prism/commit/729cb28b) + * Some encouragement for visitors of PrismJS.com to request new languages ([#1760](https://github.com/PrismJS/prism/issues/1760)) [`ea769e0b`](https://github.com/PrismJS/prism/commit/ea769e0b) + * Docs: Added missing parameter ([#1774](https://github.com/PrismJS/prism/issues/1774)) [`18f2921d`](https://github.com/PrismJS/prism/commit/18f2921d) + * More persistent test page ([#1529](https://github.com/PrismJS/prism/issues/1529)) [`3100fa31`](https://github.com/PrismJS/prism/commit/3100fa31) + * Added scripts directory ([#1781](https://github.com/PrismJS/prism/issues/1781)) [`439ea1ee`](https://github.com/PrismJS/prism/commit/439ea1ee) + * Fixed download page ([#1811](https://github.com/PrismJS/prism/issues/1811)) [`77c57446`](https://github.com/PrismJS/prism/commit/77c57446) + +## 1.15.0 (2018-06-16) + +### New components + +* __Template Tookit 2__ ([#1418](https://github.com/PrismJS/prism/issues/1418)) [[`e063992`](https://github.com/PrismJS/prism/commit/e063992)] +* __XQuery__ ([#1411](https://github.com/PrismJS/prism/issues/1411)) [[`e326cb0`](https://github.com/PrismJS/prism/commit/e326cb0)] +* __TAP__ ([#1430](https://github.com/PrismJS/prism/issues/1430)) [[`8c2b71f`](https://github.com/PrismJS/prism/commit/8c2b71f)] + +### Updated components + +* __HTTP__ + * Absolute path is a valid request uri ([#1388](https://github.com/PrismJS/prism/issues/1388)) [[`f6e81cb`](https://github.com/PrismJS/prism/commit/f6e81cb)] +* __Kotlin__ + * Add keywords of Kotlin and modify it's number pattern. ([#1389](https://github.com/PrismJS/prism/issues/1389)) [[`1bf73b0`](https://github.com/PrismJS/prism/commit/1bf73b0)] + * Add `typealias` keyword ([#1437](https://github.com/PrismJS/prism/issues/1437)) [[`a21fdee`](https://github.com/PrismJS/prism/commit/a21fdee)] +* __JavaScript__ + * Improve Regexp pattern [[`5b043cf`](https://github.com/PrismJS/prism/commit/5b043cf)] + * Add support for one level of nesting inside template strings. Fix [#1397](https://github.com/PrismJS/prism/issues/1397) [[`db2d0eb`](https://github.com/PrismJS/prism/commit/db2d0eb)] +* __Elixir__ + * Elixir: Fix attributes consuming punctuation. Fix [#1392](https://github.com/PrismJS/prism/issues/1392) [[`dac0485`](https://github.com/PrismJS/prism/commit/dac0485)] +* __Bash__ + * Change reserved keyword reference ([#1396](https://github.com/PrismJS/prism/issues/1396)) [[`b94f01f`](https://github.com/PrismJS/prism/commit/b94f01f)] +* __PowerShell__ + * Allow for one level of nesting in expressions inside strings. Fix [#1407](https://github.com/PrismJS/prism/issues/1407) [[`9272d6f`](https://github.com/PrismJS/prism/commit/9272d6f)] +* __JSX__ + * Allow for two levels of nesting inside JSX tags. Fix [#1408](https://github.com/PrismJS/prism/issues/1408) [[`f1cd7c5`](https://github.com/PrismJS/prism/commit/f1cd7c5)] + * Add support for fragments short syntax. Fix [#1421](https://github.com/PrismJS/prism/issues/1421) [[`38ce121`](https://github.com/PrismJS/prism/commit/38ce121)] +* __Pascal__ + * Add `objectpascal` as an alias to `pascal` ([#1426](https://github.com/PrismJS/prism/issues/1426)) [[`a0bfc84`](https://github.com/PrismJS/prism/commit/a0bfc84)] +* __Swift__ + * Fix Swift 'protocol' keyword ([#1440](https://github.com/PrismJS/prism/issues/1440)) [[`081e318`](https://github.com/PrismJS/prism/commit/081e318)] + +### Updated plugins + +* __File Highlight__ + * Fix issue causing the Download button to show up on every code blocks. [[`cd22499`](https://github.com/PrismJS/prism/commit/cd22499)] + * Simplify lang regex on File Highlight plugin ([#1399](https://github.com/PrismJS/prism/issues/1399)) [[`7bc9a4a`](https://github.com/PrismJS/prism/commit/7bc9a4a)] +* __Show Language__ + * Don't process language if block language not set ([#1410](https://github.com/PrismJS/prism/issues/1410)) [[`c111869`](https://github.com/PrismJS/prism/commit/c111869)] +* __Autoloader__ + * ASP.NET should require C# [[`fa328bb`](https://github.com/PrismJS/prism/commit/fa328bb)] +* __Line Numbers__ + * Make line-numbers styles more specific ([#1434](https://github.com/PrismJS/prism/issues/1434), [#1435](https://github.com/PrismJS/prism/issues/1435)) [[`9ee4f54`](https://github.com/PrismJS/prism/commit/9ee4f54)] + +### Updated themes + +* Add .token.class-name to rest of themes ([#1360](https://github.com/PrismJS/prism/issues/1360)) [[`f356dfe`](https://github.com/PrismJS/prism/commit/f356dfe)] + +### Other changes + +* __Website__ + * Site now loads over HTTPS! + * Use HTTPS / canonical URLs ([#1390](https://github.com/PrismJS/prism/issues/1390)) [[`95146c8`](https://github.com/PrismJS/prism/commit/95146c8)] + * Added Angular tutorial link [[`c436a7c`](https://github.com/PrismJS/prism/commit/c436a7c)] + * Use rel="icon" instead of rel="shortcut icon" ([#1398](https://github.com/PrismJS/prism/issues/1398)) [[`d95f8fb`](https://github.com/PrismJS/prism/commit/d95f8fb)] + * Fix Download page not handling multiple dependencies when from Redownload URL [[`c2ff248`](https://github.com/PrismJS/prism/commit/c2ff248)] + * Update documentation for node & webpack usage [[`1e99e96`](https://github.com/PrismJS/prism/commit/1e99e96)] +* Handle optional dependencies in `loadLanguages()` ([#1417](https://github.com/PrismJS/prism/issues/1417)) [[`84935ac`](https://github.com/PrismJS/prism/commit/84935ac)] +* Add Chinese translation [[`f2b1964`](https://github.com/PrismJS/prism/commit/f2b1964)] + ## 1.14.0 (2018-04-11) ### New components -* __GEDCOM__ (#1385) [6e0b20a41c4def9739196113f845e9ba77769ad8] -* __Lisp__ (#1297) [46468f84f4d304b4c572f30b7600a637b670b821] -* __Markup Templating__ (#1367) [5f9c078a10237699aa0a6268903ecdae10bd7f4c] -* __Soy__ (#1387) [b4509bf55e057ad7dd92e4b78528bfd799c625b7] -* __Velocity__ (#1378) [5a524f7e3d2fbae35593db74494de0cec1770a7b] -* __Visual Basic__ (#1382) [c673ec29a3209d040253fb5f4ec2f498343adaea] -* __WebAssembly__ (#1386) [c28d8c5e3710d6ce0f91bf96f87c8d0f5a35a057] +* __GEDCOM__ ([#1385](https://github.com/PrismJS/prism/issues/1385)) [[`6e0b20a`](https://github.com/PrismJS/prism/commit/6e0b20a)] +* __Lisp__ ([#1297](https://github.com/PrismJS/prism/issues/1297)) [[`46468f8`](https://github.com/PrismJS/prism/commit/46468f8)] +* __Markup Templating__ ([#1367](https://github.com/PrismJS/prism/issues/1367)) [[`5f9c078`](https://github.com/PrismJS/prism/commit/5f9c078)] +* __Soy__ ([#1387](https://github.com/PrismJS/prism/issues/1387)) [[`b4509bf`](https://github.com/PrismJS/prism/commit/b4509bf)] +* __Velocity__ ([#1378](https://github.com/PrismJS/prism/issues/1378)) [[`5a524f7`](https://github.com/PrismJS/prism/commit/5a524f7)] +* __Visual Basic__ ([#1382](https://github.com/PrismJS/prism/issues/1382)) [[`c673ec2`](https://github.com/PrismJS/prism/commit/c673ec2)] +* __WebAssembly__ ([#1386](https://github.com/PrismJS/prism/issues/1386)) [[`c28d8c5`](https://github.com/PrismJS/prism/commit/c28d8c5)] ### Updated components * __Bash__: - * Add curl to the list of common functions. Close #1160 [1bfc084836254e3d06a3dffbedce258c58966312] + * Add curl to the list of common functions. Close [#1160](https://github.com/PrismJS/prism/issues/1160) [[`1bfc084`](https://github.com/PrismJS/prism/commit/1bfc084)] * __C-like__: - * Make single-line comments greedy. Fix #1337. Make sure #1340 stays fixed. [571f2c507a96e3e2356dcc7219690071b62412d4] + * Make single-line comments greedy. Fix [#1337](https://github.com/PrismJS/prism/issues/1337). Make sure [#1340](https://github.com/PrismJS/prism/issues/1340) stays fixed. [[`571f2c5`](https://github.com/PrismJS/prism/commit/571f2c5)] * __C#__: - * More generic class-name highlighting. Fix #1365 [a6837d24da56845a14b6f7f042093e735cc99966] - * More specific class-name highlighting. Fix #1371 [0a95f69d97c4638d9111fc96300f7e75fe81c0b0] + * More generic class-name highlighting. Fix [#1365](https://github.com/PrismJS/prism/issues/1365) [[`a6837d2`](https://github.com/PrismJS/prism/commit/a6837d2)] + * More specific class-name highlighting. Fix [#1371](https://github.com/PrismJS/prism/issues/1371) [[`0a95f69`](https://github.com/PrismJS/prism/commit/0a95f69)] * __Eiffel__: - * Fix verbatim strings. Fix #1379 [04df41b3374f96d86d773360b644b57ed87e6ef8] + * Fix verbatim strings. Fix [#1379](https://github.com/PrismJS/prism/issues/1379) [[`04df41b`](https://github.com/PrismJS/prism/commit/04df41b)] * __Elixir__ - * Make regexps greedy, remove comment hacks. Update known failures and tests. [e93d61f304492dcdc7799aa8418a1b76aaa04e1d] + * Make regexps greedy, remove comment hacks. Update known failures and tests. [[`e93d61f`](https://github.com/PrismJS/prism/commit/e93d61f)] * __ERB__: - * Make highlighting work properly in NodeJS (#1367) [5f9c078a10237699aa0a6268903ecdae10bd7f4c] + * Make highlighting work properly in NodeJS ([#1367](https://github.com/PrismJS/prism/issues/1367)) [[`5f9c078`](https://github.com/PrismJS/prism/commit/5f9c078)] * __Fortran__: - * Make single-line comments greedy. Update known failures and tests. [c083b78c4ffc66f982f708c96ade9f3703f14efa] + * Make single-line comments greedy. Update known failures and tests. [[`c083b78`](https://github.com/PrismJS/prism/commit/c083b78)] * __Handlebars__: - * Make highlighting work properly in NodeJS (#1367) [5f9c078a10237699aa0a6268903ecdae10bd7f4c] + * Make highlighting work properly in NodeJS ([#1367](https://github.com/PrismJS/prism/issues/1367)) [[`5f9c078`](https://github.com/PrismJS/prism/commit/5f9c078)] * __Java__: - * Add support for generics. Fix #1351 [a5cf3025b99cfc2d6a757c77400dea1d7cb3606b] + * Add support for generics. Fix [#1351](https://github.com/PrismJS/prism/issues/1351) [[`a5cf302`](https://github.com/PrismJS/prism/commit/a5cf302)] * __JavaScript__: - * Add support for constants. Fix #1348 [9084481f3705b3792b439bd6d1b8bf98002905f4] - * Improve Regex matching [172d351a2a4dbd81a1a5dac7674af461d554b61d] + * Add support for constants. Fix [#1348](https://github.com/PrismJS/prism/issues/1348) [[`9084481`](https://github.com/PrismJS/prism/commit/9084481)] + * Improve Regex matching [[`172d351`](https://github.com/PrismJS/prism/commit/172d351)] * __JSX__: - * Fix highlighting of empty objects. Fix #1364 [b26bbb8383106add989efbeee11185136504d87a] + * Fix highlighting of empty objects. Fix [#1364](https://github.com/PrismJS/prism/issues/1364) [[`b26bbb8`](https://github.com/PrismJS/prism/commit/b26bbb8)] * __Monkey__: - * Make comments greedy. Update known failures and tests. [d7b2b43c8556814081950f14ad59d6d464f03b9a] + * Make comments greedy. Update known failures and tests. [[`d7b2b43`](https://github.com/PrismJS/prism/commit/d7b2b43)] * __PHP__: - * Make highlighting work properly in NodeJS (#1367) [5f9c078a10237699aa0a6268903ecdae10bd7f4c] + * Make highlighting work properly in NodeJS ([#1367](https://github.com/PrismJS/prism/issues/1367)) [[`5f9c078`](https://github.com/PrismJS/prism/commit/5f9c078)] * __Puppet__: - * Make heredoc, comments, regexps and strings greedy. Update known failures and tests. [0c139d1f5cf630fc3f90e851ca3ff8b0c57b0864] + * Make heredoc, comments, regexps and strings greedy. Update known failures and tests. [[`0c139d1`](https://github.com/PrismJS/prism/commit/0c139d1)] * __Q__: - * Make comments greedy. Update known failures and tests. [a0f50811d327b59421bf20ae3ccf62346ac60a5d] + * Make comments greedy. Update known failures and tests. [[`a0f5081`](https://github.com/PrismJS/prism/commit/a0f5081)] * __Ruby__: - * Make multi-line comments greedy, remove single-line comment hack. Update known failures and tests. [b0e34fbef0f27e0143c0b1f698c309e717463f2a] + * Make multi-line comments greedy, remove single-line comment hack. Update known failures and tests. [[`b0e34fb`](https://github.com/PrismJS/prism/commit/b0e34fb)] * __SQL__: - * Add missing keywords. Fix #1374 [238b195207223156f8d3587875b4a27b8baf00fc] + * Add missing keywords. Fix [#1374](https://github.com/PrismJS/prism/issues/1374) [[`238b195`](https://github.com/PrismJS/prism/commit/238b195)] ### Updated plugins * __Command Line__: - * Command Line: Allow specifying output prefix using data-filter-output attribute. (#856) [094d5463f6bab69d334231b403f440ad74a76026] + * Command Line: Allow specifying output prefix using data-filter-output attribute. ([#856](https://github.com/PrismJS/prism/issues/856)) [[`094d546`](https://github.com/PrismJS/prism/commit/094d546)] * __File Highlight__: - * Add option to provide a download button, when used with the Toolbar plugin. Fix #1030 [9f22952deb41300c4ab615bd5183484d9531e80e] + * Add option to provide a download button, when used with the Toolbar plugin. Fix [#1030](https://github.com/PrismJS/prism/issues/1030) [[`9f22952`](https://github.com/PrismJS/prism/commit/9f22952)] ### Updated themes * __Default__: - * Reach AA contrast ratio level (#1296) [8aea939a6287f0147d1d64d3f0a238b6cadbc9c6] + * Reach AA contrast ratio level ([#1296](https://github.com/PrismJS/prism/issues/1296)) [[`8aea939`](https://github.com/PrismJS/prism/commit/8aea939)] ### Other changes -* Website: Remove broken third-party tutorials from homepage [0efd6e1674cef322cfb51559f3b059ca160c76f6] -* Docs: Mention `loadLanguages()` function on homepage in the nodeJS section. Close #972, close #593 [4a14d208bc04ff4f790b71466c4299a35b169bb1] -* Core: Greedy patterns should always be matched against the full string. Fix #1355 [294efaae75e9a7614831080c3aed484ba713f6e3] -* Crystal: Update known failures. [e1d2d420ae1ef78d95bb2c1feba3dd4c5f3614ab] -* D: Update known failures and tests. [13d9991536ab6fdbc570571d0617a136956a6854] -* Markdown: Update known failures. [5b6c76dc56ae03c6044075ee238b307efff77405] -* Matlab: Update known failures. [259b6fc5abd5eec4e528a3b24c0dc8854efdc164] -* Website: Remove non-existent anchor to failures. Reword on homepage to make is less misleading. [8c0911acb9eba2e3d3c540678a13ae7368168872] -* Website: Add link to Keep Markup plugin in FAQ [e8cb6d4c4dd31a73c8956ed070f75bb358687b7b] -* Test suite: Memory leak in vm.runInNewContext() seems fixed. Revert [9a4b6fa3ec770a382eccc149b849cc1c3112aa53] to drastically improve tests execution time. [9bceece812bcfc658399a5c98799c308a9638828, 7c7602b49cfd331ce8bd2368f0a6eeb5a27765bd] -* Gulp: Don't minify `components/index.js` [689227ba1a04151ca243c98429cc04f70ba20ac2] -* Website: Fix theme selection on Download page, when theme is in query string or hash. [b4d3063f41505ddf7c1d6424e65cbb6ce69f300d] -* Update JSPM config to also include unminified components. Close #995 [218f1603204b131749d8497d50b0c6b616a52e83] -* Core: Fix support for language alias containing dash `-` [659ea3141cb3cf9cd9414d2d07fed01ef552abd5] +* Website: Remove broken third-party tutorials from homepage [[`0efd6e1`](https://github.com/PrismJS/prism/commit/0efd6e1)] +* Docs: Mention `loadLanguages()` function on homepage in the nodeJS section. Close [#972](https://github.com/PrismJS/prism/issues/972), close [#593](https://github.com/PrismJS/prism/issues/593) [[`4a14d20`](https://github.com/PrismJS/prism/commit/4a14d20)] +* Core: Greedy patterns should always be matched against the full string. Fix [#1355](https://github.com/PrismJS/prism/issues/1355) [[`294efaa`](https://github.com/PrismJS/prism/commit/294efaa)] +* Crystal: Update known failures. [[`e1d2d42`](https://github.com/PrismJS/prism/commit/e1d2d42)] +* D: Update known failures and tests. [[`13d9991`](https://github.com/PrismJS/prism/commit/13d9991)] +* Markdown: Update known failures. [[`5b6c76d`](https://github.com/PrismJS/prism/commit/5b6c76d)] +* Matlab: Update known failures. [[`259b6fc`](https://github.com/PrismJS/prism/commit/259b6fc)] +* Website: Remove non-existent anchor to failures. Reword on homepage to make is less misleading. [[`8c0911a`](https://github.com/PrismJS/prism/commit/8c0911a)] +* Website: Add link to Keep Markup plugin in FAQ [[`e8cb6d4`](https://github.com/PrismJS/prism/commit/e8cb6d4)] +* Test suite: Memory leak in vm.runInNewContext() seems fixed. Revert [[`9a4b6fa`](https://github.com/PrismJS/prism/commit/9a4b6fa)] to drastically improve tests execution time. [[`9bceece`](https://github.com/PrismJS/prism/commit/9bceece), [`7c7602b`](https://github.com/PrismJS/prism/commit/7c7602b)] +* Gulp: Don't minify `components/index.js` [[`689227b`](https://github.com/PrismJS/prism/commit/689227b)] +* Website: Fix theme selection on Download page, when theme is in query string or hash. [[`b4d3063`](https://github.com/PrismJS/prism/commit/b4d3063)] +* Update JSPM config to also include unminified components. Close [#995](https://github.com/PrismJS/prism/issues/995) [[`218f160`](https://github.com/PrismJS/prism/commit/218f160)] +* Core: Fix support for language alias containing dash `-` [[`659ea31`](https://github.com/PrismJS/prism/commit/659ea31)] ## 1.13.0 (2018-03-21) @@ -87,15 +1737,15 @@ * __Markup__: * Make tags greedy. Fix [#1356](https://github.com/PrismJS/prism/issues/1356) [[`af834be`](https://github.com/PrismJS/prism/commit/af834be)] * __Powershell__: - * Add lookbehind to fix function interpolation inside strings. Fix [#1361](https://github.com/PrismJS/prism/issues/1361) [[`d2c026e`](https://github.com/PrismJS/prism/commit/d2c026e)] + * Add lookbehind to fix function interpolation inside strings. Fix [#1361](https://github.com/PrismJS/prism/issues/1361) [[`d2c026e`](https://github.com/PrismJS/prism/commit/d2c026e)] * __Rust__: - * Improve char pattern so that lifetime annotations are matched better. Fix [#1353](https://github.com/PrismJS/prism/issues/1353) [[`efdccbf`](https://github.com/PrismJS/prism/commit/efdccbf)] + * Improve char pattern so that lifetime annotations are matched better. Fix [#1353](https://github.com/PrismJS/prism/issues/1353) [[`efdccbf`](https://github.com/PrismJS/prism/commit/efdccbf)] ### Updated themes * __Default__: - * Add color for class names [[`8572474`](https://github.com/PrismJS/prism/commit/8572474)] + * Add color for class names [[`8572474`](https://github.com/PrismJS/prism/commit/8572474)] * __Coy__: - * Inherit pre's height on code, so it does not break on Download page. [[`c6c7fd1`](https://github.com/PrismJS/prism/commit/c6c7fd1)] + * Inherit pre's height on code, so it does not break on Download page. [[`c6c7fd1`](https://github.com/PrismJS/prism/commit/c6c7fd1)] ### Other changes * Website: Auto-generate example headers [[`c3ed5b5`](https://github.com/PrismJS/prism/commit/c3ed5b5)] @@ -126,7 +1776,7 @@ ## 1.12.0 (2018-03-07) ### New components -* __ARFF__ ([#1327](https://github.com/PrismJS/prism/issues/1327)) [[`0bc98ac`](https://github.com/PrismJS/prism/commit/0bc98ac)] +* __ARFF__ ([#1327](https://github.com/PrismJS/prism/issues/1327)) [[`0bc98ac`](https://github.com/PrismJS/prism/commit/0bc98ac)] * __Clojure__ ([#1311](https://github.com/PrismJS/prism/issues/1311)) [[`8b4d3bd`](https://github.com/PrismJS/prism/commit/8b4d3bd)] * __Liquid__ ([#1326](https://github.com/PrismJS/prism/issues/1326)) [[`f0b2c9e`](https://github.com/PrismJS/prism/commit/f0b2c9e)] @@ -150,7 +1800,7 @@ * __Ruby__: * Add keywords "protected", "private" and "public" [[`4593837`](https://github.com/PrismJS/prism/commit/4593837)] * __Rust__: - * Add support for lifetime-annotation and => operator. Fix [#1339](https://github.com/PrismJS/prism/issues/1339) [[`926f6f8`](https://github.com/PrismJS/prism/commit/926f6f8)] + * Add support for lifetime-annotation and => operator. Fix [#1339](https://github.com/PrismJS/prism/issues/1339) [[`926f6f8`](https://github.com/PrismJS/prism/commit/926f6f8)] * __Scheme__: * Don't highlight first number of a list as a function. Fix [#1331](https://github.com/PrismJS/prism/issues/1331) [[`51bff80`](https://github.com/PrismJS/prism/commit/51bff80)] * __SQL__: @@ -158,7 +1808,7 @@ ### Updated plugins * __Autolinker__: - * Allow more chars in query string and hash to match more URLs. Fix [#1142](https://github.com/PrismJS/prism/issues/1142) [[`109bd6f`](https://github.com/PrismJS/prism/commit/109bd6f)] + * Allow more chars in query string and hash to match more URLs. Fix [#1142](https://github.com/PrismJS/prism/issues/1142) [[`109bd6f`](https://github.com/PrismJS/prism/commit/109bd6f)] * __Copy to Clipboard__: * Bump ClipboardJS to 2.0.0 and remove hack ([#1314](https://github.com/PrismJS/prism/issues/1314)) [[`e9f410e`](https://github.com/PrismJS/prism/commit/e9f410e)] * __Toolbar__: @@ -213,7 +1863,7 @@ * __Previewers__: * New plugin combining previous plugins Previewer: Base, Previewer: Angle, Previewer: Color, Previewer: Easing, Previewer: Gradient and Previewer: Time. ([#1244](https://github.com/PrismJS/prism/issues/1244)) [[`28e4b4c`](https://github.com/PrismJS/prism/commit/28e4b4c)] * __Unescaped Markup__: - * Make it work with any language ([#1265](https://github.com/PrismJS/prism/issues/1265)) [[`7bcdae7`](https://github.com/PrismJS/prism/commit/7bcdae7)] + * Make it work with any language ([#1265](https://github.com/PrismJS/prism/issues/1265)) [[`7bcdae7`](https://github.com/PrismJS/prism/commit/7bcdae7)] ### Other changes * Add attribute `style` in `package.json` ([#1256](https://github.com/PrismJS/prism/issues/1256)) [[`a9b6785`](https://github.com/PrismJS/prism/commit/a9b6785)] @@ -229,9 +1879,9 @@ * __JSX__: * JSX: Improve highlighting support. Fix [#1235](https://github.com/PrismJS/prism/issues/1235) and [#1236](https://github.com/PrismJS/prism/issues/1236) [[`f41c5cd`](https://github.com/PrismJS/prism/commit/f41c5cd)] * __Markup__: - * Make CSS and JS inclusions in Markup greedy. Fix [#1240](https://github.com/PrismJS/prism/issues/1240) [[`7dc1e45`](https://github.com/PrismJS/prism/commit/7dc1e45)] + * Make CSS and JS inclusions in Markup greedy. Fix [#1240](https://github.com/PrismJS/prism/issues/1240) [[`7dc1e45`](https://github.com/PrismJS/prism/commit/7dc1e45)] * __PHP__: - * Add support for multi-line strings. Fix [#1233](https://github.com/PrismJS/prism/issues/1233) [[`9a542a0`](https://github.com/PrismJS/prism/commit/9a542a0)] + * Add support for multi-line strings. Fix [#1233](https://github.com/PrismJS/prism/issues/1233) [[`9a542a0`](https://github.com/PrismJS/prism/commit/9a542a0)] ### Updated plugins * __Copy to clipboard__: @@ -240,7 +1890,7 @@ * __Line highlight__: * Fixes to compatibility of line number and line higlight plugins ([#1194](https://github.com/PrismJS/prism/issues/1194)) [[`e63058f`](https://github.com/PrismJS/prism/commit/e63058f), [`3842a91`](https://github.com/PrismJS/prism/commit/3842a91)] * __Unescaped Markup__: - * Fix ambiguity in documentation by improving examples. Fix [#1197](https://github.com/PrismJS/prism/issues/1197) [[`924784a`](https://github.com/PrismJS/prism/commit/924784a)] + * Fix ambiguity in documentation by improving examples. Fix [#1197](https://github.com/PrismJS/prism/issues/1197) [[`924784a`](https://github.com/PrismJS/prism/commit/924784a)] ### Other changes * Allow any element being root instead of document. ([#1230](https://github.com/PrismJS/prism/issues/1230)) [[`69f2e2c`](https://github.com/PrismJS/prism/commit/69f2e2c), [`6e50d44`](https://github.com/PrismJS/prism/commit/6e50d44)] @@ -253,7 +1903,7 @@ ### Updated components * __ABAP__: - * Regexp optimisation [[`7547f83`](https://github.com/PrismJS/prism/commit/7547f83)] + * Regexp optimisation [[`e7b411e`](https://github.com/PrismJS/prism/commit/e7b411e)] * __ActionScript__: * Fix XML regex + optimise [[`75d00d7`](https://github.com/PrismJS/prism/commit/75d00d7)] * __Ada__: @@ -303,78 +1953,78 @@ * __Elixir__: * Regexp optimisation + uniform behavior between ~r and ~s [[`5d12e80`](https://github.com/PrismJS/prism/commit/5d12e80)] * __Erlang__: - * Regexp optimisation [[`e7b411e`](https://github.com/PrismJS/prism/commit/e7b411e)] + * Regexp optimisation [[`7547f83`](https://github.com/PrismJS/prism/commit/7547f83)] * __F#__: - * Regexp optimisation + don't use captures if not needed [[`7753fc4`](https://github.com/PrismJS/prism/commit/7753fc4)] + * Regexp optimisation + don't use captures if not needed [[`7753fc4`](https://github.com/PrismJS/prism/commit/7753fc4)] * __Gherkin__: - * Regexp optimisation + don't use captures if not needed + added explanation comment on table-body regexp [[`f26197a`](https://github.com/PrismJS/prism/commit/f26197a)] + * Regexp optimisation + don't use captures if not needed + added explanation comment on table-body regexp [[`f26197a`](https://github.com/PrismJS/prism/commit/f26197a)] * __Git__: - * Regexp optimisation [[`b9483b9`](https://github.com/PrismJS/prism/commit/b9483b9)] + * Regexp optimisation [[`b9483b9`](https://github.com/PrismJS/prism/commit/b9483b9)] * __GLSL__: - * Regexp optimisation [[`e66d21b`](https://github.com/PrismJS/prism/commit/e66d21b)] + * Regexp optimisation [[`e66d21b`](https://github.com/PrismJS/prism/commit/e66d21b)] * __Go__: - * Regexp optimisation + don't use captures if not needed [[`88caabb`](https://github.com/PrismJS/prism/commit/88caabb)] + * Regexp optimisation + don't use captures if not needed [[`88caabb`](https://github.com/PrismJS/prism/commit/88caabb)] * __GraphQL__: - * Regexp optimisation and simplification [[`2474f06`](https://github.com/PrismJS/prism/commit/2474f06)] + * Regexp optimisation and simplification [[`2474f06`](https://github.com/PrismJS/prism/commit/2474f06)] * __Groovy__: - * Regexp optimisation + don't use captures if not needed [[`e74e00c`](https://github.com/PrismJS/prism/commit/e74e00c)] + * Regexp optimisation + don't use captures if not needed [[`e74e00c`](https://github.com/PrismJS/prism/commit/e74e00c)] * __Haml__: - * Regexp optimisation + don't use captures if not needed + fix typo in comment [[`23e3b43`](https://github.com/PrismJS/prism/commit/23e3b43)] + * Regexp optimisation + don't use captures if not needed + fix typo in comment [[`23e3b43`](https://github.com/PrismJS/prism/commit/23e3b43)] * __Handlebars__: - * Regexp optimisation + don't use captures if not needed [[`09dbfce`](https://github.com/PrismJS/prism/commit/09dbfce)] + * Regexp optimisation + don't use captures if not needed [[`09dbfce`](https://github.com/PrismJS/prism/commit/09dbfce)] * __Haskell__: - * Regexp simplification + don't use captures if not needed [[`f11390a`](https://github.com/PrismJS/prism/commit/f11390a)] + * Regexp simplification + don't use captures if not needed [[`f11390a`](https://github.com/PrismJS/prism/commit/f11390a)] * __HTTP__: - * Regexp simplification + don't use captures if not needed [[`37ef24e`](https://github.com/PrismJS/prism/commit/37ef24e)] + * Regexp simplification + don't use captures if not needed [[`37ef24e`](https://github.com/PrismJS/prism/commit/37ef24e)] * __Icon__: - * Regexp optimisation [[`9cf64a0`](https://github.com/PrismJS/prism/commit/9cf64a0)] + * Regexp optimisation [[`9cf64a0`](https://github.com/PrismJS/prism/commit/9cf64a0)] * __J__: - * Regexp simplification [[`de15150`](https://github.com/PrismJS/prism/commit/de15150)] + * Regexp simplification [[`de15150`](https://github.com/PrismJS/prism/commit/de15150)] * __Java__: - * Don't use captures if not needed [[`96b35c8`](https://github.com/PrismJS/prism/commit/96b35c8)] + * Don't use captures if not needed [[`96b35c8`](https://github.com/PrismJS/prism/commit/96b35c8)] * __JavaScript__: - * Regexp optimisation + don't use captures if not needed [[`93d4002`](https://github.com/PrismJS/prism/commit/93d4002)] + * Regexp optimisation + don't use captures if not needed [[`93d4002`](https://github.com/PrismJS/prism/commit/93d4002)] * __Jolie__: - * Regexp optimisation + don't use captures if not needed + remove duplicates in keywords [[`a491f9e`](https://github.com/PrismJS/prism/commit/a491f9e)] + * Regexp optimisation + don't use captures if not needed + remove duplicates in keywords [[`a491f9e`](https://github.com/PrismJS/prism/commit/a491f9e)] * __JSON__: * Make strings greedy, remove negative look-ahead for ":". Fix [#1204](https://github.com/PrismJS/prism/issues/1204) [[`98acd2d`](https://github.com/PrismJS/prism/commit/98acd2d)] - * Regexp optimisation + don't use captures if not needed [[`8fc1b03`](https://github.com/PrismJS/prism/commit/8fc1b03)] + * Regexp optimisation + don't use captures if not needed [[`8fc1b03`](https://github.com/PrismJS/prism/commit/8fc1b03)] * __JSX__: - * Regexp optimisation + handle spread operator as a whole [[`28de4e2`](https://github.com/PrismJS/prism/commit/28de4e2)] + * Regexp optimisation + handle spread operator as a whole [[`28de4e2`](https://github.com/PrismJS/prism/commit/28de4e2)] * __Julia__: - * Regexp optimisation and simplification [[`12684c0`](https://github.com/PrismJS/prism/commit/12684c0)] + * Regexp optimisation and simplification [[`12684c0`](https://github.com/PrismJS/prism/commit/12684c0)] * __Keyman__: - * Regexp optimisation + don't use captures if not needed [[`9726087`](https://github.com/PrismJS/prism/commit/9726087)] + * Regexp optimisation + don't use captures if not needed [[`9726087`](https://github.com/PrismJS/prism/commit/9726087)] * __Kotlin__: - * Regexp simplification [[`12ff8dc`](https://github.com/PrismJS/prism/commit/12ff8dc)] + * Regexp simplification [[`12ff8dc`](https://github.com/PrismJS/prism/commit/12ff8dc)] * __LaTeX__: - * Regexp optimisation and simplification [[`aa426b0`](https://github.com/PrismJS/prism/commit/aa426b0)] + * Regexp optimisation and simplification [[`aa426b0`](https://github.com/PrismJS/prism/commit/aa426b0)] * __LiveScript__: - * Make interpolated strings greedy + fix variable and identifier regexps [[`c581049`](https://github.com/PrismJS/prism/commit/c581049)] + * Make interpolated strings greedy + fix variable and identifier regexps [[`c581049`](https://github.com/PrismJS/prism/commit/c581049)] * __LOLCODE__: - * Don't use captures if not needed [[`52903af`](https://github.com/PrismJS/prism/commit/52903af)] + * Don't use captures if not needed [[`52903af`](https://github.com/PrismJS/prism/commit/52903af)] * __Makefile__: - * Regexp optimisation [[`20ae2e5`](https://github.com/PrismJS/prism/commit/20ae2e5)] + * Regexp optimisation [[`20ae2e5`](https://github.com/PrismJS/prism/commit/20ae2e5)] * __Markdown__: - * Don't use captures if not needed [[`f489a1e`](https://github.com/PrismJS/prism/commit/f489a1e)] + * Don't use captures if not needed [[`f489a1e`](https://github.com/PrismJS/prism/commit/f489a1e)] * __Markup__: - * Regexp optimisation + fix punctuation inside attr-value [[`ea380c6`](https://github.com/PrismJS/prism/commit/ea380c6)] + * Regexp optimisation + fix punctuation inside attr-value [[`ea380c6`](https://github.com/PrismJS/prism/commit/ea380c6)] * __MATLAB__: - * Make strings greedy + handle line feeds better [[`4cd4f01`](https://github.com/PrismJS/prism/commit/4cd4f01)] + * Make strings greedy + handle line feeds better [[`4cd4f01`](https://github.com/PrismJS/prism/commit/4cd4f01)] * __Monkey__: - * Don't use captures if not needed [[`7f47140`](https://github.com/PrismJS/prism/commit/7f47140)] + * Don't use captures if not needed [[`7f47140`](https://github.com/PrismJS/prism/commit/7f47140)] * __N4JS__: - * Don't use captures if not needed [[`2d3f9df`](https://github.com/PrismJS/prism/commit/2d3f9df)] + * Don't use captures if not needed [[`2d3f9df`](https://github.com/PrismJS/prism/commit/2d3f9df)] * __NASM__: - * Regexp optimisation and simplification + don't use captures if not needed [[`9937428`](https://github.com/PrismJS/prism/commit/9937428)] + * Regexp optimisation and simplification + don't use captures if not needed [[`9937428`](https://github.com/PrismJS/prism/commit/9937428)] * __nginx__: - * Remove trailing comma + remove duplicates in keywords [[`c6e7195`](https://github.com/PrismJS/prism/commit/c6e7195)] + * Remove trailing comma + remove duplicates in keywords [[`c6e7195`](https://github.com/PrismJS/prism/commit/c6e7195)] * __NSIS__: - * Regexp optimisation + don't use captures if not needed [[`beeb107`](https://github.com/PrismJS/prism/commit/beeb107)] + * Regexp optimisation + don't use captures if not needed [[`beeb107`](https://github.com/PrismJS/prism/commit/beeb107)] * __Objective-C__: - * Don't use captures if not needed [[`9be0f88`](https://github.com/PrismJS/prism/commit/9be0f88)] + * Don't use captures if not needed [[`9be0f88`](https://github.com/PrismJS/prism/commit/9be0f88)] * __OCaml__: - * Regexp simplification [[`5f5f38c`](https://github.com/PrismJS/prism/commit/5f5f38c)] + * Regexp simplification [[`5f5f38c`](https://github.com/PrismJS/prism/commit/5f5f38c)] * __OpenCL__: * Don't use captures if not needed [[`5e70f1d`](https://github.com/PrismJS/prism/commit/5e70f1d)] * __Oz__: @@ -382,77 +2032,77 @@ * __PARI/GP__: * Regexp optimisation [[`2c7b59b`](https://github.com/PrismJS/prism/commit/2c7b59b)] * __Parser__: - * Regexp simplification [[`569d511`](https://github.com/PrismJS/prism/commit/569d511)] + * Regexp simplification [[`569d511`](https://github.com/PrismJS/prism/commit/569d511)] * __Perl__: - * Regexp optimisation and simplification + don't use captures if not needed [[`0fe4cf6`](https://github.com/PrismJS/prism/commit/0fe4cf6)] + * Regexp optimisation and simplification + don't use captures if not needed [[`0fe4cf6`](https://github.com/PrismJS/prism/commit/0fe4cf6)] * __PHP__: * Don't use captures if not needed Golmote [[`5235f18`](https://github.com/PrismJS/prism/commit/5235f18)] * __PHP Extras__: - * Add word boundary after global keywords + don't use captures if not needed [[`9049a2a`](https://github.com/PrismJS/prism/commit/9049a2a)] + * Add word boundary after global keywords + don't use captures if not needed [[`9049a2a`](https://github.com/PrismJS/prism/commit/9049a2a)] * __PowerShell__: - * Regexp optimisation + don't use captures if not needed [[`0d05957`](https://github.com/PrismJS/prism/commit/0d05957)] + * Regexp optimisation + don't use captures if not needed [[`0d05957`](https://github.com/PrismJS/prism/commit/0d05957)] * __Processing__: - * Regexp simplification [[`8110d38`](https://github.com/PrismJS/prism/commit/8110d38)] + * Regexp simplification [[`8110d38`](https://github.com/PrismJS/prism/commit/8110d38)] * __.properties__: - * Regexp optimisation [[`678b621`](https://github.com/PrismJS/prism/commit/678b621)] + * Regexp optimisation [[`678b621`](https://github.com/PrismJS/prism/commit/678b621)] * __Protocol Buffers__: - * Don't use captures if not needed [[`3e256d8`](https://github.com/PrismJS/prism/commit/3e256d8)] + * Don't use captures if not needed [[`3e256d8`](https://github.com/PrismJS/prism/commit/3e256d8)] * __Pug__: - * Don't use captures if not needed [[`76dc925`](https://github.com/PrismJS/prism/commit/76dc925)] + * Don't use captures if not needed [[`76dc925`](https://github.com/PrismJS/prism/commit/76dc925)] * __Pure__: - * Make inline-lang greedy [[`92318b0`](https://github.com/PrismJS/prism/commit/92318b0)] + * Make inline-lang greedy [[`92318b0`](https://github.com/PrismJS/prism/commit/92318b0)] * __Python__: * Add Python builtin function highlighting ([#1205](https://github.com/PrismJS/prism/issues/1205)) [[`2169c99`](https://github.com/PrismJS/prism/commit/2169c99)] * Python: Add highlighting to functions with space between name and parentheses ([#1207](https://github.com/PrismJS/prism/issues/1207)) [[`3badd8a`](https://github.com/PrismJS/prism/commit/3badd8a)] - * Make triple-quoted strings greedy + regexp optimisation and simplification [[`f09f9f5`](https://github.com/PrismJS/prism/commit/f09f9f5)] + * Make triple-quoted strings greedy + regexp optimisation and simplification [[`f09f9f5`](https://github.com/PrismJS/prism/commit/f09f9f5)] * __Qore__: * Regexp simplification [[`69459f0`](https://github.com/PrismJS/prism/commit/69459f0)] * __R__: - * Regexp optimisation [[`06a9da4`](https://github.com/PrismJS/prism/commit/06a9da4)] + * Regexp optimisation [[`06a9da4`](https://github.com/PrismJS/prism/commit/06a9da4)] * __Reason__: - * Regexp optimisation + don't use capture if not needed [[`19d79b4`](https://github.com/PrismJS/prism/commit/19d79b4)] + * Regexp optimisation + don't use capture if not needed [[`19d79b4`](https://github.com/PrismJS/prism/commit/19d79b4)] * __Ren'py__: - * Make strings greedy + don't use captures if not needed [[`91d84d9`](https://github.com/PrismJS/prism/commit/91d84d9)] + * Make strings greedy + don't use captures if not needed [[`91d84d9`](https://github.com/PrismJS/prism/commit/91d84d9)] * __reST__: - * Regexp simplification + don't use captures if not needed [[`1a8b3e9`](https://github.com/PrismJS/prism/commit/1a8b3e9)] + * Regexp simplification + don't use captures if not needed [[`1a8b3e9`](https://github.com/PrismJS/prism/commit/1a8b3e9)] * __Rip__: - * Regexp optimisation [[`d7f0ee8`](https://github.com/PrismJS/prism/commit/d7f0ee8)] + * Regexp optimisation [[`d7f0ee8`](https://github.com/PrismJS/prism/commit/d7f0ee8)] * __Ruby__: - * Regexp optimisation and simplification + don't use captures if not needed [[`4902ed4`](https://github.com/PrismJS/prism/commit/4902ed4)] + * Regexp optimisation and simplification + don't use captures if not needed [[`4902ed4`](https://github.com/PrismJS/prism/commit/4902ed4)] * __Rust__: - * Regexp optimisation and simplification + don't use captures if not needed [[`cc9d874`](https://github.com/PrismJS/prism/commit/cc9d874)] + * Regexp optimisation and simplification + don't use captures if not needed [[`cc9d874`](https://github.com/PrismJS/prism/commit/cc9d874)] * __Sass__: - * Regexp simplification Golmote [[`165d957`](https://github.com/PrismJS/prism/commit/165d957)] + * Regexp simplification Golmote [[`165d957`](https://github.com/PrismJS/prism/commit/165d957)] * __Scala__: - * Regexp optimisation Golmote [[`5f50c12`](https://github.com/PrismJS/prism/commit/5f50c12)] + * Regexp optimisation Golmote [[`5f50c12`](https://github.com/PrismJS/prism/commit/5f50c12)] * __Scheme__: * Regexp optimisation [[`bd19b04`](https://github.com/PrismJS/prism/commit/bd19b04)] * __SCSS__: - * Regexp simplification [[`c60b7d4`](https://github.com/PrismJS/prism/commit/c60b7d4)] + * Regexp simplification [[`c60b7d4`](https://github.com/PrismJS/prism/commit/c60b7d4)] * __Smalltalk__: - * Regexp simplification [[`41a2c76`](https://github.com/PrismJS/prism/commit/41a2c76)] + * Regexp simplification [[`41a2c76`](https://github.com/PrismJS/prism/commit/41a2c76)] * __Smarty__: - * Regexp optimisation and simplification [[`e169be9`](https://github.com/PrismJS/prism/commit/e169be9)] + * Regexp optimisation and simplification [[`e169be9`](https://github.com/PrismJS/prism/commit/e169be9)] * __SQL__: - * Regexp optimisation [[`a6244a4`](https://github.com/PrismJS/prism/commit/a6244a4)] + * Regexp optimisation [[`a6244a4`](https://github.com/PrismJS/prism/commit/a6244a4)] * __Stylus__: - * Regexp optimisation [[`df9506c`](https://github.com/PrismJS/prism/commit/df9506c)] + * Regexp optimisation [[`df9506c`](https://github.com/PrismJS/prism/commit/df9506c)] * __Swift__: - * Don't use captures if not needed [[`a2d737a`](https://github.com/PrismJS/prism/commit/a2d737a)] + * Don't use captures if not needed [[`a2d737a`](https://github.com/PrismJS/prism/commit/a2d737a)] * __Tcl__: - * Regexp simplification + don't use captures if not needed [[`f0b8a33`](https://github.com/PrismJS/prism/commit/f0b8a33)] + * Regexp simplification + don't use captures if not needed [[`f0b8a33`](https://github.com/PrismJS/prism/commit/f0b8a33)] * __Textile__: - * Regexp optimisation + don't use captures if not needed [[`08139ad`](https://github.com/PrismJS/prism/commit/08139ad)] + * Regexp optimisation + don't use captures if not needed [[`08139ad`](https://github.com/PrismJS/prism/commit/08139ad)] * __Twig__: * Regexp optimisation and simplification + don't use captures if not needed [[`0b10fd0`](https://github.com/PrismJS/prism/commit/0b10fd0)] * __TypeScript__: - * Don't use captures if not needed [[`e296caf`](https://github.com/PrismJS/prism/commit/e296caf)] + * Don't use captures if not needed [[`e296caf`](https://github.com/PrismJS/prism/commit/e296caf)] * __Verilog__: - * Regexp simplification [[`1b24b34`](https://github.com/PrismJS/prism/commit/1b24b34)] + * Regexp simplification [[`1b24b34`](https://github.com/PrismJS/prism/commit/1b24b34)] * __VHDL__: - * Regexp optimisation and simplification [[`7af36df`](https://github.com/PrismJS/prism/commit/7af36df)] + * Regexp optimisation and simplification [[`7af36df`](https://github.com/PrismJS/prism/commit/7af36df)] * __vim__: - * Remove duplicates in keywords [[`700505e`](https://github.com/PrismJS/prism/commit/700505e)] + * Remove duplicates in keywords [[`700505e`](https://github.com/PrismJS/prism/commit/700505e)] * __Wiki markup__: * Fix escaping consistency [[`1fd690d`](https://github.com/PrismJS/prism/commit/1fd690d)] * __YAML__: @@ -461,7 +2111,7 @@ ### Other changes * Remove comments spellcheck for AMP validation ([#1106](https://github.com/PrismJS/prism/issues/1106)) [[`de996d7`](https://github.com/PrismJS/prism/commit/de996d7)] * Prevent error from throwing when element does not have a parentNode in highlightElement. [[`c33be19`](https://github.com/PrismJS/prism/commit/c33be19)] -* Provide a way to load Prism from inside a Worker without listening to messages. ([#1188](https://github.com/PrismJS/prism/issues/1188)) [[`d09982d`](https://github.com/PrismJS/prism/commit/d09982d)] +* Provide a way to load Prism from inside a Worker without listening to messages. ([#1188](https://github.com/PrismJS/prism/issues/1188)) [[`d09982d`](https://github.com/PrismJS/prism/commit/d09982d)] ## 1.8.3 (2017-10-19) @@ -499,7 +2149,7 @@ ### Updated plugins * __Autolinker__: - * Silently catch any error thrown by decodeURIComponent. Fixes [#1186](https://github.com/PrismJS/prism/issues/1186) [[`2e43fcf`](https://github.com/PrismJS/prism/commit/2e43fcf)] + * Silently catch any error thrown by decodeURIComponent. Fixes [#1186](https://github.com/PrismJS/prism/issues/1186) [[`2e43fcf`](https://github.com/PrismJS/prism/commit/2e43fcf)] ## 1.7.0 (2017-09-09) @@ -516,11 +2166,11 @@ * Add left shoe underbar and right shoe underbar ([#1072](https://github.com/PrismJS/prism/issues/1072)) [[`12238c5`](https://github.com/PrismJS/prism/commit/12238c5)] * Update prism-apl.js ([#1126](https://github.com/PrismJS/prism/issues/1126)) [[`a5f3cdb`](https://github.com/PrismJS/prism/commit/a5f3cdb)] * __C__: - * Add more keywords and constants for C. ([#1029](https://github.com/PrismJS/prism/issues/1029)) [[`43a388e`](https://github.com/PrismJS/prism/commit/43a388e)] + * Add more keywords and constants for C. ([#1029](https://github.com/PrismJS/prism/issues/1029)) [[`43a388e`](https://github.com/PrismJS/prism/commit/43a388e)] * __C#__: * Fix wrong highlighting when three slashes appear inside string. Fix [#1091](https://github.com/PrismJS/prism/issues/1091) [[`dfb6f17`](https://github.com/PrismJS/prism/commit/dfb6f17)] * __C-like__: - * Add support for unclosed block comments. Close [#828](https://github.com/PrismJS/prism/issues/828) [[`3426ed1`](https://github.com/PrismJS/prism/commit/3426ed1)] + * Add support for unclosed block comments. Close [#828](https://github.com/PrismJS/prism/issues/828) [[`3426ed1`](https://github.com/PrismJS/prism/commit/3426ed1)] * __Crystal__: * Update Crystal keywords ([#1092](https://github.com/PrismJS/prism/issues/1092)) [[`125bff1`](https://github.com/PrismJS/prism/commit/125bff1)] * __CSS Extras__: @@ -535,23 +2185,23 @@ * __JavaScript__: * Properly match every operator as a whole token. Fix [#1133](https://github.com/PrismJS/prism/issues/1133) [[`9f649fb`](https://github.com/PrismJS/prism/commit/9f649fb)] * Allows uppercase prefixes in JS number literals ([#1151](https://github.com/PrismJS/prism/issues/1151)) [[`d4ee904`](https://github.com/PrismJS/prism/commit/d4ee904)] - * Reduced backtracking in regex pattern. Fix [#1159](https://github.com/PrismJS/prism/issues/1159) [[`ac09e97`](https://github.com/PrismJS/prism/commit/ac09e97)] + * Reduced backtracking in regex pattern. Fix [#1159](https://github.com/PrismJS/prism/issues/1159) [[`ac09e97`](https://github.com/PrismJS/prism/commit/ac09e97)] * __JSON__: * Fix property and string patterns performance. Fix [#1080](https://github.com/PrismJS/prism/issues/1080) [[`0ca1353`](https://github.com/PrismJS/prism/commit/0ca1353)] * __JSX__: * JSX spread operator break. Fixes [#1061](https://github.com/PrismJS/prism/issues/1061) ([#1094](https://github.com/PrismJS/prism/issues/1094)) [[`561bceb`](https://github.com/PrismJS/prism/commit/561bceb)] * Fix highlighting of attributes containing spaces [[`867ea42`](https://github.com/PrismJS/prism/commit/867ea42)] - * Improved performance for tags (when not matching) Fix [#1152](https://github.com/PrismJS/prism/issues/1152) [[`b0fe103`](https://github.com/PrismJS/prism/commit/b0fe103)] + * Improved performance for tags (when not matching) Fix [#1152](https://github.com/PrismJS/prism/issues/1152) [[`b0fe103`](https://github.com/PrismJS/prism/commit/b0fe103)] * __LOLCODE__: * Make strings greedy Golmote [[`1a5e7a4`](https://github.com/PrismJS/prism/commit/1a5e7a4)] * __Markup__: * Support HTML entities in attribute values ([#1143](https://github.com/PrismJS/prism/issues/1143)) [[`1d5047d`](https://github.com/PrismJS/prism/commit/1d5047d)] * __NSIS__: * Update patterns ([#1033](https://github.com/PrismJS/prism/issues/1033)) [[`01a59d8`](https://github.com/PrismJS/prism/commit/01a59d8)] - * Add support for NSIS 3.02 ([#1169](https://github.com/PrismJS/prism/issues/1169)) [[`393b5f7`](https://github.com/PrismJS/prism/commit/393b5f7)] + * Add support for NSIS 3.02 ([#1169](https://github.com/PrismJS/prism/issues/1169)) [[`393b5f7`](https://github.com/PrismJS/prism/commit/393b5f7)] * __PHP__: * Fix the PHP language ([#1100](https://github.com/PrismJS/prism/issues/1100)) [[`1453fa7`](https://github.com/PrismJS/prism/commit/1453fa7)] - * Check for possible pre-existing marker strings in PHP [[`36bc560`](https://github.com/PrismJS/prism/commit/36bc560)] + * Check for possible pre-existing marker strings in PHP [[`36bc560`](https://github.com/PrismJS/prism/commit/36bc560)] * __Ruby__: * Fix slash regex performance. Fix [#1083](https://github.com/PrismJS/prism/issues/1083) [[`a708730`](https://github.com/PrismJS/prism/commit/a708730)] * Add support for =begin =end comments. Manual merge of [#1121](https://github.com/PrismJS/prism/issues/1121). [[`62cdaf8`](https://github.com/PrismJS/prism/commit/62cdaf8)] @@ -559,19 +2209,19 @@ * Check for possible pre-existing marker strings in Smarty [[`5df26e2`](https://github.com/PrismJS/prism/commit/5df26e2)] * __TypeScript__: * Update typescript keywords ([#1064](https://github.com/PrismJS/prism/issues/1064)) [[`52020a0`](https://github.com/PrismJS/prism/commit/52020a0)] - * Chmod -x prism-typescript component ([#1145](https://github.com/PrismJS/prism/issues/1145)) [[`afe0542`](https://github.com/PrismJS/prism/commit/afe0542)] + * Chmod -x prism-typescript component ([#1145](https://github.com/PrismJS/prism/issues/1145)) [[`afe0542`](https://github.com/PrismJS/prism/commit/afe0542)] * __YAML__: - * Make strings greedy (partial fix for [#1075](https://github.com/PrismJS/prism/issues/1075)) [[`565a2cc`](https://github.com/PrismJS/prism/commit/565a2cc)] + * Make strings greedy (partial fix for [#1075](https://github.com/PrismJS/prism/issues/1075)) [[`565a2cc`](https://github.com/PrismJS/prism/commit/565a2cc)] ### Updated plugins * __Autolinker__: - * Fixed an rendering issue for encoded urls ([#1173](https://github.com/PrismJS/prism/issues/1173)) [[`abc007f`](https://github.com/PrismJS/prism/commit/abc007f)] + * Fixed an rendering issue for encoded urls ([#1173](https://github.com/PrismJS/prism/issues/1173)) [[`abc007f`](https://github.com/PrismJS/prism/commit/abc007f)] * __Custom Class__: * Add missing noCSS property for the Custom Class plugin [[`ba64f8d`](https://github.com/PrismJS/prism/commit/ba64f8d)] * Added a default for classMap. Fixes [#1137](https://github.com/PrismJS/prism/issues/1137). ([#1157](https://github.com/PrismJS/prism/issues/1157)) [[`5400af9`](https://github.com/PrismJS/prism/commit/5400af9)] * __Keep Markup__: - * Store highlightedCode after reinserting markup. Fix [#1127](https://github.com/PrismJS/prism/issues/1127) [[`6df2ceb`](https://github.com/PrismJS/prism/commit/6df2ceb)] + * Store highlightedCode after reinserting markup. Fix [#1127](https://github.com/PrismJS/prism/issues/1127) [[`6df2ceb`](https://github.com/PrismJS/prism/commit/6df2ceb)] * __Line Highlight__: * Cleanup left-over line-highlight tags before other plugins run [[`79b723d`](https://github.com/PrismJS/prism/commit/79b723d)] * Avoid conflict between line-highlight and other plugins [[`224fdb8`](https://github.com/PrismJS/prism/commit/224fdb8)] @@ -600,7 +2250,7 @@ * Add Composer support ([#648](https://github.com/PrismJS/prism/issues/648)) [[`2989633`](https://github.com/PrismJS/prism/commit/2989633)] * Remove IE8 plugin ([#992](https://github.com/PrismJS/prism/issues/992)) [[`25788eb`](https://github.com/PrismJS/prism/commit/25788eb)] * Website: remove width and height on logo.svg, so it becomes scalable. Close [#1005](https://github.com/PrismJS/prism/issues/1005) [[`0621ff7`](https://github.com/PrismJS/prism/commit/0621ff7)] -* Remove yarn.lock ([#1098](https://github.com/PrismJS/prism/issues/1098)) [[`11eed25`](https://github.com/PrismJS/prism/commit/11eed25)] +* Remove yarn.lock ([#1098](https://github.com/PrismJS/prism/issues/1098)) [[`11eed25`](https://github.com/PrismJS/prism/commit/11eed25)] ## 1.6.0 (2016-12-03) @@ -626,13 +2276,13 @@ * Make CSS strings greedy. Fix [#1013](https://github.com/PrismJS/prism/issues/1013). [[`e57e26d`](https://github.com/PrismJS/prism/commit/e57e26d)] * __CSS Extras__: * Match attribute inside selectors [[`13fed76`](https://github.com/PrismJS/prism/commit/13fed76)] -* _Groovy__: +* __Groovy__: * Fix order of decoding entities in groovy. Fixes [#1049](https://github.com/PrismJS/prism/issues/1049) ([#1050](https://github.com/PrismJS/prism/issues/1050)) [[`d75da8e`](https://github.com/PrismJS/prism/commit/d75da8e)] * __Ini__: * Remove important token in ini definition ([#1047](https://github.com/PrismJS/prism/issues/1047)) [[`fe8ad8b`](https://github.com/PrismJS/prism/commit/fe8ad8b)] * __JavaScript__: * Add exponentiation & spread/rest operator ([#991](https://github.com/PrismJS/prism/issues/991)) [[`b2de65a`](https://github.com/PrismJS/prism/commit/b2de65a), [`268d01e`](https://github.com/PrismJS/prism/commit/268d01e)] -* __JSON_: +* __JSON__: * JSON: Fixed issues with properties and strings + added tests. Fix [#1025](https://github.com/PrismJS/prism/issues/1025) [[`25a541d`](https://github.com/PrismJS/prism/commit/25a541d)] * __Markup__: * Allow for dots in Markup tag names, but not in HTML tags included in Textile. Fixes [#888](https://github.com/PrismJS/prism/issues/888). [[`31ea66b`](https://github.com/PrismJS/prism/commit/31ea66b)] @@ -801,7 +2451,7 @@ * __AsciiDoc__ ([#800](https://github.com/PrismJS/prism/issues/800)) [[`6803ca0`](https://github.com/PrismJS/prism/commit/6803ca0)] * __Haxe__ ([#811](https://github.com/PrismJS/prism/issues/811)) [[`bd44341`](https://github.com/PrismJS/prism/commit/bd44341)] * __Icon__ ([#803](https://github.com/PrismJS/prism/issues/803)) [[`b43c5f3`](https://github.com/PrismJS/prism/commit/b43c5f3)] -* __Kotlin ([#814](https://github.com/PrismJS/prism/issues/814)) [[`e8a31a5`](https://github.com/PrismJS/prism/commit/e8a31a5)] +* __Kotlin__ ([#814](https://github.com/PrismJS/prism/issues/814)) [[`e8a31a5`](https://github.com/PrismJS/prism/commit/e8a31a5)] * __Lua__ ([#804](https://github.com/PrismJS/prism/issues/804)) [[`a36bc4a`](https://github.com/PrismJS/prism/commit/a36bc4a)] * __Nix__ ([#795](https://github.com/PrismJS/prism/issues/795)) [[`9b275c8`](https://github.com/PrismJS/prism/commit/9b275c8)] * __Oz__ ([#805](https://github.com/PrismJS/prism/issues/805)) [[`388c53f`](https://github.com/PrismJS/prism/commit/388c53f)] diff --git a/README.md b/README.md index 3406859cf7..711ea63880 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,40 @@ -# [Prism](http://prismjs.com/) +# [Prism](https://prismjs.com/) -Prism is a lightweight, robust, elegant syntax highlighting library. It's a spin-off project from [Dabblet](http://dabblet.com/). +[![Build Status](https://github.com/PrismJS/prism/workflows/CI/badge.svg)](https://github.com/PrismJS/prism/actions) +[![npm](https://img.shields.io/npm/dw/prismjs.svg)](https://www.npmjs.com/package/prismjs) -You can learn more on http://prismjs.com/. +Prism is a lightweight, robust, and elegant syntax highlighting library. It's a spin-off project from [Dabblet](https://dabblet.com/). -Why another syntax highlighter?: http://lea.verou.me/2012/07/introducing-prism-an-awesome-new-syntax-highlighter/#more-1841 +You can learn more on [prismjs.com](https://prismjs.com/). + +[Why another syntax highlighter?](https://lea.verou.me/2012/07/introducing-prism-an-awesome-new-syntax-highlighter/#more-1841) + +[More themes for Prism!](https://github.com/PrismJS/prism-themes) ## Contribute to Prism! -Prism depends on community contributions to expand and cover a wider array of use cases. If you like it, considering giving back by sending a pull request. Here are a few tips: +Prism depends on community contributions to expand and cover a wider array of use cases. If you like it, consider giving back by sending a pull request. Here are a few tips: -- Read the [documentation](http://prismjs.com/extending.html). Prism was designed to be extensible. -- Do not edit `prism.js`, it’s just the version of Prism used by the Prism website and is built automatically. Limit your changes to the unminified files in the components/ folder. The minified files are also generated automatically. -- The build system uses [gulp](https://github.com/gulpjs/gulp) to minify the files and build `prism.js`. Having gulp installed, you just need to run the command `gulp`. +- Read the [documentation](https://prismjs.com/extending.html). Prism was designed to be extensible. +- Do not edit `prism.js`, it’s just the version of Prism used by the Prism website and is built automatically. Limit your changes to the unminified files in the `components/` folder. `prism.js` and all minified files are generated by our build system (see below). +- Use `npm ci` to install Prism's dependencies. Do not use `npm install` because it will cause non-deterministic builds. +- The build system uses [gulp](https://github.com/gulpjs/gulp) to minify the files and build `prism.js`. With all of Prism's dependencies installed, you just need to run the command `npm run build`. - Please follow the code conventions used in the files already. For example, I use [tabs for indentation and spaces for alignment](http://lea.verou.me/2012/01/why-tabs-are-clearly-superior/). Opening braces are on the same line, closing braces on their own line regardless of construct. There is a space before the opening brace. etc etc. -- Please try to err towards more smaller PRs rather than few huge PRs. If a PR includes changes I want to merge and changes I don't, handling it becomes difficult. -- My time is very limited these days, so it might take a long time to review longer PRs (short ones are usually merged very quickly), especially those modifying the Prism Core. This doesn't mean your PR is rejected. +- Please try to err towards more smaller PRs rather than a few huge PRs. If a PR includes changes that I want to merge and also changes that I don't, handling it becomes difficult. +- My time is very limited these days, so it might take a long time to review bigger PRs (small ones are usually merged very quickly), especially those modifying the Prism Core. This doesn't mean your PR is rejected. - If you contribute a new language definition, you will be responsible for handling bug reports about that language definition. -- If you add a new language definition, theme or plugin, you need to add it to `components.js` as well, so that it becomes available to the download build page. +- If you [add a new language definition](https://prismjs.com/extending.html#creating-a-new-language-definition) or plugin, you need to add it to `components.json` as well and rebuild Prism by running `npm run build`, so that it becomes available to the download build page. For new languages, please also add a few [tests](https://prismjs.com/test-suite.html) and an example in the `examples/` folder. +- Go to [prism-themes](https://github.com/PrismJS/prism-themes) if you want to add a new theme. Thank you so much for contributing!! + +### Software requirements + +Prism will run on [almost any browser](https://prismjs.com/#features-full) and Node.js version but you need the following software to contribute: + +- Node.js >= 10.x +- npm >= 6.x + +## Translations + +* [简体中文](https://www.awesomes.cn/repo/PrismJS/prism) (if unavailable, see [here](https://deepmind.t-salon.cc/article/113)) diff --git a/assets/code.js b/assets/code.js new file mode 100644 index 0000000000..0415b1bd77 --- /dev/null +++ b/assets/code.js @@ -0,0 +1,247 @@ +(function () { + + if (!document.body.addEventListener) { + return; + } + + $$('[data-plugin-header]').forEach(function (element) { + var plugin = components.plugins[element.getAttribute('data-plugin-header')]; + element.innerHTML = '
\n' + + '

' + plugin.title + '

\n

' + plugin.description + '

'; + }); + + $$('[data-src][data-type="text/html"]').forEach(function (element) { + var src = element.getAttribute('data-src'); + var html = element.getAttribute('data-type') === 'text/html'; + var contentProperty = html ? 'innerHTML' : 'textContent'; + + $u.xhr({ + url: src, + callback: function (xhr) { + try { + element[contentProperty] = xhr.responseText; + + // Run JS + + $$('script', element).forEach(function (script) { + var parent = script.parentNode; + parent.removeChild(script); + document.head.appendChild(script); + }); + } catch (e) { /* noop */ } + } + }); + }); + +}()); + +/** + * Table of contents + */ +(function () { + var toc = document.createElement('ol'); + + $$('body > section > h1').forEach(function (h1) { + var section = h1.parentNode; + var text = h1.textContent; + var id = h1.id || section.id; + + // Assign id if one does not exist + if (!id) { + id = text.toLowerCase(); + + // Replace spaces with hyphens, only keep first 10 words + id = id.split(/\s+/g, 10).join('-'); + + // Remove non-word characters + id = id.replace(/[^\w-]/g, ''); + + section.id = id; + } + + // Linkify heading text + if (h1.children.length === 0) { + h1.innerHTML = ''; + + $u.element.create('a', { + properties: { + href: window.location.pathname + '#' + id + }, + contents: text, + inside: h1 + }); + } + + $u.element.create('li', { + contents: { + tag: 'a', + properties: { + href: window.location.pathname + '#' + (h1.id || section.id) + }, + contents: text + }, + inside: toc + }); + }); + + if (toc.children.length > 0) { + $u.element.create('section', { + properties: { + id: 'toc' + }, + contents: [{ + tag: 'h1', + contents: 'On this page' + }, toc], + before: $('body > section') + }); + } + +}()); + +/** + * Linkify h2 + */ +(function () { + $$('section h2[id]').forEach(function (h2) { + var text = h2.textContent; + h2.innerHTML = ''; + + $u.element.create('a', { + properties: { + href: window.location.pathname + '#' + h2.id + }, + contents: text, + inside: h2 + }); + }); +}()); + +// calc() +(function () { + if (!window.PrefixFree) { + return; + } + + if (PrefixFree.functions.indexOf('calc') == -1) { + var style = document.createElement('_').style; + style.width = 'calc(1px + 1%)'; + + if (!style.width) { + // calc not supported + var header = $('header'); + var footer = $('footer'); + + function calculatePadding() { + header.style.padding = + footer.style.padding = '30px ' + (innerWidth / 2 - 450) + 'px'; + } + + addEventListener('resize', calculatePadding); + calculatePadding(); + } + } +}()); + +// setTheme is intentionally global, +// so it can be accessed from download.js +var setTheme; +(function () { + var p = $u.element.create('p', { + properties: { + id: 'theme' + }, + contents: { + tag: 'p', + contents: 'Theme:' + }, + after: '.intro' + }); + + var themes = components.themes; + var current = (location.search.match(/theme=([\w-]+)/) || [])[1]; + + if (!(current in themes)) { + current = undefined; + } + + if (current === undefined) { + var stored = localStorage.getItem('theme'); + + current = stored in themes ? stored : 'prism'; + } + + setTheme = function (id) { + var link = $$('link[href^="themes/prism"]')[0]; + + link.href = themes.meta.path.replace(/\{id\}/g, id); + localStorage.setItem('theme', id); + }; + + for (var id in themes) { + + if (id === 'meta') { + continue; + } + + $u.element.create('input', { + properties: { + type: 'radio', + name: 'theme', + id: 'theme=' + id, + checked: current === id, + value: id, + onclick: function () { + setTheme(this.value); + } + }, + inside: p + }); + + $u.element.create('label', { + properties: { + htmlFor: 'theme=' + id + }, + contents: themes[id].title || themes[id], + inside: p + }); + } + + setTheme(current); +}()); + +(function () { + + function listPlugins(ul) { + for (var id in components.plugins) { + if (id == 'meta') { + continue; + } + + var plugin = components.plugins[id]; + + var li = $u.element.create('li', { + contents: [ + { + tag: 'a', + prop: { + href: 'plugins/' + id + }, + contents: plugin.title || plugin + }, + { + tag: 'br' + } + ], + inside: ul + }); + + var desc = document.createElement('div'); + desc.innerHTML = plugin.description; + li.appendChild(desc); + } + } + + $$('.plugin-list').forEach(listPlugins); + +}()); diff --git a/assets/download.js b/assets/download.js new file mode 100644 index 0000000000..9e880c106d --- /dev/null +++ b/assets/download.js @@ -0,0 +1,629 @@ +/** + * Manage downloads + */ + +(function () { + + var cache = {}; + var form = $('form'); + var minified = true; + + var dependencies = {}; + + var treeURL = 'https://api.github.com/repos/PrismJS/prism/git/trees/master?recursive=1'; + var treePromise = new Promise(function (resolve) { + $u.xhr({ + url: treeURL, + callback: function (xhr) { + if (xhr.status < 400) { + resolve(JSON.parse(xhr.responseText).tree); + } + } + }); + }); + + /** + * Converts the given value into an array. + * + * @param {T | T[] | null | undefined} value + * @returns {T[]} + * @template T + */ + function toArray(value) { + if (Array.isArray(value)) { + return value; + } else { + return value == null ? [] : [value]; + } + } + + var hstr = window.location.hash.match(/(?:languages|plugins)=[-+\w]+|themes=[-\w]+/g); + if (hstr) { + hstr.forEach(function (str) { + var kv = str.split('=', 2); + var category = kv[0]; + var ids = kv[1].split('+'); + if (category !== 'meta' && category !== 'core' && components[category]) { + for (var id in components[category]) { + if (components[category][id].option) { + delete components[category][id].option; + } + } + if (category === 'themes' && ids.length) { + var themeInput = $('#theme input[value="' + ids[0] + '"]'); + if (themeInput) { + themeInput.checked = true; + } + // eslint-disable-next-line no-undef + setTheme(ids[0]); + } + var makeDefault = function (id) { + if (id !== 'meta') { + if (components[category][id]) { + if (components[category][id].option !== 'default') { + if (typeof components[category][id] === 'string') { + components[category][id] = { title: components[category][id] }; + } + components[category][id].option = 'default'; + } + + toArray(components[category][id].require).forEach(makeDefault); + } + } + }; + ids.forEach(makeDefault); + } + }); + } + + // Stay compatible with old querystring feature + var qstr = window.location.search.match(/(?:languages|plugins)=[-+\w]+|themes=[-\w]+/g); + if (qstr && !hstr) { + window.location.hash = window.location.search.replace(/^\?/, ''); + window.location.search = ''; + } + + var storedTheme = localStorage.getItem('theme'); + + for (var category in components) { + var all = components[category]; + + all.meta.section = $u.element.create('section', { + className: 'options', + id: 'category-' + category, + contents: { + tag: 'h1', + contents: category.charAt(0).toUpperCase() + category.slice(1) + }, + inside: '#components' + }); + + if (all.meta.addCheckAll) { + $u.element.create('label', { + attributes: { + 'data-id': 'check-all-' + category + }, + contents: [ + { + tag: 'input', + properties: { + type: 'checkbox', + name: 'check-all-' + category, + value: '', + checked: false, + onclick: (function (category, all) { + return function () { + var checkAll = this; + $$('input[name="download-' + category + '"]').forEach(function (input) { + all[input.value].enabled = input.checked = checkAll.checked; + }); + + update(category); + }; + }(category, all)) + } + }, + 'Select/unselect all' + ], + inside: all.meta.section + }); + } + + for (var id in all) { + if (id === 'meta') { + continue; + } + + var checked = false; var disabled = false; + var option = all[id].option || all.meta.option; + + switch (option) { + case 'mandatory': disabled = true; // fallthrough + case 'default': checked = true; + } + if (category === 'themes' && storedTheme) { + checked = id === storedTheme; + } + + var filepath = all.meta.path.replace(/\{id\}/g, id); + + var info = all[id] = { + title: all[id].title || all[id], + aliasTitles: all[id].aliasTitles, + noCSS: all[id].noCSS || all.meta.noCSS, + noJS: all[id].noJS || all.meta.noJS, + enabled: checked, + require: toArray(all[id].require), + after: toArray(all[id].after), + modify: toArray(all[id].modify), + owner: all[id].owner, + files: { + minified: { + paths: [], + size: 0 + }, + dev: { + paths: [], + size: 0 + } + } + }; + + info.require.forEach(function (v) { + dependencies[v] = (dependencies[v] || []).concat(id); + }); + + if (!all[id].noJS && !/\.css$/.test(filepath)) { + info.files.minified.paths.push(filepath.replace(/(\.js)?$/, '.min.js')); + info.files.dev.paths.push(filepath.replace(/(\.js)?$/, '.js')); + } + + + if ((!all[id].noCSS && !/\.js$/.test(filepath)) || /\.css$/.test(filepath)) { + var cssFile = filepath.replace(/(\.css)?$/, '.css'); + var minCSSFile = cssFile.replace(/(?:\.css)$/, '.min.css'); + + info.files.minified.paths.push(minCSSFile); + info.files.dev.paths.push(cssFile); + } + + function getLanguageTitle(lang) { + if (!lang.aliasTitles) { + return lang.title; + } + + var titles = [lang.title]; + for (var alias in lang.aliasTitles) { + if (lang.aliasTitles.hasOwnProperty(alias)) { + titles.push(lang.aliasTitles[alias]); + } + } + return titles.join(' + '); + } + + var label = $u.element.create('label', { + attributes: { + 'data-id': id + }, + contents: [ + { + tag: 'input', + properties: { + type: all.meta.exclusive ? 'radio' : 'checkbox', + name: 'download-' + category, + value: id, + checked: checked, + disabled: disabled, + onclick: (function (id, category, all) { + return function () { + $$('input[name="' + this.name + '"]').forEach(function (input) { + all[input.value].enabled = input.checked; + }); + + if (all[id].require && this.checked) { + all[id].require.forEach(function (v) { + var input = $('label[data-id="' + v + '"] > input'); + input.checked = true; + + input.onclick(); + }); + } + + if (dependencies[id] && !this.checked) { // It’s required by others + dependencies[id].forEach(function (dependent) { + var input = $('label[data-id="' + dependent + '"] > input'); + input.checked = false; + + input.onclick(); + }); + } + + update(category, id); + }; + }(id, category, all)) + } + }, + all.meta.link ? { + tag: 'a', + properties: { + href: all.meta.link.replace(/\{id\}/g, id), + className: 'name' + }, + contents: info.title + } : { + tag: 'span', + properties: { + className: 'name' + }, + contents: getLanguageTitle(info) + }, + ' ', + all[id].owner ? { + tag: 'a', + properties: { + href: 'https://github.com/' + all[id].owner, + className: 'owner', + target: '_blank' + }, + contents: all[id].owner + } : ' ', + { + tag: 'strong', + className: 'filesize' + } + ], + inside: all.meta.section + }); + + // Add click events on main theme selector too. + (function (label) { + if (category === 'themes') { + var themeInput = $('#theme input[value="' + id + '"]'); + var input = $('input', label); + if (themeInput) { + var themeInputOnclick = themeInput.onclick; + themeInput.onclick = function () { + input.checked = true; + input.onclick(); + themeInputOnclick && themeInputOnclick.call(themeInput); + }; + } + } + }(label)); + } + } + + form.elements.compression[0].onclick = + form.elements.compression[1].onclick = function () { + minified = !!+this.value; + + getFilesSizes(); + }; + + function getFileSize(filepath) { + return treePromise.then(function (tree) { + for (var i = 0, l = tree.length; i < l; i++) { + if (tree[i].path === filepath) { + return tree[i].size; + } + } + }); + } + + function getFilesSizes() { + for (var category in components) { + var all = components[category]; + + for (var id in all) { + if (id === 'meta') { + continue; + } + + var distro = all[id].files[minified ? 'minified' : 'dev']; + var files = distro.paths; + + files.forEach(function (filepath) { + var file = cache[filepath] = cache[filepath] || {}; + + if (!file.size) { + + (function (category, id) { + getFileSize(filepath).then(function (size) { + if (size) { + file.size = size; + distro.size += file.size; + + update(category, id); + } + }); + }(category, id)); + } else { + update(category, id); + } + }); + } + } + } + + getFilesSizes(); + + function getFileContents(filepath) { + return new Promise(function (resolve, reject) { + $u.xhr({ + url: filepath, + callback: function (xhr) { + if (xhr.status < 400 && xhr.responseText) { + resolve(xhr.responseText); + } else { + reject(); + } + } + }); + }); + } + + function prettySize(size) { + return Math.round(100 * size / 1024) / 100 + 'KB'; + } + + function update(updatedCategory, updatedId) { + // Update total size + var total = { js: 0, css: 0 }; var updated = { js: 0, css: 0 }; + + for (var category in components) { + var all = components[category]; + var allChecked = true; + + for (var id in all) { + var info = all[id]; + + if (info.enabled || id == updatedId) { + var distro = info.files[minified ? 'minified' : 'dev']; + + distro.paths.forEach(function (path) { + if (cache[path]) { + var file = cache[path]; + + var type = path.match(/\.(\w+)$/)[1]; + var size = file.size || 0; + + if (info.enabled) { + + if (!file.contentsPromise) { + file.contentsPromise = getFileContents(path); + } + + total[type] += size; + } + + if (id == updatedId) { + updated[type] += size; + } + } + }); + } + if (id !== 'meta' && !info.enabled) { + allChecked = false; + } + + // Select main theme + if (category === 'themes' && id === updatedId && info.enabled) { + var themeInput = $('#theme input[value="' + updatedId + '"]'); + if (themeInput) { + themeInput.checked = true; + } + // eslint-disable-next-line no-undef + setTheme(updatedId); + } + } + + if (all.meta.addCheckAll) { + $('input[name="check-all-' + category + '"]').checked = allChecked; + } + } + + total.all = total.js + total.css; + + if (updatedId) { + updated.all = updated.js + updated.css; + + $u.element.prop($('label[data-id="' + updatedId + '"] .filesize'), { + textContent: prettySize(updated.all), + title: (updated.js ? Math.round(100 * updated.js / updated.all) + '% JavaScript' : '') + + (updated.js && updated.css ? ' + ' : '') + + (updated.css ? Math.round(100 * updated.css / updated.all) + '% CSS' : '') + }); + } + + $('#filesize').textContent = prettySize(total.all); + + $u.element.prop($('#percent-js'), { + textContent: Math.round(100 * total.js / total.all) + '%', + title: prettySize(total.js) + }); + + $u.element.prop($('#percent-css'), { + textContent: Math.round(100 * total.css / total.all) + '%', + title: prettySize(total.css) + }); + + delayedGenerateCode(); + } + + var timerId = 0; + // "debounce" multiple rapid requests to generate and highlight code + function delayedGenerateCode() { + if (timerId !== 0) { + clearTimeout(timerId); + } + timerId = setTimeout(generateCode, 500); + } + + function generateCode() { + /** @type {CodePromiseInfo[]} */ + var promises = []; + var redownload = {}; + + for (var category in components) { + for (var id in components[category]) { + if (id === 'meta') { + continue; + } + + var info = components[category][id]; + if (info.enabled) { + if (category !== 'core') { + redownload[category] = redownload[category] || []; + redownload[category].push(id); + } + info.files[minified ? 'minified' : 'dev'].paths.forEach(function (path) { + if (cache[path]) { + var type = path.match(/\.(\w+)$/)[1]; + + promises.push({ + contentsPromise: cache[path].contentsPromise, + id: id, + category: category, + path: path, + type: type + }); + } + }); + } + } + } + + // Hide error message if visible + var error = $('#download .error'); + error.style.display = ''; + + Promise.all([buildCode(promises), getVersion()]).then(function (arr) { + var res = arr[0]; + var version = arr[1]; + var code = res.code; + var errors = res.errors; + + if (errors.length) { + error.style.display = 'block'; + error.innerHTML = ''; + $u.element.contents(error, errors); + } + + var redownloadUrl = window.location.href.split('#')[0] + '#'; + for (var category in redownload) { + redownloadUrl += category + '=' + redownload[category].join('+') + '&'; + } + redownloadUrl = redownloadUrl.replace(/&$/, ''); + window.location.replace(redownloadUrl); + + var versionComment = '/* PrismJS ' + version + '\n' + redownloadUrl + ' */'; + + for (var type in code) { + (function (type) { + var text = versionComment + '\n' + code[type]; + var fileName = 'prism.' + type; + + var codeElement = $('#download-' + type + ' code'); + var pre = codeElement.parentElement; + + var newCode = document.createElement('CODE'); + newCode.className = codeElement.className; + newCode.textContent = text; + + Prism.highlightElement(newCode, true, function () { + pre.replaceChild(newCode, codeElement); + }); + + + $('#download-' + type + ' .download-button').onclick = function () { + saveAs(new Blob([text], { type: 'application/octet-stream;charset=utf-8' }), fileName); + }; + }(type)); + } + }); + } + + /** + * Returns a promise of the code of the Prism bundle. + * + * @param {CodePromiseInfo[]} promises + * @returns {Promise<{ code: { js: string, css: string }, errors: HTMLElement[] }>} + * + * @typedef CodePromiseInfo + * @property {Promise} contentsPromise + * @property {string} id + * @property {string} category + * @property {string} path + * @property {string} type + */ + function buildCode(promises) { + // sort the promises + + /** @type {CodePromiseInfo[]} */ + var finalPromises = []; + /** @type {Object} */ + var toSortMap = {}; + + promises.forEach(function (p) { + if (p.category == 'core' || p.category == 'themes') { + finalPromises.push(p); + } else { + var infos = toSortMap[p.id]; + if (!infos) { + toSortMap[p.id] = infos = []; + } + infos.push(p); + } + }); + + // this assumes that the ids in `toSortMap` are complete under transitive requirements + getLoader(components, Object.keys(toSortMap)).getIds().forEach(function (id) { + if (!toSortMap[id]) { + console.error(id + ' not found.'); + } + finalPromises.push.apply(finalPromises, toSortMap[id]); + }); + promises = finalPromises; + + // build + var i = 0; + var l = promises.length; + var code = { js: '', css: '' }; + var errors = []; + + var f = function (resolve) { + if (i < l) { + var p = promises[i]; + p.contentsPromise.then(function (contents) { + code[p.type] += contents + (p.type === 'js' && !/;\s*$/.test(contents) ? ';' : '') + '\n'; + i++; + f(resolve); + }); + p.contentsPromise['catch'](function () { + errors.push($u.element.create({ + tag: 'p', + prop: { + textContent: 'An error occurred while fetching the file "' + p.path + '".' + } + })); + i++; + f(resolve); + }); + } else { + resolve({ code: code, errors: errors }); + } + }; + + return new Promise(f); + } + + /** + * @returns {Promise} + */ + function getVersion() { + return getFileContents('./package.json').then(function (jsonStr) { + return JSON.parse(jsonStr).version; + }); + } + +}()); diff --git a/assets/examples.js b/assets/examples.js new file mode 100644 index 0000000000..a72b37e8d7 --- /dev/null +++ b/assets/examples.js @@ -0,0 +1,200 @@ +/** + * Manage examples + */ + +(function () { + + var examples = {}; + + var treeURL = 'https://api.github.com/repos/PrismJS/prism/git/trees/master?recursive=1'; + var treePromise = new Promise(function (resolve) { + $u.xhr({ + url: treeURL, + callback: function (xhr) { + if (xhr.status < 400) { + resolve(JSON.parse(xhr.responseText).tree); + } + } + }); + }); + + var languages = components.languages; + + Promise.all(Object.keys(languages).filter(function (id) { return id !== 'meta'; }).map(function (id) { + var language = languages[id]; + + language.enabled = language.option === 'default'; + language.path = languages.meta.path.replace(/\{id\}/g, id) + '.js'; + language.examplesPath = languages.meta.examplesPath.replace(/\{id\}/g, id) + '.html'; + + return fileExists(language.examplesPath).then(function (exists) { + return { id: id, exists: exists }; + }); + })).then(function (values) { + values.forEach(function (result) { + var id = result.id; + var exists = result.exists; + var language = languages[id]; + var checked = language.enabled; + + $u.element.create('label', { + attributes: { + 'data-id': id, + 'title': !exists ? 'No examples are available for this language.' : '' + }, + className: !exists ? 'unavailable' : '', + contents: [ + { + tag: 'input', + properties: { + type: 'checkbox', + name: 'language', + value: id, + checked: checked && exists, + disabled: !exists, + onclick: function () { + $$('input[name="' + this.name + '"]').forEach(function (input) { + languages[input.value].enabled = input.checked; + }); + + update(id); + } + } + }, + language.title + ], + inside: '#languages' + }); + examples[id] = $u.element.create('section', { + 'id': 'language-' + id, + 'className': 'language-' + id, + inside: '#examples' + }); + if (checked) { + update(id); + } + }); + }); + + + function fileExists(filepath) { + return treePromise.then(function (tree) { + for (var i = 0, l = tree.length; i < l; i++) { + if (tree[i].path === filepath) { + return true; + } + } + + // on localhost: The missing example might be for a new language + if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') { + return getFileContents(filepath).then(function () { return true; }, function () { return false; }); + } + + return false; + }); + } + + function getFileContents(filepath) { + return new Promise(function (resolve, reject) { + $u.xhr({ + url: filepath, + callback: function (xhr) { + if (xhr.status < 400 && xhr.responseText) { + resolve(xhr.responseText); + } else { + reject(); + } + } + }); + }); + } + + function buildContentsHeader(id) { + function toArray(value) { + if (Array.isArray(value)) { + return value; + } else if (value != null) { + return [value]; + } else { + return []; + } + } + + var language = languages[id]; + var header = '

' + language.title + '

'; + + if (language.alias) { + var alias = toArray(language.alias); + + header += '

To use this language, use one of the following classes:

'; + header += ''; + } else { + header += '

To use this language, use the class "language-' + id + '".

'; + } + + function wrapCode(text) { + return '' + text + ''; + } + + var deps = []; + if (language.require) { + deps.push('requires ' + toArray(language.require).map(wrapCode).join(', ')); + } + if (language.optional) { + deps.push('optionally uses ' + toArray(language.optional).map(wrapCode).join(', ')); + } + if (language.modify) { + deps.push('modifies ' + toArray(language.modify).map(wrapCode).join(', ')); + } + if (deps.length) { + header += '

'; + header += 'Dependencies:'; + header += ' This component'; + if (deps.length === 1) { + header += ' ' + deps[0] + '.'; + } else { + header += ':'; + header += '

'; + } + header += '

'; + } + + return header; + } + + function update(id) { + var language = languages[id]; + if (language.enabled) { + if (!language.examplesPromise) { + language.examplesPromise = getFileContents(language.examplesPath); + } + language.examplesPromise.then(function (contents) { + examples[id].innerHTML = buildContentsHeader(id) + contents; + + /** @type {HTMLElement} */ + var container = examples[id]; + container.innerHTML = buildContentsHeader(id) + contents; + + // the current language might be an extension of a language + // so to be safe, we explicitly add a dependency to the current language + $$('pre', container).forEach(/** @param {HTMLElement} pre */function (pre) { + var dependencies = (pre.getAttribute('data-dependencies') || '').trim(); + dependencies = dependencies ? dependencies + ',' + id : id; + pre.setAttribute('data-dependencies', dependencies); + }); + + Prism.highlightAllUnder(container); + }); + } else { + examples[id].innerHTML = ''; + } + } +}()); diff --git a/favicon.png b/assets/favicon.png similarity index 100% rename from favicon.png rename to assets/favicon.png diff --git a/assets/img/failures/coy-overlap.png b/assets/img/failures/coy-overlap.png new file mode 100644 index 0000000000..ac3c79e09d Binary files /dev/null and b/assets/img/failures/coy-overlap.png differ diff --git a/img/logo-ala.png b/assets/img/logo-ala.png similarity index 100% rename from img/logo-ala.png rename to assets/img/logo-ala.png diff --git a/img/logo-css-tricks.png b/assets/img/logo-css-tricks.png similarity index 100% rename from img/logo-css-tricks.png rename to assets/img/logo-css-tricks.png diff --git a/img/logo-drupal.png b/assets/img/logo-drupal.png similarity index 100% rename from img/logo-drupal.png rename to assets/img/logo-drupal.png diff --git a/img/logo-mdn.png b/assets/img/logo-mdn.png similarity index 100% rename from img/logo-mdn.png rename to assets/img/logo-mdn.png diff --git a/assets/img/logo-mysql.png b/assets/img/logo-mysql.png new file mode 100644 index 0000000000..d6f1328045 Binary files /dev/null and b/assets/img/logo-mysql.png differ diff --git a/img/logo-react.png b/assets/img/logo-react.png similarity index 100% rename from img/logo-react.png rename to assets/img/logo-react.png diff --git a/img/logo-sitepoint.png b/assets/img/logo-sitepoint.png similarity index 100% rename from img/logo-sitepoint.png rename to assets/img/logo-sitepoint.png diff --git a/img/logo-smashing.png b/assets/img/logo-smashing.png similarity index 100% rename from img/logo-smashing.png rename to assets/img/logo-smashing.png diff --git a/img/logo-stripe.png b/assets/img/logo-stripe.png similarity index 100% rename from img/logo-stripe.png rename to assets/img/logo-stripe.png diff --git a/img/spectrum.png b/assets/img/spectrum.png similarity index 100% rename from img/spectrum.png rename to assets/img/spectrum.png diff --git a/logo.svg b/assets/logo.svg similarity index 100% rename from logo.svg rename to assets/logo.svg diff --git a/style.css b/assets/style.css similarity index 67% rename from style.css rename to assets/style.css index 9e5a247d63..0ad8a28c43 100644 --- a/style.css +++ b/assets/style.css @@ -1,15 +1,15 @@ -@import url(http://fonts.googleapis.com/css?family=Questrial); -@import url(http://fonts.googleapis.com/css?family=Arvo); +@import url(https://fonts.googleapis.com/css?family=Questrial); +@import url(https://fonts.googleapis.com/css?family=Arvo); @font-face { - src: url(http://lea.verou.me/logo.otf); + src: url(https://lea.verou.me/logo.otf); font-family: 'LeaVerou'; } /* Shared styles */ - + section h1, #features li strong, header h2, @@ -24,7 +24,6 @@ footer p { * { margin: 0; padding: 0; - font-weight: normal; } body { @@ -44,16 +43,18 @@ section h1 { section section h1 { font-size: 150%; } - + section h1 code { font-style: normal; } - - section h1 > a { + + section h1 > a, + section h2[id] > a { text-decoration: none; } - - section h1 > a:before { + + section h1 > a:before, + section h2[id] > a:before { content: '§'; position: absolute; padding: 0 .2em; @@ -62,8 +63,9 @@ section h1 { color: silver; text-shadow: 0 1px white; } - - section h1 > a:hover:before { + + section h1 > a:hover:before, + section h2[id] > a:hover:before { color: black; background: #f1ad26; } @@ -73,10 +75,16 @@ p { } section h1, -h2 { +h2, +h3 { margin: 1em 0 .3em; } +h2, +h3 { + font-weight: normal; +} + dt { margin: 1em 0 0 0; font-size: 130%; @@ -104,9 +112,12 @@ pre { overflow: auto; } -pre > code.highlight { +mark { outline: .4em solid red; outline-offset: .4em; + margin: .4em 0; + background-color: transparent; + display: inline-block; } header, @@ -121,8 +132,9 @@ header, footer { padding: 30px -webkit-calc(50% - 450px); /* Workaround for bug */ padding: 30px calc(50% - 450px); color: white; - text-shadow: 0 -1px 2px black; - background: url(img/spectrum.png) fixed; + text-shadow: 0 -1px 2px black, 0 0 4px black, + 0 -1px 0 black, 0 1px 0 black, -1px 0 0 black, 1px 0 0 black; + background: linear-gradient(transparent, rgba(0, 0, 0, 0.6)), url(img/spectrum.png) fixed; } header:before, @@ -135,17 +147,13 @@ footer:before { background-repeat: repeat-x; background-image: linear-gradient(45deg, transparent 34%, white 34%, white 66%, transparent 66%), linear-gradient(135deg, transparent 34%, white 34%, white 66%, transparent 66%); -} - -header { - } header .intro, html.simple header { overflow: hidden; } - + header h1 { float: left; margin-right: 30px; @@ -155,12 +163,12 @@ header { text-transform: uppercase; letter-spacing: .25em; } - + header h2 { margin-top: .5em; color: #f1ad26; } - + header h1 a { text-decoration: none; } @@ -172,65 +180,68 @@ header { margin-bottom: .3em; border: 0; } - + header h2 { font-size: 300%; } - + header .intro p { margin: 0; font: 150%/1.4 Questrial, sans-serif; font-size: 150%; } - + #features { - width: 66em; - margin-top: 2em; - font-size: 80%; + margin-top: 1.6em; } - + #features li { - margin: 0 0 2em 0; + margin: 0 0 1.6em 0; list-style: none; display: inline-block; - width: 27em; + width: 49%; + box-sizing: border-box; vertical-align: top; } - + #features li:nth-child(odd) { - margin-right: 5em; + padding-right: 2em; } - + #features li:nth-child(even) { + padding-left: 2em; + } + #features li:before { content: '✓'; float: left; margin-left: -.8em; color: #7fab14; - font-size: 400%; + font-size: 320%; line-height: 1; } - + #features li strong { display: block; margin-bottom: .1em; - font-size: 200%; - } - + font-size: 160%; + } + header .download-button { float: right; margin: 0 0 .5em .5em; } - + #theme { position: relative; z-index: 1; float: right; - margin-right: -1em; + margin-right: -9em; text-align: center; text-transform: uppercase; letter-spacing: .2em; + text-shadow: 0 -1px 2px black; } - + #theme > p { position: absolute; left: 100%; @@ -238,7 +249,7 @@ header { transform-origin: top left; font-size: 130%; } - + #theme > label { position: relative; display: flex; @@ -253,7 +264,7 @@ header { font-size: 90%; padding: 0; } - + #theme > label:before { content: ''; position: absolute; @@ -262,29 +273,104 @@ header { border-radius: inherit; background: url(img/spectrum.png) fixed; } - + #theme > label:nth-of-type(n+2) { margin-top: -2.5em; } - + #theme > input:not(:checked) + label:hover { background: hsla(77, 80%, 60%, .5); } - + #theme > input { position: absolute; + left: 0; clip: rect(0,0,0,0); } - + #theme > input:checked + label { background: #7fab14; } + @media (max-width: 1300px) and (min-width: 1051px) { + #theme { + position: relative; + z-index: 1; + float: left; + margin: 1em 0; + width: 100%; + } + #theme + * { + clear: both; + } + + #theme > p { + margin-top: .5em; + } + + #theme > label { + float: left; + font-size: 82.6%; + } + + #theme > label:before { + display: none; + } + + #theme > label:nth-of-type(n+2) { + margin-top: 0; + } + } + + @media (max-width: 1050px) { + #theme { + position: relative; + z-index: 1; + float: left; + margin: 1em 0; + } + #theme + * { + clear: both; + } + + #theme > p { + left: inherit; + right: -1em; + } + + #theme > label { + float: left; + } + + #theme > label:before { + display: none; + } + + #theme > label:nth-of-type(n+2) { + margin-top: 0; + } + #theme > label:nth-of-type(n+5) { + margin-top: -2.5em; + } + #theme > label:nth-of-type(4n+1) { + margin-left: 12.5em; + } + } + + @media (max-width: 800px) { + #theme > label:nth-of-type(4) { + margin-right: 4em; + } + #theme > label:nth-of-type(4n+1) { + margin-left: 4em; + } + } + + footer { margin-top: 2em; background-position: bottom; color: white; - text-shadow: 0 -1px 2px black; } footer:before { @@ -332,10 +418,15 @@ footer { #toc { position: fixed; - left: 1%; - max-width: calc(48% - 450px); + bottom: 15px; + max-width: calc(50% - 450px - 40px); font-size: 80%; - opacity: .3; + z-index: 999; + background: white; + color: rgba(0,0,0,.5); + padding: 0 10px 10px; + border-radius: 0 3px 3px 0; + box-sizing: border-box; } @media (max-width: 1200px) { @@ -345,17 +436,24 @@ footer { } #toc:hover { - opacity: 1; + color: rgba(0,0,0,1); } #toc h1 { font-size: 180%; + margin-top: .75rem; } - + #toc li { list-style: none; + line-height: 1.2; + padding: .2em 0; + } + + #toc li a { + padding: .2em 0; } - + #logo:before { content: '☠'; float: right; @@ -383,7 +481,7 @@ footer { left: 50%; transform: translate(-50%, -50%); } - + label a.owner { margin: 0 .5em; } @@ -404,4 +502,18 @@ label a.owner:not(:hover) { padding-bottom: 1em; margin-bottom: 1em; margin-right: 1em; - } \ No newline at end of file + } + +ul.plugin-list { + column-count: 2; +} + ul.plugin-list > li { + break-inside: avoid; + page-break-inside: avoid; + } + ul.plugin-list > li > a { + font-size: 110%; + } + ul.plugin-list > li > div { + margin-bottom: .5em; + } diff --git a/assets/templates/footer.html b/assets/templates/footer.html new file mode 100644 index 0000000000..006ce4bd28 --- /dev/null +++ b/assets/templates/footer.html @@ -0,0 +1,16 @@ + +

Handcrafted with ♥, by Lea Verou, Golmote, +James DiGioia, Michael Schmidt +& all these awesome people

+ + diff --git a/templates/header-download.html b/assets/templates/header-download.html similarity index 100% rename from templates/header-download.html rename to assets/templates/header-download.html diff --git a/templates/header-main.html b/assets/templates/header-main.html similarity index 79% rename from templates/header-main.html rename to assets/templates/header-main.html index 01fe940603..be01eeb48f 100644 --- a/templates/header-main.html +++ b/assets/templates/header-main.html @@ -1,10 +1,10 @@ -

Prism

+

Prism

Download

Prism is a lightweight, extensible syntax highlighter, built with modern web standards in mind. - It’s used in thousands of websites, including some of those you visit daily. + It’s used in millions of websites, including some of those you visit daily.

)/}); -// Updated html tag pattern to allow template tags inside html tags -Prism.languages.django.tag.pattern = /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^>=]+))?)*\s*\/?>/i; -Prism.languages.insertBefore('django', 'entity', _django_template); -Prism.languages.insertBefore('inside', 'tag', _django_template, Prism.languages.django.tag); + Prism.languages.django = { + 'comment': /^\{#[\s\S]*?#\}$/, + 'tag': { + pattern: /(^\{%[+-]?\s*)\w+/, + lookbehind: true, + alias: 'keyword' + }, + 'delimiter': { + pattern: /^\{[{%][+-]?|[+-]?[}%]\}$/, + alias: 'punctuation' + }, + 'string': { + pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/, + greedy: true + }, + 'filter': { + pattern: /(\|)\w+/, + lookbehind: true, + alias: 'function' + }, + 'test': { + pattern: /(\bis\s+(?:not\s+)?)(?!not\b)\w+/, + lookbehind: true, + alias: 'function' + }, + 'function': /\b[a-z_]\w+(?=\s*\()/i, + 'keyword': /\b(?:and|as|by|else|for|if|import|in|is|loop|not|or|recursive|with|without)\b/, + 'operator': /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/, + 'number': /\b\d+(?:\.\d+)?\b/, + 'boolean': /[Ff]alse|[Nn]one|[Tt]rue/, + 'variable': /\b\w+\b/, + 'punctuation': /[{}[\](),.:;]/ + }; -if (Prism.languages.javascript) { - // Combine js code and template tags painting inside + + + + + + + + + + + + + + + + + +
+ +

hooks

+ + + + + + + +
+ +
+ +

+ Prism. + + hooks +

+ + +
+ +
+ +
+ + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) add(name, callback)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Adds the given callback to the list of callbacks for the given hook.

+

The callback will be invoked when the hook it is registered for is run. +Hooks are usually directly run by a highlight function but you can also run hooks yourself.

+

One callback function can be registered to multiple hooks and the same hook multiple times.

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The name of the hook.

callback + + +HookCallback + + + +

The callback function which is given environment variables.

+ + + + + + + + + + + + + + + + + + + + + + + + +

(static) run(name, env)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Runs a hook invoking all registered callbacks with the given environment variables.

+

Callbacks will be invoked synchronously and in the order in which they were registered.

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + +

The name of the hook.

env + + +Object.<string, any> + + + +

The environment variables of the hook passed to all callbacks registered.

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Prism.html b/docs/Prism.html new file mode 100644 index 0000000000..73efd742d1 --- /dev/null +++ b/docs/Prism.html @@ -0,0 +1,1460 @@ + + + + + + Prism - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

Prism

+ + + + + + + +
+ +
+ +

+ Prism +

+ + +
+ +
+ +
+ + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + +
Author:
+
+
    +
  • Lea Verou <https://lea.verou.me>
  • +
+
+ + + + + +
License:
+
  • MIT
+ + + + + + + + + +
+ + + + + +

Prism: Lightweight, robust, elegant syntax highlighting

+ + + + +
+ + + + + + + + + + + + + +

Namespaces

+ +
+
hooks
+
+ +
languages
+
+
+ + + +

Members

+ + + +

(static) disableWorkerMessageHandler :boolean

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Default Value:
+
    +
  • false
  • +
+ + + + + + + +
+ + + + + +
+

By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses +addEventListener to communicate with its parent instance. However, if you're using Prism manually in your +own worker, you don't want it to do this.

+

By setting this value to true, Prism will not add its own listeners to the worker.

+

You obviously have to change this value before Prism executes. To do this, you can add an +empty Prism object into the global scope before loading the Prism script like this:

+
window.Prism = window.Prism || {};
+Prism.disableWorkerMessageHandler = true;
+// Load Prism's script
+
+
+ + + +
Type:
+
    +
  • + +boolean + + +
  • +
+ + + + + + + + +

(static) manual :boolean

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Default Value:
+
    +
  • false
  • +
+ + + + + + + +
+ + + + + +
+

By default, Prism will attempt to highlight all code elements (by calling Prism.highlightAll) on the +current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load +additional languages or plugins yourself.

+

By setting this value to true, Prism will not automatically highlight all code elements on the page.

+

You obviously have to change this value before the automatic highlighting started. To do this, you can add an +empty Prism object into the global scope before loading the Prism script like this:

+
window.Prism = window.Prism || {};
+Prism.manual = true;
+// add a new <script> to load Prism's script
+
+
+ + + +
Type:
+
    +
  • + +boolean + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

(static) highlight(text, grammar, language) → {string}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Low-level function, only use if you know what you’re doing. It accepts a string of text as input +and the language definitions to use, and returns a string with the HTML produced.

+

The following hooks will be run:

+
    +
  1. before-tokenize
  2. +
  3. after-tokenize
  4. +
  5. wrap: On each Token.
  6. +
+
+ + + + + + + + + +
Example
+ +
Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
text + + +string + + + +

A string with the code to be highlighted.

grammar + + +Grammar + + + +

An object containing the tokens to use.

+

Usually a language definition like Prism.languages.markup.

language + + +string + + + +

The name of the language definition passed to grammar.

+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+

The highlighted HTML.

+
+ + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + +

(static) highlightAll(asyncopt, callbackopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

This is the most high-level function in Prism’s API. +It fetches all the elements that have a .language-xxxx class and then calls Prism.highlightElement on +each one of them.

+

This is equivalent to Prism.highlightAllUnder(document, async, callback).

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
async + + +boolean + + + + + + <optional>
+ + + + + +
+ + false + +

Same as in Prism.highlightAllUnder.

callback + + +HighlightCallback + + + + + + <optional>
+ + + + + +
+ +

Same as in Prism.highlightAllUnder.

+ + + + + + + + + + + + + + + + + + + + + + + + +

(static) highlightAllUnder(container, asyncopt, callbackopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Fetches all the descendants of container that have a .language-xxxx class and then calls +Prism.highlightElement on each one of them.

+

The following hooks will be run:

+
    +
  1. before-highlightall
  2. +
  3. before-all-elements-highlight
  4. +
  5. All hooks of Prism.highlightElement for each element.
  6. +
+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
container + + +ParentNode + + + + + + + + + + + +

The root element, whose descendants that have a .language-xxxx class will be highlighted.

async + + +boolean + + + + + + <optional>
+ + + + + +
+ + false + +

Whether each element is to be highlighted asynchronously using Web Workers.

callback + + +HighlightCallback + + + + + + <optional>
+ + + + + +
+ +

An optional callback to be invoked on each element after its highlighting is done.

+ + + + + + + + + + + + + + + + + + + + + + + + +

(static) highlightElement(element, asyncopt, callbackopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Highlights the code inside a single element.

+

The following hooks will be run:

+
    +
  1. before-sanity-check
  2. +
  3. before-highlight
  4. +
  5. All hooks of Prism.highlight. These hooks will be run by an asynchronous worker if async is true.
  6. +
  7. before-insert
  8. +
  9. after-highlight
  10. +
  11. complete
  12. +
+

Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for +the element's language.

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
element + + +Element + + + + + + + + + + + +

The element containing the code. +It must have a class of language-xxxx to be processed, where xxxx is a valid language identifier.

async + + +boolean + + + + + + <optional>
+ + + + + +
+ + false + +

Whether the element is to be highlighted asynchronously using Web Workers +to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is +disabled by default.

+

Note: All language definitions required to highlight the code must be included in the main prism.js file for +asynchronous highlighting to work. You can build your own bundle on the +Download page.

callback + + +HighlightCallback + + + + + + <optional>
+ + + + + +
+ +

An optional callback to be invoked after the highlighting is done. +Mostly useful when async is true, since in that case, the highlighting is done asynchronously.

+ + + + + + + + + + + + + + + + + + + + + + + + +

(static) tokenize(text, grammar) → {TokenStream}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input +and the language definitions to use, and returns an array with the tokenized code.

+

When the language definition includes nested tokens, the function is called recursively on each of these tokens.

+

This method could be useful in other contexts as well, as a very crude parser.

+
+ + + + + + + + + +
Example
+ +
let code = `var foo = 0;`;
+let tokens = Prism.tokenize(code, Prism.languages.javascript);
+tokens.forEach(token => {
+    if (token instanceof Prism.Token && token.type === 'number') {
+        console.log(`Found numeric literal: ${token.content}`);
+    }
+});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
text + + +string + + + +

A string with the code to be highlighted.

grammar + + +Grammar + + + +

An object containing the tokens to use.

+

Usually a language definition like Prism.languages.markup.

+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+

An array of strings and tokens, a token stream.

+
+ + + +
+
+ Type +
+
+ +TokenStream + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Prism.languages.html b/docs/Prism.languages.html new file mode 100644 index 0000000000..0acd142d73 --- /dev/null +++ b/docs/Prism.languages.html @@ -0,0 +1,683 @@ + + + + + + languages - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

languages

+ + + + + + + +
+ +
+ +

+ Prism. + + languages +

+ + +
+ +
+ +
+ + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +

This namespace contains all currently loaded languages and the some helper functions to create and modify languages.

+ + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) extend(id, redef) → {Grammar}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Creates a deep copy of the language with the given id and appends the given tokens.

+

If a token in redef also appears in the copied language, then the existing token in the copied language +will be overwritten at its original position.

+

Best practices

+

Since the position of overwriting tokens (token in redef that overwrite tokens in the copied language) +doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to +understand the language definition because, normally, the order of tokens matters in Prism grammars.

+

Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens. +Furthermore, all non-overwriting tokens should be placed after the overwriting ones.

+
+ + + + + + + + + +
Example
+ +
Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
+    // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
+    // at its original position
+    'comment': { ... },
+    // CSS doesn't have a 'color' token, so this token will be appended
+    'color': /\b(?:red|green|blue)\b/
+});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
id + + +string + + + +

The id of the language to extend. This has to be a key in Prism.languages.

redef + + +Grammar + + + +

The new tokens to append.

+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+

The new language created.

+
+ + + +
+
+ Type +
+
+ +Grammar + + +
+
+ + + + + + + + + + +

(static) insertBefore(inside, before, insert, rootopt) → {Grammar}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Inserts tokens before another token in a language definition or any other grammar.

+

Usage

+

This helper method makes it easy to modify existing languages. For example, the CSS language definition +not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded +in HTML through <style> elements. To do this, it needs to modify Prism.languages.markup and add the +appropriate tokens. However, Prism.languages.markup is a regular JavaScript object literal, so if you do +this:

+
Prism.languages.markup.style = {
+    // token
+};
+
+

then the style token will be added (and processed) at the end. insertBefore allows you to insert tokens +before existing tokens. For the CSS example above, you would use it like this:

+
Prism.languages.insertBefore('markup', 'cdata', {
+    'style': {
+        // token
+    }
+});
+
+

Special cases

+

If the grammars of inside and insert have tokens with the same name, the tokens in inside's grammar +will be ignored.

+

This behavior can be used to insert tokens after before:

+
Prism.languages.insertBefore('markup', 'comment', {
+    'comment': Prism.languages.markup.comment,
+    // tokens after 'comment'
+});
+
+

Limitations

+

The main problem insertBefore has to solve is iteration order. Since ES2015, the iteration order for object +properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave +differently when keys are deleted and re-inserted. So insertBefore can't be implemented by temporarily +deleting properties which is necessary to insert at arbitrary positions.

+

To solve this problem, insertBefore doesn't actually insert the given tokens into the target object. +Instead, it will create a new object and replace all references to the target object with the new one. This +can be done without temporarily deleting properties, so the iteration order is well-defined.

+

However, only references that can be reached from Prism.languages or insert will be replaced. I.e. if +you hold the target object in a variable, then the value of the variable will not change.

+
var oldMarkup = Prism.languages.markup;
+var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... });
+
+assert(oldMarkup !== Prism.languages.markup);
+assert(newMarkup === Prism.languages.markup);
+
+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
inside + + +string + + + + + + + + + +

The property of root (e.g. a language id in Prism.languages) that contains the +object to be modified.

before + + +string + + + + + + + + + +

The key to insert before.

insert + + +Grammar + + + + + + + + + +

An object containing the key-value pairs to be inserted.

root + + +Object.<string, any> + + + + + + <optional>
+ + + + + +

The object containing inside, i.e. the object that contains the +object to be modified.

+

Defaults to Prism.languages.

+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+

The new grammar object.

+
+ + + +
+
+ Type +
+
+ +Grammar + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Token.html b/docs/Token.html new file mode 100644 index 0000000000..f35d4b397f --- /dev/null +++ b/docs/Token.html @@ -0,0 +1,631 @@ + + + + + + Token - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

Token

+ + + + + + + +
+ +
+ +

+ Token +

+ + +
+ +
+ +
+ + + + + +

new Token(type, content, aliasopt, matchedStropt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

Creates a new token.

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
type + + +string + + + + + + + + + + + +

See type

content + + +string +| + +TokenStream + + + + + + + + + + + +

See content

alias + + +string +| + +Array.<string> + + + + + + <optional>
+ + + + + +
+ +

The alias(es) of the token.

matchedStr + + +string + + + + + + <optional>
+ + + + + +
+ + "" + +

A copy of the full string this token was created from.

+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +

Members

+ + + +

alias :string|Array.<string>

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + +
+ + + + + +
+

The alias(es) of the token.

+
+ + + +
Type:
+
    +
  • + +string +| + +Array.<string> + + +
  • +
+ + + + + + + + +

content :string|TokenStream

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

The strings or tokens contained by this token.

+

This will be a token stream if the pattern matched also defined an inside grammar.

+
+ + + +
Type:
+ + + + + + + + + +

type :string

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
See:
+
+ +
+ + + +
+ + + + + +
+

The type of the token.

+

This is usually the key of a pattern in a Grammar.

+
+ + + +
Type:
+
    +
  • + +string + + +
  • +
+ + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/Montserrat/Montserrat-Bold.eot b/docs/fonts/Montserrat/Montserrat-Bold.eot new file mode 100644 index 0000000000..f2970bbdc7 Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Bold.eot differ diff --git a/docs/fonts/Montserrat/Montserrat-Bold.ttf b/docs/fonts/Montserrat/Montserrat-Bold.ttf new file mode 100644 index 0000000000..3bfd79b66f Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Bold.ttf differ diff --git a/docs/fonts/Montserrat/Montserrat-Bold.woff b/docs/fonts/Montserrat/Montserrat-Bold.woff new file mode 100644 index 0000000000..92607654b7 Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Bold.woff differ diff --git a/docs/fonts/Montserrat/Montserrat-Bold.woff2 b/docs/fonts/Montserrat/Montserrat-Bold.woff2 new file mode 100644 index 0000000000..d9940cd116 Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Bold.woff2 differ diff --git a/docs/fonts/Montserrat/Montserrat-Regular.eot b/docs/fonts/Montserrat/Montserrat-Regular.eot new file mode 100644 index 0000000000..735d12b51e Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Regular.eot differ diff --git a/docs/fonts/Montserrat/Montserrat-Regular.ttf b/docs/fonts/Montserrat/Montserrat-Regular.ttf new file mode 100644 index 0000000000..5da852a349 Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Regular.ttf differ diff --git a/docs/fonts/Montserrat/Montserrat-Regular.woff b/docs/fonts/Montserrat/Montserrat-Regular.woff new file mode 100644 index 0000000000..bf9183271b Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Regular.woff differ diff --git a/docs/fonts/Montserrat/Montserrat-Regular.woff2 b/docs/fonts/Montserrat/Montserrat-Regular.woff2 new file mode 100644 index 0000000000..72d13c60bd Binary files /dev/null and b/docs/fonts/Montserrat/Montserrat-Regular.woff2 differ diff --git a/docs/global.html b/docs/global.html new file mode 100644 index 0000000000..69c177f9b2 --- /dev/null +++ b/docs/global.html @@ -0,0 +1,965 @@ + + + + + + Global - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

Global

+ + + + + + + +
+ +
+ +

+ +

+ + +
+ +
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + +

Grammar

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
rest + + +Grammar + + + + + + <optional>
+ + + +

An optional grammar object that will be appended to this grammar.

+ + + + + + + + +
Type:
+ + + + + + + + + +

GrammarToken

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
pattern + + +RegExp + + + + + + + + + +

The regular expression of the token.

lookbehind + + +boolean + + + + + + <optional>
+ + + +
+ + false + +

If true, then the first capturing group of pattern will (effectively) +behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token.

greedy + + +boolean + + + + + + <optional>
+ + + +
+ + false + +

Whether the token is greedy.

alias + + +string +| + +Array.<string> + + + + + + <optional>
+ + + +
+ +

An optional alias or list of aliases.

inside + + +Grammar + + + + + + <optional>
+ + + +
+ +

The nested grammar of this token.

+

The inside grammar will be used to tokenize the text value of each token of this kind.

+

This can be used to make nested and even recursive language definitions.

+

Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into +each another.

+ + + + + + +
+

The expansion of a simple RegExp literal to support additional properties.

+
+ + + + + + + + + + + + + +

HighlightCallback(element) → {void}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

A function which will invoked after an element was successfully highlighted.

+
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
element + + +Element + + + +

The element successfully highlighted.

+ + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + + + + +

HookCallback(env) → {void}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
env + + +Object.<string, any> + + + +

The environment variables of the hook.

+ + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +void + + +
+
+ + + + + + + +

TokenStream

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+

A token stream is an array of strings and Token objects.

+

Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process +them.

+
    +
  1. +

    No adjacent strings.

    +
  2. +
  3. +

    No empty strings.

    +

    The only exception here is the token stream that only contains the empty string and nothing else.

    +
  4. +
+
+ + + +
Type:
+
    +
  • + +Array.<(string|Token)> + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000000..fec3654329 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,114 @@ + + + + + + Home - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+

Prism

+

Build Status +npm

+

Prism is a lightweight, robust, and elegant syntax highlighting library. It's a spin-off project from Dabblet.

+

You can learn more on prismjs.com.

+

Why another syntax highlighter?

+

More themes for Prism!

+

Contribute to Prism!

+

Prism depends on community contributions to expand and cover a wider array of use cases. If you like it, consider giving back by sending a pull request. Here are a few tips:

+
    +
  • Read the documentation. Prism was designed to be extensible.
  • +
  • Do not edit prism.js, it’s just the version of Prism used by the Prism website and is built automatically. Limit your changes to the unminified files in the components/ folder. prism.js and all minified files are generated by our build system (see below).
  • +
  • Use npm ci to install Prism's dependencies. Do not use npm install because it will cause non-deterministic builds.
  • +
  • The build system uses gulp to minify the files and build prism.js. With all of Prism's dependencies installed, you just need to run the command npm run build.
  • +
  • Please follow the code conventions used in the files already. For example, I use tabs for indentation and spaces for alignment. Opening braces are on the same line, closing braces on their own line regardless of construct. There is a space before the opening brace. etc etc.
  • +
  • Please try to err towards more smaller PRs rather than a few huge PRs. If a PR includes changes that I want to merge and also changes that I don't, handling it becomes difficult.
  • +
  • My time is very limited these days, so it might take a long time to review bigger PRs (small ones are usually merged very quickly), especially those modifying the Prism Core. This doesn't mean your PR is rejected.
  • +
  • If you contribute a new language definition, you will be responsible for handling bug reports about that language definition.
  • +
  • If you add a new language definition or plugin, you need to add it to components.json as well and rebuild Prism by running npm run build, so that it becomes available to the download build page. For new languages, please also add a few tests and an example in the examples/ folder.
  • +
  • Go to prism-themes if you want to add a new theme.
  • +
+

Thank you so much for contributing!!

+

Software requirements

+

Prism will run on almost any browser and Node.js version but you need the following software to contribute:

+
    +
  • Node.js >= 10.x
  • +
  • npm >= 6.x
  • +
+

Translations

+
+
+ + + + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/prism-core.js.html b/docs/prism-core.js.html new file mode 100644 index 0000000000..c895242f5b --- /dev/null +++ b/docs/prism-core.js.html @@ -0,0 +1,1345 @@ + + + + + + prism-core.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

prism-core.js

+ + + + + + + +
+
+
/// <reference lib="WebWorker"/>
+
+var _self = (typeof window !== 'undefined')
+	? window   // if in browser
+	: (
+		(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
+			? self // if in worker
+			: {}   // if in node js
+	);
+
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ *
+ * @license MIT <https://opensource.org/licenses/MIT>
+ * @author Lea Verou <https://lea.verou.me>
+ * @namespace
+ * @public
+ */
+var Prism = (function (_self) {
+
+	// Private helper vars
+	var lang = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i;
+	var uniqueId = 0;
+
+	// The grammar object for plaintext
+	var plainTextGrammar = {};
+
+
+	var _ = {
+		/**
+		 * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the
+		 * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load
+		 * additional languages or plugins yourself.
+		 *
+		 * By setting this value to `true`, Prism will not automatically highlight all code elements on the page.
+		 *
+		 * You obviously have to change this value before the automatic highlighting started. To do this, you can add an
+		 * empty Prism object into the global scope before loading the Prism script like this:
+		 *
+		 * ```js
+		 * window.Prism = window.Prism || {};
+		 * Prism.manual = true;
+		 * // add a new <script> to load Prism's script
+		 * ```
+		 *
+		 * @default false
+		 * @type {boolean}
+		 * @memberof Prism
+		 * @public
+		 */
+		manual: _self.Prism && _self.Prism.manual,
+		/**
+		 * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses
+		 * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your
+		 * own worker, you don't want it to do this.
+		 *
+		 * By setting this value to `true`, Prism will not add its own listeners to the worker.
+		 *
+		 * You obviously have to change this value before Prism executes. To do this, you can add an
+		 * empty Prism object into the global scope before loading the Prism script like this:
+		 *
+		 * ```js
+		 * window.Prism = window.Prism || {};
+		 * Prism.disableWorkerMessageHandler = true;
+		 * // Load Prism's script
+		 * ```
+		 *
+		 * @default false
+		 * @type {boolean}
+		 * @memberof Prism
+		 * @public
+		 */
+		disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
+
+		/**
+		 * A namespace for utility methods.
+		 *
+		 * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may
+		 * change or disappear at any time.
+		 *
+		 * @namespace
+		 * @memberof Prism
+		 */
+		util: {
+			encode: function encode(tokens) {
+				if (tokens instanceof Token) {
+					return new Token(tokens.type, encode(tokens.content), tokens.alias);
+				} else if (Array.isArray(tokens)) {
+					return tokens.map(encode);
+				} else {
+					return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
+				}
+			},
+
+			/**
+			 * Returns the name of the type of the given value.
+			 *
+			 * @param {any} o
+			 * @returns {string}
+			 * @example
+			 * type(null)      === 'Null'
+			 * type(undefined) === 'Undefined'
+			 * type(123)       === 'Number'
+			 * type('foo')     === 'String'
+			 * type(true)      === 'Boolean'
+			 * type([1, 2])    === 'Array'
+			 * type({})        === 'Object'
+			 * type(String)    === 'Function'
+			 * type(/abc+/)    === 'RegExp'
+			 */
+			type: function (o) {
+				return Object.prototype.toString.call(o).slice(8, -1);
+			},
+
+			/**
+			 * Returns a unique number for the given object. Later calls will still return the same number.
+			 *
+			 * @param {Object} obj
+			 * @returns {number}
+			 */
+			objId: function (obj) {
+				if (!obj['__id']) {
+					Object.defineProperty(obj, '__id', { value: ++uniqueId });
+				}
+				return obj['__id'];
+			},
+
+			/**
+			 * Creates a deep clone of the given object.
+			 *
+			 * The main intended use of this function is to clone language definitions.
+			 *
+			 * @param {T} o
+			 * @param {Record<number, any>} [visited]
+			 * @returns {T}
+			 * @template T
+			 */
+			clone: function deepClone(o, visited) {
+				visited = visited || {};
+
+				var clone; var id;
+				switch (_.util.type(o)) {
+					case 'Object':
+						id = _.util.objId(o);
+						if (visited[id]) {
+							return visited[id];
+						}
+						clone = /** @type {Record<string, any>} */ ({});
+						visited[id] = clone;
+
+						for (var key in o) {
+							if (o.hasOwnProperty(key)) {
+								clone[key] = deepClone(o[key], visited);
+							}
+						}
+
+						return /** @type {any} */ (clone);
+
+					case 'Array':
+						id = _.util.objId(o);
+						if (visited[id]) {
+							return visited[id];
+						}
+						clone = [];
+						visited[id] = clone;
+
+						(/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) {
+							clone[i] = deepClone(v, visited);
+						});
+
+						return /** @type {any} */ (clone);
+
+					default:
+						return o;
+				}
+			},
+
+			/**
+			 * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
+			 *
+			 * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
+			 *
+			 * @param {Element} element
+			 * @returns {string}
+			 */
+			getLanguage: function (element) {
+				while (element) {
+					var m = lang.exec(element.className);
+					if (m) {
+						return m[1].toLowerCase();
+					}
+					element = element.parentElement;
+				}
+				return 'none';
+			},
+
+			/**
+			 * Sets the Prism `language-xxxx` class of the given element.
+			 *
+			 * @param {Element} element
+			 * @param {string} language
+			 * @returns {void}
+			 */
+			setLanguage: function (element, language) {
+				// remove all `language-xxxx` classes
+				// (this might leave behind a leading space)
+				element.className = element.className.replace(RegExp(lang, 'gi'), '');
+
+				// add the new `language-xxxx` class
+				// (using `classList` will automatically clean up spaces for us)
+				element.classList.add('language-' + language);
+			},
+
+			/**
+			 * Returns the script element that is currently executing.
+			 *
+			 * This does __not__ work for line script element.
+			 *
+			 * @returns {HTMLScriptElement | null}
+			 */
+			currentScript: function () {
+				if (typeof document === 'undefined') {
+					return null;
+				}
+				if ('currentScript' in document && 1 < 2 /* hack to trip TS' flow analysis */) {
+					return /** @type {any} */ (document.currentScript);
+				}
+
+				// IE11 workaround
+				// we'll get the src of the current script by parsing IE11's error stack trace
+				// this will not work for inline scripts
+
+				try {
+					throw new Error();
+				} catch (err) {
+					// Get file src url from stack. Specifically works with the format of stack traces in IE.
+					// A stack will look like this:
+					//
+					// Error
+					//    at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
+					//    at Global code (http://localhost/components/prism-core.js:606:1)
+
+					var src = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(err.stack) || [])[1];
+					if (src) {
+						var scripts = document.getElementsByTagName('script');
+						for (var i in scripts) {
+							if (scripts[i].src == src) {
+								return scripts[i];
+							}
+						}
+					}
+					return null;
+				}
+			},
+
+			/**
+			 * Returns whether a given class is active for `element`.
+			 *
+			 * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated
+			 * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the
+			 * given class is just the given class with a `no-` prefix.
+			 *
+			 * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is
+			 * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its
+			 * ancestors have the given class or the negated version of it, then the default activation will be returned.
+			 *
+			 * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated
+			 * version of it, the class is considered active.
+			 *
+			 * @param {Element} element
+			 * @param {string} className
+			 * @param {boolean} [defaultActivation=false]
+			 * @returns {boolean}
+			 */
+			isActive: function (element, className, defaultActivation) {
+				var no = 'no-' + className;
+
+				while (element) {
+					var classList = element.classList;
+					if (classList.contains(className)) {
+						return true;
+					}
+					if (classList.contains(no)) {
+						return false;
+					}
+					element = element.parentElement;
+				}
+				return !!defaultActivation;
+			}
+		},
+
+		/**
+		 * This namespace contains all currently loaded languages and the some helper functions to create and modify languages.
+		 *
+		 * @namespace
+		 * @memberof Prism
+		 * @public
+		 */
+		languages: {
+			/**
+			 * The grammar for plain, unformatted text.
+			 */
+			plain: plainTextGrammar,
+			plaintext: plainTextGrammar,
+			text: plainTextGrammar,
+			txt: plainTextGrammar,
+
+			/**
+			 * Creates a deep copy of the language with the given id and appends the given tokens.
+			 *
+			 * If a token in `redef` also appears in the copied language, then the existing token in the copied language
+			 * will be overwritten at its original position.
+			 *
+			 * ## Best practices
+			 *
+			 * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language)
+			 * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to
+			 * understand the language definition because, normally, the order of tokens matters in Prism grammars.
+			 *
+			 * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.
+			 * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
+			 *
+			 * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`.
+			 * @param {Grammar} redef The new tokens to append.
+			 * @returns {Grammar} The new language created.
+			 * @public
+			 * @example
+			 * Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
+			 *     // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
+			 *     // at its original position
+			 *     'comment': { ... },
+			 *     // CSS doesn't have a 'color' token, so this token will be appended
+			 *     'color': /\b(?:red|green|blue)\b/
+			 * });
+			 */
+			extend: function (id, redef) {
+				var lang = _.util.clone(_.languages[id]);
+
+				for (var key in redef) {
+					lang[key] = redef[key];
+				}
+
+				return lang;
+			},
+
+			/**
+			 * Inserts tokens _before_ another token in a language definition or any other grammar.
+			 *
+			 * ## Usage
+			 *
+			 * This helper method makes it easy to modify existing languages. For example, the CSS language definition
+			 * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded
+			 * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the
+			 * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do
+			 * this:
+			 *
+			 * ```js
+			 * Prism.languages.markup.style = {
+			 *     // token
+			 * };
+			 * ```
+			 *
+			 * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens
+			 * before existing tokens. For the CSS example above, you would use it like this:
+			 *
+			 * ```js
+			 * Prism.languages.insertBefore('markup', 'cdata', {
+			 *     'style': {
+			 *         // token
+			 *     }
+			 * });
+			 * ```
+			 *
+			 * ## Special cases
+			 *
+			 * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar
+			 * will be ignored.
+			 *
+			 * This behavior can be used to insert tokens after `before`:
+			 *
+			 * ```js
+			 * Prism.languages.insertBefore('markup', 'comment', {
+			 *     'comment': Prism.languages.markup.comment,
+			 *     // tokens after 'comment'
+			 * });
+			 * ```
+			 *
+			 * ## Limitations
+			 *
+			 * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object
+			 * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave
+			 * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily
+			 * deleting properties which is necessary to insert at arbitrary positions.
+			 *
+			 * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object.
+			 * Instead, it will create a new object and replace all references to the target object with the new one. This
+			 * can be done without temporarily deleting properties, so the iteration order is well-defined.
+			 *
+			 * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if
+			 * you hold the target object in a variable, then the value of the variable will not change.
+			 *
+			 * ```js
+			 * var oldMarkup = Prism.languages.markup;
+			 * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... });
+			 *
+			 * assert(oldMarkup !== Prism.languages.markup);
+			 * assert(newMarkup === Prism.languages.markup);
+			 * ```
+			 *
+			 * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the
+			 * object to be modified.
+			 * @param {string} before The key to insert before.
+			 * @param {Grammar} insert An object containing the key-value pairs to be inserted.
+			 * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the
+			 * object to be modified.
+			 *
+			 * Defaults to `Prism.languages`.
+			 * @returns {Grammar} The new grammar object.
+			 * @public
+			 */
+			insertBefore: function (inside, before, insert, root) {
+				root = root || /** @type {any} */ (_.languages);
+				var grammar = root[inside];
+				/** @type {Grammar} */
+				var ret = {};
+
+				for (var token in grammar) {
+					if (grammar.hasOwnProperty(token)) {
+
+						if (token == before) {
+							for (var newToken in insert) {
+								if (insert.hasOwnProperty(newToken)) {
+									ret[newToken] = insert[newToken];
+								}
+							}
+						}
+
+						// Do not insert token which also occur in insert. See #1525
+						if (!insert.hasOwnProperty(token)) {
+							ret[token] = grammar[token];
+						}
+					}
+				}
+
+				var old = root[inside];
+				root[inside] = ret;
+
+				// Update references in other language definitions
+				_.languages.DFS(_.languages, function (key, value) {
+					if (value === old && key != inside) {
+						this[key] = ret;
+					}
+				});
+
+				return ret;
+			},
+
+			// Traverse a language definition with Depth First Search
+			DFS: function DFS(o, callback, type, visited) {
+				visited = visited || {};
+
+				var objId = _.util.objId;
+
+				for (var i in o) {
+					if (o.hasOwnProperty(i)) {
+						callback.call(o, i, o[i], type || i);
+
+						var property = o[i];
+						var propertyType = _.util.type(property);
+
+						if (propertyType === 'Object' && !visited[objId(property)]) {
+							visited[objId(property)] = true;
+							DFS(property, callback, null, visited);
+						} else if (propertyType === 'Array' && !visited[objId(property)]) {
+							visited[objId(property)] = true;
+							DFS(property, callback, i, visited);
+						}
+					}
+				}
+			}
+		},
+
+		plugins: {},
+
+		/**
+		 * This is the most high-level function in Prism’s API.
+		 * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on
+		 * each one of them.
+		 *
+		 * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`.
+		 *
+		 * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}.
+		 * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}.
+		 * @memberof Prism
+		 * @public
+		 */
+		highlightAll: function (async, callback) {
+			_.highlightAllUnder(document, async, callback);
+		},
+
+		/**
+		 * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls
+		 * {@link Prism.highlightElement} on each one of them.
+		 *
+		 * The following hooks will be run:
+		 * 1. `before-highlightall`
+		 * 2. `before-all-elements-highlight`
+		 * 3. All hooks of {@link Prism.highlightElement} for each element.
+		 *
+		 * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted.
+		 * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers.
+		 * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done.
+		 * @memberof Prism
+		 * @public
+		 */
+		highlightAllUnder: function (container, async, callback) {
+			var env = {
+				callback: callback,
+				container: container,
+				selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
+			};
+
+			_.hooks.run('before-highlightall', env);
+
+			env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
+
+			_.hooks.run('before-all-elements-highlight', env);
+
+			for (var i = 0, element; (element = env.elements[i++]);) {
+				_.highlightElement(element, async === true, env.callback);
+			}
+		},
+
+		/**
+		 * Highlights the code inside a single element.
+		 *
+		 * The following hooks will be run:
+		 * 1. `before-sanity-check`
+		 * 2. `before-highlight`
+		 * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`.
+		 * 4. `before-insert`
+		 * 5. `after-highlight`
+		 * 6. `complete`
+		 *
+		 * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for
+		 * the element's language.
+		 *
+		 * @param {Element} element The element containing the code.
+		 * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier.
+		 * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers
+		 * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is
+		 * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default).
+		 *
+		 * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for
+		 * asynchronous highlighting to work. You can build your own bundle on the
+		 * [Download page](https://prismjs.com/download.html).
+		 * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done.
+		 * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously.
+		 * @memberof Prism
+		 * @public
+		 */
+		highlightElement: function (element, async, callback) {
+			// Find language
+			var language = _.util.getLanguage(element);
+			var grammar = _.languages[language];
+
+			// Set language on the element, if not present
+			_.util.setLanguage(element, language);
+
+			// Set language on the parent, for styling
+			var parent = element.parentElement;
+			if (parent && parent.nodeName.toLowerCase() === 'pre') {
+				_.util.setLanguage(parent, language);
+			}
+
+			var code = element.textContent;
+
+			var env = {
+				element: element,
+				language: language,
+				grammar: grammar,
+				code: code
+			};
+
+			function insertHighlightedCode(highlightedCode) {
+				env.highlightedCode = highlightedCode;
+
+				_.hooks.run('before-insert', env);
+
+				env.element.innerHTML = env.highlightedCode;
+
+				_.hooks.run('after-highlight', env);
+				_.hooks.run('complete', env);
+				callback && callback.call(env.element);
+			}
+
+			_.hooks.run('before-sanity-check', env);
+
+			// plugins may change/add the parent/element
+			parent = env.element.parentElement;
+			if (parent && parent.nodeName.toLowerCase() === 'pre' && !parent.hasAttribute('tabindex')) {
+				parent.setAttribute('tabindex', '0');
+			}
+
+			if (!env.code) {
+				_.hooks.run('complete', env);
+				callback && callback.call(env.element);
+				return;
+			}
+
+			_.hooks.run('before-highlight', env);
+
+			if (!env.grammar) {
+				insertHighlightedCode(_.util.encode(env.code));
+				return;
+			}
+
+			if (async && _self.Worker) {
+				var worker = new Worker(_.filename);
+
+				worker.onmessage = function (evt) {
+					insertHighlightedCode(evt.data);
+				};
+
+				worker.postMessage(JSON.stringify({
+					language: env.language,
+					code: env.code,
+					immediateClose: true
+				}));
+			} else {
+				insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
+			}
+		},
+
+		/**
+		 * Low-level function, only use if you know what you’re doing. It accepts a string of text as input
+		 * and the language definitions to use, and returns a string with the HTML produced.
+		 *
+		 * The following hooks will be run:
+		 * 1. `before-tokenize`
+		 * 2. `after-tokenize`
+		 * 3. `wrap`: On each {@link Token}.
+		 *
+		 * @param {string} text A string with the code to be highlighted.
+		 * @param {Grammar} grammar An object containing the tokens to use.
+		 *
+		 * Usually a language definition like `Prism.languages.markup`.
+		 * @param {string} language The name of the language definition passed to `grammar`.
+		 * @returns {string} The highlighted HTML.
+		 * @memberof Prism
+		 * @public
+		 * @example
+		 * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');
+		 */
+		highlight: function (text, grammar, language) {
+			var env = {
+				code: text,
+				grammar: grammar,
+				language: language
+			};
+			_.hooks.run('before-tokenize', env);
+			if (!env.grammar) {
+				throw new Error('The language "' + env.language + '" has no grammar.');
+			}
+			env.tokens = _.tokenize(env.code, env.grammar);
+			_.hooks.run('after-tokenize', env);
+			return Token.stringify(_.util.encode(env.tokens), env.language);
+		},
+
+		/**
+		 * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input
+		 * and the language definitions to use, and returns an array with the tokenized code.
+		 *
+		 * When the language definition includes nested tokens, the function is called recursively on each of these tokens.
+		 *
+		 * This method could be useful in other contexts as well, as a very crude parser.
+		 *
+		 * @param {string} text A string with the code to be highlighted.
+		 * @param {Grammar} grammar An object containing the tokens to use.
+		 *
+		 * Usually a language definition like `Prism.languages.markup`.
+		 * @returns {TokenStream} An array of strings and tokens, a token stream.
+		 * @memberof Prism
+		 * @public
+		 * @example
+		 * let code = `var foo = 0;`;
+		 * let tokens = Prism.tokenize(code, Prism.languages.javascript);
+		 * tokens.forEach(token => {
+		 *     if (token instanceof Prism.Token && token.type === 'number') {
+		 *         console.log(`Found numeric literal: ${token.content}`);
+		 *     }
+		 * });
+		 */
+		tokenize: function (text, grammar) {
+			var rest = grammar.rest;
+			if (rest) {
+				for (var token in rest) {
+					grammar[token] = rest[token];
+				}
+
+				delete grammar.rest;
+			}
+
+			var tokenList = new LinkedList();
+			addAfter(tokenList, tokenList.head, text);
+
+			matchGrammar(text, tokenList, grammar, tokenList.head, 0);
+
+			return toArray(tokenList);
+		},
+
+		/**
+		 * @namespace
+		 * @memberof Prism
+		 * @public
+		 */
+		hooks: {
+			all: {},
+
+			/**
+			 * Adds the given callback to the list of callbacks for the given hook.
+			 *
+			 * The callback will be invoked when the hook it is registered for is run.
+			 * Hooks are usually directly run by a highlight function but you can also run hooks yourself.
+			 *
+			 * One callback function can be registered to multiple hooks and the same hook multiple times.
+			 *
+			 * @param {string} name The name of the hook.
+			 * @param {HookCallback} callback The callback function which is given environment variables.
+			 * @public
+			 */
+			add: function (name, callback) {
+				var hooks = _.hooks.all;
+
+				hooks[name] = hooks[name] || [];
+
+				hooks[name].push(callback);
+			},
+
+			/**
+			 * Runs a hook invoking all registered callbacks with the given environment variables.
+			 *
+			 * Callbacks will be invoked synchronously and in the order in which they were registered.
+			 *
+			 * @param {string} name The name of the hook.
+			 * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered.
+			 * @public
+			 */
+			run: function (name, env) {
+				var callbacks = _.hooks.all[name];
+
+				if (!callbacks || !callbacks.length) {
+					return;
+				}
+
+				for (var i = 0, callback; (callback = callbacks[i++]);) {
+					callback(env);
+				}
+			}
+		},
+
+		Token: Token
+	};
+	_self.Prism = _;
+
+
+	// Typescript note:
+	// The following can be used to import the Token type in JSDoc:
+	//
+	//   @typedef {InstanceType<import("./prism-core")["Token"]>} Token
+
+	/**
+	 * Creates a new token.
+	 *
+	 * @param {string} type See {@link Token#type type}
+	 * @param {string | TokenStream} content See {@link Token#content content}
+	 * @param {string|string[]} [alias] The alias(es) of the token.
+	 * @param {string} [matchedStr=""] A copy of the full string this token was created from.
+	 * @class
+	 * @global
+	 * @public
+	 */
+	function Token(type, content, alias, matchedStr) {
+		/**
+		 * The type of the token.
+		 *
+		 * This is usually the key of a pattern in a {@link Grammar}.
+		 *
+		 * @type {string}
+		 * @see GrammarToken
+		 * @public
+		 */
+		this.type = type;
+		/**
+		 * The strings or tokens contained by this token.
+		 *
+		 * This will be a token stream if the pattern matched also defined an `inside` grammar.
+		 *
+		 * @type {string | TokenStream}
+		 * @public
+		 */
+		this.content = content;
+		/**
+		 * The alias(es) of the token.
+		 *
+		 * @type {string|string[]}
+		 * @see GrammarToken
+		 * @public
+		 */
+		this.alias = alias;
+		// Copy of the full string this token was created from
+		this.length = (matchedStr || '').length | 0;
+	}
+
+	/**
+	 * A token stream is an array of strings and {@link Token Token} objects.
+	 *
+	 * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process
+	 * them.
+	 *
+	 * 1. No adjacent strings.
+	 * 2. No empty strings.
+	 *
+	 *    The only exception here is the token stream that only contains the empty string and nothing else.
+	 *
+	 * @typedef {Array<string | Token>} TokenStream
+	 * @global
+	 * @public
+	 */
+
+	/**
+	 * Converts the given token or token stream to an HTML representation.
+	 *
+	 * The following hooks will be run:
+	 * 1. `wrap`: On each {@link Token}.
+	 *
+	 * @param {string | Token | TokenStream} o The token or token stream to be converted.
+	 * @param {string} language The name of current language.
+	 * @returns {string} The HTML representation of the token or token stream.
+	 * @memberof Token
+	 * @static
+	 */
+	Token.stringify = function stringify(o, language) {
+		if (typeof o == 'string') {
+			return o;
+		}
+		if (Array.isArray(o)) {
+			var s = '';
+			o.forEach(function (e) {
+				s += stringify(e, language);
+			});
+			return s;
+		}
+
+		var env = {
+			type: o.type,
+			content: stringify(o.content, language),
+			tag: 'span',
+			classes: ['token', o.type],
+			attributes: {},
+			language: language
+		};
+
+		var aliases = o.alias;
+		if (aliases) {
+			if (Array.isArray(aliases)) {
+				Array.prototype.push.apply(env.classes, aliases);
+			} else {
+				env.classes.push(aliases);
+			}
+		}
+
+		_.hooks.run('wrap', env);
+
+		var attributes = '';
+		for (var name in env.attributes) {
+			attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
+		}
+
+		return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
+	};
+
+	/**
+	 * @param {RegExp} pattern
+	 * @param {number} pos
+	 * @param {string} text
+	 * @param {boolean} lookbehind
+	 * @returns {RegExpExecArray | null}
+	 */
+	function matchPattern(pattern, pos, text, lookbehind) {
+		pattern.lastIndex = pos;
+		var match = pattern.exec(text);
+		if (match && lookbehind && match[1]) {
+			// change the match to remove the text matched by the Prism lookbehind group
+			var lookbehindLength = match[1].length;
+			match.index += lookbehindLength;
+			match[0] = match[0].slice(lookbehindLength);
+		}
+		return match;
+	}
+
+	/**
+	 * @param {string} text
+	 * @param {LinkedList<string | Token>} tokenList
+	 * @param {any} grammar
+	 * @param {LinkedListNode<string | Token>} startNode
+	 * @param {number} startPos
+	 * @param {RematchOptions} [rematch]
+	 * @returns {void}
+	 * @private
+	 *
+	 * @typedef RematchOptions
+	 * @property {string} cause
+	 * @property {number} reach
+	 */
+	function matchGrammar(text, tokenList, grammar, startNode, startPos, rematch) {
+		for (var token in grammar) {
+			if (!grammar.hasOwnProperty(token) || !grammar[token]) {
+				continue;
+			}
+
+			var patterns = grammar[token];
+			patterns = Array.isArray(patterns) ? patterns : [patterns];
+
+			for (var j = 0; j < patterns.length; ++j) {
+				if (rematch && rematch.cause == token + ',' + j) {
+					return;
+				}
+
+				var patternObj = patterns[j];
+				var inside = patternObj.inside;
+				var lookbehind = !!patternObj.lookbehind;
+				var greedy = !!patternObj.greedy;
+				var alias = patternObj.alias;
+
+				if (greedy && !patternObj.pattern.global) {
+					// Without the global flag, lastIndex won't work
+					var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0];
+					patternObj.pattern = RegExp(patternObj.pattern.source, flags + 'g');
+				}
+
+				/** @type {RegExp} */
+				var pattern = patternObj.pattern || patternObj;
+
+				for ( // iterate the token list and keep track of the current token/string position
+					var currentNode = startNode.next, pos = startPos;
+					currentNode !== tokenList.tail;
+					pos += currentNode.value.length, currentNode = currentNode.next
+				) {
+
+					if (rematch && pos >= rematch.reach) {
+						break;
+					}
+
+					var str = currentNode.value;
+
+					if (tokenList.length > text.length) {
+						// Something went terribly wrong, ABORT, ABORT!
+						return;
+					}
+
+					if (str instanceof Token) {
+						continue;
+					}
+
+					var removeCount = 1; // this is the to parameter of removeBetween
+					var match;
+
+					if (greedy) {
+						match = matchPattern(pattern, pos, text, lookbehind);
+						if (!match || match.index >= text.length) {
+							break;
+						}
+
+						var from = match.index;
+						var to = match.index + match[0].length;
+						var p = pos;
+
+						// find the node that contains the match
+						p += currentNode.value.length;
+						while (from >= p) {
+							currentNode = currentNode.next;
+							p += currentNode.value.length;
+						}
+						// adjust pos (and p)
+						p -= currentNode.value.length;
+						pos = p;
+
+						// the current node is a Token, then the match starts inside another Token, which is invalid
+						if (currentNode.value instanceof Token) {
+							continue;
+						}
+
+						// find the last node which is affected by this match
+						for (
+							var k = currentNode;
+							k !== tokenList.tail && (p < to || typeof k.value === 'string');
+							k = k.next
+						) {
+							removeCount++;
+							p += k.value.length;
+						}
+						removeCount--;
+
+						// replace with the new match
+						str = text.slice(pos, p);
+						match.index -= pos;
+					} else {
+						match = matchPattern(pattern, 0, str, lookbehind);
+						if (!match) {
+							continue;
+						}
+					}
+
+					// eslint-disable-next-line no-redeclare
+					var from = match.index;
+					var matchStr = match[0];
+					var before = str.slice(0, from);
+					var after = str.slice(from + matchStr.length);
+
+					var reach = pos + str.length;
+					if (rematch && reach > rematch.reach) {
+						rematch.reach = reach;
+					}
+
+					var removeFrom = currentNode.prev;
+
+					if (before) {
+						removeFrom = addAfter(tokenList, removeFrom, before);
+						pos += before.length;
+					}
+
+					removeRange(tokenList, removeFrom, removeCount);
+
+					var wrapped = new Token(token, inside ? _.tokenize(matchStr, inside) : matchStr, alias, matchStr);
+					currentNode = addAfter(tokenList, removeFrom, wrapped);
+
+					if (after) {
+						addAfter(tokenList, currentNode, after);
+					}
+
+					if (removeCount > 1) {
+						// at least one Token object was removed, so we have to do some rematching
+						// this can only happen if the current pattern is greedy
+
+						/** @type {RematchOptions} */
+						var nestedRematch = {
+							cause: token + ',' + j,
+							reach: reach
+						};
+						matchGrammar(text, tokenList, grammar, currentNode.prev, pos, nestedRematch);
+
+						// the reach might have been extended because of the rematching
+						if (rematch && nestedRematch.reach > rematch.reach) {
+							rematch.reach = nestedRematch.reach;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * @typedef LinkedListNode
+	 * @property {T} value
+	 * @property {LinkedListNode<T> | null} prev The previous node.
+	 * @property {LinkedListNode<T> | null} next The next node.
+	 * @template T
+	 * @private
+	 */
+
+	/**
+	 * @template T
+	 * @private
+	 */
+	function LinkedList() {
+		/** @type {LinkedListNode<T>} */
+		var head = { value: null, prev: null, next: null };
+		/** @type {LinkedListNode<T>} */
+		var tail = { value: null, prev: head, next: null };
+		head.next = tail;
+
+		/** @type {LinkedListNode<T>} */
+		this.head = head;
+		/** @type {LinkedListNode<T>} */
+		this.tail = tail;
+		this.length = 0;
+	}
+
+	/**
+	 * Adds a new node with the given value to the list.
+	 *
+	 * @param {LinkedList<T>} list
+	 * @param {LinkedListNode<T>} node
+	 * @param {T} value
+	 * @returns {LinkedListNode<T>} The added node.
+	 * @template T
+	 */
+	function addAfter(list, node, value) {
+		// assumes that node != list.tail && values.length >= 0
+		var next = node.next;
+
+		var newNode = { value: value, prev: node, next: next };
+		node.next = newNode;
+		next.prev = newNode;
+		list.length++;
+
+		return newNode;
+	}
+	/**
+	 * Removes `count` nodes after the given node. The given node will not be removed.
+	 *
+	 * @param {LinkedList<T>} list
+	 * @param {LinkedListNode<T>} node
+	 * @param {number} count
+	 * @template T
+	 */
+	function removeRange(list, node, count) {
+		var next = node.next;
+		for (var i = 0; i < count && next !== list.tail; i++) {
+			next = next.next;
+		}
+		node.next = next;
+		next.prev = node;
+		list.length -= i;
+	}
+	/**
+	 * @param {LinkedList<T>} list
+	 * @returns {T[]}
+	 * @template T
+	 */
+	function toArray(list) {
+		var array = [];
+		var node = list.head.next;
+		while (node !== list.tail) {
+			array.push(node.value);
+			node = node.next;
+		}
+		return array;
+	}
+
+
+	if (!_self.document) {
+		if (!_self.addEventListener) {
+			// in Node.js
+			return _;
+		}
+
+		if (!_.disableWorkerMessageHandler) {
+			// In worker
+			_self.addEventListener('message', function (evt) {
+				var message = JSON.parse(evt.data);
+				var lang = message.language;
+				var code = message.code;
+				var immediateClose = message.immediateClose;
+
+				_self.postMessage(_.highlight(code, _.languages[lang], lang));
+				if (immediateClose) {
+					_self.close();
+				}
+			}, false);
+		}
+
+		return _;
+	}
+
+	// Get current script and highlight
+	var script = _.util.currentScript();
+
+	if (script) {
+		_.filename = script.src;
+
+		if (script.hasAttribute('data-manual')) {
+			_.manual = true;
+		}
+	}
+
+	function highlightAutomaticallyCallback() {
+		if (!_.manual) {
+			_.highlightAll();
+		}
+	}
+
+	if (!_.manual) {
+		// If the document state is "loading", then we'll use DOMContentLoaded.
+		// If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
+		// DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they
+		// might take longer one animation frame to execute which can create a race condition where only some plugins have
+		// been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
+		// See https://github.com/PrismJS/prism/issues/2102
+		var readyState = document.readyState;
+		if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {
+			document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
+		} else {
+			if (window.requestAnimationFrame) {
+				window.requestAnimationFrame(highlightAutomaticallyCallback);
+			} else {
+				window.setTimeout(highlightAutomaticallyCallback, 16);
+			}
+		}
+	}
+
+	return _;
+
+}(_self));
+
+if (typeof module !== 'undefined' && module.exports) {
+	module.exports = Prism;
+}
+
+// hack for components to work correctly in node.js
+if (typeof global !== 'undefined') {
+	global.Prism = Prism;
+}
+
+// some additional documentation/types
+
+/**
+ * The expansion of a simple `RegExp` literal to support additional properties.
+ *
+ * @typedef GrammarToken
+ * @property {RegExp} pattern The regular expression of the token.
+ * @property {boolean} [lookbehind=false] If `true`, then the first capturing group of `pattern` will (effectively)
+ * behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token.
+ * @property {boolean} [greedy=false] Whether the token is greedy.
+ * @property {string|string[]} [alias] An optional alias or list of aliases.
+ * @property {Grammar} [inside] The nested grammar of this token.
+ *
+ * The `inside` grammar will be used to tokenize the text value of each token of this kind.
+ *
+ * This can be used to make nested and even recursive language definitions.
+ *
+ * Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into
+ * each another.
+ * @global
+ * @public
+ */
+
+/**
+ * @typedef Grammar
+ * @type {Object<string, RegExp | GrammarToken | Array<RegExp | GrammarToken>>}
+ * @property {Grammar} [rest] An optional grammar object that will be appended to this grammar.
+ * @global
+ * @public
+ */
+
+/**
+ * A function which will invoked after an element was successfully highlighted.
+ *
+ * @callback HighlightCallback
+ * @param {Element} element The element successfully highlighted.
+ * @returns {void}
+ * @global
+ * @public
+ */
+
+/**
+ * @callback HookCallback
+ * @param {Object<string, any>} env The environment variables of the hook.
+ * @returns {void}
+ * @global
+ * @public
+ */
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/docs/scripts/collapse.js b/docs/scripts/collapse.js new file mode 100644 index 0000000000..327039fb34 --- /dev/null +++ b/docs/scripts/collapse.js @@ -0,0 +1,20 @@ +function hideAllButCurrent(){ + //by default all submenut items are hidden + //but we need to rehide them for search + document.querySelectorAll("nav > ul > li > ul li").forEach(function(parent) { + parent.style.display = "none"; + }); + + //only current page (if it exists) should be opened + var file = window.location.pathname.split("/").pop().replace(/\.html/, ''); + document.querySelectorAll("nav > ul > li > a").forEach(function(parent) { + var href = parent.attributes.href.value.replace(/\.html/, ''); + if (file === href) { + parent.parentNode.querySelectorAll("ul li").forEach(function(elem) { + elem.style.display = "block"; + }); + } + }); +} + +hideAllButCurrent(); \ No newline at end of file diff --git a/docs/scripts/linenumber.js b/docs/scripts/linenumber.js new file mode 100644 index 0000000000..8d52f7eafd --- /dev/null +++ b/docs/scripts/linenumber.js @@ -0,0 +1,25 @@ +/*global document */ +(function() { + var source = document.getElementsByClassName('prettyprint source linenums'); + var i = 0; + var lineNumber = 0; + var lineId; + var lines; + var totalLines; + var anchorHash; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = 'line' + lineNumber; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/docs/scripts/nav.js b/docs/scripts/nav.js new file mode 100644 index 0000000000..6dd8313429 --- /dev/null +++ b/docs/scripts/nav.js @@ -0,0 +1,12 @@ +function scrollToNavItem() { + var path = window.location.href.split('/').pop().replace(/\.html/, ''); + document.querySelectorAll('nav a').forEach(function(link) { + var href = link.attributes.href.value.replace(/\.html/, ''); + if (path === href) { + link.scrollIntoView({block: 'center'}); + return; + } + }) + } + + scrollToNavItem(); diff --git a/docs/scripts/polyfill.js b/docs/scripts/polyfill.js new file mode 100644 index 0000000000..44b4c92dcd --- /dev/null +++ b/docs/scripts/polyfill.js @@ -0,0 +1,4 @@ +//IE Fix, src: https://www.reddit.com/r/programminghorror/comments/6abmcr/nodelist_lacks_foreach_in_internet_explorer/ +if (typeof(NodeList.prototype.forEach)!==typeof(alert)){ + NodeList.prototype.forEach=Array.prototype.forEach; +} \ No newline at end of file diff --git a/docs/scripts/prettify/lang-css.js b/docs/scripts/prettify/lang-css.js new file mode 100644 index 0000000000..041e1f5906 --- /dev/null +++ b/docs/scripts/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/docs/scripts/prettify/prettify.js b/docs/scripts/prettify/prettify.js new file mode 100644 index 0000000000..eef5ad7e6a --- /dev/null +++ b/docs/scripts/prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p ul > li:not(.level-hide)").forEach(function(elem) { + elem.style.display = "block"; + }); + + if (typeof hideAllButCurrent === "function"){ + //let's do what ever collapse wants to do + hideAllButCurrent(); + } else { + //menu by default should be opened + document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { + elem.style.display = "block"; + }); + } + } else { + //we are searching + document.documentElement.setAttribute(searchAttr, ''); + + //show all parents + document.querySelectorAll("nav > ul > li").forEach(function(elem) { + elem.style.display = "block"; + }); + //hide all results + document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { + elem.style.display = "none"; + }); + //show results matching filter + document.querySelectorAll("nav > ul > li > ul a").forEach(function(elem) { + if (!contains(elem.parentNode, search)) { + return; + } + elem.parentNode.style.display = "block"; + }); + //hide parents without children + document.querySelectorAll("nav > ul > li").forEach(function(parent) { + var countSearchA = 0; + parent.querySelectorAll("a").forEach(function(elem) { + if (contains(elem, search)) { + countSearchA++; + } + }); + + var countUl = 0; + var countUlVisible = 0; + parent.querySelectorAll("ul").forEach(function(ulP) { + // count all elements that match the search + if (contains(ulP, search)) { + countUl++; + } + + // count all visible elements + var children = ulP.children + for (i=0; i ul { + padding: 0 10px; +} + +nav > ul > li > a { + color: #606; + margin-top: 10px; +} + +nav ul ul a { + color: hsl(207, 1%, 60%); + border-left: 1px solid hsl(207, 10%, 86%); +} + +nav ul ul a, +nav ul ul a:active { + padding-left: 20px +} + +nav h2 { + font-size: 13px; + margin: 10px 0 0 0; + padding: 0; +} + +nav > h2 > a { + margin: 10px 0 -10px; + color: #606 !important; +} + +footer { + color: hsl(0, 0%, 28%); + margin-left: 250px; + display: block; + padding: 15px; + font-style: italic; + font-size: 90%; +} + +.ancestors { + color: #999 +} + +.ancestors a { + color: #999 !important; +} + +.clear { + clear: both +} + +.important { + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px +} + +.type-signature { + color: #CA79CA +} + +.type-signature:last-child { + color: #eee; +} + +.name, .signature { + font-family: Consolas, Monaco, 'Andale Mono', monospace +} + +.signature { + color: #fc83ff; +} + +.details { + margin-top: 6px; + border-left: 2px solid #DDD; + line-height: 20px; + font-size: 14px; +} + +.details dt { + width: auto; + float: left; + padding-left: 10px; +} + +.details dd { + margin-left: 70px; + margin-top: 6px; + margin-bottom: 6px; +} + +.details ul { + margin: 0 +} + +.details ul { + list-style-type: none +} + +.details pre.prettyprint { + margin: 0 +} + +.details .object-value { + padding-top: 0 +} + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption { + font-style: italic; + font-size: 107%; + margin: 0; +} + +.prettyprint { + font-size: 14px; + overflow: auto; +} + +.prettyprint.source { + width: inherit; + line-height: 18px; + display: block; + background-color: #0d152a; + color: #aeaeae; +} + +.prettyprint code { + line-height: 18px; + display: block; + background-color: #0d152a; + color: #4D4E53; +} + +.prettyprint > code { + padding: 15px; +} + +.prettyprint .linenums code { + padding: 0 15px +} + +.prettyprint .linenums li:first-of-type code { + padding-top: 15px +} + +.prettyprint code span.line { + display: inline-block +} + +.prettyprint.linenums { + padding-left: 70px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol { + padding-left: 0 +} + +.prettyprint.linenums li { + border-left: 3px #34446B solid; +} + +.prettyprint.linenums li.selected, .prettyprint.linenums li.selected * { + background-color: #34446B; +} + +.prettyprint.linenums li * { + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.prettyprint.linenums li code:empty:after { + content:""; + display:inline-block; + width:0px; +} + +table { + border-spacing: 0; + border: 1px solid #ddd; + border-collapse: collapse; + border-radius: 3px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + width: 100%; + font-size: 14px; + margin: 1em 0; +} + +td, th { + margin: 0px; + text-align: left; + vertical-align: top; + padding: 10px; + display: table-cell; +} + +thead tr, thead tr { + background-color: #fff; + font-weight: bold; + border-bottom: 1px solid #ddd; +} + +.params .type { + white-space: nowrap; +} + +.params code { + white-space: pre; +} + +.params td, .params .name, .props .name, .name code { + color: #4D4E53; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 100%; +} + +.params td { + border-top: 1px solid #eee +} + +.params td.description > p:first-child, .props td.description > p:first-child { + margin-top: 0; + padding-top: 0; +} + +.params td.description > p:last-child, .props td.description > p:last-child { + margin-bottom: 0; + padding-bottom: 0; +} + +span.param-type, .params td .param-type, .param-type dd { + color: #606; + font-family: Consolas, Monaco, 'Andale Mono', monospace +} + +.param-type dt, .param-type dd { + display: inline-block +} + +.param-type { + margin: 14px 0; +} + +.disabled { + color: #454545 +} + +/* navicon button */ +.navicon-button { + display: none; + position: relative; + padding: 2.0625rem 1.5rem; + transition: 0.25s; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + opacity: .8; +} +.navicon-button .navicon:before, .navicon-button .navicon:after { + transition: 0.25s; +} +.navicon-button:hover { + transition: 0.5s; + opacity: 1; +} +.navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after { + transition: 0.25s; +} +.navicon-button:hover .navicon:before { + top: .825rem; +} +.navicon-button:hover .navicon:after { + top: -.825rem; +} + +/* navicon */ +.navicon { + position: relative; + width: 2.5em; + height: .3125rem; + background: #000; + transition: 0.3s; + border-radius: 2.5rem; +} +.navicon:before, .navicon:after { + display: block; + content: ""; + height: .3125rem; + width: 2.5rem; + background: #000; + position: absolute; + z-index: -1; + transition: 0.3s 0.25s; + border-radius: 1rem; +} +.navicon:before { + top: .625rem; +} +.navicon:after { + top: -.625rem; +} + +/* open */ +.nav-trigger:checked + label:not(.steps) .navicon:before, +.nav-trigger:checked + label:not(.steps) .navicon:after { + top: 0 !important; +} + +.nav-trigger:checked + label .navicon:before, +.nav-trigger:checked + label .navicon:after { + transition: 0.5s; +} + +/* Minus */ +.nav-trigger:checked + label { + -webkit-transform: scale(0.75); + transform: scale(0.75); +} + +/* × and + */ +.nav-trigger:checked + label.plus .navicon, +.nav-trigger:checked + label.x .navicon { + background: transparent; +} + +.nav-trigger:checked + label.plus .navicon:before, +.nav-trigger:checked + label.x .navicon:before { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + background: #FFF; +} + +.nav-trigger:checked + label.plus .navicon:after, +.nav-trigger:checked + label.x .navicon:after { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + background: #FFF; +} + +.nav-trigger:checked + label.plus { + -webkit-transform: scale(0.75) rotate(45deg); + transform: scale(0.75) rotate(45deg); +} + +.nav-trigger:checked ~ nav { + left: 0 !important; +} + +.nav-trigger:checked ~ .overlay { + display: block; +} + +.nav-trigger { + position: fixed; + top: 0; + clip: rect(0, 0, 0, 0); +} + +.overlay { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + background: hsla(0, 0%, 0%, 0.5); + z-index: 1; +} + +/* nav level */ +.level-hide { + display: none; +} +html[data-search-mode] .level-hide { + display: block; +} + + +@media only screen and (max-width: 680px) { + body { + overflow-x: hidden; + } + + nav { + background: #FFF; + width: 250px; + height: 100%; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: -250px; + z-index: 3; + padding: 0 10px; + transition: left 0.2s; + } + + .navicon-button { + display: inline-block; + position: fixed; + top: 1.5em; + right: 0; + z-index: 2; + } + + #main { + width: 100%; + } + + #main h1.page-title { + margin: 1em 0; + } + + #main section { + padding: 0; + } + + footer { + margin-left: 0; + } +} + +/** Add a '#' to static members */ +[data-type="member"] a::before { + content: '#'; + display: inline-block; + margin-left: -14px; + margin-right: 5px; +} + +#disqus_thread{ + margin-left: 30px; +} + +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 400; + src: url('../fonts/Montserrat/Montserrat-Regular.eot'); /* IE9 Compat Modes */ + src: url('../fonts/Montserrat/Montserrat-Regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/Montserrat/Montserrat-Regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Regular.woff') format('woff'), /* Pretty Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Regular.ttf') format('truetype'); /* Safari, Android, iOS */ +} + +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 700; + src: url('../fonts/Montserrat/Montserrat-Bold.eot'); /* IE9 Compat Modes */ + src: url('../fonts/Montserrat/Montserrat-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/Montserrat/Montserrat-Bold.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Bold.woff') format('woff'), /* Pretty Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Bold.ttf') format('truetype'); /* Safari, Android, iOS */ +} + +@font-face { + font-family: 'Source Sans Pro'; + src: url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot'); + src: url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2') format('woff2'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff') format('woff'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf') format('truetype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg#source_sans_proregular') format('svg'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Source Sans Pro'; + src: url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot'); + src: url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2') format('woff2'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff') format('woff'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf') format('truetype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg#source_sans_prolight') format('svg'); + font-weight: 300; + font-style: normal; + +} \ No newline at end of file diff --git a/docs/styles/overwrites.css b/docs/styles/overwrites.css new file mode 100644 index 0000000000..37596f1bb0 --- /dev/null +++ b/docs/styles/overwrites.css @@ -0,0 +1,19 @@ +/* + * This file contains specific fixes and changes from some parts of the theme. + * + * This file is part of Prism and not of the theme! + */ + +pre.prettyprint > ol.linenums { + /* I don't know why but this fixes the extra little scroll bar some code block have. */ + margin-bottom: 1em; +} + +.description > *:not(pre) { + /* + * Text will span across the whole width of the page by default. + * This makes is really hard to read, so this will put a max width to the elements (except code block) of all + * description blocks, so text breaks after some width. + */ + max-width: 60em; +} diff --git a/docs/styles/prettify.css b/docs/styles/prettify.css new file mode 100644 index 0000000000..d9521ec85e --- /dev/null +++ b/docs/styles/prettify.css @@ -0,0 +1,79 @@ +.pln { + color: #ddd; +} + +/* string content */ +.str { + color: #61ce3c; +} + +/* a keyword */ +.kwd { + color: #fbde2d; +} + +/* a comment */ +.com { + color: #aeaeae; +} + +/* a type name */ +.typ { + color: #8da6ce; +} + +/* a literal value */ +.lit { + color: #fbde2d; +} + +/* punctuation */ +.pun { + color: #ddd; +} + +/* lisp open bracket */ +.opn { + color: #000000; +} + +/* lisp close bracket */ +.clo { + color: #000000; +} + +/* a markup tag name */ +.tag { + color: #8da6ce; +} + +/* a markup attribute name */ +.atn { + color: #fbde2d; +} + +/* a markup attribute value */ +.atv { + color: #ddd; +} + +/* a declaration */ +.dec { + color: #EF5050; +} + +/* a variable name */ +.var { + color: #c82829; +} + +/* a function name */ +.fun { + color: #4271ae; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} diff --git a/download.html b/download.html index 3cb74e2413..4d51e4c9df 100644 --- a/download.html +++ b/download.html @@ -3,19 +3,33 @@ - + Download ▲ Prism - + - + - +
-
- +
+

Customize your download

Select your compression level, as well as the languages and plugins you need.

@@ -141,39 +145,41 @@

Customize your download

- +
- +

Total filesize: ( JavaScript + CSS)

-

Note: The filesizes displayed refer to non-gizipped files and include any CSS code required. The CSS code is not minified.

- +

Note: The filesizes displayed refer to non-gizipped files and include any CSS code required.

+
- Download JS +
- +
- Download CSS +
- + - + -
+
+ - - - - + + + + + - \ No newline at end of file + diff --git a/download.js b/download.js deleted file mode 100644 index 5e23075016..0000000000 --- a/download.js +++ /dev/null @@ -1,571 +0,0 @@ -/** - * Manage downloads - */ - -(function() { - -var cache = {}; -var form = $('form'); -var minified = true; - -var dependencies = {}; - -var treeURL = 'https://api.github.com/repos/PrismJS/prism/git/trees/gh-pages?recursive=1'; -var treePromise = new Promise(function(resolve) { - $u.xhr({ - url: treeURL, - callback: function(xhr) { - if (xhr.status < 400) { - resolve(JSON.parse(xhr.responseText).tree); - } - } - }); -}); - -var hstr = window.location.hash.match(/(?:languages|plugins)=[-+\w]+|themes=[-\w]+/g); -if (hstr) { - hstr.forEach(function(str) { - var kv = str.split('=', 2), - category = kv[0], - ids = kv[1].split('+'); - if (category !== 'meta' && category !== 'core' && components[category]) { - for (var id in components[category]) { - if (components[category][id].option) { - delete components[category][id].option; - } - } - if (category === 'themes' && ids.length) { - var themeInput = $('#theme input[value="' + ids[0] + '"]'); - if (themeInput) { - themeInput.checked = true; - } - setTheme(ids[0]); - } - ids.forEach(function(id) { - if (id !== 'meta') { - if (components[category][id]) { - var requireId = id; - while (requireId && components[category][requireId] && components[category][requireId].option !== 'default') { - if (typeof components[category][requireId] === 'string') { - components[category][requireId] = { title: components[category][requireId] } - } - components[category][requireId].option = 'default'; - requireId = components[category][requireId].require; - } - } - } - }); - } - }); -} - -// Stay compatible with old querystring feature -var qstr = window.location.search.match(/(?:languages|plugins)=[-+\w]+|themes=[-\w]+/g); -if (qstr && !hstr) { - window.location.hash = window.location.search.replace(/^\?/, ''); - window.location.search = ''; -} - -var storedTheme = localStorage.getItem('theme'); - -for (var category in components) { - var all = components[category]; - - all.meta.section = $u.element.create('section', { - className: 'options', - id: 'category-' + category, - contents: { - tag: 'h1', - contents: category.charAt(0).toUpperCase() + category.slice(1) - }, - inside: '#components' - }); - - if (all.meta.addCheckAll) { - $u.element.create('label', { - attributes: { - 'data-id': 'check-all-' + category - }, - contents: [ - { - tag: 'input', - properties: { - type: 'checkbox', - name: 'check-all-' + category, - value: '', - checked: false, - onclick: (function(category, all){ - return function () { - var checkAll = this; - $$('input[name="download-' + category + '"]').forEach(function(input) { - all[input.value].enabled = input.checked = checkAll.checked; - }); - - update(category); - }; - })(category, all) - } - }, - 'Select/unselect all' - ], - inside: all.meta.section - }); - } - - for (var id in all) { - if(id === 'meta') { - continue; - } - - var checked = false, disabled = false; - var option = all[id].option || all.meta.option; - - switch (option) { - case 'mandatory': disabled = true; // fallthrough - case 'default': checked = true; - } - if (category === 'themes' && storedTheme) { - checked = id === storedTheme; - } - - var filepath = all.meta.path.replace(/\{id}/g, id); - - var info = all[id] = { - title: all[id].title || all[id], - noCSS: all[id].noCSS || all.meta.noCSS, - noJS: all[id].noJS || all.meta.noJS, - enabled: checked, - require: $u.type(all[id].require) === 'string' ? [all[id].require] : all[id].require, - after: $u.type(all[id].after) === 'string' ? [all[id].after] : all[id].after, - owner: all[id].owner, - files: { - minified: { - paths: [], - size: 0 - }, - dev: { - paths: [], - size: 0 - } - } - }; - - if (info.require) { - info.require.forEach(function (v) { - dependencies[v] = (dependencies[v] || []).concat(id); - }); - } - - if (!all[id].noJS && !/\.css$/.test(filepath)) { - info.files.minified.paths.push(filepath.replace(/(\.js)?$/, '.min.js')); - info.files.dev.paths.push(filepath.replace(/(\.js)?$/, '.js')); - } - - - if ((!all[id].noCSS && !/\.js$/.test(filepath)) || /\.css$/.test(filepath)) { - var cssFile = filepath.replace(/(\.css)?$/, '.css'); - - info.files.minified.paths.push(cssFile); - info.files.dev.paths.push(cssFile); - } - - var label = $u.element.create('label', { - attributes: { - 'data-id': id - }, - contents: [ - { - tag: 'input', - properties: { - type: all.meta.exclusive? 'radio' : 'checkbox', - name: 'download-' + category, - value: id, - checked: checked, - disabled: disabled, - onclick: (function(id, category, all){ - return function () { - $$('input[name="' + this.name + '"]').forEach(function(input) { - all[input.value].enabled = input.checked; - }); - - if (all[id].require && this.checked) { - all[id].require.forEach(function(v) { - var input = $('label[data-id="' + v + '"] > input'); - input.checked = true; - - input.onclick(); - }); - } - - if (dependencies[id] && !this.checked) { // It’s required by others - dependencies[id].forEach(function(dependent) { - var input = $('label[data-id="' + dependent + '"] > input'); - input.checked = false; - - input.onclick(); - }); - } - - update(category, id); - }; - })(id, category, all) - } - }, - all.meta.link? { - tag: 'a', - properties: { - href: all.meta.link.replace(/\{id}/g, id) - }, - contents: info.title - } : info.title, - all[id].owner? { - tag: 'a', - properties: { - href: 'http://github.com/' + all[id].owner, - className: 'owner', - target: '_blank' - }, - contents: all[id].owner - } : ' ', - { - tag: 'strong', - className: 'filesize' - } - ], - inside: all.meta.section - }); - - // Add click events on main theme selector too. - (function (label) { - if (category === 'themes') { - var themeInput = $('#theme input[value="' + id + '"]'); - var input = $('input', label); - if (themeInput) { - var themeInputOnclick = themeInput.onclick; - themeInput.onclick = function () { - input.checked = true; - input.onclick(); - themeInputOnclick && themeInputOnclick.call(themeInput); - }; - } - } - }(label)); - } -} - -form.elements.compression[0].onclick = -form.elements.compression[1].onclick = function() { - minified = !!+this.value; - - getFilesSizes(); -}; - -function getFileSize(filepath) { - return treePromise.then(function(tree) { - for(var i=0, l=tree.length; i i) { - notNow = true; - break; - } - } - if (notNow) { - var tmp = sorted[i]; - sorted[i] = sorted[indexOfRequirement]; - sorted[indexOfRequirement] = tmp; - } - else { - i++; - } - } - return sorted; -} - -function getSortedComponentsByRequirements(components){ - var sorted = getSortedComponents(components, "after"); - return getSortedComponents(components, "require", sorted); -} - -function generateCode(){ - var promises = []; - var redownload = {}; - - for (var category in components) { - var all = components[category]; - - // In case if one component requires other, required component should go first. - var sorted = getSortedComponentsByRequirements(all); - - for (var i = 0; i < sorted.length; i++) { - var id = sorted[i]; - - if(id === 'meta') { - continue; - } - - var info = all[id]; - if (info.enabled) { - if (category !== 'core') { - redownload[category] = redownload[category] || []; - redownload[category].push(id); - } - info.files[minified? 'minified' : 'dev'].paths.forEach(function (path) { - if (cache[path]) { - var type = path.match(/\.(\w+)$/)[1]; - - promises.push({ - contentsPromise: cache[path].contentsPromise, - path: path, - type: type - }); - } - }); - } - } - } - - // Hide error message if visible - var error = $('#download .error'); - error.style.display = ''; - - Promise.all([buildCode(promises), getVersion()]).then(function(arr) { - var res = arr[0]; - var version = arr[1]; - var code = res.code; - var errors = res.errors; - - if(errors.length) { - error.style.display = 'block'; - error.innerHTML = ''; - $u.element.contents(error, errors); - } - - var redownloadUrl = window.location.href.split("#")[0] + "#"; - for (var category in redownload) { - redownloadUrl += category + "=" + redownload[category].join('+') + "&"; - } - redownloadUrl = redownloadUrl.replace(/&$/,""); - window.location.replace(redownloadUrl); - - var versionComment = "/* PrismJS " + version + "\n" + redownloadUrl + " */"; - - for (var type in code) { - var codeElement = $('#download-' + type + ' code'); - - codeElement.textContent = versionComment + "\n" + code[type]; - Prism.highlightElement(codeElement, true); - - $('#download-' + type + ' .download-button').href = 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(versionComment + "\n" + code[type]); - } - }); -} - -function buildCode(promises) { - var i = 0, - l = promises.length; - var code = {js: '', css: ''}; - var errors = []; - - var f = function(resolve) { - if(i < l) { - var p = promises[i]; - p.contentsPromise.then(function(contents) { - code[p.type] += contents + (p.type === 'js' && !/;\s*$/.test(contents) ? ';' : '') + '\n'; - i++; - f(resolve); - }); - p.contentsPromise['catch'](function() { - errors.push($u.element.create({ - tag: 'p', - prop: { - textContent: 'An error occurred while fetching the file "' + p.path + '".' - } - })); - i++; - f(resolve); - }); - } else { - resolve({code: code, errors: errors}); - } - }; - - return new Promise(f); -} - -function getVersion() { - return getFileContents('./package.json').then(function (jsonStr) { - return JSON.parse(jsonStr).version; - }); -} - -})(); \ No newline at end of file diff --git a/examples.html b/examples.html index 600e8e9574..0d979d5981 100644 --- a/examples.html +++ b/examples.html @@ -3,9 +3,9 @@ - + Examples ▲ Prism - + - + - +
-
+

Examples

The examples in this page serve a dual purpose: They act as unit tests, making it easy to spot bugs, and at the same time demonstrate what Prism can do, on simple and on edge cases.

@@ -97,14 +97,15 @@

Per language examples

-
+
+ - + - - - + + + diff --git a/examples.js b/examples.js deleted file mode 100644 index ba275c5559..0000000000 --- a/examples.js +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Manage examples - */ - -(function() { - -var examples = {}; - -var treeURL = 'https://api.github.com/repos/PrismJS/prism/git/trees/gh-pages?recursive=1'; -var treePromise = new Promise(function (resolve) { - $u.xhr({ - url: treeURL, - callback: function (xhr) { - if (xhr.status < 400) { - resolve(JSON.parse(xhr.responseText).tree); - } - } - }); -}); - -var languages = components.languages; - -for (var id in languages) { - if (id === 'meta') { - continue; - } - - (function (id) { - var language = languages[id]; - var checked = false; - - if (language.option === 'default') { - checked = true; - } - - language.enabled = checked; - language.path = languages.meta.path.replace(/\{id}/g, id) + '.js'; - language.examplesPath = languages.meta.examplesPath.replace(/\{id}/g, id) + '.html'; - - fileExists(language.examplesPath).then(function (exists) { - $u.element.create('label', { - attributes: { - 'data-id': id, - 'title': !exists ? 'No examples are available for this language.' : '' - }, - className: !exists ? 'unavailable' : '', - contents: [ - { - tag: 'input', - properties: { - type: 'checkbox', - name: 'language', - value: id, - checked: checked && exists, - disabled: !exists, - onclick: function () { - $$('input[name="' + this.name + '"]').forEach(function (input) { - languages[input.value].enabled = input.checked; - }); - - update(id); - } - } - }, - language.title - ], - inside: '#languages' - }); - examples[id] = $u.element.create('section', { - 'id': 'language-' + id, - 'className': 'language-' + id, - inside: '#examples' - }); - if (checked) { - update(id); - } - }); - }(id)); -} - -function fileExists(filepath) { - return treePromise.then(function (tree) { - for (var i = 0, l = tree.length; i < l; i++) { - if (tree[i].path === filepath) { - return true; - } - } - return false; - }); -} - -function getFileContents(filepath) { - return new Promise(function (resolve, reject) { - $u.xhr({ - url: filepath, - callback: function (xhr) { - if (xhr.status < 400 && xhr.responseText) { - resolve(xhr.responseText); - } else { - reject(); - } - } - }); - }); -} - -function buildContentsHeader(id) { - var language = languages[id]; - var header = '

' + language.title + '

'; - if (language.overrideExampleHeader) { - return header; - } - if (language.alias) { - var alias = language.alias; - if (Prism.util.type(alias) !== 'Array') { - alias = [alias]; - } - - header += '

To use this language, use one of the following classes:

'; - header += '
  • "language-' + id + '"
  • '; - alias.forEach(function (alias) { - header += '
  • "language-' + alias + '"
  • '; - }); - header += '
'; - } else { - header += '

To use this language, use the class "language-' + id + '".

'; - } - if (language.require) { - var require = language.require; - if (Prism.util.type(require) !== 'Array') { - require = [require]; - } - - header += '

Dependencies: The following dependencies need to be loaded before this component: '; - header += require.map(function (dep) { - return '' + dep + ''; - }).join(', '); - header += '.

'; - } - return header; -} - -function update(id) { - var language = languages[id]; - if (language.enabled) { - if (!language.examplesPromise) { - language.examplesPromise = getFileContents(language.examplesPath); - } - language.examplesPromise.then(function (contents) { - examples[id].innerHTML = buildContentsHeader(id) + contents; - - loadLanguage(id).then(function () { - var elements = examples[id].querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'); - - for (var i=0, element; element = elements[i++];) { - Prism.highlightElement(element); - } - }); - }); - } else { - examples[id].innerHTML = ''; - } -} - -/** - * Loads a language, including all dependencies - * - * @param {string} lang the language to load - * @type {Promise} the promise which resolves as soon as everything is loaded - */ -function loadLanguage (lang) -{ - // at first we need to fetch all dependencies for the main language - // Note: we need to do this, even if the main language already is loaded (just to be sure..) - // - // We load an array of all dependencies and call recursively this function on each entry - // - // dependencies is now an (possibly empty) array of loading-promises - var dependencies = getDependenciesOfLanguage(lang).map(loadLanguage); - - // We create a promise, which will resolve, as soon as all dependencies are loaded. - // They need to be fully loaded because the main language may extend them. - return Promise.all(dependencies) - .then(function () { - - // If the main language itself isn't already loaded, load it now - // and return the newly created promise (we chain the promises). - // If the language is already loaded, just do nothing - the next .then() - // will immediately be called - if (!Prism.languages[lang]) { - return new Promise(function (resolve) { - $u.script('components/prism-' + lang + '.js', resolve); - }); - } - }); -} - - -/** - * Returns all dependencies (as identifiers) of a specific language - * - * @param {string} lang - * @returns {Array.} the list of dependencies. Empty if the language has none. - */ -function getDependenciesOfLanguage (lang) -{ - if (!components.languages[lang] || !components.languages[lang].require) - { - return []; - } - - return ($u.type(components.languages[lang].require) === "array") - ? components.languages[lang].require - : [components.languages[lang].require]; -} - -}()); diff --git a/examples/prism-abap.html b/examples/prism-abap.html index dfda1f7f18..103a454d58 100644 --- a/examples/prism-abap.html +++ b/examples/prism-abap.html @@ -1,11 +1,11 @@

Comments


 * Line Comments
-" End of line comment used as line comment.
-value = 1. " End of line comment
+" End of line comment used as line comment.
+value = 1. " End of line comment
 
 DATA:
-  "! ABAPDoc comment
+  "! ABAPDoc comment
   value TYPE i.
 
@@ -16,7 +16,7 @@

Strings

my_string = 'String with an escaped '' inside'. my_string = |A string template: { nvalue } times|. my_string = |A string template: { nvalue } times|. -my_string = |Characters \|, \{, and \} have to be escaped by \\ in literal text.|. +my_string = |Characters \|, \{, and \} have to be escaped by \\ in literal text.|.

Numbers and Operators

@@ -62,4 +62,4 @@

Structures and Classes

CREATE OBJECT lo_instace. my_structure-component = lo_instace->my_method( ). - \ No newline at end of file + diff --git a/examples/prism-abnf.html b/examples/prism-abnf.html new file mode 100644 index 0000000000..c983c985b8 --- /dev/null +++ b/examples/prism-abnf.html @@ -0,0 +1,60 @@ +

Full example

+
rulelist       =  1*( rule / (*c-wsp c-nl) )
+
+rule           =  rulename defined-as elements c-nl
+                       ; continues if next line starts
+                       ;  with white space
+
+rulename       =  ALPHA *(ALPHA / DIGIT / "-")
+
+defined-as     =  *c-wsp ("=" / "=/") *c-wsp
+                       ; basic rules definition and
+                       ;  incremental alternatives
+
+elements       =  alternation *c-wsp
+
+c-wsp          =  WSP / (c-nl WSP)
+
+c-nl           =  comment / CRLF
+                       ; comment or newline
+
+comment        =  ";" *(WSP / VCHAR) CRLF
+
+alternation    =  concatenation
+                  *(*c-wsp "/" *c-wsp concatenation)
+
+concatenation  =  repetition *(1*c-wsp repetition)
+
+repetition     =  [repeat] element
+
+repeat         =  1*DIGIT / (*DIGIT "*" *DIGIT)
+
+element        =  rulename / group / option /
+                  char-val / num-val / prose-val
+
+group          =  "(" *c-wsp alternation *c-wsp ")"
+
+option         =  "[" *c-wsp alternation *c-wsp "]"
+
+char-val       =  DQUOTE *(%x20-21 / %x23-7E) DQUOTE
+                       ; quoted string of SP and VCHAR
+                       ;  without DQUOTE
+
+num-val        =  "%" (bin-val / dec-val / hex-val)
+
+bin-val        =  "b" 1*BIT
+                  [ 1*("." 1*BIT) / ("-" 1*BIT) ]
+                       ; series of concatenated bit values
+                       ;  or single ONEOF range
+
+dec-val        =  "d" 1*DIGIT
+                  [ 1*("." 1*DIGIT) / ("-" 1*DIGIT) ]
+
+hex-val        =  "x" 1*HEXDIG
+                  [ 1*("." 1*HEXDIG) / ("-" 1*HEXDIG) ]
+
+prose-val      =  "<" *(%x20-3D / %x3F-7E) ">"
+                       ; bracketed string of SP and VCHAR
+                       ;  without angles
+                       ; prose description, to be used as
+                       ;  last resort
diff --git a/examples/prism-actionscript.html b/examples/prism-actionscript.html index abb5804dbb..9ef3987ead 100644 --- a/examples/prism-actionscript.html +++ b/examples/prism-actionscript.html @@ -93,7 +93,7 @@

Full example

var gradientBmp:BitmapData = new BitmapData(256, 10, false, 0); gradientBmp.draw(gradient); RLUT = new Array(); GLUT = new Array(); BLUT = new Array(); - for (var i:int = 0; i < 256; i++) { + for (var i:int = 0; i < 256; i++) { var pixelColor:uint = gradientBmp.getPixel(i, 0); //I drew the gradient backwards, so sue me RLUT[256-i] = pixelColor & 0xff0000; @@ -130,4 +130,4 @@

Full example

colorBmp.paletteMap(sourceBmp, sourceBmp.rect, O, RLUT, GLUT, BLUT, null); } } -} \ No newline at end of file +} diff --git a/examples/prism-agda.html b/examples/prism-agda.html new file mode 100644 index 0000000000..2c3d2572ec --- /dev/null +++ b/examples/prism-agda.html @@ -0,0 +1,169 @@ +

Agda Full Example

+

** Copyright - this piece of code is a modified version of [https://plfa.github.io/Naturals/] by Philip Wadler, Wen Kokke, Jeremy G Siek and contributors.

+
-- 1.1 Naturals
+
+module plfa.part1.Naturals where
+
+-- The standard way to enter Unicode math symbols in Agda
+-- is to use the IME provided by agda-mode.
+-- for example ℕ can be entered by typing \bN.
+
+-- The inductive definition of natural numbers.
+-- In Agda, data declarations correspond to axioms.
+-- Also types correspond to sets.
+-- CHAR: \bN → ℕ
+data ℕ : Set where
+	-- This corresponds to the `zero` rule in Dedekin-Peano's axioms.
+	-- Note that the syntax resembles Haskell GADTs.
+	-- Also note that the `has-type` operator is `:` (as in Idris), not `::` (as in Haskell).
+	zero : ℕ
+	-- This corresponds to the `succesor` rule in Dedekin-Peano's axioms.
+	-- In such a constructive system in Agda, induction rules etc comes by nature.
+	-- The function arrow can be either `->` or `→`.
+	-- CHAR: \to or \-> or \r- → →
+	suc  : ℕ → ℕ
+
+-- EXERCISE `seven`
+seven : ℕ
+seven = suc (suc (suc (suc (suc (suc (suc zero))))))
+
+-- This line is a compiler pragma.
+-- It makes `ℕ` correspond to Haskell's type `Integer`
+-- and allows us to use number literals (0, 1, 2, ...) to express `ℕ`.
+{-# BUILTIN NATURAL ℕ #-}
+
+-- Agda has a module system corresponding to the project file structure.
+-- e.g. `My.Namespace` is in
+-- `project path/My/Namespace.agda`.
+
+-- The `import` statement does NOT expose the names to the top namespace.
+-- You'll have to use `My.Namespace.thing` instead of directly `thing`.
+import Relation.Binary.PropositionalEquality as Eq
+-- The `open` statement unpacks all the names in a imported namespace and exposes them to the top namespace.
+-- Alternatively the `open import` statement imports a namespace and opens it at the same time.
+-- The `using (a; ..)` clause can limit a range of names to expose, instead of all of them.
+-- Alternatively, the `hiding (a; ..)` clause can limit a range of names NOT to expose.
+-- Also the `renaming (a to b; ..)` clause can rename names.
+-- CHAR: \== → ≡
+--       \gt → ⟨
+--       \lt → ⟩
+--       \qed → ∎
+open Eq using (_≡_; refl)
+open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _∎)
+
+-- Addition of `ℕ`.
+-- Note that Agda functions are *like* Haskell functions.
+-- In Agda, operators can be mixfix (incl. infix, prefix, suffix, self-bracketing and many others).
+-- All the `holes` are represented by `_`s. Unlike Haskell, operator names don't need to be put in parentheses.
+-- Operators can also be called in the manner of normal functions.
+-- e.g. a + b = _+_ a b.
+-- Sections are also available, though somehow weird.
+-- e.g. a +_ = _+_ a.
+_+_ : ℕ → ℕ → ℕ
+-- Lhs can also be infix!
+-- This is the standard definition in both Peano and Agda stdlib.
+-- We do pattern match on the first parameter, it's both convention and for convenience.
+-- Agda does a termination check on recursive function.
+-- Here the first parameter decreases over evaluation thus it is *well-founded*.
+zero    + n = n
+(suc m) + n = suc (m + n)
+
+-- Here we take a glance at the *dependent type*.
+-- In dependent type, we can put values into type level, and vice versa.
+-- This is especially useful when we're expecting to make the types more precise.
+-- Here `_≡_` is a type that says that two values are *the same*, that is, samely constructed.
+_ : 2 + 3 ≡ 5
+-- We can do it by ≡-Reasoning, that is writing a (unreasonably long) chain of equations.
+_ =
+	begin
+		2 + 3
+	≡⟨⟩ -- This operator means the lhs and rhs can be reduced to the same form so that they are equal.
+		suc (1 + 3)
+	≡⟨⟩
+		suc (suc (0 + 3)) -- Just simulating the function evaluation
+	≡⟨⟩
+		suc (suc 3)
+	≡⟨⟩
+		5
+	∎ -- The *tombstone*, QED.
+
+-- Well actually we can also get this done by simply writing `refl`.
+-- `refl` is a proof that says "If two values evaluates to the same form, then they are equal".
+-- Since Agda can automatically evaluate the terms for us, this makes sense.
+_ : 2 + 3 ≡ 5
+_ = refl
+
+-- Multiplication of `ℕ`, defined with addition.
+_*_ : ℕ → ℕ → ℕ
+-- Here we can notice that in Agda we prefer to indent by *visual blocks* instead by a fixed number of spaces.
+zero    * n = zero
+-- Here the addition is at the front, to be consistent with addition.
+(suc m) * n = n + (m * n)
+
+-- EXERCISE `_^_`, Exponentation of `ℕ`.
+_^_ : ℕ → ℕ → ℕ
+-- We can only pattern match the 2nd argument.
+m ^ zero    = suc zero
+m ^ (suc n) = m * (m ^ n)
+
+-- *Monus* (a wordplay on minus), the non-negative subtraction of `ℕ`.
+-- if less than 0 then we get 0.
+-- CHAR: \.- → ∸
+_∸_ : ℕ → ℕ → ℕ
+m     ∸ zero  = m
+zero  ∸ suc n = zero
+suc m ∸ suc n = m ∸ n
+
+-- Now we define the precedence of the operators, as in Haskell.
+infixl 6 _+_ _∸_
+infixl 7 _*_
+
+-- These are some more pragmas. Should be self-explaining.
+{-# BUILTIN NATPLUS _+_ #-}
+{-# BUILTIN NATTIMES _*_ #-}
+{-# BUILTIN NATMINUS _∸_ #-}
+
+-- EXERCISE `Bin`. We define a binary representation of natural numbers.
+-- Leading `O`s are acceptable.
+data Bin : Set where
+	⟨⟩ : Bin
+	_O : Bin → Bin
+	_I : Bin → Bin
+
+-- Like `suc` for `Bin`.
+inc : Bin → Bin
+inc ⟨⟩ = ⟨⟩ I
+inc (b O) = b I
+inc (b I) = (inc b) O
+
+-- `ℕ` to `Bin`. This is a Θ(n) solution and awaits a better Θ(log n) reimpelementation.
+to : ℕ → Bin
+to zero    = ⟨⟩ O
+to (suc n) = inc (to n)
+
+-- `Bin` to `ℕ`.
+from : Bin → ℕ
+from ⟨⟩    = 0
+from (b O) = 2 * (from b)
+from (b I) = 1 + 2 * (from b)
+
+-- Simple tests from 0 to 4.
+_ : from (to 0) ≡ 0
+_ = refl
+
+_ : from (to 1) ≡ 1
+_ = refl
+
+_ : from (to 2) ≡ 2
+_ = refl
+
+_ : from (to 3) ≡ 3
+_ = refl
+
+_ : from (to 4) ≡ 4
+_ = refl
+
+-- EXERCISE END `Bin`
+
+-- STDLIB: import Data.Nat using (ℕ; zero; suc; _+_; _*_; _^_; _∸_)
+
\ No newline at end of file diff --git a/examples/prism-al.html b/examples/prism-al.html new file mode 100644 index 0000000000..8b5c2086af --- /dev/null +++ b/examples/prism-al.html @@ -0,0 +1,60 @@ +

Full example

+
// Source: https://github.com/microsoft/AL/blob/master/samples/ControlAddIn/al/Page/CustomerCardAddIn.al
+
+pageextension 50300 CustomerCardAddIn extends "Customer Card"
+{
+	layout
+	{
+		addafter(Blocked)
+		{
+			usercontrol(ControlName; TestAddIn)
+			{
+				ApplicationArea = All;
+
+				trigger Callback(i : integer; s: text; d : decimal; c : char)
+				begin
+					Message('Got from js: %1, %2, %3, %4', i, s, d, c);
+				end;
+			}
+		}
+	}
+
+	actions
+	{
+		addafter(Approve)
+		{
+			action(CallJavaScript)
+			{
+				ApplicationArea = All;
+
+				trigger OnAction();
+				begin
+					CurrPage.ControlName.CallJavaScript(5, 'text', 6.3, 'c');
+				end;
+			}
+
+			action(CallViaCodeunit)
+			{
+				ApplicationArea = All;
+
+				trigger OnAction();
+				var c : Codeunit AddInHelpers;
+				begin
+					c.CallJavaScript(CurrPage.ControlName);
+				end;
+			}
+
+			action(CallStaleControlAddIn)
+			{
+				ApplicationArea = All;
+
+				trigger OnAction();
+				var c : Codeunit AddInHelpersSingleton;
+				begin
+					c.CallStaleAddInMethod();
+					Message('Probably nothing should happen...');
+				end;
+			}
+		}
+	}
+}
diff --git a/examples/prism-antlr4.html b/examples/prism-antlr4.html new file mode 100644 index 0000000000..2a4753e85d --- /dev/null +++ b/examples/prism-antlr4.html @@ -0,0 +1,75 @@ +

Full example

+
// Source: https://github.com/antlr/grammars-v4/blob/master/json/JSON.g4
+
+/** Taken from "The Definitive ANTLR 4 Reference" by Terence Parr */
+
+// Derived from http://json.org
+grammar JSON;
+
+json
+   : value
+   ;
+
+obj
+   : '{' pair (',' pair)* '}'
+   | '{' '}'
+   ;
+
+pair
+   : STRING ':' value
+   ;
+
+array
+   : '[' value (',' value)* ']'
+   | '[' ']'
+   ;
+
+value
+   : STRING
+   | NUMBER
+   | obj
+   | array
+   | 'true'
+   | 'false'
+   | 'null'
+   ;
+
+
+STRING
+   : '"' (ESC | SAFECODEPOINT)* '"'
+   ;
+
+
+fragment ESC
+   : '\\' (["\\/bfnrt] | UNICODE)
+   ;
+fragment UNICODE
+   : 'u' HEX HEX HEX HEX
+   ;
+fragment HEX
+   : [0-9a-fA-F]
+   ;
+fragment SAFECODEPOINT
+   : ~ ["\\\u0000-\u001F]
+   ;
+
+
+NUMBER
+   : '-'? INT ('.' [0-9] +)? EXP?
+   ;
+
+fragment INT
+   : '0' | [1-9] [0-9]*
+   ;
+
+// no leading zeros
+
+fragment EXP
+   : [Ee] [+\-]? INT
+   ;
+
+// \- since - means "range" inside [...]
+
+WS
+   : [ \t\n\r] + -> skip
+   ;
diff --git a/examples/prism-apex.html b/examples/prism-apex.html new file mode 100644 index 0000000000..f942f29da3 --- /dev/null +++ b/examples/prism-apex.html @@ -0,0 +1,152 @@ +

Full example

+
// source: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_shopping_cart_example_code.htm
+
+trigger calculate on Item__c (after insert, after update, after delete) {
+
+// Use a map because it doesn't allow duplicate values
+
+Map<ID, Shipping_Invoice__C> updateMap = new Map<ID, Shipping_Invoice__C>();
+
+// Set this integer to -1 if we are deleting
+Integer subtract ;
+
+// Populate the list of items based on trigger type
+List<Item__c> itemList;
+	if(trigger.isInsert || trigger.isUpdate){
+		itemList = Trigger.new;
+		subtract = 1;
+	}
+	else if(trigger.isDelete)
+	{
+		// Note -- there is no trigger.new in delete
+		itemList = trigger.old;
+		subtract = -1;
+	}
+
+// Access all the information we need in a single query
+// rather than querying when we need it.
+// This is a best practice for bulkifying requests
+
+set<Id> AllItems = new set<id>();
+
+for(item__c i :itemList){
+// Assert numbers are not negative.
+// None of the fields would make sense with a negative value
+
+System.assert(i.quantity__c > 0, 'Quantity must be positive');
+System.assert(i.weight__c >= 0, 'Weight must be non-negative');
+System.assert(i.price__c >= 0, 'Price must be non-negative');
+
+// If there is a duplicate Id, it won't get added to a set
+AllItems.add(i.Shipping_Invoice__C);
+}
+
+// Accessing all shipping invoices associated with the items in the trigger
+List<Shipping_Invoice__C> AllShippingInvoices = [SELECT Id, ShippingDiscount__c,
+                   SubTotal__c, TotalWeight__c, Tax__c, GrandTotal__c
+                   FROM Shipping_Invoice__C WHERE Id IN :AllItems];
+
+// Take the list we just populated and put it into a Map.
+// This will make it easier to look up a shipping invoice
+// because you must iterate a list, but you can use lookup for a map,
+Map<ID, Shipping_Invoice__C> SIMap = new Map<ID, Shipping_Invoice__C>();
+
+for(Shipping_Invoice__C sc : AllShippingInvoices)
+{
+	SIMap.put(sc.id, sc);
+}
+
+// Process the list of items
+	if(Trigger.isUpdate)
+	{
+		// Treat updates like a removal of the old item and addition of the
+		// revised item rather than figuring out the differences of each field
+		// and acting accordingly.
+		// Note updates have both trigger.new and trigger.old
+		for(Integer x = 0; x < Trigger.old.size(); x++)
+		{
+			Shipping_Invoice__C myOrder;
+			myOrder = SIMap.get(trigger.old[x].Shipping_Invoice__C);
+
+			// Decrement the previous value from the subtotal and weight.
+			myOrder.SubTotal__c -= (trigger.old[x].price__c *
+			                        trigger.old[x].quantity__c);
+			myOrder.TotalWeight__c -= (trigger.old[x].weight__c *
+			                           trigger.old[x].quantity__c);
+
+			// Increment the new subtotal and weight.
+			myOrder.SubTotal__c += (trigger.new[x].price__c *
+			                        trigger.new[x].quantity__c);
+			myOrder.TotalWeight__c += (trigger.new[x].weight__c *
+			                           trigger.new[x].quantity__c);
+		}
+
+		for(Shipping_Invoice__C myOrder : AllShippingInvoices)
+		{
+
+			// Set tax rate to 9.25%  Please note, this is a simple example.
+			// Generally, you would never hard code values.
+			// Leveraging Custom Settings for tax rates is a best practice.
+			// See Custom Settings in the Apex Developer Guide
+			// for more information.
+			myOrder.Tax__c = myOrder.Subtotal__c * .0925;
+
+			// Reset the shipping discount
+			myOrder.ShippingDiscount__c = 0;
+
+			// Set shipping rate to 75 cents per pound.
+			// Generally, you would never hard code values.
+			// Leveraging Custom Settings for the shipping rate is a best practice.
+			// See Custom Settings in the Apex Developer Guide
+			// for more information.
+			myOrder.Shipping__c = (myOrder.totalWeight__c * .75);
+			myOrder.GrandTotal__c = myOrder.SubTotal__c + myOrder.tax__c +
+			                        myOrder.Shipping__c;
+			updateMap.put(myOrder.id, myOrder);
+		}
+	}
+	else
+	{
+		for(Item__c itemToProcess : itemList)
+		{
+			Shipping_Invoice__C myOrder;
+
+			// Look up the correct shipping invoice from the ones we got earlier
+			myOrder = SIMap.get(itemToProcess.Shipping_Invoice__C);
+			myOrder.SubTotal__c += (itemToProcess.price__c *
+			                        itemToProcess.quantity__c * subtract);
+			myOrder.TotalWeight__c += (itemToProcess.weight__c *
+			                           itemToProcess.quantity__c * subtract);
+		}
+
+		for(Shipping_Invoice__C myOrder : AllShippingInvoices)
+		{
+
+			// Set tax rate to 9.25%  Please note, this is a simple example.
+			// Generally, you would never hard code values.
+			// Leveraging Custom Settings for tax rates is a best practice.
+			// See Custom Settings in the Apex Developer Guide
+			// for more information.
+			myOrder.Tax__c = myOrder.Subtotal__c * .0925;
+
+			// Reset shipping discount
+			myOrder.ShippingDiscount__c = 0;
+
+			// Set shipping rate to 75 cents per pound.
+			// Generally, you would never hard code values.
+			// Leveraging Custom Settings for the shipping rate is a best practice.
+			// See Custom Settings in the Apex Developer Guide
+			// for more information.
+			myOrder.Shipping__c = (myOrder.totalWeight__c * .75);
+			myOrder.GrandTotal__c = myOrder.SubTotal__c + myOrder.tax__c +
+			                        myOrder.Shipping__c;
+
+			updateMap.put(myOrder.id, myOrder);
+
+		}
+	}
+
+	// Only use one DML update at the end.
+	// This minimizes the number of DML requests generated from this trigger.
+	update updateMap.values();
+}
diff --git a/examples/prism-applescript.html b/examples/prism-applescript.html index c88390e819..9567b87148 100644 --- a/examples/prism-applescript.html +++ b/examples/prism-applescript.html @@ -24,18 +24,3 @@

Classes and units

set averageTemp to 63 as degrees Fahrenheit set circleArea to (pi * 7 * 7) as square yards - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Comments only support one level of nesting

-
(* Nested block
-	(* comments
-		(* on more than
-		2 levels *)
-	are *)
-not supported *)
\ No newline at end of file diff --git a/examples/prism-aql.html b/examples/prism-aql.html new file mode 100644 index 0000000000..e195fe3241 --- /dev/null +++ b/examples/prism-aql.html @@ -0,0 +1,17 @@ +

Full example

+
FOR u IN users
+    FOR f IN friends
+        FILTER u.active == @active && f.active == true && u.id == f.userId
+        RETURN { "name" : u.name, "friends" : friends }
+
+LET name = "Peter"
+LET age = 42
+RETURN { name, age }
+
+FOR u IN users
+    FILTER u.status == "not active"
+    UPDATE u WITH { status: "inactive" } IN users
+
+FOR i IN 1..100
+    INSERT { value: i } IN test
+    RETURN NEW
diff --git a/examples/prism-arduino.html b/examples/prism-arduino.html index 915f700f48..cc96f2657e 100644 --- a/examples/prism-arduino.html +++ b/examples/prism-arduino.html @@ -14,7 +14,7 @@

Booleans

false;

Operators

-
a < b;
+
a < b;
 c && d;

Full example

@@ -28,7 +28,7 @@

Full example

* runs once before everyhing else */ void setup() { - pinMode(piezo, OUTPUT); + pinMode(piezo, OUTPUT); } /** diff --git a/examples/prism-asciidoc.html b/examples/prism-asciidoc.html index d6df3021b5..bd2aedfc84 100644 --- a/examples/prism-asciidoc.html +++ b/examples/prism-asciidoc.html @@ -88,7 +88,7 @@

Tables

[cols="e,m,^,>s",width="25%"]
 |============================
 |1 >s|2 |3 |4
-^|5 2.2+^.^|6 .3+<.>m|7
+^|5 2.2+^.^|6 .3+<.>m|7
 ^|8
 |9 2+>|10
 |============================
@@ -101,4 +101,4 @@

Inline styles

Attribute entries

:Author Initials: JB
 {authorinitials}
-:Author Initials!:
\ No newline at end of file +:Author Initials!:
diff --git a/examples/prism-asmatmel.html b/examples/prism-asmatmel.html new file mode 100644 index 0000000000..577916c292 --- /dev/null +++ b/examples/prism-asmatmel.html @@ -0,0 +1,78 @@ +

Comments

+
; This is a comment
+ +

Labels

+
label1:   ; a label
+ +

Opcodes

+
LD
+OUT
+
+; lowercase
+ldi
+jmp label1
+
+ +

Assembler directives

+
.segment CODE
+.word $07d3
+
+ +

Registers

+
LD A  ; "A"
+LDA label1,x  ; "x"
+
+ +

Strings

+
.include "header.asm"
+
+ +

Numbers

+
ldi r24,#127
+ldi r24,$80f0
+ldi r24,#%01011000
+
+ +

Constants

+
ldi r16, (0<<PB5)|(1<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)
+ +

Example program to light up LEDs

+

Attach an LED (through a 220 ohm resistor) to any of the pins 0-12

+
; Pin Constant Values (Tested on Arduino UNO)
+; PD0 - 0
+; PD1 - 1
+; PD2 - 2
+; PD3 - 3
+; PD4 - 4
+; PD5 - 5
+; PD6 - 6
+; PD7 - 7
+
+; PB0 - 8
+; PB1 - 9
+; PB2 - 10
+; PB3 - 11
+; PB4 - 12
+; PB5 - 13 - System LED
+
+start:
+
+	; Set pins 0-7 to high
+	ldi		r17, (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0)
+	out		PORTD, r17
+
+	; Set pins 8-13 to high
+	ldi		r16, (1<<PB5)|(1<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1)|(1<<PB0)
+	out		PORTB, r16
+
+	; Set pins 0-7 to output mode
+	ldi		r18, (1<<DDD7)|(1<<DDD6)|(1<<DDD5)|(1<<DDD4)|(1<<DDD3)|(1<<DDD2)|(1<<DDD1)|(1<<DDD0)
+	out		DDRD, r18
+
+	; Set pins 8-13 to output mode
+	ldi		r19, (1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0)
+	out		DDRB, r19
+
+loop:
+	rjmp loop ; loop forever
+
diff --git a/examples/prism-aspnet.html b/examples/prism-aspnet.html index d9c30fcf96..d65a84d85e 100644 --- a/examples/prism-aspnet.html +++ b/examples/prism-aspnet.html @@ -1,17 +1,17 @@

Comments

-
<%-- This is a comment --%>
-<%-- This is a
+
<%-- This is a comment --%>
+<%-- This is a
 multi-line comment --%>

Page directives

-
<%@ Page Title="Products" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"  CodeBehind="ProductList.aspx.cs" Inherits="WingtipToys.ProductList" %>
+
<%@ Page Title="Products" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"  CodeBehind="ProductList.aspx.cs" Inherits="WingtipToys.ProductList" %>
 

Directive tag

-
<%: Page.Title %>
-<a href="ProductDetails.aspx?productID=<%#:Item.ProductID%>">
+
<%: Page.Title %>
+<a href="ProductDetails.aspx?productID=<%#:Item.ProductID%>">
 <span>
-    <%#:Item.ProductName%>
+	<%#:Item.ProductName%>
 </span>

Highlighted C# inside scripts

@@ -19,18 +19,18 @@

Highlighted C# inside scripts

On this page, check C# before checking ASP.NET should make the example below work properly.

<script runat="server">
-    // The following variables are visible to all procedures
-    // within the script block.
-    String str;
-    int i;
-    int i2;
+	// The following variables are visible to all procedures
+	// within the script block.
+	String str;
+	int i;
+	int i2;
 
-    int DoubleIt(int inpt)
-    {
-        // The following variable is visible only within
-        // the DoubleIt procedure.
-        int factor = 2;
+	int DoubleIt(int inpt)
+	{
+		// The following variable is visible only within
+		// the DoubleIt procedure.
+		int factor = 2;
 
-        return inpt * factor;
-    }
-</script>
\ No newline at end of file + return inpt * factor; + } +</script>
diff --git a/examples/prism-autohotkey.html b/examples/prism-autohotkey.html index 620edb2eab..3e7ced7064 100644 --- a/examples/prism-autohotkey.html +++ b/examples/prism-autohotkey.html @@ -19,7 +19,7 @@

Full example

return if f_class = #32770 ; It's a dialog. { - if f_Edit1Pos <> ; And it has an Edit1 control. + if f_Edit1Pos <> ; And it has an Edit1 control. { ; Activate the window so that if the user is middle-clicking ; outside the dialog, subsequent clicks will also work: @@ -37,7 +37,7 @@

Full example

} else if f_class in ExploreWClass,CabinetWClass ; In Explorer, switch folders. { - if f_Edit1Pos <> ; And it has an Edit1 control. + if f_Edit1Pos <> ; And it has an Edit1 control. { ControlSetText, Edit1, %f_path%, ahk_id %f_window_id% ; Tekl reported the following: "If I want to change to Folder L:\folder @@ -65,4 +65,4 @@

Full example

; 2) It's a supported type but it lacks an Edit1 control to facilitate the custom ; action, so instead do the default action below. Run, Explorer %f_path% ; Might work on more systems without double quotes. -return
\ No newline at end of file +return
diff --git a/examples/prism-autoit.html b/examples/prism-autoit.html index 51220b421c..be283a4473 100644 --- a/examples/prism-autoit.html +++ b/examples/prism-autoit.html @@ -36,17 +36,3 @@

Keywords and variables

EndIf MsgBox($MB_SYSTEMMODAL, "", "The value of $i is: " & $i) Next - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nested block comments

-
#cs
-	#cs
-		foo()
-	#ce
-#ce
\ No newline at end of file diff --git a/examples/prism-avisynth.html b/examples/prism-avisynth.html new file mode 100644 index 0000000000..e78fecd9e9 --- /dev/null +++ b/examples/prism-avisynth.html @@ -0,0 +1,24 @@ +

Full Example

+
/*
+ * Example AviSynth script for PrismJS demonstration.
+ * By Zinfidel
+ */
+
+SetFilterMTMode("DEFAULT_MT_MODE", MT_MULTI_INSTANCE)
+AddAutoloadDir("MAINSCRIPTDIR/programs/plugins")
+
+# Multiplies clip size and changes aspect ratio to 4:3
+function CorrectAspectRatio(clip c, int scaleFactor, bool "useNearestNeighbor") {
+    useNearestNeighbor = default(useNearestNeighbor, false)
+    stretchFactor = (c.Height * (4 / 3)) / c.Width
+
+    return useNearestNeighbor \
+        ? c.PointResize(c.Width * scaleFactor * stretchFactor, c.Height * scaleFactor) \
+        : c.Lanczos4Resize(c.Width * scaleFactor * stretchFactor, c.Height * scaleFactor)
+}
+
+AviSource("myclip.avi")
+last.CorrectAspectRatio(3, yes)
+
+
+Prefetch(4)
\ No newline at end of file diff --git a/examples/prism-avro-idl.html b/examples/prism-avro-idl.html new file mode 100644 index 0000000000..d6572b7130 --- /dev/null +++ b/examples/prism-avro-idl.html @@ -0,0 +1,44 @@ +

Full example

+
// Source: https://avro.apache.org/docs/current/idl.html#example
+
+/**
+ * An example protocol in Avro IDL
+ */
+@namespace("org.apache.avro.test")
+protocol Simple {
+
+	@aliases(["org.foo.KindOf"])
+	enum Kind {
+		FOO,
+		BAR, // the bar enum value
+		BAZ
+	}
+
+	fixed MD5(16);
+
+	record TestRecord {
+		@order("ignore")
+		string name;
+
+		@order("descending")
+		Kind kind;
+
+		MD5 hash;
+
+		union { MD5, null} @aliases(["hash"]) nullableHash;
+
+		array<long> arrayOfLongs;
+	}
+
+	error TestError {
+		string message;
+	}
+
+	string hello(string greeting);
+	TestRecord echo(TestRecord `record`);
+	int add(int arg1, int arg2);
+	bytes echoBytes(bytes data);
+	void `error`() throws TestError;
+	void ping() oneway;
+}
+
diff --git a/examples/prism-bash.html b/examples/prism-bash.html index 3e0febfaba..5cf56d1b59 100644 --- a/examples/prism-bash.html +++ b/examples/prism-bash.html @@ -21,7 +21,7 @@

Variables

echo ${args[0]} ${args[1]} ${args[2]}

Keywords

-
for (( i=0;i<$ELEMENTS;i++)); do
+
for (( i=0;i<$ELEMENTS;i++)); do
 	echo ${ARRAY[${i}]}
 done
 while read LINE; do
@@ -46,4 +46,4 @@ 

Some well-known commands

git pull origin master -sudo gpg --refresh-keys; sudo apt-key update; sudo rm -rf /var/lib/apt/{lists,lists.old}; sudo mkdir -p /var/lib/apt/lists/partial; sudo apt-get clean all; sudo apt-get update
\ No newline at end of file +sudo gpg --refresh-keys; sudo apt-key update; sudo rm -rf /var/lib/apt/{lists,lists.old}; sudo mkdir -p /var/lib/apt/lists/partial; sudo apt-get clean all; sudo apt-get update
diff --git a/examples/prism-basic.html b/examples/prism-basic.html index 3630a8a2c0..241a0571aa 100644 --- a/examples/prism-basic.html +++ b/examples/prism-basic.html @@ -57,7 +57,7 @@

QuickBASIC example

CALL PrintSomeStars(NumStars) DO INPUT "Do you want more stars? ", Answer$ - LOOP UNTIL Answer$ <> "" + LOOP UNTIL Answer$ <> "" Answer$ = LEFT$(Answer$, 1) LOOP WHILE UCASE$(Answer$) = "Y" PRINT "Goodbye "; UserName$ @@ -66,4 +66,4 @@

QuickBASIC example

REM This procedure uses a local variable called Stars$ Stars$ = STRING$(StarCount, "*") PRINT Stars$ -END SUB \ No newline at end of file +END SUB diff --git a/examples/prism-bbcode.html b/examples/prism-bbcode.html new file mode 100644 index 0000000000..a7416eac51 --- /dev/null +++ b/examples/prism-bbcode.html @@ -0,0 +1,21 @@ +

Full example

+
[list]
+[*]Entry A
+[*]Entry B
+[/list]
+
+[list=1]
+[*]Entry 1
+[*]Entry 2
+[/list]
+
+[style color="fuchsia"]Text in fuchsia[/style] or
+[style color=#FF00FF]Text in fuchsia[/style] or
+[color=#FF00FF]Text in fuchsia[/color]
+[quote]quoted text[/quote]
+[quote="author"]quoted text[/quote]
+
+[:-)]
+
+[url]https://en.wikipedia.org[/url]
+[url=https://en.wikipedia.org]English Wikipedia[/url]
diff --git a/examples/prism-bicep.html b/examples/prism-bicep.html new file mode 100644 index 0000000000..31a0697021 --- /dev/null +++ b/examples/prism-bicep.html @@ -0,0 +1,19 @@ +

Variable assignment

+
var foo = 'bar'
+ +

Operators

+
(1 + 2 * 3)/4 >= 3 && 4 < 5 || 6 > 7
+ +

Keywords

+
resource appServicePlan 'Microsoft.Web/serverfarms@2020-09-01' existing =  = if (diagnosticsEnabled) {
+	name: logAnalyticsWsName
+  }
+  module cosmosDb './cosmosdb.bicep' = {
+	name: 'cosmosDbDeploy'
+  }
+  param env string
+  var oneNumber = 123
+  output databaseName string = cosmosdbDatabaseName
+  for item in cosmosdbAllowedIpAddresses: {
+	  ipAddressOrRange: item
+  }
diff --git a/examples/prism-birb.html b/examples/prism-birb.html new file mode 100644 index 0000000000..cdc572707d --- /dev/null +++ b/examples/prism-birb.html @@ -0,0 +1,31 @@ +

Comments

+
// Single line comment
+/* Block comment
+on multiple lines */
+ +

Annotations

+
<Supersede> // marks an instance member as overriding a superclass
+ +

Numbers

+
int x = 1;
+double y = 1.1;
+
+ +

Strings

+
String s1 = 'Strings allow single quotes';
+String s2 = "as well as double quotes";
+var s2 = 'Birb strings are
+	multiline by default';
+ +

Full example

+
class Birb {
+  final String name;
+  int age = 19;
+
+  void construct(String newName){
+	nest.name = newName;
+  }
+}
+Birb.construct('Yoko');
+screm(Birb.name);
+
\ No newline at end of file diff --git a/examples/prism-bison.html b/examples/prism-bison.html index 9c7edeb8da..a4ccf8dd64 100644 --- a/examples/prism-bison.html +++ b/examples/prism-bison.html @@ -50,7 +50,7 @@

Full example

string* op_val; } -%start input +%start input %token <int_val> INTEGER_LITERAL %type <int_val> exp @@ -74,7 +74,7 @@

Full example

{ extern int yylineno; // defined and maintained in lex.c extern char *yytext; // defined and maintained in lex.c - + cerr << "ERROR: " << s << " at symbol \"" << yytext; cerr << "\" on line " << yylineno << endl; exit(1); @@ -84,21 +84,3 @@

Full example

{ return yyerror(string(s)); } - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Two levels of nesting inside C section

-
{
-	if($1) {
-		if($2) {
-
-		}
-	}
-} // <- Broken
-%%
-%%
\ No newline at end of file diff --git a/examples/prism-bnf.html b/examples/prism-bnf.html new file mode 100644 index 0000000000..bf30e1fe9d --- /dev/null +++ b/examples/prism-bnf.html @@ -0,0 +1,27 @@ +

Full example

+
<number>   ::= "+" <unsigned> | "-" <unsigned> | <unsigned>
+<unsigned> ::= "NaN" | "Infinity" | <decimal> | <decimal> <exponent>
+<decimal>  ::= <integer> | "." <non-zero-integer> | <non-zero-integer> "." | <integer> "." <integer>
+
+<exponent>      ::= <exponent-char> <exponent-sign> <integer>
+<exponent-char> ::= "e" | "E"
+<exponent-sign> ::= "+" | "-" | ""
+
+<integer>          ::= "0" | <non-zero-integer>
+<non-zero-integer> ::= <non-zero-digit> | <non-zero-digit> <digits>
+
+<digits>         ::= <digit> | <digit> <digits>
+<digit>          ::= "0" | <non-zero-digit>
+<non-zero-digit> ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
+ +

Routing Backus–Naur form

+
<number>   ::= [ "+" | "-" ] <unsigned>
+<unsigned> ::= "NaN" | "Infinity" | <decimal> [ <exponent> ]
+<decimal>  ::= <integer> [ "." <integer> ] | "." <non-zero-integer> | <non-zero-integer> "."
+<exponent> ::= ( "e" | "E" ) [ "+" | "-" ] <integer>
+
+<integer>          ::= "0" | <non-zero-integer>
+<non-zero-integer> ::= <non-zero-digit> [ <digit>... ]
+
+<digit>          ::= "0" | <non-zero-digit>
+<non-zero-digit> ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
diff --git a/examples/prism-brainfuck.html b/examples/prism-brainfuck.html index 89a435c92f..d47a974406 100644 --- a/examples/prism-brainfuck.html +++ b/examples/prism-brainfuck.html @@ -7,15 +7,15 @@

Full example

>+++ Add 3 to Cell #3 >+++ Add 3 to Cell #4 >+ Add 1 to Cell #5 - <<<<- Decrement the loop counter in Cell #1 + <<<<- Decrement the loop counter in Cell #1 ] Loop till Cell #1 is zero; number of iterations is 4 >+ Add 1 to Cell #2 >+ Add 1 to Cell #3 >- Subtract 1 from Cell #4 >>+ Add 1 to Cell #6 - [<] Move back to the first zero cell you find; this will + [<] Move back to the first zero cell you find; this will be Cell #1 which was cleared by the previous loop - <- Decrement the loop Counter in Cell #0 + <- Decrement the loop Counter in Cell #0 ] Loop till Cell #0 is zero; number of iterations is 8 The result of this is: @@ -27,11 +27,11 @@

Full example

>---. Subtract 3 from Cell #3 to get 101 which is 'e' +++++++..+++. Likewise for 'llo' from Cell #3 >>. Cell #5 is 32 for the space -<-. Subtract 1 from Cell #4 for 87 to give a 'W' -<. Cell #3 was set to 'o' from the end of 'Hello' +<-. Subtract 1 from Cell #4 for 87 to give a 'W' +<. Cell #3 was set to 'o' from the end of 'Hello' +++.------.--------. Cell #3 for 'rl' and 'd' >>+. Add 1 to Cell #5 gives us an exclamation point >++. And finally a newline from Cell #6

One-line example

-
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
+
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
diff --git a/examples/prism-brightscript.html b/examples/prism-brightscript.html new file mode 100644 index 0000000000..15bef53ed0 --- /dev/null +++ b/examples/prism-brightscript.html @@ -0,0 +1,13 @@ +

Full example

+
Function Main()
+	MyFunA(4)
+	MyFunB(4)
+End Function
+
+Function MyFunA(p as Object) as Void
+	print "A",p,type(p)
+End Function
+
+Function MyFunB(p as Integer) as Void
+	print "B",p,type(p)
+End Function
diff --git a/examples/prism-bro.html b/examples/prism-bro.html index 83d6374e67..86d3b3d9ea 100644 --- a/examples/prism-bro.html +++ b/examples/prism-bro.html @@ -55,100 +55,100 @@

Full example

# Whether to consider UDP "connections" for scan detection. # Can lead to false positives due to UDP fanout from some P2P apps. - const suppress_UDP_scan_checks = F &redef; + const suppress_UDP_scan_checks = F &redef; - const activate_priv_port_check = T &redef; - const activate_landmine_check = F &redef; - const landmine_thresh_trigger = 5 &redef; + const activate_priv_port_check = T &redef; + const activate_landmine_check = F &redef; + const landmine_thresh_trigger = 5 &redef; - const landmine_address: set[addr] &redef; + const landmine_address: set[addr] &redef; - const scan_summary_trigger = 25 &redef; - const port_summary_trigger = 20 &redef; - const lowport_summary_trigger = 10 &redef; + const scan_summary_trigger = 25 &redef; + const port_summary_trigger = 20 &redef; + const lowport_summary_trigger = 10 &redef; # Raise ShutdownThresh after this many failed attempts - const shut_down_thresh = 100 &redef; + const shut_down_thresh = 100 &redef; # Which services should be analyzed when detecting scanning # (not consulted if analyze_all_services is set). - const analyze_services: set[port] &redef; - const analyze_all_services = T &redef; + const analyze_services: set[port] &redef; + const analyze_all_services = T &redef; # Track address scaners only if at least these many hosts contacted. - const addr_scan_trigger = 0 &redef; + const addr_scan_trigger = 0 &redef; # Ignore address scanners for further scan detection after # scanning this many hosts. # 0 disables. - const ignore_scanners_threshold = 0 &redef; + const ignore_scanners_threshold = 0 &redef; # Report a scan of peers at each of these points. const report_peer_scan: vector of count = { 20, 100, 1000, 10000, 50000, 100000, 250000, 500000, 1000000, - } &redef; + } &redef; const report_outbound_peer_scan: vector of count = { 100, 1000, 10000, - } &redef; + } &redef; # Report a scan of ports at each of these points. const report_port_scan: vector of count = { 50, 250, 1000, 5000, 10000, 25000, 65000, - } &redef; + } &redef; # Once a source has scanned this many different ports (to however many # different remote hosts), start tracking its per-destination access. - const possible_port_scan_thresh = 20 &redef; + const possible_port_scan_thresh = 20 &redef; # Threshold for scanning privileged ports. - const priv_scan_trigger = 5 &redef; + const priv_scan_trigger = 5 &redef; const troll_skip_service = { 25/tcp, 21/tcp, 22/tcp, 20/tcp, 80/tcp, - } &redef; + } &redef; const report_accounts_tried: vector of count = { 20, 100, 1000, 10000, 100000, 1000000, - } &redef; + } &redef; const report_remote_accounts_tried: vector of count = { 100, 500, - } &redef; + } &redef; # Report a successful password guessing if the source attempted # at least this many. - const password_guessing_success_threshhold = 20 &redef; + const password_guessing_success_threshhold = 20 &redef; - const skip_accounts_tried: set[addr] &redef; + const skip_accounts_tried: set[addr] &redef; const addl_web = { 81/tcp, 443/tcp, 8000/tcp, 8001/tcp, 8080/tcp, } - &redef; + &redef; - const skip_services = { 113/tcp, } &redef; + const skip_services = { 113/tcp, } &redef; const skip_outbound_services = { 21/tcp, addl_web, } - &redef; + &redef; const skip_scan_sources = { 255.255.255.255, # who knows why we see these, but we do - } &redef; + } &redef; - const skip_scan_nets: set[subnet] = {} &redef; + const skip_scan_nets: set[subnet] = {} &redef; # List of well known local server/ports to exclude for scanning # purposes. - const skip_dest_server_ports: set[addr, port] = {} &redef; + const skip_dest_server_ports: set[addr, port] = {} &redef; # Reverse (SYN-ack) scans seen from these ports are considered # to reflect possible SYN-flooding backscatter, and not true # (stealth) scans. const backscatter_ports = { 80/tcp, 8080/tcp, 53/tcp, 53/udp, 179/tcp, 6666/tcp, 6667/tcp, - } &redef; + } &redef; const report_backscatter: vector of count = { 20, - } &redef; + } &redef; global check_scan: function(c: connection, established: bool, reverse: bool): bool; @@ -174,14 +174,14 @@

Full example

# Indexed by scanner address, yields # distinct peers scanned. # pre_distinct_peers tracks until addr_scan_trigger hosts first. global pre_distinct_peers: table[addr] of set[addr] - &read_expire = 15 mins &redef; + &read_expire = 15 mins &redef; global distinct_peers: table[addr] of set[addr] - &read_expire = 15 mins &expire_func=scan_summary &redef; + &read_expire = 15 mins &expire_func=scan_summary &redef; global distinct_ports: table[addr] of set[port] - &read_expire = 15 mins &expire_func=port_summary &redef; + &read_expire = 15 mins &expire_func=port_summary &redef; global distinct_low_ports: table[addr] of set[port] - &read_expire = 15 mins &expire_func=lowport_summary &redef; + &read_expire = 15 mins &expire_func=lowport_summary &redef; # Indexed by scanner address, yields a table with scanned hosts # (and ports). @@ -196,23 +196,23 @@

Full example

global accounts_tried: table[addr] of set[string, string] &read_expire = 1 days; - global ignored_scanners: set[addr] &create_expire = 1 day &redef; + global ignored_scanners: set[addr] &create_expire = 1 day &redef; # These tables track whether a threshold has been reached. # More precisely, the counter is the next index of threshold vector. global shut_down_thresh_reached: table[addr] of bool &default=F; global rb_idx: table[addr] of count - &default=1 &read_expire = 1 days &redef; + &default=1 &read_expire = 1 days &redef; global rps_idx: table[addr] of count - &default=1 &read_expire = 1 days &redef; + &default=1 &read_expire = 1 days &redef; global rops_idx: table[addr] of count - &default=1 &read_expire = 1 days &redef; + &default=1 &read_expire = 1 days &redef; global rpts_idx: table[addr,addr] of count - &default=1 &read_expire = 1 days &redef; + &default=1 &read_expire = 1 days &redef; global rat_idx: table[addr] of count - &default=1 &read_expire = 1 days &redef; + &default=1 &read_expire = 1 days &redef; global rrat_idx: table[addr] of count - &default=1 &read_expire = 1 days &redef; + &default=1 &read_expire = 1 days &redef; } global thresh_check: function(v: vector of count, idx: table[addr] of count, @@ -300,7 +300,7 @@

Full example

# because c might not correspond to an active connection (which # causes the function to fail). if ( suppress_UDP_scan_checks && - service >= 0/udp && service <= 65535/udp ) + service >= 0/udp && service <= 65535/udp ) return F; if ( service in skip_services && ! outbound ) @@ -343,8 +343,8 @@

Full example

empty_bs_table; } - if ( ++distinct_backscatter_peers[orig][resp] <= 2 && - # The test is <= 2 because we get two check_scan() + if ( ++distinct_backscatter_peers[orig][resp] <= 2 && + # The test is <= 2 because we get two check_scan() # calls, once on connection attempt and once on # tear-down. @@ -380,7 +380,7 @@

Full example

pre_distinct_peers[orig] = set(); add pre_distinct_peers[orig][resp]; - if ( |pre_distinct_peers[orig]| < addr_scan_trigger ) + if ( |pre_distinct_peers[orig]| < addr_scan_trigger ) ignore = T; } @@ -388,7 +388,7 @@

Full example

{ # XXXXX if ( orig !in distinct_peers ) - distinct_peers[orig] = set() &mergeable; + distinct_peers[orig] = set() &mergeable; if ( resp !in distinct_peers[orig] ) add distinct_peers[orig][resp]; @@ -448,7 +448,7 @@

Full example

if ( orig !in distinct_ports || service !in distinct_ports[orig] ) { if ( orig !in distinct_ports ) - distinct_ports[orig] = set() &mergeable; + distinct_ports[orig] = set() &mergeable; if ( service !in distinct_ports[orig] ) add distinct_ports[orig][service]; @@ -456,20 +456,20 @@

Full example

if ( |distinct_ports[orig]| >= possible_port_scan_thresh && orig !in scan_triples ) { - scan_triples[orig] = table() &mergeable; + scan_triples[orig] = table() &mergeable; add possible_scan_sources[orig]; } } # Check for low ports. - if ( activate_priv_port_check && ! outbound && service < 1024/tcp && + if ( activate_priv_port_check && ! outbound && service < 1024/tcp && service !in troll_skip_service ) { if ( orig !in distinct_low_ports || service !in distinct_low_ports[orig] ) { if ( orig !in distinct_low_ports ) - distinct_low_ports[orig] = set() &mergeable; + distinct_low_ports[orig] = set() &mergeable; add distinct_low_ports[orig][service]; @@ -494,10 +494,10 @@

Full example

if ( orig in possible_scan_sources ) { if ( orig !in scan_triples ) - scan_triples[orig] = table() &mergeable; + scan_triples[orig] = table() &mergeable; if ( resp !in scan_triples[orig] ) - scan_triples[orig][resp] = set() &mergeable; + scan_triples[orig][resp] = set() &mergeable; if ( service !in scan_triples[orig][resp] ) { @@ -559,7 +559,7 @@

Full example

return F; } - if ( idx[orig] <= |v| && n >= v[idx[orig]] ) + if ( idx[orig] <= |v| && n >= v[idx[orig]] ) { ++idx[orig]; return T; @@ -578,7 +578,7 @@

Full example

return F; } - if ( idx[orig,resp] <= |v| && n >= v[idx[orig, resp]] ) + if ( idx[orig,resp] <= |v| && n >= v[idx[orig, resp]] ) { ++idx[orig,resp]; return T; @@ -642,4 +642,4 @@

Full example

for ( orig in distinct_low_ports ) lowport_summary(distinct_low_ports, orig); } - \ No newline at end of file + diff --git a/examples/prism-bsl.html b/examples/prism-bsl.html new file mode 100644 index 0000000000..163000b060 --- /dev/null +++ b/examples/prism-bsl.html @@ -0,0 +1,386 @@ +

Comments

+
 // This is a 1C:Enterprise comments
+//
+ +

Strings and characters

+
"This is a 1C:Enterprise string"
+""
+"a"
+"A tabulator character: ""#9"" is easy to embed"
+ +

Numbers

+
123
+123.456
+
+ +

Full example

+
///////////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2019, ООО 1С-Софт
+// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
+// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
+// Текст лицензии доступен по ссылке:
+// https://creativecommons.org/licenses/by/4.0/legalcode
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#Область СлужебныеПроцедурыИФункции
+
+////////////////////////////////////////////////////////////////////////////////
+//  Основные процедуры и функции поиска контактов.
+
+// Получает представление и всю контактную информацию контакта.
+//
+// Параметры:
+//  Контакт                 - ОпределяемыйТип.КонтактВзаимодействия - контакт для которого получается информация.
+//  Представление           - Строка - в данный параметр будет помещено полученное представление.
+//  СтрокаКИ                - Строка - в данный параметр будет помещено полученная контактная информация.
+//  ТипКонтактнойИнформации - Перечисления.ТипыКонтактнойИнформации - возможность установить отбор по типу получаемой
+//                                                                    контактной информации.
+//
+Процедура ПредставлениеИВсяКонтактнаяИнформациюКонтакта(Контакт, Представление, СтрокаКИ,ТипКонтактнойИнформации = Неопределено) Экспорт
+	
+	Представление = "";
+	СтрокаКИ = "";
+	Если Не ЗначениеЗаполнено(Контакт) 
+		ИЛИ ТипЗнч(Контакт) = Тип("СправочникСсылка.СтроковыеКонтактыВзаимодействий") Тогда
+		Контакт = Неопределено;
+		Возврат;
+	КонецЕсли;
+	
+	ИмяТаблицы = Контакт.Метаданные().Имя;
+	ИмяПоляДляНаименованияВладельца = Взаимодействия.ИмяПоляДляНаименованияВладельца(ИмяТаблицы);
+	
+	Запрос = Новый Запрос;
+	Запрос.Текст =
+	"ВЫБРАТЬ
+	|	СправочникКонтакт.Наименование          КАК Наименование,
+	|	" + ИмяПоляДляНаименованияВладельца + " КАК НаименованиеВладельца
+	|ИЗ
+	|	Справочник." + ИмяТаблицы + " КАК СправочникКонтакт
+	|ГДЕ
+	|	СправочникКонтакт.Ссылка = &Контакт
+	|";
+	
+	Запрос.УстановитьПараметр("Контакт", Контакт);
+	Запрос.УстановитьПараметр("ТипКонтактнойИнформации", ТипКонтактнойИнформации);
+	Выборка = Запрос.Выполнить().Выбрать();
+	Если Не Выборка.Следующий() Тогда
+		Возврат;
+	КонецЕсли;
+	
+	Представление = Выборка.Наименование;
+	
+	Если Не ПустаяСтрока(Выборка.НаименованиеВладельца) Тогда
+		Представление = Представление + " (" + Выборка.НаименованиеВладельца + ")";
+	КонецЕсли;
+	
+	МассивКонтактов = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Контакт);
+	ТаблицаКИ = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъектов(МассивКонтактов, ТипКонтактнойИнформации, Неопределено, ТекущаяДатаСеанса());
+	
+	Для Каждого СтрокаТаблицы Из ТаблицаКИ Цикл
+		Если СтрокаТаблицы.Тип <> Перечисления.ТипыКонтактнойИнформации.Другое Тогда
+			СтрокаКИ = СтрокаКИ + ?(ПустаяСтрока(СтрокаКИ), "", "; ") + СтрокаТаблицы.Представление;
+		КонецЕсли;
+	КонецЦикла;
+	
+КонецПроцедуры
+
+// Получает наименование и адреса электронной почты контакта.
+//
+// Параметры:
+//  Контакт - Ссылка - контакт, для которого получаются данные.
+//
+// Возвращаемое значение:
+//  Структура - содержит наименование контакта и список значений электронной почты контакта.
+//
+Функция НаименованиеИАдресаЭлектроннойПочтыКонтакта(Контакт) Экспорт
+	
+	Если Не ЗначениеЗаполнено(Контакт) 
+		Или ТипЗнч(Контакт) = Тип("СправочникСсылка.СтроковыеКонтактыВзаимодействий") Тогда
+		Возврат Неопределено;
+	КонецЕсли;
+	
+	МетаданныеКонтакта = Контакт.Метаданные();
+	
+	Если МетаданныеКонтакта.Иерархический Тогда
+		Если Контакт.ЭтоГруппа Тогда
+			Возврат Неопределено;
+		КонецЕсли;
+	КонецЕсли;
+	
+	МассивОписанияТиповКонтактов = ВзаимодействияКлиентСервер.ОписанияКонтактов();
+	ЭлементМассиваОписания = Неопределено;
+	Для Каждого ЭлементМассива Из МассивОписанияТиповКонтактов Цикл
+		
+		Если ЭлементМассива.Имя = МетаданныеКонтакта.Имя Тогда
+			ЭлементМассиваОписания = ЭлементМассива;
+			Прервать;
+		КонецЕсли;
+		
+	КонецЦикла;
+	
+	Если ЭлементМассиваОписания = Неопределено Тогда
+		Возврат Неопределено;
+	КонецЕсли;
+	
+	ИмяТаблицы = МетаданныеКонтакта.ПолноеИмя();
+	
+	ТекстЗапроса =
+	"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
+	|	ЕСТЬNULL(ТаблицаКонтактнаяИнформация.АдресЭП,"""") КАК АдресЭП,
+	|	СправочникКонтакт." + ЭлементМассиваОписания.ИмяРеквизитаПредставлениеКонтакта + " КАК Наименование
+	|ИЗ
+	|	" + ИмяТаблицы + " КАК СправочникКонтакт
+	|		ЛЕВОЕ СОЕДИНЕНИЕ " + ИмяТаблицы + ".КонтактнаяИнформация КАК ТаблицаКонтактнаяИнформация
+	|		ПО (ТаблицаКонтактнаяИнформация.Ссылка = СправочникКонтакт.Ссылка)
+	|			И (ТаблицаКонтактнаяИнформация.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.АдресЭлектроннойПочты))
+	|ГДЕ
+	|	СправочникКонтакт.Ссылка = &Контакт
+	|ИТОГИ ПО
+	|	Наименование";
+	
+	Запрос = Новый Запрос;
+	Запрос.Текст = ТекстЗапроса;
+	Запрос.УстановитьПараметр("Контакт", Контакт);
+	Выборка = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
+	
+	Если Не Выборка.Следующий() Тогда
+		Возврат Неопределено;
+	КонецЕсли;
+	
+	Адреса = Новый Структура("Наименование,Адреса", Выборка.Наименование, Новый СписокЗначений);
+	ВыборкаАдреса = Выборка.Выбрать();
+	Пока ВыборкаАдреса.Следующий() Цикл
+		Адреса.Адреса.Добавить(ВыборкаАдреса.АдресЭП);
+	КонецЦикла;
+	
+	Возврат Адреса;
+	
+КонецФункции
+
+// Получает адреса электронной почты контакта.
+//
+// Параметры:
+//  Контакт - ОпределяемыйТип.КонтактВзаимодействия - контакт, для которого получаются данные.
+//
+// Возвращаемое значение:
+//  Массив - массив структур содержащих адреса, виды и представления адресов.
+//
+Функция ПолучитьАдресаЭлектроннойПочтыКонтакта(Контакт, ВключатьНезаполненныеВиды = Ложь) Экспорт
+	
+	Если Не ЗначениеЗаполнено(Контакт) Тогда
+		Возврат Неопределено;
+	КонецЕсли;
+	
+	Запрос = Новый Запрос;
+	ИмяМетаданныхКонтакта = Контакт.Метаданные().Имя;
+	
+	Если ВключатьНезаполненныеВиды Тогда
+		
+		Запрос.Текст =
+		"ВЫБРАТЬ
+		|	ВидыКонтактнойИнформации.Ссылка КАК Вид,
+		|	ВидыКонтактнойИнформации.Наименование КАК ВидНаименование,
+		|	Контакты.Ссылка КАК Контакт
+		|ПОМЕСТИТЬ КонтактВидыКИ
+		|ИЗ
+		|	Справочник.ВидыКонтактнойИнформации КАК ВидыКонтактнойИнформации,
+		|	Справочник." + ИмяМетаданныхКонтакта + " КАК Контакты
+		|ГДЕ
+		|	ВидыКонтактнойИнформации.Родитель = &ГруппаВидаКонтактнойИнформации
+		|	И Контакты.Ссылка = &Контакт
+		|	И ВидыКонтактнойИнформации.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.АдресЭлектроннойПочты)
+		|;
+		|
+		|////////////////////////////////////////////////////////////////////////////////
+		|ВЫБРАТЬ
+		|	Представление(КонтактВидыКИ.Контакт) КАК Представление,
+		|	ЕСТЬNULL(КонтактнаяИнформация.АдресЭП, """") КАК АдресЭП,
+		|	КонтактВидыКИ.Вид,
+		|	КонтактВидыКИ.ВидНаименование
+		|ИЗ
+		|	КонтактВидыКИ КАК КонтактВидыКИ
+		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник." + ИмяМетаданныхКонтакта + ".КонтактнаяИнформация КАК КонтактнаяИнформация
+		|		ПО (КонтактнаяИнформация.Ссылка = КонтактВидыКИ.Контакт)
+		|			И (КонтактнаяИнформация.Вид = КонтактВидыКИ.Вид)";
+		
+		ГруппаВидаКонтактнойИнформации = УправлениеКонтактнойИнформацией.ВидКонтактнойИнформацииПоИмени("Справочник" + ИмяМетаданныхКонтакта);
+		Запрос.УстановитьПараметр("ГруппаВидаКонтактнойИнформации", ГруппаВидаКонтактнойИнформации);
+	Иначе
+		
+		Запрос.Текст =
+		"ВЫБРАТЬ
+		|	Таблицы.АдресЭП,
+		|	Таблицы.Вид,
+		|	Таблицы.Представление,
+		|	Таблицы.Вид.Наименование КАК ВидНаименование
+		|ИЗ
+		|	Справочник." + ИмяМетаданныхКонтакта + ".КонтактнаяИнформация КАК Таблицы
+		|ГДЕ
+		|	Таблицы.Ссылка = &Контакт
+		|	И Таблицы.Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.АдресЭлектроннойПочты)";
+		
+	КонецЕсли;
+	
+	Запрос.УстановитьПараметр("Контакт", Контакт);
+	
+	Выборка = Запрос.Выполнить().Выбрать();
+	Если Выборка.Количество() = 0 Тогда
+		Возврат Новый Массив;
+	КонецЕсли;
+	
+	Результат = Новый Массив;
+	Пока Выборка.Следующий() Цикл
+		Адрес = Новый Структура;
+		Адрес.Вставить("АдресЭП",         Выборка.АдресЭП);
+		Адрес.Вставить("Вид",             Выборка.Вид);
+		Адрес.Вставить("Представление",   Выборка.Представление);
+		Адрес.Вставить("ВидНаименование", Выборка.ВидНаименование);
+		Результат.Добавить(Адрес);
+	КонецЦикла;
+	
+	Возврат Результат;
+	
+КонецФункции
+
+Функция ОтправитьПолучитьПочтуПользователяВФоне(УникальныйИдентификатор) Экспорт
+	
+	ПараметрыПроцедуры = Новый Структура;
+	
+	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
+	ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Получение и отправка электронной почты пользователя'");
+	
+	ДлительнаяОперация = ДлительныеОперации.ВыполнитьВФоне("УправлениеЭлектроннойПочтой.ОтправитьЗагрузитьПочтуПользователя",
+		ПараметрыПроцедуры,	ПараметрыВыполнения);
+	Возврат ДлительнаяОперация;
+	
+КонецФункции
+
+////////////////////////////////////////////////////////////////////////////////
+//  Прочее
+
+// Устанавливает предмет для массива взаимодействий.
+//
+// Параметры:
+//  МассивВзаимодействий - Массив - массив взаимодействий для которых будет установлен предмет.
+//  Предмет  - Ссылка - предмет, на который будет выполнена замена.
+//  ПроверятьНаличиеДругихЦепочек - Булево - если Истина, то будет выполнена замена предмета и для взаимодействий,
+//                                           которые входят в  цепочки взаимодействий первым взаимодействием которых
+//                                           является взаимодействие входящее в массив.
+//
+Процедура УстановитьПредметДляМассиваВзаимодействий(МассивВзаимодействий, Предмет, ПроверятьНаличиеДругихЦепочек = Ложь) Экспорт
+
+	Если ПроверятьНаличиеДругихЦепочек Тогда
+		
+		Запрос = Новый Запрос;
+		Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
+		|	ПредметыВзаимодействий.Взаимодействие КАК Ссылка
+		|ИЗ
+		|	РегистрСведений.ПредметыПапкиВзаимодействий КАК ПредметыВзаимодействий
+		|ГДЕ
+		|	НЕ (НЕ ПредметыВзаимодействий.Предмет В (&МассивВзаимодействий)
+		|			И НЕ ПредметыВзаимодействий.Взаимодействие В (&МассивВзаимодействий))";
+		
+		Запрос.УстановитьПараметр("МассивВзаимодействий", МассивВзаимодействий);
+		МассивВзаимодействий = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
+		
+	КонецЕсли;
+	
+	НачатьТранзакцию();
+	Попытка
+		Блокировка = Новый БлокировкаДанных;
+		РегистрыСведений.ПредметыПапкиВзаимодействий.ЗаблокироватьПредметыПапокВзаимодействий(Блокировка, МассивВзаимодействий);
+		Блокировка.Заблокировать();
+		
+		Если ТипЗнч(Предмет) = Тип("РегистрСведенийКлючЗаписи.СостоянияПредметовВзаимодействий") Тогда
+			Предмет = Предмет.Предмет;
+		КонецЕсли;
+		
+		Запрос = Новый Запрос;
+		Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
+		|	ПредметыПапкиВзаимодействий.Предмет
+		|ИЗ
+		|	РегистрСведений.ПредметыПапкиВзаимодействий КАК ПредметыПапкиВзаимодействий
+		|ГДЕ
+		|	ПредметыПапкиВзаимодействий.Взаимодействие В(&МассивВзаимодействий)
+		|
+		|ОБЪЕДИНИТЬ ВСЕ
+		|
+		|ВЫБРАТЬ
+		|	&Предмет";
+		
+		Запрос.УстановитьПараметр("Предмет", Предмет);
+		Запрос.УстановитьПараметр("МассивВзаимодействий", МассивВзаимодействий);
+		
+		ВыборкаПредметы = Запрос.Выполнить().Выбрать();
+		
+		Для Каждого Взаимодействие Из МассивВзаимодействий Цикл
+			Взаимодействия.УстановитьПредмет(Взаимодействие, Предмет, Ложь);
+		КонецЦикла;
+		
+		Взаимодействия.РассчитатьРассмотреноПоПредметам(Взаимодействия.ТаблицаДанныхДляРасчетаРассмотрено(ВыборкаПредметы, "Предмет"));
+		ЗафиксироватьТранзакцию();
+	Исключение
+		ОтменитьТранзакцию();
+		ВызватьИсключение;
+	КонецПопытки;	
+КонецПроцедуры
+
+// Преобразует письмо в двоичные данные и подготавливает к сохранению на диск.
+//
+// Параметры:
+//  Письмо                  - ДокументСсылка.ЭлектронноеПисьмоВходящее,
+//                            ДокументСсылка.ЭлектронноеПисьмоИсходящее - письмо, которое подготавливается к сохранению.
+//  УникальныйИдентификатор - УникальныйИдентификатор - уникальный идентификатор формы, из которой была вызвана команда сохранения.
+//
+// Возвращаемое значение:
+//  Структура - структура, содержащая подготовленные данные письма.
+//
+Функция ДанныеПисьмаДляСохраненияКакФайл(Письмо, УникальныйИдентификатор) Экспорт
+
+	ДанныеФайла = СтруктураДанныхФайла();
+	
+	ДанныеПисьма = Взаимодействия.ИнтернетПочтовоеСообщениеИзПисьма(Письмо);
+	Если ДанныеПисьма <> Неопределено Тогда
+		
+		ДвоичныеДанные = ДанныеПисьма.ИнтернетПочтовоеСообщение.ПолучитьИсходныеДанные();
+		ДанныеФайла.СсылкаНаДвоичныеДанныеФайла = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
+
+		ДанныеФайла.Наименование = Взаимодействия.ПредставлениеПисьма(ДанныеПисьма.ИнтернетПочтовоеСообщение.Тема,
+			ДанныеПисьма.ДатаПисьма);
+		
+		ДанныеФайла.Расширение  = "eml";
+		ДанныеФайла.ИмяФайла    = ДанныеФайла.Наименование + "." + ДанныеФайла.Расширение;
+		ДанныеФайла.Размер      = ДвоичныеДанные.Размер();
+		ПапкаДляСохранитьКак = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("НастройкиПрограммы", "ПапкаДляСохранитьКак");
+		ДанныеФайла.Вставить("ПапкаДляСохранитьКак", ПапкаДляСохранитьКак);
+		ДанныеФайла.ДатаМодификацииУниверсальная = ТекущаяДатаСеанса();
+		ДанныеФайла.ПолноеНаименованиеВерсии = ДанныеФайла.ИмяФайла;
+		
+	КонецЕсли;
+	
+	Возврат ДанныеФайла;
+
+КонецФункции
+
+Функция СтруктураДанныхФайла()
+
+	СтруктураДанныхФайла = Новый Структура;
+	СтруктураДанныхФайла.Вставить("СсылкаНаДвоичныеДанныеФайла",        "");
+	СтруктураДанныхФайла.Вставить("ОтносительныйПуть",                  "");
+	СтруктураДанныхФайла.Вставить("ДатаМодификацииУниверсальная",       Дата(1, 1, 1));
+	СтруктураДанныхФайла.Вставить("ИмяФайла",                           "");
+	СтруктураДанныхФайла.Вставить("Наименование",                       "");
+	СтруктураДанныхФайла.Вставить("Расширение",                         "");
+	СтруктураДанныхФайла.Вставить("Размер",                             "");
+	СтруктураДанныхФайла.Вставить("Редактирует",                        Неопределено);
+	СтруктураДанныхФайла.Вставить("ПодписанЭП",                         Ложь);
+	СтруктураДанныхФайла.Вставить("Зашифрован",                         Ложь);
+	СтруктураДанныхФайла.Вставить("ФайлРедактируется",                  Ложь);
+	СтруктураДанныхФайла.Вставить("ФайлРедактируетТекущийПользователь", Ложь);
+	СтруктураДанныхФайла.Вставить("ПолноеНаименованиеВерсии",           "");
+	
+	Возврат СтруктураДанныхФайла;
+
+КонецФункции 
+
+#КонецОбласти
\ No newline at end of file diff --git a/examples/prism-c.html b/examples/prism-c.html index aee1c06a87..635b01fd5d 100644 --- a/examples/prism-c.html +++ b/examples/prism-c.html @@ -16,7 +16,7 @@

Full example

{ int c; printf("Number of command line arguments passed: %d\n", argc); - for ( c = 0 ; c < argc ; c++) + for ( c = 0 ; c < argc ; c++) printf("%d. Command line argument passed is %s\n", c+1, argv[c]); return 0; -} \ No newline at end of file +} diff --git a/examples/prism-cfscript.html b/examples/prism-cfscript.html new file mode 100644 index 0000000000..6a0a771bb0 --- /dev/null +++ b/examples/prism-cfscript.html @@ -0,0 +1,43 @@ +

Comments

+
// This is a comment
+
+/* This is a comment
+on multiple lines */
+
+/**
+* This is a Javadoc style comment
+*
+* @hint This is an annotation
+*/
+
+ +

Functions

+
public boolean function myFunc(required any arg) {
+  return true;
+}
+ +

Full example

+
component accessors="true" {
+  property type="string" name="prop1" default="";
+  property string prop2;
+  function init(){
+    this.prop3 = 12;
+    return this;
+  }
+
+  /**
+  * @hint Annotations supported
+  * @foo.hint
+  */
+  public any function build( required foo, color="blue", boolean bar=true ){
+    arguments.foo = {
+      'name' : "something",
+      test = true
+    }
+    var foobar = function( required string baz, x=true, y=false ){
+      return "bar!";
+    };
+    return foo;
+  }
+}
+
diff --git a/examples/prism-chaiscript.html b/examples/prism-chaiscript.html new file mode 100644 index 0000000000..a167d39a49 --- /dev/null +++ b/examples/prism-chaiscript.html @@ -0,0 +1,56 @@ +

Full example

+
// http://chaiscript.com/examples.html#ChaiScript_Language_Examples
+// Source: https://gist.github.com/lefticus/cf058f2927fef68d58e0#file-chaiscript_overview-chai
+
+// ChaiScript supports the normal kind of control blocks you've come to expect from
+// C++ and JavaScript
+
+
+if (5 > 2) {
+  print("Yup, 5 > 2");
+} else if (2 > 5) {
+  // never gonna happen
+} else {
+  // really not going to happen
+}
+
+var x = true;
+
+while (x)
+{
+  print("x was true")
+  x = false;
+}
+
+for (var i = 1; i < 10; ++i)
+{
+  print(i); // prints 1 through 9
+}
+
+
+// function definition
+
+def myFunc(x) {
+  print(x);
+}
+
+// function definition with function guards
+def myFunc(x) : x > 2 && x < 5 {
+  print(to_string(x) + " is between 2 and 5")
+}
+
+def myFunc(x) : x >= 5 {
+  print(t_string(x) + " is greater than or equal to 5")
+}
+
+myFunc(3)
+
+// ChaiScript also supports in string evaluation, which C++ does not
+
+print("${3 + 5} is 8");
+
+// And dynamic code evaluation
+
+var value = eval("4 + 2 + 12");
+
+// value is equal to 18
diff --git a/examples/prism-cil.html b/examples/prism-cil.html new file mode 100644 index 0000000000..0d228d363a --- /dev/null +++ b/examples/prism-cil.html @@ -0,0 +1,49 @@ +

Full example

+
// Metadata version: v4.0.30319
+.assembly extern mscorlib
+{
+  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
+  .ver 4:0:0:0
+}
+.assembly i1ohgbkl
+{
+  .hash algorithm 0x00008004
+  .ver 0:0:0:0
+}
+.module i1ohgbkl.dll
+// MVID: {AC981AA1-16FE-413D-BBED-D83AE719F45C}
+.imagebase 0x10000000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       // WINDOWS_CUI
+.corflags 0x00000001    //  ILONLY
+// Image base: 0x017C0000
+​
+​
+// =============== CLASS MEMBERS DECLARATION ===================
+​
+.class public auto ansi beforefieldinit Program
+       extends [mscorlib]System.Object
+{
+  .method public hidebysig static void  Main() cil managed
+  {
+    //
+    .maxstack  8
+    IL_0000:  nop
+    IL_0001:  ldstr      "Hello World"
+    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
+    IL_000b:  nop
+    IL_000c:  ret
+  } // end of method Program::Main
+​
+  .method public hidebysig specialname rtspecialname
+          instance void  .ctor() cil managed
+  {
+    //
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
+    IL_0006:  ret
+  } // end of method Program::.ctor
+​
+} // end of class Program
diff --git a/examples/prism-clike.html b/examples/prism-clike.html index 79a8076409..b5aab46540 100644 --- a/examples/prism-clike.html +++ b/examples/prism-clike.html @@ -1,6 +1,5 @@ -

The C-like component is not really a language on its own, - it is the basis of many other components. To use it directly, however, - use the class "language-clike".

+

Note: The C-like component is not really a language on its own, + it is the basis of many other components.

Comments

// Single line comment
@@ -25,4 +24,4 @@ 

Functions

foo();
 Bar();
 _456();
-
\ No newline at end of file +
diff --git a/examples/prism-clojure.html b/examples/prism-clojure.html index abc50194b3..8e12fca893 100644 --- a/examples/prism-clojure.html +++ b/examples/prism-clojure.html @@ -255,8 +255,8 @@

Full example

; The "Thread-first" macro (->) inserts into each form the result of ; the previous, as the first argument (second item) -(-> - {:a 1 :b 2} +(-> + {:a 1 :b 2} (assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3) (dissoc :b)) ;=> (dissoc (assoc {:a 1 :b 2} :c 3) :b) @@ -275,7 +275,7 @@

Full example

; Result: [1 3 5 7 9] ; When you are in a situation where you want more freedom as where to -; put the result of previous data transformations in an +; put the result of previous data transformations in an ; expression, you can use the as-> macro. With it, you can assign a ; specific name to transformations' output and use it as a ; placeholder in your chained expressions: @@ -334,14 +334,14 @@

Full example

java.util.Calendar)) ; Use the class name with a "." at the end to make a new instance -(Date.) ; +(Date.) ; <a date object> ; Use . to call methods. Or, use the ".method" shortcut -(. (Date.) getTime) ; +(. (Date.) getTime) ; <a timestamp> (.getTime (Date.)) ; exactly the same thing. ; Use / to call static methods -(System/currentTimeMillis) ; (system is always present) +(System/currentTimeMillis) ; <a timestamp> (system is always present) ; Use doto to make dealing with (mutable) classes more tolerable (import java.util.Calendar) @@ -365,7 +365,7 @@

Full example

(swap! my-atom assoc :b 2) ; Sets my-atom to the result of (assoc {:a 1} :b 2) ; Use '@' to dereference the atom and get the value -my-atom ;=> Atom<#...> (Returns the Atom object) +my-atom ;=> Atom<#...> (Returns the Atom object) @my-atom ; => {:a 1 :b 2} ; Here's a simple counter using an atom @@ -383,4 +383,4 @@

Full example

; Other STM constructs are refs and agents. ; Refs: http://clojure.org/refs -; Agents: http://clojure.org/agents \ No newline at end of file +; Agents: http://clojure.org/agents diff --git a/examples/prism-cmake.html b/examples/prism-cmake.html new file mode 100644 index 0000000000..cec9576110 --- /dev/null +++ b/examples/prism-cmake.html @@ -0,0 +1,102 @@ +

Comments

+
# This is a comment
+ +

Keywords

+
add_library(foo main.cpp)
+target_link_libraries(foo bar)
+
+ +

Functions

+
user_defined_function()
+another_custom_function(argument)
+
+ +

Variables

+
CMAKE_COMPILER_IS_GNUG77
+CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY
+CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_WHATEVER
+CMAKE_CONFIGURATION_TYPES
+CMAKE_CPACK_COMMAND
+CMAKE_CROSSCOMPILING
+CMAKE_CROSSCOMPILING_EMULATOR
+CMAKE_CTEST_COMMAND
+CMAKE_CUDA_EXTENSIONS
+CMAKE_CUDA_HOST_COMPILER
+CMAKE_CUDA_SEPARABLE_COMPILATION
+CMAKE_CUDA_STANDARD
+CMAKE_CUDA_STANDARD_REQUIRED
+"${INSIDE_STRING}"
+"${PROPER}chaining${VARIABLES}"
+
+ +

Properties

+
CUDA_STANDARD
+CUDA_STANDARD_REQUIRED
+CXX_EXTENSIONS
+CXX_STANDARD
+cxx_std_17
+cxx_variadic_templates
+ +

Strings

+
"A string"
+    "A multi
+    line
+    string"
+    "A ${VARIABLE} insde a string"
+ +

Full example

+
cmake_minimum_required(VERSION 3.13)
+
+project(crypto)
+
+add_library(base INTERFACE)
+target_compile_features(base INTERFACE
+    cxx_std_17
+    )
+
+add_subdirectory(helpers)
+add_subdirectory(msg)
+
+add_library(analyzers-obj OBJECT
+    CryptoAnalyzer.cpp
+    )
+
+target_include_directories(analyzers-obj
+    PUBLIC
+        ${CMAKE_CURRENT_SOURCE_DIR}
+    )
+
+find_package(predi REQUIRED)
+target_link_libraries(analyzers-obj
+    PUBLIC
+        base
+        predi::predi
+        crypto::helpers
+    )
+
+set_target_properties(analyzers-obj
+    PROPERTIES
+        POSITION_INDEPENDENT_CODE ON
+    )
+
+add_library(analyzers SHARED
+    $<TARGET_OBJECTS:analyzers-obj>
+    )
+
+target_link_libraries(analyzers PUBLIC analyzers-obj)
+
+add_executable(crypto
+    main.cpp
+    )
+
+target_link_libraries(crypto
+    PUBLIC
+        analyzers
+    PRIVATE
+        base
+        messages
+    )
+
+enable_testing()
+add_subdirectory(tests)
+
\ No newline at end of file diff --git a/examples/prism-cobol.html b/examples/prism-cobol.html new file mode 100644 index 0000000000..c807cf10c8 --- /dev/null +++ b/examples/prism-cobol.html @@ -0,0 +1,26 @@ +

Full example

+
       *> https://en.wikipedia.org/w/index.php?title=COBOL&oldid=1011483106
+       RD  sales-report
+           PAGE LIMITS 60 LINES
+           FIRST DETAIL 3
+           CONTROLS seller-name.
+
+       01  TYPE PAGE HEADING.
+           03  COL 1                    VALUE "Sales Report".
+           03  COL 74                   VALUE "Page".
+           03  COL 79                   PIC Z9 SOURCE PAGE-COUNTER.
+
+       01  sales-on-day TYPE DETAIL, LINE + 1.
+           03  COL 3                    VALUE "Sales on".
+           03  COL 12                   PIC 99/99/9999 SOURCE sales-date.
+           03  COL 21                   VALUE "were".
+           03  COL 26                   PIC $$$$9.99 SOURCE sales-amount.
+
+       01  invalid-sales TYPE DETAIL, LINE + 1.
+           03  COL 3                    VALUE "INVALID RECORD:".
+           03  COL 19                   PIC X(34) SOURCE sales-record.
+
+       01  TYPE CONTROL HEADING seller-name, LINE + 2.
+           03  COL 1                    VALUE "Seller:".
+           03  COL 9                    PIC X(30) SOURCE seller-name.
+
diff --git a/examples/prism-concurnas.html b/examples/prism-concurnas.html new file mode 100644 index 0000000000..87b9a4ce06 --- /dev/null +++ b/examples/prism-concurnas.html @@ -0,0 +1,89 @@ +

Comments

+
// This is a comment
+/* This is a comment
+on multiple lines */
+ +

Numbers

+
12
+12e5
+12.f
+12f
+12d
+12.d
+12.0
+12.0f
+12.0d
+ +

strings and language extensions

+
"hi"
+'hi'
+'c'
+'what "yach"'
+s'c'
+"c"
+r"[a-z|A-Z]+"
+ +

Functions

+
def add(a int, b int) => a + b
+ +

Language Extensions

+
dcalc = mylisp||(+ 1 2 (* 2 3))|| // == 9
+
+myFortran || program hello
+          		print *, "Hello World!"
+       		 end program hello|| //prints "Hello World!"
+
+lotto = myAPL || x[⍋x←6?40] || //6 unique random numbers from 1 to 40
+ +

Full example

+
//an overloaded function
+def adder(a int, b int) => a + b
+def adder(a int, b float) => adder(a, b as int)
+def adder(a int) => adder(a, 10)
+
+//a default value
+def powerPlus(a int, raiseTo = 2, c int) => a ** raiseTo + c
+
+//call our function with a default value
+res1 = powerPlus(4, 10)//second argument defaults to '2'
+res2 = powerPlus(4, 3, 10)//second argument provided
+
+//calling a function with named parameters:
+def powerAdder(a int, raiseATo = 2, b int, raiseBTo = 2) => a**raiseATo + b**raiseBTo
+res3 = powerAdder(2, 4, raiseATo=3)//equivalent to: powerAdder(2, 3, 4, 2)
+
+//varargs:
+def sum(elms int...) int {
+  res = 0
+  for(elm in elms){
+    res += elm
+  }
+  res
+}
+
+//call our function with a vararg
+thesum = sum(1, 2, 3, 4, 5)
+
+//partially defined typedef
+typedef NameMap<X> = java.util.ArrayList<java.util.HashMap<String, java.util.HashSet<X>>>
+
+//using typedefs...
+nm NameMap<String>= new NameMap<String>()
+
+@Annotation
+class MyClass(a int, b int, c String){
+  override toString() => 'MyClass({a}, {b}, "{c}")'
+}
+
+mc1 = MyClass(12, 14, "hi there")
+mc2 = mc1@ //copy mc1
+
+assert mc1 == mc2//same values!
+assert mc1 &<> mc2//different objects!
+
+mc3 = mc1@(a = 100)//copy mc1 but overwrite value of a
+assert 'MyClass(100, 14, "hi there")' == mc3.toString()
+
+mc4 = mc1@(<a, b>)//copy mc1 but exclude a and b
+assert 'MyClass(0, 0, "hi there")' == mc3.toString()
+
diff --git a/examples/prism-coq.html b/examples/prism-coq.html new file mode 100644 index 0000000000..1e9b51db32 --- /dev/null +++ b/examples/prism-coq.html @@ -0,0 +1,45 @@ +

Full example

+
(* Source: https://coq.inria.fr/a-short-introduction-to-coq *)
+
+Inductive seq : nat -> Set :=
+| niln : seq 0
+| consn : forall n : nat, nat -> seq n -> seq (S n).
+
+Fixpoint length (n : nat) (s : seq n) {struct s} : nat :=
+  match s with
+  | niln => 0
+  | consn i _ s' => S (length i s')
+  end.
+
+Theorem length_corr : forall (n : nat) (s : seq n), length n s = n.
+Proof.
+  intros n s.
+
+  (* reasoning by induction over s. Then, we have two new goals
+     corresponding on the case analysis about s (either it is
+     niln or some consn *)
+  induction s.
+
+    (* We are in the case where s is void. We can reduce the
+       term: length 0 niln *)
+    simpl.
+
+    (* We obtain the goal 0 = 0. *)
+    trivial.
+
+    (* now, we treat the case s = consn n e s with induction
+       hypothesis IHs *)
+    simpl.
+
+    (* The induction hypothesis has type length n s = n.
+       So we can use it to perform some rewriting in the goal: *)
+    rewrite IHs.
+
+    (* Now the goal is the trivial equality: S n = S n *)
+    trivial.
+
+  (* Now all sub cases are closed, we perform the ultimate
+     step: typing the term built using tactics and save it as
+     a witness of the theorem. *)
+Qed.
+
diff --git a/examples/prism-cpp.html b/examples/prism-cpp.html index 32bdcbda56..f0fa1d3d20 100644 --- a/examples/prism-cpp.html +++ b/examples/prism-cpp.html @@ -32,7 +32,7 @@

Full example

vector<int> left, vector<int> right ){ - if( (left[5]) < (right[5]) ){ + if( (left[5]) < (right[5]) ){ return( right ); }; // else @@ -40,18 +40,18 @@

Full example

} int vector_demo(void){ - cout << "vector demo" << endl; + cout << "vector demo" << endl; vector<int> left(7); vector<int> right(7); left[5] = 7; right[5] = 8; - cout << left[5] << endl; - cout << right[5] << endl; + cout << left[5] << endl; + cout << right[5] << endl; vector<int> biggest( pick_vector_with_biggest_fifth_element( left, right ) ); - cout << biggest[5] << endl; + cout << biggest[5] << endl; return 0; } diff --git a/examples/prism-csharp.html b/examples/prism-csharp.html index c6d76c2b44..fc60c71076 100644 --- a/examples/prism-csharp.html +++ b/examples/prism-csharp.html @@ -5,12 +5,9 @@

Comments

Strings

"foo \"bar\" baz"
-'foo \'bar\' baz'
 @"Verbatim strings"
 @"Luis: ""Patrick, where did you get that overnight bag?""
     Patrick: ""Jean Paul Gaultier.""";
-@'Luis: ''Patrick, where did you get that overnight bag?''
-    Patrick: ''Jean Paul Gaultier.''';
 

Full example

@@ -57,4 +54,4 @@

Full example

DialogResult dialogResult = form.ShowDialog(); value = textBox.Text; return dialogResult; -} \ No newline at end of file +} diff --git a/examples/prism-cshtml.html b/examples/prism-cshtml.html new file mode 100644 index 0000000000..cc11eeb9ae --- /dev/null +++ b/examples/prism-cshtml.html @@ -0,0 +1,36 @@ +

Full example

+
@* Source: https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studio#the-home-page *@
+
+@page
+@model RazorPagesContacts.Pages.Customers.IndexModel
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
+
+<h1>Contacts home page</h1>
+<form method="post">
+	<table class="table">
+		<thead>
+			<tr>
+				<th>ID</th>
+				<th>Name</th>
+				<th></th>
+			</tr>
+		</thead>
+		<tbody>
+			@foreach (var contact in Model.Customer)
+			{
+				<tr>
+					<td> @contact.Id  </td>
+					<td>@contact.Name</td>
+					<td>
+						<a asp-page="./Edit" asp-route-id="@contact.Id">Edit</a> |
+						<button type="submit" asp-page-handler="delete"
+								asp-route-id="@contact.Id">delete
+						</button>
+					</td>
+				</tr>
+			}
+		</tbody>
+	</table>
+	<a asp-page="Create">Create New</a>
+</form>
+
diff --git a/examples/prism-css-extras.html b/examples/prism-css-extras.html new file mode 100644 index 0000000000..c780d93536 --- /dev/null +++ b/examples/prism-css-extras.html @@ -0,0 +1,28 @@ +

Selectors

+
a#id.class:hover {}
+li:nth-child(2n+1) {}
+span::before {}
+a[title], a[href$=".pdf"] {}, a[href$=".jpg" i] {}
+
+ +

Some of added tokens aren't supported by Prism's default themes.

+ +

Variables

+
:root {
+	--foo: 12px;
+}
+a {
+	font-size: var(--foo);
+	padding: calc(var(--foo) + .5em);
+}
+
+ +

Colors

+
span {
+	background: rgba(0, 128, 255, .4);
+	color: red;
+	color: green;
+	color: blue;
+	border: 1px solid #FFF;
+}
+
diff --git a/examples/prism-css.html b/examples/prism-css.html index e211053efd..a36f196676 100644 --- a/examples/prism-css.html +++ b/examples/prism-css.html @@ -7,7 +7,13 @@

Simple rule

p { color: red; }

Important rule

-
p { color: red !important; }
+

+p {
+    color: red !important;
+    line-height: normal!important;
+}
+p{position:absolute!important}
+

@ rule

@media screen and (min-width: 100px) {}
@@ -25,4 +31,4 @@

String

content: 'foo';

URL

-
content: url(foo.png);
\ No newline at end of file +
content: url(foo.png);
diff --git a/examples/prism-csv.html b/examples/prism-csv.html new file mode 100644 index 0000000000..cbba8d9dcc --- /dev/null +++ b/examples/prism-csv.html @@ -0,0 +1,7 @@ +

Full example

+
Year,Make,Model,Description,Price
+1997,Ford,E350,"ac, abs, moon",3000.00
+1999,Chevy,"Venture ""Extended Edition""","",4900.00
+1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
+1996,Jeep,Grand Cherokee,"MUST SELL!
+air, moon roof, loaded",4799.00
diff --git a/examples/prism-cypher.html b/examples/prism-cypher.html new file mode 100644 index 0000000000..e290a05c95 --- /dev/null +++ b/examples/prism-cypher.html @@ -0,0 +1,8 @@ +

Full example

+
MATCH (person:Person)-[:WORKS_FOR]->(company)
+WHERE company.name STARTS WITH "Company"
+AND EXISTS {
+  MATCH (person)-[:LIKES]->(t:Technology)
+  WHERE size((t)<-[:LIKES]-()) >= 3
+}
+RETURN person.name as person, company.name AS company;
diff --git a/examples/prism-d.html b/examples/prism-d.html index d4bf34cc8c..9ef1d6c78a 100644 --- a/examples/prism-d.html +++ b/examples/prism-d.html @@ -252,16 +252,3 @@

Full example

assert(_totalc >= _argc); } } - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Comments only support one level of nesting

-
/+ /+ /+ this does not work +/ +/ +/
- -

Token strings only support one level of nesting

-
q{ q{ q{ this does not work } } }
\ No newline at end of file diff --git a/examples/prism-dataweave.html b/examples/prism-dataweave.html new file mode 100644 index 0000000000..f66a2da7d2 --- /dev/null +++ b/examples/prism-dataweave.html @@ -0,0 +1,39 @@ +

Full example

+

+%dw 2.0
+input payalod application/json
+ns ns0 http://localhost.com
+var a = 123
+type T = String
+fun test(a: Number) = a + 123
+output application/json
+---
+{
+    // This is a comment
+    /**
+    This is a multiline comment
+    **/
+    name: payload.name,
+    string: "this",
+    'another string': true,
+    "regex": /123/,
+    fc: test(1),
+    "dates": |12-12-2020-T12:00:00|,
+    number: 123,
+    "null": null,
+
+    a: {} match {
+        case  is {} -> foo.name
+    },
+    b: {} update {
+    case name at .user.name ->  "123"
+    },
+    stringMultiLine: "This is a multiline
+        string
+    ",
+    a: if( !true > 2) a else 2,
+    b: do {
+            {}
+        }
+}
+
diff --git a/examples/prism-dax.html b/examples/prism-dax.html new file mode 100644 index 0000000000..1309c4a59e --- /dev/null +++ b/examples/prism-dax.html @@ -0,0 +1,39 @@ +

Comments

+
// This is a comment
+

Simple example

+

+Sales YTD := 
+CALCULATE (
+    [Sales Amount], 
+    DATESYTD( 'Date'[Date] )
+)
+
+

Full example

+

+Burn Rate (Hours) = 
+
+// Only consider those projects which have been alread created
+VAR filterDate = 
+    FILTER (
+        ALL ( 'Date'[Date] ),
+        'Date'[Date] <= MAX('Date'[Date])
+    )
+
+RETURN
+IF (
+    // Show blank for months before project start
+    MAX ( 'Project'[Project Created Relative Months Pos] ) < SELECTEDVALUE ( 'Date'[Fiscal RelativeMonthPos] ),
+    BLANK (),
+    MIN(
+        1,
+        DIVIDE (
+            // Add 0 to consider months with no hours
+            [Hours Actual Billable] + 0,
+            CALCULATE (
+                [Planned Hours] + 0,
+                filterDate
+            )
+        )
+    )
+)
+
diff --git a/examples/prism-dhall.html b/examples/prism-dhall.html new file mode 100644 index 0000000000..9005686d6e --- /dev/null +++ b/examples/prism-dhall.html @@ -0,0 +1,30 @@ +

Full example

+

+-- source: https://github.com/dhall-lang/dhall-lang/blob/master/Prelude/Optional/head.dhall
+
+{-
+Returns the first non-empty `Optional` value in a `List`
+-}
+let head
+    : ∀(a : Type) → List (Optional a) → Optional a
+    = λ(a : Type) →
+      λ(xs : List (Optional a)) →
+        List/fold
+          (Optional a)
+          xs
+          (Optional a)
+          ( λ(l : Optional a) →
+            λ(r : Optional a) →
+              merge { Some = λ(x : a) → Some x, None = r } l
+          )
+          (None a)
+
+let example0 = assert : head Natural [ None Natural, Some 1, Some 2 ] ≡ Some 1
+
+let example1 =
+      assert : head Natural [ None Natural, None Natural ] ≡ None Natural
+
+let example2 =
+      assert : head Natural ([] : List (Optional Natural)) ≡ None Natural
+
+in  head
diff --git a/examples/prism-diff.html b/examples/prism-diff.html index b9229a1740..e753f7ff0f 100644 --- a/examples/prism-diff.html +++ b/examples/prism-diff.html @@ -30,4 +30,4 @@

Unified Diff

headers: "src/*.h" - qt: core + qt: core gui - public_headers: "src/*.h" \ No newline at end of file + public_headers: "src/*.h" diff --git a/examples/prism-dns-zone-file.html b/examples/prism-dns-zone-file.html new file mode 100644 index 0000000000..00f5a04322 --- /dev/null +++ b/examples/prism-dns-zone-file.html @@ -0,0 +1,14 @@ +

Full example

+
$TTL 3d
+@ IN SOA root.localhost. root.sneaky.net. (
+    2015050503 ; serial
+    12h        ; refresh
+    15m        ; retry
+    3w         ; expire
+    3h         ; negative response TTL
+  )
+  IN NS root.localhost.
+  IN NS localhost. ; secondary name server is preferably externally maintained
+
+www IN A 3.141.59.26
+ww1 IN CNAME www
diff --git a/examples/prism-docker.html b/examples/prism-docker.html index 86511b3889..206d84314a 100644 --- a/examples/prism-docker.html +++ b/examples/prism-docker.html @@ -2,6 +2,8 @@

Comments

# These are the comments for a dockerfile.
 # I want to make sure $(variables) don't break out,
 # and we shouldn't see keywords like ADD or ENTRYPOINT
+
+# I also want to make sure that this "string" and this 'string' don't break out.
 

Full example

@@ -10,7 +12,7 @@

Full example

# VERSION 0.0.1 FROM ubuntu -MAINTAINER Victor Vieux +MAINTAINER Victor Vieux <victor@docker.com> LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0" RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server diff --git a/examples/prism-dot.html b/examples/prism-dot.html new file mode 100644 index 0000000000..21af68c8f3 --- /dev/null +++ b/examples/prism-dot.html @@ -0,0 +1,31 @@ +

Full example

+
// source: http://www.ryandesign.com/canviz/graphs/dot/directed/ctext.gv.txt
+# Generated Tue Aug 21 10:21:21 GMT 2007 by dot - Graphviz version 2.15.20070819.0440 (Tue Aug 21 09:56:32 GMT 2007)
+#
+#
+# real	0m0.105s
+# user	0m0.076s
+# sys	0m0.022s
+
+digraph G {
+	node [label="\N"];
+	graph [bb="0,0,352,238",
+		_draw_="c 5 -white C 5 -white P 4 0 0 0 238 352 238 352 0 ",
+		xdotversion="1.2"];
+	xyz [label="hello\nworld", color=slateblue, fontsize=24, fontname="Palatino-Italic", style=filled, fontcolor=hotpink, pos="67,191", width="1.64", height="1.29", _draw_="S 6 -filled c 9 -slateblue C 9 -slateblue E 67 191 59 47 ", _ldraw_="F 24.000000 15 -Palatino-Italic c 7 -hotpink T 67 196 0 65 5 -hello F 24.000000 15 -Palatino-Italic c 7 -hotpink T 67 167 0 75 5\
+ -world "];
+	red [color=red, style=filled, pos="171,191", width="0.75", height="0.50", _draw_="S 6 -filled c 3 -red C 3 -red E 171 191 27 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 171 186 0 24 3 -red "];
+	green [color=green, style=filled, pos="128,90", width="0.92", height="0.50", _draw_="S 6 -filled c 5 -green C 5 -green E 128 90 33 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 128 85 0 41 5 -green "];
+	blue [color=blue, style=filled, fontcolor=black, pos="214,90", width="0.78", height="0.50", _draw_="S 6 -filled c 4 -blue C 4 -blue E 214 90 28 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 214 85 0 31 4 -blue "];
+	cyan [color=cyan, style=filled, pos="214,18", width="0.83", height="0.50", _draw_="S 6 -filled c 4 -cyan C 4 -cyan E 214 18 30 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 214 13 0 34 4 -cyan "];
+	magenta [color=magenta, style=filled, pos="307,18", width="1.25", height="0.50", _draw_="S 6 -filled c 7 -magenta C 7 -magenta E 307 18 45 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 307 13 0 64 7 -magenta "];
+	yellow [color=yellow, style=filled, pos="36,18", width="1.00", height="0.50", _draw_="S 6 -filled c 6 -yellow C 6 -yellow E 36 18 36 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 36 13 0 47 6 -yellow "];
+	orange [color=orange, style=filled, pos="128,18", width="1.06", height="0.50", _draw_="S 6 -filled c 6 -orange C 6 -orange E 128 18 38 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 128 13 0 51 6 -orange "];
+	red -> green [pos="e,136,108 164,173 157,158 147,135 140,118", _draw_="c 5 -black B 4 164 173 157 158 147 135 140 118 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 143 116 136 108 136 119 "];
+	red -> blue [pos="e,206,108 178,173 185,158 195,135 202,118", _draw_="c 5 -black B 4 178 173 185 158 195 135 202 118 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 206 119 206 108 199 116 "];
+	blue -> cyan [pos="e,214,36 214,72 214,64 214,55 214,46", _draw_="c 5 -black B 4 214 72 214 64 214 55 214 46 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 218 46 214 36 211 46 "];
+	blue -> magenta [pos="e,286,34 232,76 246,66 263,52 278,40", _draw_="c 5 -black B 4 232 76 246 66 263 52 278 40 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 280 43 286 34 276 37 "];
+	green -> yellow [pos="e,56,33 109,75 96,65 78,51 64,40", _draw_="c 5 -black B 4 109 75 96 65 78 51 64 40 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 66 37 56 33 61 42 "];
+	green -> orange [pos="e,128,36 128,72 128,64 128,55 128,46", _draw_="c 5 -black B 4 128 72 128 64 128 55 128 46 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 132 46 128 36 125 46 "];
+}
+
diff --git a/examples/prism-ebnf.html b/examples/prism-ebnf.html new file mode 100644 index 0000000000..c787639066 --- /dev/null +++ b/examples/prism-ebnf.html @@ -0,0 +1,63 @@ +

Full example

+
SYNTAX = SYNTAX RULE, { SYNTAX RULE } ;
+SYNTAX RULE
+  = META IDENTIFIER, '=', DEFINITIONS LIST, ' ;' ;
+DEFINITIONS LIST
+  = SINGLE DEFINITION,
+    { '|', SINGLE DEFINITION } ;
+SINGLE DEFINITION = TERM, { ',', TERM } ;
+TERM = FACTOR, [ '-', EXCEPTION ] ;
+EXCEPTION = FACTOR ;
+FACTOR = [ INTEGER, '*' ], PRIMARY ;
+PRIMARY
+  = OPTIONAL SEQUENCE | REPEATED SEQUENCE
+  | SPECIAL SEQUENCE | GROUPED SEQUENCE
+  | META IDENTIFIER | TERMINAL | EMPTY ;
+EMPTY = ;
+OPTIONAL SEQUENCE = '[', DEFINITIONS LIST, ']' ;
+REPEATED SEQUENCE = '{', DEFINITIONS LIST, '}' ;
+GROUPED SEQUENCE = '(', DEFINITIONS LIST, ')' ;
+TERMINAL
+  = "'", CHARACTER - "'",
+    { CHARACTER - "'" }, "'"
+  | '"', CHARACTER - '"',
+    { CHARACTER - '"' }, '"' ;
+META IDENTIFIER = LETTER, { LETTER | DIGIT } ;
+INTEGER = DIGIT, { DIGIT } ;
+SPECIAL SEQUENCE = '?', { CHARACTER - '?' }, '?' ;
+COMMENT = '(*', { COMMENT SYMBOL }, '*)' ;
+COMMENT SYMBOL
+  = COMMENT | TERMINAL | SPECIAL SEQUENCE
+    | CHARACTER ;
+ +

Full example with alternative syntax

+
SYNTAX = SYNTAX RULE, (: SYNTAX RULE :).
+SYNTAX RULE
+  = META IDENTIFIER, '=', DEFINITIONS LIST, '.'. (* '.' instead of ';' *)
+DEFINITIONS LIST
+  = SINGLE DEFINITION,
+    (: '/', SINGLE DEFINITION :).
+SINGLE DEFINITION = TERM, (: ',', TERM :).
+TERM = FACTOR, (/ '-', EXCEPTION /).
+EXCEPTION = FACTOR.
+FACTOR = (/ INTEGER, '*' /), PRIMARY.
+PRIMARY
+  = OPTIONAL SEQUENCE / REPEATED SEQUENCE (* / is the same as | *)
+  / SPECIAL SEQUENCE / GROUPED SEQUENCE
+  / META IDENTIFIER / TERMINAL / EMPTY.
+EMPTY = .
+OPTIONAL SEQUENCE = '(/', DEFINITIONS LIST, '/)'.
+REPEATED SEQUENCE = '(:', DEFINITIONS LIST, ':)'.
+GROUPED SEQUENCE = '(', DEFINITIONS LIST, ')'.
+TERMINAL
+  = "'", CHARACTER - "'",
+    (: CHARACTER - "'" :), "'"
+  / '"', CHARACTER - '"',
+    (: CHARACTER - '"' :), '"'.
+META IDENTIFIER = LETTER, (: LETTER / DIGIT :).
+INTEGER = DIGIT, (: DIGIT :).
+SPECIAL SEQUENCE = '?', (: CHARACTER - '?' :), '?'.
+COMMENT = '(*', (: COMMENT SYMBOL :), '*)'.
+COMMENT SYMBOL
+  = COMMENT / TERMINAL / SPECIAL SEQUENCE
+    / CHARACTER.
diff --git a/examples/prism-editorconfig.html b/examples/prism-editorconfig.html new file mode 100644 index 0000000000..eb317a362a --- /dev/null +++ b/examples/prism-editorconfig.html @@ -0,0 +1,47 @@ +

Comment

+
# This is a comment
+; And this is too
+ +

Section Header

+
[*]
+[*.js]
+[*.{bash,sh,zsh}]
+ +

Key-Value Pair

+
key = value
+indent_style = space
+ +

Full example

+
# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+# Matches multiple files with brace expansion notation
+# Set default charset
+[*.{js,py}]
+charset = utf-8
+
+# 4 space indentation
+[*.py]
+indent_style = space
+indent_size = 4
+
+# Tab indentation (no size specified)
+[Makefile]
+indent_style = tab
+
+# Indentation override for all JS under lib directory
+[lib/**.js]
+indent_style = space
+indent_size = 2
+
+# Matches the exact files either package.json or .travis.yml
+[{package.json,.travis.yml}]
+indent_style = space
+indent_size = 2
diff --git a/examples/prism-ejs.html b/examples/prism-ejs.html new file mode 100644 index 0000000000..bf5537dd42 --- /dev/null +++ b/examples/prism-ejs.html @@ -0,0 +1,16 @@ +

Full example

+
<h1>Let's have fun!</h1>
+<%
+    const fruits = ["Apple", "Pear", "Orange", "Lemon"];
+    const random = Array.from({ length: 198 }).map(x => Math.random());
+%>
+
+<p>These fruits are amazing:</p>
+<ul><% for (const fruit of fruits) { %>
+  <li><%=fruit%>s</li><% } %>
+</ul>
+
+<p>Some random numbers:</p>
+
+<% random.forEach((c, i) => {
+%> <%- c.toFixed(10) + ((i + 1) % 6 === 0 ? " <br>\n": "") %><%});%>
diff --git a/examples/prism-elixir.html b/examples/prism-elixir.html index 7112fbca5b..df4426be74 100644 --- a/examples/prism-elixir.html +++ b/examples/prism-elixir.html @@ -450,13 +450,3 @@

Full example

# The shell is also a process, you can use `self` to get the current pid self() #=> #PID<0.27.0> - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

String interpolation in single-quoted strings

-
'#{:atom} <- this should not be highligted'
\ No newline at end of file diff --git a/examples/prism-etlua.html b/examples/prism-etlua.html new file mode 100644 index 0000000000..d24707a62c --- /dev/null +++ b/examples/prism-etlua.html @@ -0,0 +1,12 @@ +

Full example

+
<div class="foo">
+	<% if true then %>
+		Hello <%= name %>,
+		Here are your items:
+		<% for i, item in pairs(items) do %>
+			 * <%= item -%>
+			<% --[[ comment block ]] %>
+		<% end %>
+		<%- "<b>this is not escaped</b>" %>
+	<% end %>
+</div>
diff --git a/examples/prism-excel-formula.html b/examples/prism-excel-formula.html new file mode 100644 index 0000000000..ccce7aa984 --- /dev/null +++ b/examples/prism-excel-formula.html @@ -0,0 +1,10 @@ +

Full example

+
=SUM(G7*9)
+=INT(RAND()*999)
+=AVERAGE(A4:A13)+N("Average user rating")
+=CONCATENATE(F4, ",", " ", G4," ",H4)
+=IF($A4>500, $A4, 0)
+=AND($B4>=501,$C4<=500)
+=SUBTOTAL(103,staff[Name])
+=TRIMMEAN(staff[Salary],10%)
+=SUM([Sales.xlsx]Jan!B2:B5)
diff --git a/examples/prism-factor.html b/examples/prism-factor.html new file mode 100644 index 0000000000..90bb143025 --- /dev/null +++ b/examples/prism-factor.html @@ -0,0 +1,127 @@ +

Comments

+
! FIXME: a comment
+
+USE: multiline
+
+![[ comment ]]
+/* comment */
+ +

Strings

+
"a string" "\"" "\x8" "%s"
+
+SBUF" asbdef"
+
+USE: multiline
+
+STRING: name
+content
+;
+
+HEREDOC: marker
+text
+marker
+
+[==[
+	str
+	ing
+]==]
+
+ +

Numbers

+
5 1/5 +9 -9 +1/5 -1/5 -1/5. 23+1/5 -23-1/5 23-1/5 ! NOTE: last one = word
+
++12.13 0.01 0e0 3E4 3e-4 3E-4 030 0xd 0o30 0b1100
+-12.13 -0 -0.01 -0e0 -3E4 -3E-4 -030 -0xd -0o30 -0b1100
+
+348756424956392657834385437598743583648756332457
+-348756424956392657834385437598743583648756332457
+
+NAN: a
+NAN: 80000deadbeef
+
+0b1.010p2 0x1.0p3 0x1.p1 0b1.111111p1111 ...
+ +

Sequences

+
{ 1 2 3 4 }
+{ a b c d e t f }
+{ "a" "b" "c" }
+
+{ { a b } { c d } }
+H{ { a b } { c d } }
+H{ { "a" "b" } { "c" "d" } }
+V{ 1 2 3 4 }
+V{ "1" "2" "3" "4" }
+BV{ 1 2 3 4 }
+ +

Regular Expressions

+
USE: regexp
+R/ abcde?.*+\?\.\*\+\/\\\/idmsr-idmsr/idmsr-idmsr
+ +

Colon parsing words

+
: a ( -- ) ;
+:: ; ! ; is not a word name
+:: ;a ! ;a is a word name
+USING: a b c ;
+USE: a
+IN: a.b
+CHAR: a
+GENERIC#: x 1 ( x: integer quot: ( x -- y ) -- )
+ +

Special words (builtins, conventions)

+
and not with map filter
+
+new last-index + - neg
+
+<array> <=> SYNTAX: x $[ xyz ]
+
+set-x change-x with-variable ?of if* (gensym) hex. $description reader>> >>setter writer<<
+
+string>number >hex base> mutater!
+
+ +

Full example

+
USING: accessors arrays assocs combinators
+combinators.short-circuit effects io kernel sequences
+sequences.deep splitting strings vocabs words ;
+IN: prism
+
+: make-prism-syntax ( syntax-vocab -- seq )
+ 	vocab-words [
+		dup name>> ">>" = [ drop t ] [
+			{
+				[ "delimiter" word-prop ]
+				[ name>> last { CHAR: : CHAR: { CHAR: [ CHAR: ( CHAR: ) CHAR: ? CHAR: " } member? ]
+				[ name>> { "t" "f" } member? ]
+			} 1|| not
+		] if
+	] filter ;
+
+: combinator? ( word -- ? )
+	[ "declared-effect" word-prop in>> flatten
+		[
+			[ effect? ] [ { "quots" "quot" } member? ] bi or
+		] any?
+	] [
+		"help" word-prop ?first flatten [ dup word? [ name>> ] when "quot" swap subseq? ] any?
+	] bi or ;
+
+: classify ( vocab-spec -- seq )
+	vocab-words [
+		dup {
+			{ [ dup combinator? ] [ drop "combinator" ] }
+			{ [ dup "macro" word-prop ] [ drop "macro" ] }
+			[ drop "ordinary" ]
+		} cond 2array
+	] map ;
+
+: print-strings ( strs -- )
+	[ name>> "'" dup surround ] map ", " join print ; recursive ! WARN: not recursive
+
+: combinators. ( vocab-spec -- )
+	classify [ nip "combinator" = ] assoc-filter keys print-strings ; flushable
+
+: ordinaries. ( vocab-spec -- )
+	classify [ nip "ordinary" = ] assoc-filter keys print-strings ; foldable
+
+: macros. ( vocab-spec -- )
+	classify [ nip "macro" = ] assoc-filter keys print-strings ; inline
diff --git a/examples/prism-false.html b/examples/prism-false.html new file mode 100644 index 0000000000..cbc3bc6d0a --- /dev/null +++ b/examples/prism-false.html @@ -0,0 +1,52 @@ +

Hello, world!

+ +
"Hello, world!"
+ +

Lambda functions

+ +

Increment

+ +
5 [7+]! . {Outputs 12.}
+ +

Square numbers

+ +
[$*] s: 7s;! . {Outputs 49.}
+ +

Conditions

+ +

Equal, less, or greater than

+ +
5x:
+7y:
+x;y;=
+$
+x;
+.
+[" equals "]?
+~[
+    x;y;>
+    $
+    [" is greater than "]?
+    ~[" is less than "]?
+]?
+y;
+.
+ +

Loops

+ +

English alphabet

+ +
'Ai: 'Zm: 1m;+ m: [m;i;>][i;, 1i;+ i:]#
+ +

Ten Green Bottles

+ +
[$ . " green bottle" 1> ["s"]? ".
+"] f:
+10n: [n;0>][n;f;! n;1- n:]#
+ +

User input

+ +

Reverse a string

+ +
"Enter the string character by character (or a space to finish):
+"0i: [ß ^ $ 32=~][i;1+ i:]# % "Reverse: " [i;0>][, i;1- i:]#
diff --git a/examples/prism-firestore-security-rules.html b/examples/prism-firestore-security-rules.html new file mode 100644 index 0000000000..08b0cc486c --- /dev/null +++ b/examples/prism-firestore-security-rules.html @@ -0,0 +1,37 @@ +

Full example

+
rules_version = '2';
+service cloud.firestore {
+
+  match /databases/{database}/documents {
+
+    // Returns `true` if the requested post is 'published'
+    // or the user authored the post
+    function authorOrPublished() {
+      return resource.data.published == true || request.auth.uid == resource.data.author;
+    }
+
+    match /{path=**}/posts/{post} {
+
+      // Anyone can query published posts
+      // Authors can query their unpublished posts
+      allow list: if authorOrPublished();
+
+      // Anyone can retrieve a published post
+      // Authors can retrieve an unpublished post
+      allow get: if authorOrPublished();
+    }
+
+    match /forums/{forumid}/posts/{postid} {
+      // Only a post's author can write to a post
+      allow write: if request.auth.uid == resource.data.author;
+    }
+  }
+
+  match /databases/{database}/reviews {
+    // Assign roles to all users and refine access based on user roles
+    match /some_collection/{document} {
+      allow read: if get(/databases/$(database)/reviews/users/$(request.auth.uid)).data.role == "Reader"
+      allow write: if get(/databases/$(database)/reviews/users/$(request.auth.uid)).data.role == "Writer"
+    }
+  }
+}
diff --git a/examples/prism-fsharp.html b/examples/prism-fsharp.html index 6a4330b652..c0b9921710 100644 --- a/examples/prism-fsharp.html +++ b/examples/prism-fsharp.html @@ -5,7 +5,6 @@

Comments

Strings

"foo \"bar\" baz"
-'foo \'bar\' baz'
 @"Verbatim strings"
 """Alternate "verbatim" strings"""
 
@@ -58,32 +57,32 @@

Numbers

Full example

-
// The declaration creates a constructor that takes two values, name and age. 
+
// The declaration creates a constructor that takes two values, name and age.
 type Person(name:string, age:int) =
-    // A Person object's age can be changed. The mutable keyword in the 
-    // declaration makes that possible. 
+    // A Person object's age can be changed. The mutable keyword in the
+    // declaration makes that possible.
     let mutable internalAge = age
 
-    // Declare a second constructor that takes only one argument, a name. 
-    // This constructor calls the constructor that requires two arguments, 
-    // sending 0 as the value for age. 
+    // Declare a second constructor that takes only one argument, a name.
+    // This constructor calls the constructor that requires two arguments,
+    // sending 0 as the value for age.
     new(name:string) = Person(name, 0)
 
-    // A read-only property. 
+    // A read-only property.
     member this.Name = name
-    // A read/write property. 
+    // A read/write property.
     member this.Age
         with get() = internalAge
         and set(value) = internalAge <- value
 
-    // Instance methods. 
-    // Increment the person's age. 
+    // Instance methods.
+    // Increment the person's age.
     member this.HasABirthday () = internalAge <- internalAge + 1
 
-    // Check current age against some threshold. 
+    // Check current age against some threshold.
     member this.IsOfAge targetAge = internalAge >= targetAge
 
-    // Display the person's name and age. 
-    override this.ToString () = 
+    // Display the person's name and age.
+    override this.ToString () =
         "Name:  " + name + "\n" + "Age:   " + (string)internalAge
-
\ No newline at end of file +
diff --git a/examples/prism-ftl.html b/examples/prism-ftl.html new file mode 100644 index 0000000000..76bf52b586 --- /dev/null +++ b/examples/prism-ftl.html @@ -0,0 +1,21 @@ +

Full example

+
<html>
+<head>
+	<title>Welcome!</title>
+</head>
+<body>
+	<h1>
+		Welcome ${user}<#if user == "Big Joe">, our beloved leader</#if>!
+	</h1>
+	<p>Our latest product:
+	<a href="${latestProduct.url}">${latestProduct.name}</a>!
+	<p>See what our happy customers have to say!</p>
+	<ul>
+	<#list userStories as story>
+		<li>
+			<p>${story.text?esc} - by <span>${story.user.name}</span>
+		<li>
+	</#list>
+	</ul>
+</body>
+</html>
diff --git a/examples/prism-gap.html b/examples/prism-gap.html new file mode 100644 index 0000000000..01e3f08cd7 --- /dev/null +++ b/examples/prism-gap.html @@ -0,0 +1,15 @@ +

Full example

+
# Source: https://www.gap-system.org/Manuals/doc/ref/chap4.html#X815F71EA7BC0EB6F
+gap> fib := function ( n )
+>     local f1, f2, f3, i;
+>     f1 := 1; f2 := 1;
+>     for i in [3..n] do
+>       f3 := f1 + f2;
+>       f1 := f2;
+>       f2 := f3;
+>     od;
+>     return f2;
+>   end;;
+gap> List( [1..10], fib );
+[ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
+
diff --git a/examples/prism-gcode.html b/examples/prism-gcode.html new file mode 100644 index 0000000000..ebc1561569 --- /dev/null +++ b/examples/prism-gcode.html @@ -0,0 +1,22 @@ +

Comments

+
; comment
+(some more comments)
+G28 (even in here) X0
+
+ +

Quoted strings

+
"foo""bar"
+ +

Full example

+
M190 S60 ; Heat bed to 60°C
+G21 ; Set units to millimeters
+G28 ; Move to Origin (Homing)
+G29 ; Auto Bed Leveling
+G28 X0 Y0 ; Home X and Y to min endstops
+M107 ; Fan off
+M109 S200 ; Heat hotend to 200°C
+G92 E0 ; Set current extruder position as zero
+G1 F200 E15 ; Extrude 15mm filament with 200mm/min
+G92 E0 ; Set current extruder position as zero
+G1 F500
+
diff --git a/examples/prism-gdscript.html b/examples/prism-gdscript.html new file mode 100644 index 0000000000..16b510656a --- /dev/null +++ b/examples/prism-gdscript.html @@ -0,0 +1,66 @@ +

Full example

+
extends BaseClass
+class_name MyClass, "res://path/to/optional/icon.svg"
+
+# Member Variables
+
+var a = 5
+var s = "Hello"
+var arr = [1, 2, 3]
+var dict = {"key": "value", 2:3}
+var typed_var: int
+var inferred_type := "String"
+
+# Constants
+
+const ANSWER = 42
+const THE_NAME = "Charly"
+
+# Enums
+
+enum {UNIT_NEUTRAL, UNIT_ENEMY, UNIT_ALLY}
+enum Named {THING_1, THING_2, ANOTHER_THING = -1}
+
+# Built-in Vector Types
+
+var v2 = Vector2(1, 2)
+var v3 = Vector3(1, 2, 3)
+
+# Function
+
+func some_function(param1, param2):
+	var local_var = 5
+
+	if param1 < local_var:
+		print(param1)
+	elif param2 > 5:
+		print(param2)
+	else:
+		print("Fail!")
+
+	for i in range(20):
+		print(i)
+
+	while param2 != 0:
+		param2 -= 1
+
+	var local_var2 = param1 + 3
+	return local_var2
+
+# Functions override functions with the same name on the base/parent class.
+# If you still want to call them, use '.' (like 'super' in other languages).
+
+func something(p1, p2):
+	.something(p1, p2)
+
+# Inner Class
+
+class Something:
+	var a = 10
+
+# Constructor
+
+func _init():
+	print("Constructed!")
+	var lv = Something.new()
+	print(lv.a)
diff --git a/examples/prism-glsl.html b/examples/prism-glsl.html index 7492a422ba..7d64da4bfd 100644 --- a/examples/prism-glsl.html +++ b/examples/prism-glsl.html @@ -15,18 +15,18 @@

Vertex shader example

vec3 specularColor = vec3(1.0,1.0,1.0); void main(void) { - // compute position - gl_Position = _mvProj * vec4(vertex, 1.0); - - localPos = vertex; - - // compute light info - vec3 n = normalize(_norm * normal); - vec3 diffuse; - float specular; - float glowingSpecular = 50.0; - getDirectionalLight(n, _dLight, glowingSpecular, diffuse, specular); - vColor = max(diffuse,_ambient.xyz)*materialColor+specular*specularColor+_ambient; + // compute position + gl_Position = _mvProj * vec4(vertex, 1.0); + + localPos = vertex; + + // compute light info + vec3 n = normalize(_norm * normal); + vec3 diffuse; + float specular; + float glowingSpecular = 50.0; + getDirectionalLight(n, _dLight, glowingSpecular, diffuse, specular); + vColor = max(diffuse,_ambient.xyz)*materialColor+specular*specularColor+_ambient; }

Fragment shader example

@@ -42,17 +42,17 @@

Fragment shader example

varying vec3 localPos; void main() { - vec3 color; + vec3 color; vec3 position, useBrick; - + position = localPos / BrickSize.xyz; if (fract(position.y * 0.5) > 0.5){ position.x += 0.5; - position.z += 0.5; + position.z += 0.5; } - + position = fract(position); useBrick = step(position, BrickPct.xyz); @@ -62,4 +62,4 @@

Fragment shader example

gl_FragColor = vec4(color, 1.0); } - \ No newline at end of file + diff --git a/examples/prism-gml.html b/examples/prism-gml.html new file mode 100644 index 0000000000..5526c5cd3a --- /dev/null +++ b/examples/prism-gml.html @@ -0,0 +1,29 @@ +

Comments

+
// This is a comment
+/* This is a comment
+on multiple lines */
+ +

Functions

+
variable_instance_set(_inst,_var_name,_start+_change);
+ +

Full example

+
if(instance_exists(_inst) || _inst==global){
+	if(_delay<=0){
+		_time+=1;
+		if(_time<_duration){
+			event_user(0);
+		}else{
+			if(_inst!=global){
+				variable_instance_set(_inst,_var_name,_start+_change);
+			}else{
+				variable_global_set(_var_name,_start+_change);
+			}
+			instance_destroy();
+		}
+	}else{
+		_delay-=1;
+	}
+}else{
+	instance_destroy();
+}
+
diff --git a/examples/prism-gn.html b/examples/prism-gn.html new file mode 100644 index 0000000000..d0a7fa7200 --- /dev/null +++ b/examples/prism-gn.html @@ -0,0 +1,24 @@ +

Full example

+
# Source: https://gn.googlesource.com/gn/+/main/docs/cross_compiles.md
+
+declare_args() {
+  # Applies only to toolchains targeting target_cpu.
+  sysroot = ""
+}
+
+config("my_config") {
+  # Uses current_cpu because compile flags are toolchain-dependent.
+  if (current_cpu == "arm") {
+    defines = [ "CPU_IS_32_BIT" ]
+  } else {
+    defines = [ "CPU_IS_64_BIT" ]
+  }
+  # Compares current_cpu with target_cpu to see whether current_toolchain
+  # has the same architecture as target_toolchain.
+  if (sysroot != "" && current_cpu == target_cpu) {
+    cflags = [
+      "-isysroot",
+      sysroot,
+    ]
+  }
+}
diff --git a/examples/prism-go-module.html b/examples/prism-go-module.html new file mode 100644 index 0000000000..52855d457b --- /dev/null +++ b/examples/prism-go-module.html @@ -0,0 +1,15 @@ +

Full example

+
// Source: https://go.dev/doc/modules/gomod-ref#example
+
+module example.com/mymodule
+
+go 1.14
+
+require (
+    example.com/othermodule v1.2.3
+    example.com/thismodule v1.2.3
+    example.com/thatmodule v1.2.3
+)
+
+replace example.com/thatmodule => ../thatmodule
+exclude example.com/thismodule v1.3.0
diff --git a/examples/prism-go.html b/examples/prism-go.html index 205a1a7e29..da2bc7f931 100644 --- a/examples/prism-go.html +++ b/examples/prism-go.html @@ -41,7 +41,7 @@

Runes and strings

string"

Functions

-
func(a, b int, z float64) bool { return a*b < int(z) }
+
func(a, b int, z float64) bool { return a*b < int(z) }

Full example

package main
@@ -52,7 +52,7 @@ 

Full example

for _, v := range a { sum += v } - c <- sum // send sum to c + c <- sum // send sum to c } func main() { @@ -61,8 +61,8 @@

Full example

c := make(chan int) go sum(a[:len(a)/2], c) go sum(a[len(a)/2:], c) - x, y := <-c, <-c // receive from c + x, y := <-c, <-c // receive from c fmt.Println(x, y, x+y) } -
\ No newline at end of file + diff --git a/examples/prism-graphql.html b/examples/prism-graphql.html index 12113a9d80..7a030bceee 100644 --- a/examples/prism-graphql.html +++ b/examples/prism-graphql.html @@ -3,7 +3,10 @@

Comments

Strings

""
-"foo \"bar\" baz"
+"foo \"bar\" baz" +""" "Multi-line" strings +are supported.""" +

Numbers

0
@@ -28,4 +31,32 @@ 

Keywords

id name profilePic(size: 50) -}
\ No newline at end of file +} + +

Markdown inside of descriptions require markdown to be loaded. +On this page, checking Markdown before checking GraphQL should +make the example below work properly.

+ +

Descriptions

+
"""
+This is a multiline description
+# Heading
+[Prism](http://www.prismjs.com)
+
+It can contain **Markdown
+	on multiple lines**
+"""
+type Example {
+	id: ID!
+}
+
+type Sample {
+	"""
+	Simple multiline description
+	"""
+	name(
+		"This is a single line description"
+		first: Int
+	): String
+}
+
\ No newline at end of file diff --git a/examples/prism-groovy.html b/examples/prism-groovy.html index 3ec1d6d39b..ac36cf7e53 100644 --- a/examples/prism-groovy.html +++ b/examples/prism-groovy.html @@ -81,13 +81,3 @@

Full example

assert 4 / 2 == 2 } } - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Two divisions on the same line

-
2 / 3 / 4
\ No newline at end of file diff --git a/examples/prism-haml.html b/examples/prism-haml.html index c2cc670c32..364595ad01 100644 --- a/examples/prism-haml.html +++ b/examples/prism-haml.html @@ -21,7 +21,7 @@

Tags

%html{html_attrs('fr-fr')} %div[@user, :greeting] %img -%pre>< +%pre>< foo bar %img @@ -76,4 +76,4 @@

Filters

the example below work properly.

%script
   :coffee
-    console.log 'This is coffee script'
\ No newline at end of file + console.log 'This is coffee script' diff --git a/examples/prism-handlebars.html b/examples/prism-handlebars.html index c39c8b742d..8e07329166 100644 --- a/examples/prism-handlebars.html +++ b/examples/prism-handlebars.html @@ -29,13 +29,3 @@

Block helpers

This should probably work... {{/block-with-hyphens}} - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Handlebars tag in the middle of an HTML tag

-
<div{{#if test}} class="test"{{/if}}></div>
diff --git a/examples/prism-haskell.html b/examples/prism-haskell.html index de58eb79bf..799bbdfa79 100644 --- a/examples/prism-haskell.html +++ b/examples/prism-haskell.html @@ -28,7 +28,7 @@

Full example

wantReadableHandle_ "Data.ByteString.hGetLine" h $ \ h_@Handle__{haByteBuffer} -> do flushCharReadBuffer h_ - buf <- readIORef haByteBuffer + buf <- readIORef haByteBuffer if isEmptyBuffer buf then fill h_ buf 0 [] else haveBuf h_ buf 0 [] @@ -36,7 +36,7 @@

Full example

fill h_@Handle__{haByteBuffer,haDevice} buf len xss = len `seq` do - (r,buf') <- Buffered.fillReadBuffer haDevice buf + (r,buf') <- Buffered.fillReadBuffer haDevice buf if r == 0 then do writeIORef haByteBuffer buf{ bufR=0, bufL=0 } if len > 0 @@ -48,9 +48,9 @@

Full example

buf@Buffer{ bufRaw=raw, bufR=w, bufL=r } len xss = do - off <- findEOL r w raw + off <- findEOL r w raw let new_len = len + off - r - xs <- mkPS raw r off + xs <- mkPS raw r off -- if eol == True, then off is the offset of the '\n' -- otherwise off == w and the buffer is now empty. @@ -66,7 +66,7 @@

Full example

findEOL r w raw | r == w = return w | otherwise = do - c <- readWord8Buf raw r + c <- readWord8Buf raw r if c == fromIntegral (ord '\n') then return r -- NB. not r+1: don't include the '\n' else findEOL (r+1) w raw @@ -77,4 +77,4 @@

Full example

withRawBuffer buf $ \pbuf -> do copyBytes p (pbuf `plusPtr` start) len where - len = end - start \ No newline at end of file + len = end - start diff --git a/examples/prism-hcl.html b/examples/prism-hcl.html new file mode 100644 index 0000000000..5b15134ba5 --- /dev/null +++ b/examples/prism-hcl.html @@ -0,0 +1,42 @@ +

Comments

+
# Configure the AWS Provider
+// Configure the AWS Provider
+
+ +

Resources

+
resource "aws_instance" "web" {
+  ami           = "${data.aws_ami.ubuntu.id}"
+  instance_type = "t2.micro"
+
+  tags {
+    Name = "HelloWorld"
+  }
+}
+ +

Provider

+
provider "aws" {
+  access_key = "${var.aws_access_key}"
+  secret_key = "${var.aws_secret_key}"
+  region     = "us-east-1"
+}
+ +

Variables

+
variable "images" {
+  type = "map"
+
+  default = {
+    us-east-1 = "image-1234"
+    us-west-2 = "image-4567"
+  }
+}
+ +

Outputs

+
output "address" {
+  value = "${aws_instance.db.public_dns}"
+}
+ +

Modules

+
module "consul" {
+  source  = "hashicorp/consul/aws"
+  servers = 5
+}
diff --git a/examples/prism-hlsl.html b/examples/prism-hlsl.html new file mode 100644 index 0000000000..96b4bac5c9 --- /dev/null +++ b/examples/prism-hlsl.html @@ -0,0 +1,18 @@ +

Full example

+
// Source: https://github.com/mellinoe/veldrid/blob/d60e5a036add2123a15f0da02f1da65a80503d54/src/Veldrid.ImGui/Assets/HLSL/imgui-frag.hlsl
+
+struct PS_INPUT
+{
+	float4 pos : SV_POSITION;
+	float4 col : COLOR0;
+	float2 uv  : TEXCOORD0;
+};
+
+Texture2D FontTexture : register(t0);
+sampler FontSampler : register(s0);
+
+float4 FS(PS_INPUT input) : SV_Target
+{
+	float4 out_col = input.col * FontTexture.Sample(FontSampler, input.uv);
+	return out_col;
+}
diff --git a/examples/prism-hoon.html b/examples/prism-hoon.html new file mode 100644 index 0000000000..6d45086c44 --- /dev/null +++ b/examples/prism-hoon.html @@ -0,0 +1,17 @@ +

Caesar cipher

+ +
|= [a=@ b=tape]
+^- tape
+?: (gth a 25)
+$(a (sub a 26))
+%+ turn b
+|= c=@tD
+?: &((gte c 'A') (lte c 'Z'))
+=. c (add c a)
+?. (gth c 'Z') c
+(sub c 26)
+?: &((gte c 'a') (lte c 'z'))
+=. c (add c a)
+?. (gth c 'z') c
+(sub c 26)
+c
\ No newline at end of file diff --git a/examples/prism-icu-message-format.html b/examples/prism-icu-message-format.html new file mode 100644 index 0000000000..691aa47e21 --- /dev/null +++ b/examples/prism-icu-message-format.html @@ -0,0 +1,22 @@ +

Full example

+
https://unicode-org.github.io/icu/userguide/format_parse/messages/
+
+{gender_of_host, select,
+  female {
+    {num_guests, plural, offset:1
+      =0 {{host} does not give a party.}
+      =1 {{host} invites {guest} to her party.}
+      =2 {{host} invites {guest} and one other person to her party.}
+      other {{host} invites {guest} and # other people to her party.}}}
+  male {
+    {num_guests, plural, offset:1
+      =0 {{host} does not give a party.}
+      =1 {{host} invites {guest} to his party.}
+      =2 {{host} invites {guest} and one other person to his party.}
+      other {{host} invites {guest} and # other people to his party.}}}
+  other {
+    {num_guests, plural, offset:1
+      =0 {{host} does not give a party.}
+      =1 {{host} invites {guest} to their party.}
+      =2 {{host} invites {guest} and one other person to their party.}
+      other {{host} invites {guest} and # other people to their party.}}}}
diff --git a/examples/prism-idris.html b/examples/prism-idris.html new file mode 100644 index 0000000000..558f1fa8ca --- /dev/null +++ b/examples/prism-idris.html @@ -0,0 +1,56 @@ +

Comments

+
-- Single line comment
+{- Multi-line
+comment -}
+ +

Strings and characters

+
'a'
+'\n'
+'\^A'
+'\^]'
+'\NUL'
+'\23'
+'\o75'
+'\xFE'
+ +

Numbers

+
42
+123.456
+123.456e-789
+1e+3
+0o74
+0XAF
+ +

Larger example

+
module Main
+
+import Data.Vect
+
+-- this is comment
+record Person where
+  constructor MkPerson2
+  age : Integer
+  name : String
+
+||| identity function
+id : a -> a
+id x = x
+
+{-
+Bool type can be defined in
+userland
+-}
+data Bool = True | False
+
+implementation Show Bool where
+  show True = "True"
+  show False = "False"
+
+not : Bool -> Bool
+not b = case b of
+          True  => False
+          False => True
+
+vect3 : Vect 3 Int
+vect3 = with Vect (1 :: 2 :: 3 :: Nil)
+
diff --git a/examples/prism-iecst.html b/examples/prism-iecst.html new file mode 100644 index 0000000000..2bfc455654 --- /dev/null +++ b/examples/prism-iecst.html @@ -0,0 +1,40 @@ +

Code

+

+CONFIGURATION DefaultCfg
+    VAR_GLOBAL
+      Start_Stop AT %IX0.0: BOOL; (* This is a comment *)
+    END_VAR
+    TASK NewTask  (INTERVAL := T#20ms);
+    PROGRAM Main WITH NewTask : PLC_PRG;
+END_CONFIGURATION
+  
+PROGRAM demo
+    VAR_EXTERNAL
+      Start_Stop: BOOL;
+      StringVar: STRING[250] := "Test String"
+    END_VAR
+    VAR
+      a : REAL; // Another comment
+      todTest: TIME_OF_DAY := TOD#12:55;
+    END_VAR
+    a := csq(12.5);
+    IF a > REAL#100 - 16#FAC0 + 2#1001_0110 THEN
+      Start_Stop := TRUE;
+    END_IF
+END_PROGRAM;
+  
+FUNCTION_BLOCK PRIVATE MyName EXTENDS AnotherName
+      
+END_FUNCTION_BLOCK
+
+/* Get a square of the circle */
+FUNCTION csq : REAL 
+    VAR_INPUT
+      r: REAL;
+    END_VAR
+    VAR CONSTANT
+      c_pi: REAL := 3.14;
+    END_VAR
+    csq := ABS(c_pi * (r * 2));
+END_FUNCTION
+
\ No newline at end of file diff --git a/examples/prism-ignore.html b/examples/prism-ignore.html new file mode 100644 index 0000000000..9d15f97863 --- /dev/null +++ b/examples/prism-ignore.html @@ -0,0 +1,7 @@ +

Comment

+
# This is a comment
+ +

Entry

+
file[1-3].txt
+.configs/**
+!.configs/shared.cfg
diff --git a/examples/prism-inform7.html b/examples/prism-inform7.html index 9e2214f01d..d4c3b746e1 100644 --- a/examples/prism-inform7.html +++ b/examples/prism-inform7.html @@ -159,13 +159,3 @@

Full example

Instead of taking off the outfit: say "What odd ideas come into your head sometimes!" Test me with "fill glass / empty absinthe into lake / fill glass / swim / drink lake / drink / x water / x lake". - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Names starting with a number

-
The box 1A is a container
\ No newline at end of file diff --git a/examples/prism-j.html b/examples/prism-j.html index cf4c109afa..0227e31fd0 100644 --- a/examples/prism-j.html +++ b/examples/prism-j.html @@ -34,7 +34,7 @@

Examples

NB. multiply a row by a constant, NB. and add a multiple of one row to another: -E1=: <@] C. [ +E1=: <@] C. [ E2=: f`g`[} E3=: F`g`[} f=: {:@] * {.@] { [ @@ -56,4 +56,4 @@

Examples

NB. Implementation of quicksort (tacit programming)
 
-quicksort=: (($:@(<#[), (=#[), $:@(>#[)) ({~ ?@#)) ^: (1<#)
\ No newline at end of file +quicksort=: (($:@(<#[), (=#[), $:@(>#[)) ({~ ?@#)) ^: (1<#) diff --git a/examples/prism-java.html b/examples/prism-java.html index 691a6b10ec..277a1ab12b 100644 --- a/examples/prism-java.html +++ b/examples/prism-java.html @@ -39,8 +39,8 @@

Full example

public static boolean[][] gen(){ boolean[][] grid = new boolean[10][10]; - for(int r = 0; r < 10; r++) - for(int c = 0; c < 10; c++) + for(int r = 0; r < 10; r++) + for(int c = 0; c < 10; c++) if( Math.random() > 0.7 ) grid[r][c] = true; return grid; diff --git a/examples/prism-javadoc.html b/examples/prism-javadoc.html new file mode 100644 index 0000000000..4e809797bd --- /dev/null +++ b/examples/prism-javadoc.html @@ -0,0 +1,29 @@ +

Full example

+
/**
+ * Returns the value to which the specified key is mapped,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * <p>More formally, if this map contains a mapping from a key
+ * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
+ * key.equals(k))}, then this method returns {@code v}; otherwise
+ * it returns {@code null}.  (There can be at most one such mapping.)
+ *
+ * <p>If this map permits null values, then a return value of
+ * {@code null} does not <i>necessarily</i> indicate that the map
+ * contains no mapping for the key; it's also possible that the map
+ * explicitly maps the key to {@code null}.  The {@link #containsKey
+ * containsKey} operation may be used to distinguish these two cases.
+ *
+ * @param key the key whose associated value is to be returned
+ * @return the value to which the specified key is mapped, or
+ *         {@code null} if this map contains no mapping for the key
+ * @throws ClassCastException if the key is of an inappropriate type for
+ *         this map
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+ * @throws NullPointerException if the specified key is null and this map
+ *         does not permit null keys
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
+ */
+V get(Object key);
+
+// Source: Java 1.8, Map#get(Object)
diff --git a/examples/prism-javascript.html b/examples/prism-javascript.html index ef86a9023a..f073b65de0 100644 --- a/examples/prism-javascript.html +++ b/examples/prism-javascript.html @@ -49,7 +49,7 @@

A division operator on the same line as a regex

ES6 features

// Regex "y" and "u" flags
-/[a-zA-Z]+/gimyu
+var a = /[a-zA-Z]+/gimyu;
 
 // for..of loops
 for(let x of y) { }
@@ -64,17 +64,3 @@ 

ES6 features

multiple lines.` `40 + 2 = ${ 40 + 2 }` `The squares of the first 3 natural integers are ${[for (x of [1,2,3]) x*x].join(', ')}`
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

String interpolation containing a closing brace

-
`${ {foo:'bar'}.foo }`
-`${ '}' }`
- -

String interpolation containing an unescaped back-tick

-
`${ '`' }`
\ No newline at end of file diff --git a/examples/prism-javastacktrace.html b/examples/prism-javastacktrace.html new file mode 100644 index 0000000000..3511aa6ae5 --- /dev/null +++ b/examples/prism-javastacktrace.html @@ -0,0 +1,63 @@ +

Full example

+
javax.servlet.ServletException: Something bad happened
+    at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60)
+    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
+    at com.example.myproject.ExceptionHandlerFilter.doFilter(ExceptionHandlerFilter.java:28)
+    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
+    at com.example.myproject.OutputBufferFilter.doFilter(OutputBufferFilter.java:33)
+    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
+    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
+    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
+    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
+    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
+    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
+    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
+    at org.mortbay.jetty.Server.handle(Server.java:326)
+    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
+    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
+    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
+    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
+    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
+    at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
+    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
+Caused by: com.example.myproject.MyProjectServletException
+    at com.example.myproject.MyServlet.doPost(MyServlet.java:169)
+    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
+    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
+    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
+    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
+    at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:30)
+    ... 27 more
+Suppressed: org.hibernate.exception.ConstraintViolationException: could not insert: [com.example.myproject.MyEntity]
+    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
+    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
+    at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:64)
+    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2329)
+    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2822)
+    at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
+    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
+    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321)
+    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
+    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
+    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
+    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
+    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
+    at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
+    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
+    at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
+    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
+    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)
+    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
+    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
+    at java.lang.reflect.Method.invoke(Method.java:597)
+    at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:344)
+    at $Proxy19.save(Unknown Source)
+    at com.example.myproject.MyEntityService.save(MyEntityService.java:59) <-- relevant call (see notes below)
+    at com.example.myproject.MyServlet.doPost(MyServlet.java:164)
+    ... 32 more
+Caused by: java.sql.SQLException: Violation of unique constraint MY_ENTITY_UK_1: duplicate value(s) for column(s) MY_COLUMN in statement [...]
+    at org.hsqldb.jdbc.Util.throwError(Unknown Source)
+    at org.hsqldb.jdbc.jdbcPreparedStatement.executeUpdate(Unknown Source)
+    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
+    at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:57)
+    ... 54 more
diff --git a/examples/prism-jexl.html b/examples/prism-jexl.html new file mode 100644 index 0000000000..0c5a77e916 --- /dev/null +++ b/examples/prism-jexl.html @@ -0,0 +1,8 @@ +

Full example

+

+[
+  fun(1,2),
+  { obj: "1" }.obj,
+  ctx|transform
+]|join(", ")
+
diff --git a/examples/prism-jolie.html b/examples/prism-jolie.html index 8d23d995ab..9a35b009e1 100644 --- a/examples/prism-jolie.html +++ b/examples/prism-jolie.html @@ -60,7 +60,7 @@

Full example

OneWay: *(AuthenticationData) } -service SubService +service SubService { Interfaces: NetInterface @@ -92,9 +92,9 @@

Full example

.debug.showContent = true } Interfaces: NetInterface - Aggregates: SubService, + Aggregates: SubService, LoggerService - Redirects: A => SubService, + Redirects: A => SubService, B => SubService } @@ -105,11 +105,11 @@

Full example

execution{ concurrent } define netmodule { - if( request.load == 0 || request.load < 1 && - request.load <= 2 || request.load >= 3 && + if( request.load == 0 || request.load < 1 && + request.load <= 2 || request.load >= 3 && request.load > 4 || request.load%4 == 2 ) { - scope( scopeName ) { + scope( scopeName ) { // inline comment install( MyFault => println@Console( "Something \"Went\" Wrong" + ' but it\'s ok' )() ); /* @@ -127,9 +127,9 @@

Full example

with( node ){ while( .load != 100 ) { .load++ - } + } } - } + } } } @@ -159,4 +159,4 @@

Full example

} until [ quit() ]{ exit } -} \ No newline at end of file +} diff --git a/examples/prism-jq.html b/examples/prism-jq.html new file mode 100644 index 0000000000..53aead9b7a --- /dev/null +++ b/examples/prism-jq.html @@ -0,0 +1,11 @@ +

Full example

+
# comment
+def some_method:
+	to_entries | sort_by(.foo) |
+	map(.foo) as $keys |
+	map(.bar) | transpose |
+	map(
+		[$keys, .] | transpose |
+		map({foo: .[0], bar: .[1], "foo-bar": "foo\("-" + "bar")"}) | from_entries
+	)
+;
diff --git a/examples/prism-js-extras.html b/examples/prism-js-extras.html new file mode 100644 index 0000000000..fa3ea9b5a0 --- /dev/null +++ b/examples/prism-js-extras.html @@ -0,0 +1,20 @@ +

Support built-in JS classes

+
Math.sin();
+Number.isNaN();
+Object.keys();
+
+// and many more
+ +

DOM variables

+
document.querySelectorAll();
+window.parent;
+location.href;
+performance.now();
+
+// and many more
+ +

console

+
console.log();
+ +

Invisible changes

+

The goal of JS Extras is to make the tokenization of JavaScript more granular to allow for more customization in your themes. To to do this, JS Extras adds many new tokens and given existing tokens new aliases. These new tokens and aliases can be used by your theme but aren't supported by Prism's default themes and therefore invisible.

diff --git a/examples/prism-js-templates.html b/examples/prism-js-templates.html new file mode 100644 index 0000000000..e1fd09dc6c --- /dev/null +++ b/examples/prism-js-templates.html @@ -0,0 +1,25 @@ +

HTML template literals

+
html`
+<p>
+	Foo.
+</p>`;
+ +

JS DOM

+
div.innerHTML = `<p></p>`;
+div.outerHTML = `<p></p>`;
+ +

styled-jsx CSS template literals

+
css`a:hover { color: blue; }`;
+ +

styled-components CSS template literals

+
const Button = styled.button`
+	color: blue;
+	background: red;
+`;
+ +

Markdown template literals

+
markdown`# My title`;
+ +

GraphQL template literals

+
gql`{ foo }`;
+graphql`{ foo }`;
diff --git a/examples/prism-jsdoc.html b/examples/prism-jsdoc.html new file mode 100644 index 0000000000..85a7442972 --- /dev/null +++ b/examples/prism-jsdoc.html @@ -0,0 +1,21 @@ +

Full example

+
/**
+ * @typedef {object} Foo
+ * @property {string} bar
+ * @memberof Baz
+ */
+
+/**
+ * Trims the given string.
+ *
+ * @param {string} [str=""] the string.
+ * @returns {string} the trimmed string.
+ * @throws {TypeError} if the argument is not a string.
+ * @example trim(" hello ")
+ */
+function trim(str = "") {
+	if (typeof str != "string") {
+		throw new TypeError("str has to be a string");
+	}
+	return str.trim();
+}
diff --git a/examples/prism-json.html b/examples/prism-json.html new file mode 100644 index 0000000000..027f9310f7 --- /dev/null +++ b/examples/prism-json.html @@ -0,0 +1,16 @@ +

Full example

+
{
+    "data": {
+        "labels": [
+            "foo",
+            "bar"
+        ],
+        "series": [
+            [ 0, 1, 2, 3 ],
+            [ 0, -4, -8, -12 ]
+        ]
+    },
+    // we even support comments
+    "error": null,
+    "status": "Ok"
+}
diff --git a/examples/prism-json5.html b/examples/prism-json5.html new file mode 100644 index 0000000000..544e175043 --- /dev/null +++ b/examples/prism-json5.html @@ -0,0 +1,13 @@ +

Full example

+
{
+  // comments
+  unquoted: 'and you can quote me on that',
+  singleQuotes: 'I can use "double quotes" here',
+  lineBreaks: "Look, Mom! \
+No \\n's!",
+  hexadecimal: 0xdecaf,
+  leadingDecimalPoint: .8675309, andTrailing: 8675309.,
+  positiveSign: +1,
+  trailingComma: 'in objects', andIn: ['arrays',],
+  "backwardsCompatible": "with JSON",
+}
diff --git a/examples/prism-jsonp.html b/examples/prism-jsonp.html new file mode 100644 index 0000000000..5de6ffa882 --- /dev/null +++ b/examples/prism-jsonp.html @@ -0,0 +1,2 @@ +

Callbacks

+
callback({ "data": null });
diff --git a/examples/prism-jsstacktrace.html b/examples/prism-jsstacktrace.html new file mode 100644 index 0000000000..f67f68de34 --- /dev/null +++ b/examples/prism-jsstacktrace.html @@ -0,0 +1,99 @@ +

Full example

+
(node:40780) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
+    at Buffer (buffer.js:79:13)
+    at repl:1:1
+    at sigintHandlersWrap (vm.js:22:35)
+    at sigintHandlersWrap (vm.js:96:12)
+    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
+    at REPLServer.defaultEval (repl.js:313:29)
+    at bound (domain.js:280:14)
+    at REPLServer.runBound [as eval] (domain.js:293:12)
+    at REPLServer.onLine (repl.js:513:10)
+    at emitOne (events.js:101:20)
+
+Error: custom error
+    at Server.<anonymous> (/trace/showcases/http.js:4:9)
+    at emitTwo (events.js:106:13)
+    at Server.emit (events.js:191:7)
+    at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:543:12)
+    at HTTPParser.parserOnHeadersComplete (_http_common.js:105:23)
+    at new <anonymous> (_http_common.js:159:16)
+    at exports.FreeList.alloc (internal/freelist.js:14:46)
+    at Server.connectionListener (_http_server.js:316:24)
+    at emitOne (events.js:96:13)
+    at Server.emit (events.js:188:7)
+    at TCP.onconnection (net.js:1460:8)
+    at createServerHandle (net.js:1181:14)
+    at Server._listen2 (net.js:1225:14)
+    at listen (net.js:1290:10)
+    at Server.listen (net.js:1386:5)
+    at Object.<anonymous> (/trace/showcases/http.js:5:4)
+    at Module._compile (module.js:541:32)
+    at Object.Module._extensions..js (module.js:550:10)
+    at Module.load (module.js:458:32)
+    at tryModuleLoad (module.js:417:12)
+    at Function.Module._load (module.js:409:3)
+    at Module.runMain (module.js:575:10)
+    at run (bootstrap_node.js:340:7)
+    at startup (bootstrap_node.js:132:9)
+    at bootstrap_node.js:455:3
+
+
+Error: custom error
+    at /trace/showcases/basic.js:7:13
+    at _combinedTickCallback (internal/process/next_tick.js:67:7)
+    at process._tickCallback (internal/process/next_tick.js:98:9)
+    at InternalFieldObject.ondone (/trace/showcases/basic.js:6:13)
+    at /trace/showcases/basic.js:5:10
+    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:445:3)
+    at ReadFileContext.close (fs.js:358:11)
+    at FSReqWrap.readFileAfterRead [as oncomplete] (fs.js:414:15)
+    at ReadFileContext.read (fs.js:342:11)
+    at FSReqWrap.readFileAfterStat [as oncomplete] (fs.js:398:11)
+    at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:374:11)
+    at Object.fs.readFile (fs.js:303:11)
+    at Object.<anonymous> (/trace/showcases/basic.js:4:4)
+    at Module._compile (module.js:541:32)
+    at Object.Module._extensions..js (module.js:550:10)
+    at Module.load (module.js:458:32)
+    at tryModuleLoad (module.js:417:12)
+    at Function.Module._load (module.js:409:3)
+    at Module.runMain (module.js:575:10)
+    at run (bootstrap_node.js:340:7)
+    at startup (bootstrap_node.js:132:9)
+    at bootstrap_node.js:455:3
+
+
+BulkWriteError: E11000 duplicate key error collection: test.test index: _id_ dup key: { : 1 }
+    at OrderedBulkOperation.handleWriteError (/workspace/node_modules/mongodb/lib/bulk/common.js:1048:11)
+    at resultHandler (/workspace/node_modules/mongodb/lib/bulk/ordered.js:159:23)
+    at /workspace/node_modules/mongodb/node_modules/mongodb-core/lib/connection/pool.js:532:18
+    at _combinedTickCallback (internal/process/next_tick.js:131:7)
+    at process._tickCallback (internal/process/next_tick.js:180:9)
+
+Error
+    at Collection.(anonymous function) [as insertMany] (/workspace/node_modules/monogram/lib/collection.js:80:21)
+    at insert (/workspace/test.js:14:31)
+    at run (/workspace/test.js:9:9)
+    at <anonymous>
+    at process._tickCallback (internal/process/next_tick.js:188:7)
+
+Error
+    at Collection.(anonymous function) [as insertMany] (/workspace/node_modules/monogram/lib/collection.js:80:21)
+    at insert (/workspace/test.js:15:31)
+    at processTicksAndRejections (internal/process/next_tick.js:81:5)
+
+
+Deno:
+
+Error: Some error
+    at throwsA (<unknown>:1:23)
+    at <unknown>:1:13
+    at evaluate ($deno$/repl.ts:64:34)
+    at Object.replLoop ($deno$/repl.ts:153:13)
+
+Uncaught NotFound: No such file or directory (os error 2)
+    at DenoError (deno/js/errors.ts:22:5)
+    at maybeError (deno/js/errors.ts:41:12)
+    at handleAsyncMsgFromRust (deno/js/dispatch.ts:27:17)
+
diff --git a/examples/prism-keepalived.html b/examples/prism-keepalived.html new file mode 100644 index 0000000000..c8bc961c8f --- /dev/null +++ b/examples/prism-keepalived.html @@ -0,0 +1,130 @@ +

A example from keepalived document

+

+# Configuration File for keepalived
+global_defs {
+    notification_email {
+        admin@domain.com
+        0633225522@domain.com
+    }
+    notification_email_from keepalived@domain.com
+    smtp_server 192.168.200.20
+    smtp_connect_timeout 30
+    router_id LVS_MAIN
+}
+
+# VRRP Instances definitions
+vrrp_instance VI_1 {
+    state MASTER
+    interface eth0
+    virtual_router_id 51
+    priority 150
+    advert_int 1
+    authentication {
+        auth_type PASS
+        auth_pass k@l!ve1
+    }
+    virtual_ipaddress {
+        192.168.200.10
+        192.168.200.11
+    }
+}
+vrrp_instance VI_2 {
+    state MASTER
+    interface eth1
+    virtual_router_id 52
+    priority 150
+    advert_int 1
+    authentication {
+        auth_type PASS
+        auth_pass k@l!ve2
+    }
+    virtual_ipaddress {
+        192.168.100.10
+    }
+}
+vrrp_instance VI_3 {
+    state BACKUP
+    interface eth0
+    virtual_router_id 53
+    priority 100
+    advert_int 1
+    authentication {
+        auth_type PASS
+        auth_pass k@l!ve3
+    }
+    virtual_ipaddress {
+        192.168.200.12
+        192.168.200.13
+    }
+}
+vrrp_instance VI_4 {
+    state BACKUP
+    interface eth1
+    virtual_router_id 54
+    priority 100
+    advert_int 1
+    authentication {
+        auth_type PASS
+        auth_pass k@l!ve4
+    }
+    virtual_ipaddress {
+        192.168.100.11
+    }
+}
+# Virtual Servers definitions
+virtual_server 192.168.200.10 80 {
+    delay_loop 30
+    lb_algo wrr
+    lb_kind NAT
+    persistence_timeout 50
+    protocol TCP
+    sorry_server 192.168.100.100 80
+    real_server 192.168.100.2 80 {
+        weight 2
+        HTTP_GET {
+            url {
+                path /testurl/test.jsp
+                digest ec90a42b99ea9a2f5ecbe213ac9eba03
+            }
+            url {
+                path /testurl2/test.jsp
+                digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            connect_timeout 3
+            retry 3
+            delay_before_retry 2
+        }
+    }
+    real_server 192.168.100.3 80 {
+        weight 1
+        HTTP_GET {
+            url {
+                path /testurl/test.jsp
+                digest 640205b7b0fc66c1ea91c463fac6334c
+            }
+            connect_timeout 3
+            retry 3
+            delay_before_retry 2
+        }
+    }
+}
+virtual_server 192.168.200.12 443 {
+    delay_loop 20
+    lb_algo rr
+    lb_kind NAT
+    persistence_timeout 360
+    protocol TCP
+    real_server 192.168.100.2 443 {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+        }
+    }
+    real_server 192.168.100.3 443 {
+        weight 1
+        TCP_CHECK {
+            connect_timeout 3
+        }
+    }
+}
+
\ No newline at end of file diff --git a/examples/prism-kumir.html b/examples/prism-kumir.html new file mode 100644 index 0000000000..4d0af70a7f --- /dev/null +++ b/examples/prism-kumir.html @@ -0,0 +1,61 @@ +

Example

+ +
алг
+нач
+  | Решение квадратного уравнения.
+  вещ a, b, c
+  вещ таб корни[1:2]
+  цел индекс, число корней
+  вывод "Укажите первый коэффициент: "
+  ввод a
+  вывод нс, "Укажите второй коэффициент: "
+  ввод b
+  вывод нс, "Укажите свободный член: "
+  ввод c
+  решить квур(a, b, c, число корней, корни)
+  если число корней = -1
+    то
+      вывод нс, "Первый коэффициент не может быть равен нулю.", нс
+    иначе
+      если число корней = 0
+        то
+          вывод нс, "Уравнение не имеет корней.", нс
+        иначе
+          если число корней = 1
+            то
+              вывод нс, "Уравнение имеет один корень.", нс
+              вывод "x = ", корни[1], нс
+            иначе
+              вывод нс, "Уравнение имеет два корня.", нс
+              нц для индекс от 1 до число корней шаг 1
+                вывод "x", индекс, " = ", корни[индекс], нс
+              кц
+          все
+      все
+  все
+кон
+
+алг решить квур(арг вещ a, b, c, арг рез цел число корней, арг рез вещ таб корни[1:2])
+нач
+  вещ дискриминант
+  если a = 0
+    то
+      число корней := -1
+    иначе
+      дискриминант := b**2 - 4 * a * c
+      если дискриминант > 0
+        то
+          корни[1] := (-b - sqrt(дискриминант)) / (2 * a)
+          корни[2] := (-b + sqrt(дискриминант)) / (2 * a)
+          число корней := 2
+        иначе
+          если дискриминант = 0
+            то
+              корни[1] := -b / (2 * a)
+              число корней := 1
+            иначе
+              число корней := 0
+          все
+      все
+  все
+кон
diff --git a/examples/prism-kusto.html b/examples/prism-kusto.html new file mode 100644 index 0000000000..aa2fd81d60 --- /dev/null +++ b/examples/prism-kusto.html @@ -0,0 +1,8 @@ +

Full example

+
// Source: https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/tutorial?pivots=azuredataexplorer
+
+StormEvents
+| where StartTime > datetime(2007-02-01) and StartTime < datetime(2007-03-01)
+| where EventType == 'Flood' and State == 'CALIFORNIA'
+| project StartTime, EndTime , State , EventType , EpisodeNarrative
+
diff --git a/examples/prism-latte.html b/examples/prism-latte.html new file mode 100644 index 0000000000..684a693274 --- /dev/null +++ b/examples/prism-latte.html @@ -0,0 +1,16 @@ +

Full example

+
<!DOCTYPE html>
+<html>
+	<head>
+		<title>{$title|upper}</title>
+	</head>
+	<body>
+		{if count($menu) > 1}
+			<ul class="menu">
+				{foreach $menu as $item}
+				<li><a href="{$item->href}">{$item->caption}</a></li>
+				{/foreach}
+			</ul>
+		{/if}
+	</body>
+</html>
diff --git a/examples/prism-less.html b/examples/prism-less.html index db8a5e6411..56f0562177 100644 --- a/examples/prism-less.html +++ b/examples/prism-less.html @@ -48,23 +48,3 @@

Interpolation

@{property}: #0ee; background-@{property}: #999; } - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

At-rules looking like variables

-
@import "some file.less";
- -

At-rules containing interpolation

-
@import "@{themes}/tidal-wave.less";
- -

extend is not highlighted consistently

-
nav ul {
-  &:extend(.inline);
-  background: blue;
-}
-.a:extend(.b) {}
\ No newline at end of file diff --git a/examples/prism-lilypond.html b/examples/prism-lilypond.html new file mode 100644 index 0000000000..d61d94ad2d --- /dev/null +++ b/examples/prism-lilypond.html @@ -0,0 +1,60 @@ +

Full example

+
\version "2.16.0"
+\include "example-header.ily"
+
+#(ly:set-option 'point-and-click #f)
+#(set-global-staff-size 24)
+
+global = {
+    \time 4/4
+    \numericTimeSignature
+    \key c \major
+}
+
+cf = \relative c {
+  \clef bass
+  \global
+  c4 c' b a |
+  g a f d |
+  e f g g, |
+  c1
+}
+
+upper = \relative c'' {
+  \global
+  r4 s4 s2 |
+  s1*2 |
+  s2 s4 s
+  \bar "||"
+}
+
+bassFigures = \figuremode {
+  s1*2 | s4 <6> <6 4> <7> | s1
+}
+
+\markup { "Exercise 3: Write 8th notes against the given bass line." }
+
+\score {
+  \new PianoStaff <<
+    \new Staff {
+      \context Voice = "added voice" \with {
+        \consists "Balloon_engraver"
+      }
+      \upper
+    }
+
+    \new Staff = lower {
+      <<
+%      \context Voice = "cantus firmus" \with {
+%        \consists "Balloon_engraver"
+%      }
+        \context Staff = lower \cf
+        \new FiguredBass \bassFigures
+      >>
+    }
+  >>
+  \layout {}
+  %{\midi {
+    \tempo 4 = 120
+  }%}
+}
diff --git a/examples/prism-liquid.html b/examples/prism-liquid.html index 7497197558..55058a2651 100644 --- a/examples/prism-liquid.html +++ b/examples/prism-liquid.html @@ -3,7 +3,7 @@

Comments

Control Flow

-Liquid provides multiple control flow statements. +

Liquid provides multiple control flow statements.

if


@@ -18,7 +18,7 @@ 

if

unless

-The opposite of if – executes a block of code only if a certain condition is not met. +

The opposite of if – executes a block of code only if a certain condition is not met.


 {% unless product.title == 'Awesome Shoes' %}
@@ -28,7 +28,7 @@ 

unless

case

-Creates a switch statement to compare a variable with different values. case initializes the switch statement, and when compares its values. +

Creates a switch statement to compare a variable with different values. case initializes the switch statement, and when compares its values.


 {% assign handle = 'cake' %}
@@ -44,10 +44,10 @@ 

case

for

-Repeatedly executes a block of code. +

Repeatedly executes a block of code.

-break = Causes the loop to stop iterating when it encounters the break tag. -continue = Causes the loop to skip the current iteration when it encounters the continue tag. +

break = Causes the loop to stop iterating when it encounters the break tag.
+continue = Causes the loop to skip the current iteration when it encounters the continue tag.


 {% for i in (1..10) %}
diff --git a/examples/prism-llvm.html b/examples/prism-llvm.html
new file mode 100644
index 0000000000..d6b39f0f35
--- /dev/null
+++ b/examples/prism-llvm.html
@@ -0,0 +1,23 @@
+

Full Example

+

+; Declare the string constant as a global constant.
+@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00"
+
+; External declaration of the puts function
+declare i32 @puts(i8* nocapture) nounwind
+
+; Definition of main function
+define i32 @main() {   ; i32()*
+entry:
+  ; Convert [13 x i8]* to i8*...
+  %cast210 = getelementptr [13 x i8], [13 x i8]* @.str, i64 0, i64 0
+
+  ; Call puts function to write out the string to stdout.
+  call i32 @puts(i8* %cast210)
+  ret i32 0
+}
+
+; Named metadata
+!0 = !{i32 42, null, !"string"}
+!foo = !{!0}
+
diff --git a/examples/prism-log.html b/examples/prism-log.html new file mode 100644 index 0000000000..efb1d4f43d --- /dev/null +++ b/examples/prism-log.html @@ -0,0 +1,10 @@ +

Nginx example

+
/47.29.201.179 - - [28/Feb/2019:13:17:10 +0000] "GET /?p=1 HTTP/2.0" 200 5316 "https://domain1.com/?p=1" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36" "2.75"
+
Mar 19 22:10:18 xxxxxx journal: xxxxxxx.mylabserver.com nginx: photos.example.com 127.0.0.1 - - [19/Mar/2018:22:10:18 +0000] "GET / HTTP/1.1" 200 1863 "-" "curl/7.29.0" "-"
+Mar 19 22:10:24 xxxxxxx journal: xxxxxxxx.mylabserver.com nginx: photos.example.com 127.0.0.1 - - [19/Mar/2018:22:10:24 +0000] "GET / HTTP/1.1" 200 53324 "-" "curl/7.29.0" "-"
+
TLSv1.2 AES128-SHA 1.1.1.1 "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
+TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 2.2.2.2 "Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1"
+TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 3.3.3.3 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:58.0) Gecko/20100101 Firefox/58.0"
+TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 4.4.4.4 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
+TLSv1 AES128-SHA 5.5.5.5 "Mozilla/5.0 (Android 4.4.2; Tablet; rv:65.0) Gecko/65.0 Firefox/65.0"
+TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 6.6.6.6 "Mozilla/5.0 (Linux; U; Android 5.0.2; en-US; XT1068 Build/LXB22.46-28) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.10.2.1164 Mobile Safari/537.36"
diff --git a/examples/prism-lua.html b/examples/prism-lua.html index 288b7675a4..9c18b9d068 100644 --- a/examples/prism-lua.html +++ b/examples/prism-lua.html @@ -77,13 +77,3 @@

Full example

io.write(line1(i), line2(i), line3(i - 1), "\n") end end
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Functions with a single string parameter not using parentheses are not highlighted

-
foobar"param";
diff --git a/examples/prism-magma.html b/examples/prism-magma.html new file mode 100644 index 0000000000..558e819f0a --- /dev/null +++ b/examples/prism-magma.html @@ -0,0 +1,34 @@ +

Full example

+
// Source: http://magma.maths.usyd.edu.au/magma/handbook/text/115#963
+> D := Denominator;
+> N := Numerator;
+> farey := function(n)
+>    f := [ RationalField() | 0, 1/n ];
+>    p := 0;
+>    q := 1;
+>    while p/q lt 1 do
+>       p := ( D(f[#f-1]) + n) div D(f[#f]) * N(f[#f])  - N(f[#f-1]);
+>       q := ( D(f[#f-1]) + n) div D(f[#f]) * D(f[#f])  - D(f[#f-1]);
+>       Append(~f, p/q);
+>    end while;
+>    return f;
+> end function;
+> function farey(n)
+>    if n eq 1 then
+>       return [RationalField() | 0, 1 ];
+>    else
+>       f := farey(n-1);
+>       i := 0;
+>       while i lt #f-1 do
+>          i +:= 1;
+>          if D(f[i]) + D(f[i+1]) eq n then
+>             Insert( ~f, i+1, (N(f[i]) + N(f[i+1]))/(D(f[i]) + D(f[i+1])));
+>          end if;
+>       end while;
+>       return f;
+>    end if;
+> end function;
+> farey := func< n |
+>               Sort(Setseq({ a/b : a in { 0..n }, b in { 1..n } | a le b }))>;
+> farey(6);
+[ 0, 1/6, 1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5, 5/6, 1 ]
diff --git a/examples/prism-makefile.html b/examples/prism-makefile.html index 45f6f420ff..fd74713a89 100644 --- a/examples/prism-makefile.html +++ b/examples/prism-makefile.html @@ -19,7 +19,7 @@

Variables

$(objects) : defs.h -%oo: $$< $$^ $$+ $$* +%oo: $$< $$^ $$+ $$* foo : bar/lose cd $(@D) && gobble $(@F) > ../$@
@@ -260,4 +260,4 @@

Complete example

> tmp.dir/$$X ; done cd tmp.dir ; zoo aM ../tar.zoo * -rm -rf tmp.dir -
\ No newline at end of file +
diff --git a/examples/prism-markdown.html b/examples/prism-markdown.html index a57eaeafc3..ea44fea4a6 100644 --- a/examples/prism-markdown.html +++ b/examples/prism-markdown.html @@ -67,20 +67,3 @@

Raw HTML

> Containing <strong>raw HTML</strong> <p>*Italic text inside HTML tag*</p> - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nesting of elements is not fully supported

-
_ **bold** inside italic DOESN'T work _
-__ but *italic* inside bold DOES work __
-
-[Link partially *italic* DOESN'T work](http://example.com)
-_ [But link inside italic DOES work](http://example.com) _
-
-[Link partially **bold** DOESN'T work](http://example.com)
-__ [But link inside bold DOES work](http://example.com) __
\ No newline at end of file diff --git a/examples/prism-markup.html b/examples/prism-markup.html index ac00e7f637..e99c2f71b4 100644 --- a/examples/prism-markup.html +++ b/examples/prism-markup.html @@ -72,6 +72,6 @@

Multi-line attribute values

baz">

XML tags with non-ASCII characters

-
<Läufer>foo</Läufer>
-<tag läufer="läufer">bar</tag>
-<läufer:tag>baz</läufer:tag>
\ No newline at end of file +
<Läufer>foo</Läufer>
+<tag läufer="läufer">bar</tag>
+<läufer:tag>baz</läufer:tag>
diff --git a/examples/prism-matlab.html b/examples/prism-matlab.html index e78abe3612..790d71c125 100644 --- a/examples/prism-matlab.html +++ b/examples/prism-matlab.html @@ -40,7 +40,7 @@

Control flow

end n = 1; nFactorial = 1; -while nFactorial < 1e100 +while nFactorial < 1e100 n = n + 1; nFactorial = nFactorial * n; end @@ -49,4 +49,4 @@

Functions

q = integral(sqr,0,1);
 y = parabola(x)
 mygrid = @(x,y) ndgrid((-x:x/c:x),(-y:y/c:y));
-[x,y] = mygrid(pi,2*pi);
\ No newline at end of file +[x,y] = mygrid(pi,2*pi); diff --git a/examples/prism-maxscript.html b/examples/prism-maxscript.html new file mode 100644 index 0000000000..08bd94483c --- /dev/null +++ b/examples/prism-maxscript.html @@ -0,0 +1,33 @@ +

Strings

+
-- Source: https://help.autodesk.com/view/MAXDEV/2022/ENU/?guid=GUID-5E5E1A71-24E2-4605-9720-2178B941DECC
+
+plugin RenderEffect MonoChrome
+name:"MonoChrome"
+classID:#(0x9e6e9e77, 0xbe815df4)
+(
+rollout about_rollout "About..."
+(
+  label about_label "MonoChrome Filter"
+)
+on apply r_image progressCB: do
+(
+  progressCB.setTitle "MonoChrome Effect"
+  local oldEscapeEnable = escapeEnable
+  escapeEnable = false
+  bmp_w = r_image.width
+  bmp_h = r_image.height
+  for y = 0 to bmp_h-1 do
+  (
+    if progressCB.progress y (bmp_h-1) then exit
+    pixel_line = getPixels r_image [0,y] bmp_w
+    for x = 1 to bmp_w do
+    (
+      p_v = pixel_line[x].value
+      pixel_line[x] = color p_v p_v p_v pixel_line[x].alpha
+    )--end x loop
+    setPixels r_image [0,y] pixel_line
+  )--end y loop
+  escapeEnable = oldEscapeEnable
+)--end on apply
+)--end plugin
+
diff --git a/examples/prism-mel.html b/examples/prism-mel.html index e887975657..a42cf884a1 100644 --- a/examples/prism-mel.html +++ b/examples/prism-mel.html @@ -28,14 +28,14 @@

Arrays, vectors and matrices

print($array[1]); // Prints "second\n" print($array[2]); // Prints "third\n" -vector $roger = <<3.0, 7.7, 9.1>>; -vector $more = <<4.5, 6.789, 9.12356>>; +vector $roger = <<3.0, 7.7, 9.1>>; +vector $more = <<4.5, 6.789, 9.12356>>; // Assign a vector to variable $test: -vector $test = <<3.0, 7.7, 9.1>>; -$test = <<$test.x, 5.5, $test.z>> -// $test is now <<3.0, 5.5, 9.1>> +vector $test = <<3.0, 7.7, 9.1>>; +$test = <<$test.x, 5.5, $test.z>> +// $test is now <<3.0, 5.5, 9.1>> -matrix $a3[3][4] = <<2.5, 4.5, 3.25, 8.05; +matrix $a3[3][4] = <<2.5, 4.5, 3.25, 8.05; 1.12, 1.3, 9.5, 5.2; 7.23, 6.006, 2.34, 4.67>> @@ -82,7 +82,7 @@

Full example

// Check for negative $frames. This indicates // $silent mode. // - if ($frames < 0) + if ($frames < 0) { $silent = 1; $frames = -$frames; @@ -102,7 +102,7 @@

Full example

$startTime = `timerX`; // play -wait; int $i; - for ($i = 1; $i < $frames; $i++ ) + for ($i = 1; $i < $frames; $i++ ) { // Set time // @@ -110,7 +110,7 @@

Full example

int $obj; // Request count for every particle object. // - for ($obj = 0; $obj < $particleCount; $obj++) + for ($obj = 0; $obj < $particleCount; $obj++) { string $cmd = "getAttr " + $particleObjects[$obj]+".count"; eval( $cmd ); @@ -118,7 +118,7 @@

Full example

// Request position for every transform // (includes every rigid body). // - for ($obj = 0; $obj < $trCount; $obj++) + for ($obj = 0; $obj < $trCount; $obj++) { string $cmd = "getAttr " + $transforms[$obj]+".translate"; eval ($cmd); @@ -134,4 +134,4 @@

Full example

print( "Playback $rate: " + $rate + " $frames/sec\n" ); } return ( $rate ); -} // timePlayback // \ No newline at end of file +} // timePlayback // diff --git a/examples/prism-mermaid.html b/examples/prism-mermaid.html new file mode 100644 index 0000000000..c379bf27b5 --- /dev/null +++ b/examples/prism-mermaid.html @@ -0,0 +1,25 @@ +

Full example

+
%% https://github.com/mermaid-js/mermaid/blob/develop/docs/examples.md#larger-flowchart-with-some-styling
+
+graph TB
+	sq[Square shape] --> ci((Circle shape))
+
+	subgraph A
+		od>Odd shape]-- Two line<br/>edge comment --> ro
+		di{Diamond with <br/> line break} -.-> ro(Rounded<br>square<br>shape)
+		di==>ro2(Rounded square shape)
+	end
+
+	%% Notice that no text in shape are added here instead that is appended further down
+	e --> od3>Really long text with linebreak<br>in an Odd shape]
+
+	%% Comments after double percent signs
+	e((Inner / circle<br>and some odd <br>special characters)) --> f(,.?!+-*ز)
+
+	cyr[Cyrillic]-->cyr2((Circle shape Начало));
+
+	classDef green fill:#9f6,stroke:#333,stroke-width:2px;
+	classDef orange fill:#f96,stroke:#333,stroke-width:4px;
+	class sq,e green
+	class di orange
+
diff --git a/examples/prism-mizar.html b/examples/prism-mizar.html index 98d626c02f..044c5c3fe9 100644 --- a/examples/prism-mizar.html +++ b/examples/prism-mizar.html @@ -11,14 +11,14 @@

Full example

begin P: for k being Nat - st for n being Nat st n < k holds Fib (n+1) ≥ n + st for n being Nat st n < k holds Fib (n+1) ≥ n holds Fib (k+1) ≥ k proof let k be Nat; assume -IH: for n being Nat st n < k holds Fib (n+1) ≥ n; +IH: for n being Nat st n < k holds Fib (n+1) ≥ n; per cases; suppose k ≤ 1; then k = 0 or k = 0+1 by CQC_THE1:2; hence Fib (k+1) ≥ k by PRE_FF:1; - suppose 1 < k; then + suppose 1 < k; then 1+1 ≤ k by NAT_1:38; then consider m being Nat such that A: k = 1+1+m by NAT_1:28; @@ -33,8 +33,8 @@

Full example

m ≥ 1 by NAT_1:38; then B: m+(m+1) ≥ m+1+1 by REAL_1:49; C: k = m+1+1 by A, AXIOMS:13; - m < m+1 & m+1 < m+1+1 by REAL_1:69; then - m < k & m+1 < k by C, AXIOMS:22; then + m < m+1 & m+1 < m+1+1 by REAL_1:69; then + m < k & m+1 < k by C, AXIOMS:22; then D: Fib (m+1) ≥ m & Fib (m+1+1) ≥ m+1 by IH; Fib (m+1+1+1) = Fib (m+1) + Fib (m+1+1) by PRE_FF:1; then Fib (m+1+1+1) ≥ m+(m+1) by D, REAL_1:55; @@ -42,4 +42,4 @@

Full example

end; end; -for n being Nat holds Fib(n+1) ≥ n from Comp_Ind(P); \ No newline at end of file +for n being Nat holds Fib(n+1) ≥ n from Comp_Ind(P); diff --git a/examples/prism-mongodb.html b/examples/prism-mongodb.html new file mode 100644 index 0000000000..305eae5233 --- /dev/null +++ b/examples/prism-mongodb.html @@ -0,0 +1,59 @@ +

Document

+

+{
+	'_id': ObjectId('5ec72ffe00316be87cab3927'),
+	'code': Code('function () { return 22; }'),
+	'binary': BinData(1, '232sa3d323sd232a32sda3s2d3a2s1d23s21d3sa'),
+	'dbref': DBRef('namespace', ObjectId('5ec72f4200316be87cab3926'), 'db'),
+	'timestamp': Timestamp(0, 0),
+	'long': NumberLong(9223372036854775807),
+	'decimal': NumberDecimal('1000.55'),
+	'integer': 100,
+	'maxkey': MaxKey(),
+	'minkey': MinKey(),
+	'isodate': ISODate('2012-01-01T00:00:00.000Z'),
+	'regexp': RegExp('prism(js)?', 'i'),
+	'string': 'Hello World',
+	'numberArray': [1, 2, 3],
+	'stringArray': ['1','2','3'],
+	'randomKey': null,
+	'object': { 'a': 1, 'b': 2 },
+	'max_key2': MaxKey(),
+	'number': 1234,
+	'invalid-key': 123,
+	noQuotesKey: 'value',
+}
+
+ +

Query

+

+db.users.find({
+	_id: { $nin: ObjectId('5ec72ffe00316be87cab3927') },
+	age: { $gte: 18, $lte: 99 },
+	field: { $exists: true }
+})
+
+ + +

Update

+

+db.users.updateOne(
+	{
+		_id: ObjectId('5ec72ffe00316be87cab3927')
+	},
+	{
+		$set: { age: 30 },
+		$inc: { updateCount: 1 }, 
+		$push: { updateDates: new Date() } 
+	}
+)
+
+ +

Aggregate

+

+db.orders.aggregate([
+	{ $sort : { age : -1 } },
+	{ $project : { age : 1, status : 1, name : 1 } },
+	{ $limit: 5 }
+])
+
diff --git a/examples/prism-moonscript.html b/examples/prism-moonscript.html new file mode 100644 index 0000000000..f9dc2dc6a5 --- /dev/null +++ b/examples/prism-moonscript.html @@ -0,0 +1,64 @@ +

Full example

+
class List
+  new: (t) =>
+    if t then return t
+
+  append: table.insert
+  join: table.concat
+
+  map: (f,...) => List [f x,... for x in *self]
+
+  -- apply a function on a list in-place
+  apply: (f,...) =>
+    for i = 1,#@ do @[i] = f @[i],...
+    self
+
+  clone: => @slice 1
+
+  slice: (i1,i2=#@) =>
+    -- workaround for MS slice bug
+    if i2 < 0 then i2 = #@ + i2 + 1
+    List [x for x in *self[i1,i2]]
+
+  extend: (other) =>
+    i = #self + 1
+    for o in *other
+        self[i] = o
+        i += 1
+    self
+
+  partition: (pred,...) =>
+    res = {}
+    for x in *@
+        k = pred x,...
+        if not res[k] then res[k] = List!
+        res[k]\append x
+    res
+
+  lpartition: (n,npred,...) =>
+      res = List[List{} for i = 1,n]
+      for x in *@
+        k = npred x,...
+        if k >= 1 and k <= n
+            res[k]\append x
+      res
+
+  __concat: (l1,l2) ->
+        List.clone(l1)\extend l2
+
+  __tostring: =>
+    tmp = @slice(1,10)\apply tostring
+    if #@ > 10 then tmp\append '...'
+    "["..tmp\join(',').."]"
+
+-- hack to modify class so its constructor may return a new self
+patch = (klass) -> getmetatable(klass).__call = (cls,...) ->
+    self = setmetatable {}, cls.__base
+    newself = cls.__init self, ...
+    if newself
+        self = setmetatable newself, cls.__base
+    self
+
+patch List
+
+return List
diff --git a/examples/prism-n1ql.html b/examples/prism-n1ql.html new file mode 100644 index 0000000000..1f5866e0e7 --- /dev/null +++ b/examples/prism-n1ql.html @@ -0,0 +1,33 @@ +

Comments

+
# /* Multi-line
+comment */
+ +

Strings

+
"foo \"bar\" baz"
+'foo \'bar\' baz'
+"Multi-line strings
+are supported"
+'Multi-line strings
+are supported'
+ +

Parameters

+
 $1 $2 $3 
+ +

Operators

+
SELECT 1 AND 1;
+SELECT 1 OR NULL;
+SELECT EXISTS 1;
+SELECT 2 BETWEEN 1 AND 3;
+ +

Functions and keywords

+
SELECT COUNT(*) AS total, MAX(foo) AS max_foo
+FROM `my_bucket`
+WHERE `foo` IS NOT NULL;
+CREATE INDEX productName_index1 ON bucket_name(productName, ProductID)
+WHERE type="product" USING GSI
+WITH {"nodes":["node1:8091", "node2:8091", "node3:8091"]};
+ +

Identifiers

+
SELECT *
+FROM `my_bucket`;
+
\ No newline at end of file diff --git a/examples/prism-nand2tetris-hdl.html b/examples/prism-nand2tetris-hdl.html new file mode 100644 index 0000000000..318792e2b3 --- /dev/null +++ b/examples/prism-nand2tetris-hdl.html @@ -0,0 +1,23 @@ +

Comments

+
// Single line comment
+/* Multi-line
+comment */
+ +

Literal values

+
0
+32
+true
+false
+ +

Full example

+
/*
+ * Checks if two input bits are equal
+ */
+ 
+CHIP Eq {
+  IN a, b;
+  OUT out; // True iff a=b
+  PARTS:
+    Xor(a=a, b=b, out=uneq);
+    Not(in=uneq, out=out);
+}
diff --git a/examples/prism-naniscript.html b/examples/prism-naniscript.html new file mode 100644 index 0000000000..6d5397bbdc --- /dev/null +++ b/examples/prism-naniscript.html @@ -0,0 +1,72 @@ + +

Comments

+
;Text of Comment
+		;		Comment with tabs before
+
+ +

Define

+

+>DefineKey define 12 super usefull lines
+
+ +

Label

+
# Section
+#Section without whitespace
+ # Section with whitespace
+	# SectionWithTab	
+
+ +

Command

+

+@
+@ cmdWithWhiteSpaceBefore
+@cmdWithTrailingSemicolon:
+@paramlessCmd
+ @cmdWithNoParamsAndWhitespaceBefore
+		@cmdWithNoParamsAndTabBefore
+					 @cmdWithNoParamsAndTabAndSpacesBefore
+           @cmdWithNoParamsWrappedInWhitespaces             
+@cmdWithNoParamWithTrailingSpace 
+@cmdWithNoParamWithMultipleTrailingSpaces   
+@cmdWithNoParamWithTrailingTab	
+@cmdWithNoParamWithTrailingTabAndSpaces	  
+@cmdWithPositiveIntParam 1
+@cmdWithNegativeIntParam -1
+@cmdWithPositiveFloatParamAndNoFraction 1.
+@cmdWithPositiveFloatParamAndFraction 1.10
+@cmdWithPositiveHegativeFloatParamAndNoFraction -1.
+@cmdWithPositiveHegativeFloatParamAndFraction -1.10
+@cmdWithBoolParamAndPositive true
+@cmdWithBoolParamAndNegative false
+@cmdWithStringParam hello$co\:mma"d"
+@cmdWithQuotedStringNamelessParameter "hello grizzly"
+@cmdWithQuotedStringNamelessParameterWithEscapedQuotesInTheValue "hello \"grizzly\""
+@set choice="moe"
+@command hello.grizzly
+@command one,two,three
+@command 1,2,3
+@command true,false,true
+@command hi:grizzly
+@command hi:1
+@command hi:true
+@command 1 in:forest danger:true
+@char 1 pos:0.25,-0.75 look:right
+
+ +

Generic Text

+
Generic text with inlined commands[i] example[command 1 danger:true] more text here [act danger:false true:false]
+"Integer: a = {a} malesuada a + b = {a + b}", Random(a, b) = {Random(a, b)}, Random("foo", "bar", "foobar") = {Random("foo", "bar", "foobar")}
+UnclosedExpression{ab{cndum dui dolor tincidu{nt [s[fa]sdf [
+"Integer: a = {a} malesuada a + b = {a + b}", Random(a, b) = {Random(a, b)}, Random("foo", "bar", "foobar") = {Random("foo", "bar", "foobar")},}
+
+ +

Expressions

+
{}
+{ Abs(a, d) + 12 - 1 / -230.0 + "Lol ipsum" }
+Expressions inside a generic text line: Loreim ipsu,{ Abs(a, d) + 12 - 1 / -230.0 + "Lol ipsum" } doler sit amen {¯\_(ツ)_/¯}.
+@ExpressionInsteadOfNamelessParameterValue {x > 0}
+@ExpressionBlendedWithNamelessParameterValue sdf{x > 0}df
+@ExpressionsInsideNamedParameterValueWrappedInQuotes text:"{a} < {b}"
+@ExpressionsBlendedWithNamedParameterValue param:32r2f,df{x > 0},d.{Abs(0) + 12.24 > 0}ff
+@ExpressionsInsteadOfNamelessParameterAndQuotedParameter {remark} if:remark=="Saying \\"Stop { "the" } car\\" was a mistake."
+
diff --git a/examples/prism-nasm.html b/examples/prism-nasm.html index c1b7c926e3..e76146dfb7 100644 --- a/examples/prism-nasm.html +++ b/examples/prism-nasm.html @@ -57,18 +57,3 @@

Numbers

dt 3.141592653589793238462 ; pi do 1.e+4000 ; IEEE 754r quad precision - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Numbers with underscores

-
mov     ax,1100_1000b
-mov     ax,1100_1000y
-mov     ax,0b1100_1000
-mov     ax,0y1100_1000
-
-dd    1.222_222_222
\ No newline at end of file diff --git a/examples/prism-neon.html b/examples/prism-neon.html new file mode 100644 index 0000000000..831697abfe --- /dev/null +++ b/examples/prism-neon.html @@ -0,0 +1,16 @@ +

Full example

+
# my web application config
+
+php:
+	date.timezone: Europe/Prague
+	zlib.output_compression: true  # use gzip
+
+database:
+	driver: mysql
+	username: root
+	password: beruska92
+
+users:
+	- Dave
+	- Kryten
+	- Rimmer
diff --git a/examples/prism-nevod.html b/examples/prism-nevod.html new file mode 100644 index 0000000000..a9d4cf1a5f --- /dev/null +++ b/examples/prism-nevod.html @@ -0,0 +1,59 @@ +

Comment

+
/* This is
+multi-line
+comment */
+// This is single-line comment
+ +

String

+
"text in double quotes"
+'text in single quotes'
+'case-sensitive text'!
+'text ''Nevod'' in quotes'
+"text ""Nevod"" in double quotes"
+'text prefix'*
+'case-sensitive text prefix'!*
+ +

Keyword

+
@inside
+@outside
+@having
+@search
+@where
+ +

Package Import

+
@require "Common/DateTime.np"
+@require "Common/Url.np"
+ +

Namespace

+
@namespace My { }
+@namespace My.Domain { }
+ +

Pattern

+
@pattern #Percentage = Num + ?Space + {'%', 'pct.', 'pct', 'percent'};
+@pattern #GUID = Word(8) + [3 '-' + Word(4)] + '-' + Word(12);
+@pattern #HashTag = '#' + {AlphaNum, Alpha, '_'} + [0+ {Word, '_'}];
+ +

Full Example

+
@namespace Common
+{
+  @search @pattern Url(Domain, Path, Query, Anchor) =
+    Method + Domain:Url.Domain + ?Port + ?Path:Url.Path +
+    ?Query:Url.Query + ?Anchor:Url.Anchor
+  @where
+  {
+    Method = {'http', 'https' , 'ftp', 'mailto', 'file', 'data', 'irc'} + '://';
+    Domain = Word + [1+ '.' + Word + [0+ {Word, '_', '-'}]];
+    Port = ':' + Num;
+    Path = ?'/' + [0+ {Word, '/', '_', '+', '-', '%', '.'}];
+    Query = '?' + ?(Param + [0+ '&' + Param])
+    @where
+    {
+      Param = Identifier + '=' + Identifier
+      @where
+      {
+        Identifier = {Alpha, AlphaNum, '_'} + [0+ {Word, '_'}];
+      };
+    };
+    Anchor(Value) = '#' + Value:{Word};
+  };
+}
\ No newline at end of file diff --git a/examples/prism-nginx.html b/examples/prism-nginx.html index 49d14664d3..b00ffbb2aa 100644 --- a/examples/prism-nginx.html +++ b/examples/prism-nginx.html @@ -22,4 +22,5 @@

Server Block

location / { proxy_pass http://127.0.0.1:8080; } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/examples/prism-nim.html b/examples/prism-nim.html index c661125918..80296fb6ad 100644 --- a/examples/prism-nim.html +++ b/examples/prism-nim.html @@ -176,7 +176,7 @@

Full example

# Empty # OfInherit # Ident !"RootObj" - # Empty <= We want to replace this + # Empty <= We want to replace this # MethodDef # ... @@ -219,4 +219,4 @@

Full example

for a in animals: echo a.vocalize() - echo a.age_human_yrs() \ No newline at end of file + echo a.age_human_yrs() diff --git a/examples/prism-ocaml.html b/examples/prism-ocaml.html index 0534b1d165..85aa10750d 100644 --- a/examples/prism-ocaml.html +++ b/examples/prism-ocaml.html @@ -9,7 +9,8 @@

Numbers

42. 2.4E+2 10_452_102 -0xf4 0xff_10_41 +0xf4 +0xff_10_41 0o427 0b1100_1111_0000 @@ -29,7 +30,7 @@

Full example

(** [create low high] creates a new interval from [low] to [high]. If [low > high], then the interval is empty *) - let create low high = + let create ~low ~high = if Endpoint.compare low high > 0 then Empty else Interval (low,high) @@ -44,16 +45,16 @@

Full example

match t with | Empty -> false | Interval (l,h) -> - Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 + Endpoint.compare x l >= 0 && Endpoint.compare x h <= 0 (** [intersect t1 t2] returns the intersection of the two input intervals *) let intersect t1 t2 = - let min x y = if Endpoint.compare x y <= 0 then x else y in + let min x y = if Endpoint.compare x y <= 0 then x else y in let max x y = if Endpoint.compare x y >= 0 then x else y in match t1,t2 with | Empty, _ | _, Empty -> Empty | Interval (l1,h1), Interval (l2,h2) -> - create (max l1 l2) (min h1 h2) + create ~low:(max l1 l2) ~high:(min h1 h2) - end ;; \ No newline at end of file + end ;; diff --git a/examples/prism-opencl.html b/examples/prism-opencl.html index f901230bba..6bfb735703 100644 --- a/examples/prism-opencl.html +++ b/examples/prism-opencl.html @@ -1,21 +1,20 @@ -

- To use this language, use the class "language-opencl" for OpenCL kernel code. - Host code is automatically highlighted in "language-c" - respectively "language-cpp" classes. +

Note: Use the class "language-opencl" for OpenCL kernel code. + Host code is automatically highlighted with the "language-c" + or "language-cpp" class.

OpenCL host code

// OpenCL functions, constants, etc. are also highlighted in OpenCL host code in the c or cpp language
 cl::Event KernelFilterImages::runSingle(const cl::Image2D& imgSrc, SPImage2D& imgDst)
 {
-	const size_t rows = imgSrc.getImageInfo();
-	const size_t cols = imgSrc.getImageInfo();
+	const size_t rows = imgSrc.getImageInfo<CL_IMAGE_HEIGHT>();
+	const size_t cols = imgSrc.getImageInfo<CL_IMAGE_WIDTH>();
 
 	ASSERT(rows > 0 && cols > 0, "The image object seems to be invalid, no rows/cols set");
-	ASSERT(imgSrc.getImageInfo().image_channel_data_type == CL_FLOAT, "Only float type images are supported");
-	ASSERT(imgSrc.getInfo() == CL_MEM_READ_ONLY || imgSrc.getInfo() == CL_MEM_READ_WRITE, "Can't read the input image");
+	ASSERT(imgSrc.getImageInfo<CL_IMAGE_FORMAT>().image_channel_data_type == CL_FLOAT, "Only float type images are supported");
+	ASSERT(imgSrc.getInfo<CL_MEM_FLAGS>() == CL_MEM_READ_ONLY || imgSrc.getInfo<CL_MEM_FLAGS>() == CL_MEM_READ_WRITE, "Can't read the input image");
 
-	imgDst = std::make_shared(*context, CL_MEM_READ_WRITE, cl::ImageFormat(CL_R, CL_FLOAT), cols, rows);
+	imgDst = std::make_shared<cl::Image2D>(*context, CL_MEM_READ_WRITE, cl::ImageFormat(CL_R, CL_FLOAT), cols, rows);
 
 	cl::Kernel kernel(*program, "filter_single");
 	kernel.setArg(0, imgSrc);
@@ -52,11 +51,11 @@ 

OpenCL kernel code

// Image patch is row-wise accessed // Filter kernel is centred in the middle #pragma unroll - for (int y = -ROWS_HALF_3x3; y <= ROWS_HALF_3x3; ++y) // Start at the top left corner of the filter + for (int y = -ROWS_HALF_3x3; y <= ROWS_HALF_3x3; ++y) // Start at the top left corner of the filter { coordCurrent.y = coordBase.y + y; #pragma unroll - for (int x = -COLS_HALF_3x3; x <= COLS_HALF_3x3; ++x) // And end at the bottom right corner + for (int x = -COLS_HALF_3x3; x <= COLS_HALF_3x3; ++x) // And end at the bottom right corner { coordCurrent.x = coordBase.x + x; coordBorder = borderCoordinate(coordCurrent, rows, cols, border); diff --git a/examples/prism-openqasm.html b/examples/prism-openqasm.html new file mode 100644 index 0000000000..35ab2fc921 --- /dev/null +++ b/examples/prism-openqasm.html @@ -0,0 +1,43 @@ +

Full example

+
// https://github.com/Qiskit/openqasm
+/*
+ * Repeat-until-success circuit for Rz(theta),
+ * cos(theta-pi)=3/5, from Nielsen and Chuang, Chapter 4.
+ */
+OPENQASM 3;
+include "stdgates.inc";
+
+/*
+ * Applies identity if out is 01, 10, or 11 and a Z-rotation by
+ * theta + pi where cos(theta)=3/5 if out is 00.
+ * The 00 outcome occurs with probability 5/8.
+ */
+def segment qubit[2]:anc, qubit:psi -> bit[2] {
+  bit[2] b;
+  reset anc;
+  h anc;
+  ccx anc[0], anc[1], psi;
+  s psi;
+  ccx anc[0], anc[1], psi;
+  z psi;
+  h anc;
+  measure anc -> b;
+  return b;
+}
+
+qubit input;
+qubit ancilla[2];
+bit flags[2] = "11";
+bit output;
+
+reset input;
+h input;
+
+// braces are optional in this case
+while(int(flags) != 0) {
+  flags = segment ancilla, input;
+}
+rz(pi - arccos(3 / 5)) input;
+h input;
+output = measure input;  // should get zero
+
diff --git a/examples/prism-parser.html b/examples/prism-parser.html index 4b4e9c0d81..c2fc79e570 100644 --- a/examples/prism-parser.html +++ b/examples/prism-parser.html @@ -67,22 +67,4 @@

Full example

# new functionality @remove[iOffset;iLimit] $iLimit(^iLimit.int(0)) -$t[^t.select(^t.offset[]<$iOffset || ^t.offset[]>=$iOffset+$iLimit)]
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Code block starting with a comment

-
# Doesn't work
-# Does work
-
 # Does work when prefixed with a space
- -

Comments inside expressions break literals and operators

-
^if(
-    $age>=4  # not too young
-    && $age<=80  # and not too old
-)
\ No newline at end of file +$t[^t.select(^t.offset[]<$iOffset || ^t.offset[]>=$iOffset+$iLimit)] diff --git a/examples/prism-pascaligo.html b/examples/prism-pascaligo.html new file mode 100644 index 0000000000..4562c5082e --- /dev/null +++ b/examples/prism-pascaligo.html @@ -0,0 +1,63 @@ +

Comments

+
// Single line comment
+(* Multi-line
+comment *)
+ +

Strings

+
"foo \"bar\" baz";
+'foo \'bar\' baz';
+ +

Numbers

+
123
+123.456
+-123.456
+1e-23
+123.456E789
+0xaf
+0xAF
+
+ +

Functions

+
foo()
+Bar()
+_456()
+
+ +

Full Example

+

+function pop (const h : heap) : (heap * heap_element * nat) is
+	begin
+		const result : heap_element = get_top (h) ;
+		var s : nat := size(h) ;
+		const last : heap_element = get_force(s, h) ;
+		remove s from map h ;
+		h[1n] := last ;
+		s := size(h) ;
+		var i : nat := 0n ;
+		var largest : nat := 1n ;
+		var left : nat := 0n ;
+		var right : nat := 0n ;
+		var c : nat := 0n ;
+		while (largest =/= i) block {
+			c := c + 1n ;
+			i := largest ;
+			left := 2n * i ;
+			right := left + 1n ;
+			if (left <= s) then begin
+				if (heap_element_lt(get_force(left , h) , get_force(i , h))) then begin
+					largest := left ;
+					const tmp : heap_element = get_force(i , h) ;
+					h[i] := get_force(left , h) ;
+					h[left] := tmp ;
+				end else skip ;
+			end else if (right <= s) then begin
+				if (heap_element_lt(get_force(right , h) , get_force(i , h))) then begin
+					largest := right ;
+					const tmp : heap_element = get_force(i , h) ;
+					h[i] := get_force(right , h) ;
+					h[left] := tmp ;
+				end else skip ;
+			end else skip ;
+		}
+	end with (h , result , c)
+
diff --git a/examples/prism-pcaxis.html b/examples/prism-pcaxis.html new file mode 100644 index 0000000000..59ab31141d --- /dev/null +++ b/examples/prism-pcaxis.html @@ -0,0 +1,35 @@ +

Full example

+
CHARSET="ANSI";
+AXIS-VERSION="2000";
+LANGUAGE="en";
+CREATION-DATE="20170406 11:08";
+TIMEVAL("time")=TLIST(A1, "1994"-"1996");
+SUBJECT-AREA="";
+UNITS="Number";
+
+STUB="County","Sex";
+VALUES("County")="State","Carlow","Dublin","Kildare","Kilkenny","Laois","Longford","Louth","Meath","Offaly","Westmeath","Wexford",
+"Wicklow","Clare","Cork","Kerry","Limerick","Tipperary","Waterford","Galway","Leitrim","Mayo","Roscommon","Sligo","Cavan",
+"Donegal","Monaghan";
+VALUES("Sex")="Both sexes","Male","Female";
+VALUES[de]("Sex")="Beide Geschlechter","Mann","Frau";
+CODES("County")="-","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26";
+CODES("Sex")="-","1","2";
+
+DATA=
+47163 87913 70192 84531 93120 343 5911 47038 51126 47870 95976 5643 66043 38987 63125 46882
+57422 89992 11661 35817 92686 21781 37230 80669 14129 56688 81300 20184 88680 52135 17148 28192
+92218 99175 76054 79907 90207 50547 31522 4244 91079 58776 83402 54109 21254 42946 83519 31242
+10925 37377 45279 19704 96633 51732 34458 9746 91761 42687 51681 54409 61058 74227 70802 34546
+64862 12022 29896 23616 50371 89808 57186 63895 94767 76388 66475 56716 50133 6604 52853 40763
+70558 74672 58190 40909 6869 49937 9271 28067 99656 25674 69442 20608 28046 73287 60416 77515
+51639 15516 40968 95524 6694 12956 83150 77099 45687 27241 6492 94966 36856 60693 720 74671
+17309 4831 69376 67757 67499 69029 5209 50738 86947 77747 10996 9167 69176 98856 29531 5865
+27654 52277 62293 30179 85049 76961 92772 65142 16252 6768 55784 20556 26088 97219 97245 44060
+64577 91018 75157 42780 96186 62948 73288 74597 2145 16047 1671 2690 2275 45398 71478 53720
+94832 91800 10398 84830 6009 9024 53132 97850 63832 13269 45376 38564 60343 85293 9330 16810
+24898 76675 32778 26905 40945 37569 43532 38650 38316 75398 60829 91004 97946 49080 93534 78275
+20002 87183 80802 56487 12666 18416 91632 74573 70729 97984 48479 93014 10281 90382 28497 15366
+29720 25646 98513 47065 37662 94058 17383 47234 87293 37849 32087 98641 62012 12584 35492 87090
+85157 90539 31005 67590 13627 44803 46789 8026 86877 18429 8935 78118 41728 67025 69312 52172
+49224 68064 93025 1195 64873 684 90039 86065 67324 66534 1110 22354 36867 27479 76286 8539
diff --git a/examples/prism-peoplecode.html b/examples/prism-peoplecode.html new file mode 100644 index 0000000000..bcd9cd734e --- /dev/null +++ b/examples/prism-peoplecode.html @@ -0,0 +1,128 @@ +

Full example

+
/* Source: https://github.com/chrismalek/psoftToXML/blob/master/psftToXML.pcode */
+
+class psoftToXML
+	method RowsetToXML(&parentNode As XmlNode, &rowSetIn As Rowset) Returns XmlNode;
+	method RecordToXML(&parentNode As XmlNode, &recordIn As Record) Returns XmlNode;
+	method FieldToXML(&ParentNode As XmlNode, &fieldIn As Field) Returns XmlNode;
+	method RowToXML(&ParentNode As XmlNode, &rowIn As Row) Returns XmlNode;
+	method psoftToXML();
+	property array of string fieldsToSkip;
+private
+	instance string &psObjectTypeString;
+end-class;
+
+method psoftToXML
+	&psObjectTypeString = "PSOBJECTTYPE";
+	%This.fieldsToSkip = CreateArrayRept("", 0);
+end-method;
+
+method FieldToXML
+	/+ &ParentNode as XmlNode, +/
+	/+ &fieldIn as Field +/
+	/+ Returns XmlNode +/
+	Local XmlNode &outNode;
+
+	Local XmlNode &fldNode, &tempNode;
+
+	&fldNode = &ParentNode.AddElement(&fieldIn.Name);
+
+	&fldNode.AddAttribute("PSFIELDTYPE", &fieldIn.Type);
+	&fldNode.AddAttribute(%This.psObjectTypeString, "FIELD");
+
+	If &fieldIn.IsEditXlat Then
+		&fldNode.AddAttribute("LongTranslateValue", &fieldIn.LongTranslateValue);
+	End-If;
+
+	Evaluate &fieldIn.Type
+	When = "LONGCHAR"
+	When = "IMAGE"
+	When = "IMAGEREFERENCE"
+		If All(&fieldIn.Value) Then
+
+			&tempNode = &fldNode.AddCDataSection(&fieldIn.Value);
+		End-If;
+		Break;
+
+	When = "NUMBER";
+		&tempNode = &fldNode.AddText(&fieldIn.Value);
+		Break;
+	When-Other
+		If All(&fieldIn.Value) Then
+			&tempNode = &fldNode.AddText(&fieldIn.Value);
+		End-If;
+
+		Break;
+	End-Evaluate;
+
+	Return &outNode;
+end-method;
+
+
+method RecordToXML
+	/+ &parentNode as XmlNode, +/
+	/+ &recordIn as Record +/
+	/+ Returns XmlNode +/
+
+	Local XmlNode &outNode, &fieldNode;
+
+	Local integer &i;
+
+	&outNode = &parentNode.AddElement(&recordIn.Name);
+
+	&outNode.AddAttribute(%This.psObjectTypeString, "RECORD");
+
+	For &i = 1 To &recordIn.FieldCount
+
+		If %This.fieldsToSkip.Find(&recordIn.GetField(&i).Name) <= 0 Then
+			&fieldNode = %This.FieldToXML(&outNode, &recordIn.GetField(&i));
+		End-If;
+	End-For;
+
+	Return &outNode;
+end-method;
+
+
+method RowToXML
+	/+ &ParentNode as XmlNode, +/
+	/+ &rowIn as Row +/
+	/+ Returns XmlNode +/
+
+	Local XmlNode &outNode, &recNode;
+
+	Local integer &i;
+
+	&outNode = &ParentNode.AddElement("ROW");
+	&outNode.AddAttribute(&psObjectTypeString, "ROW");
+	&outNode.AddAttribute("RowNumber", String(&rowIn.RowNumber));
+
+	For &i = 1 To &rowIn.RecordCount
+		&recNode = %This.RecordToXML(&outNode, &rowIn.GetRecord(&i));
+	End-For;
+
+	Local XmlNode &rsNode;
+	For &i = 1 To &rowIn.ChildCount
+		&rsNode = %This.RowsetToXML(&outNode, &rowIn.GetRowset(&i));
+
+	End-For;
+
+	Return &outNode;
+end-method;
+
+
+method RowsetToXML
+	/+ &parentNode as XmlNode, +/
+	/+ &rowSetIn as Rowset +/
+	/+ Returns XmlNode +/
+
+	Local XmlNode &outNode, &rowNode;
+
+	Local integer &i;
+	&outNode = &parentNode.AddElement(&rowSetIn.DBRecordName);
+	&outNode.AddAttribute(&psObjectTypeString, "ROWSET");
+
+	For &i = 1 To &rowSetIn.ActiveRowCount
+		&rowNode = %This.RowToXML(&outNode, &rowSetIn.GetRow(&i));
+	End-For;
+	Return &outNode;
+end-method;
diff --git a/examples/prism-perl.html b/examples/prism-perl.html index 85c3681521..80a0874818 100644 --- a/examples/prism-perl.html +++ b/examples/prism-perl.html @@ -54,10 +54,10 @@

Full example

$conf{user} = delete $conf{username} unless $conf{user}; } else { # Process .pause manually - open my $pauserc, '<', $filename + open my $pauserc, '<', $filename or die "can't open $filename for reading: $!"; - while (<$pauserc>) { + while (<$pauserc>) { chomp; next unless $_ and $_ !~ /^\s*#/; @@ -68,4 +68,4 @@

Full example

} return \%conf; -} \ No newline at end of file +} diff --git a/examples/prism-php-extras.html b/examples/prism-php-extras.html new file mode 100644 index 0000000000..cfe1214e32 --- /dev/null +++ b/examples/prism-php-extras.html @@ -0,0 +1,14 @@ +

General

+

This adds new tokens to the PHP language to allow more customization in your theme.

+

Prism's default themes do not support the new tokens, so there will be no visible changes in the following examples.

+ +

$this

+
$this->foo = 2;
+ +

Global variables

+
$_SERVER;
+$_GET;
+$_POST;
+$argc; $argv;
+
+// and many more
diff --git a/examples/prism-php.html b/examples/prism-php.html index 1a25589c7c..23d4bae604 100644 --- a/examples/prism-php.html +++ b/examples/prism-php.html @@ -41,7 +41,7 @@

PHP 5.3+ support

function getReturnDescription() { /*2*/ } } function gen_one_to_three() { - for ($i = 1; $i <= 3; $i++) { + for ($i = 1; $i <= 3; $i++) { // Note that $i is preserved between yields. yield $i; } @@ -64,4 +64,4 @@

String interpolation

FOO; $b = <<<"FOOBAR" Interpolation inside Heredoc strings {$obj->values[3]->name} -FOOBAR; \ No newline at end of file +FOOBAR; diff --git a/examples/prism-phpdoc.html b/examples/prism-phpdoc.html new file mode 100644 index 0000000000..5b2f9075fa --- /dev/null +++ b/examples/prism-phpdoc.html @@ -0,0 +1,15 @@ +

Full example

+
<?php
+
+/** @var \DateTime[] An array of DateTime objects. */
+/** @var string[] An array of string objects. */
+/** @var callable[] An array of with callable functions or methods. */
+
+/** @var \ArrayObject|\DateTime[] */
+$dates = array()
+
+/**
+ * @param bool|\DateTime $foo the first argument
+ * @return string|null
+ */
+function bar($foo) { ... }
diff --git a/examples/prism-powerquery.html b/examples/prism-powerquery.html new file mode 100644 index 0000000000..4363c273f0 --- /dev/null +++ b/examples/prism-powerquery.html @@ -0,0 +1,74 @@ +

Comments

+
// This is a comment
+

Simple example

+

+let
+    x = 1 + 1,
+    y = 2 + 2,
+    z = y + 1
+in
+    x + y + z
+
+

Another example

+

+let Orders = Table.FromRecords({  
+    [OrderID = 1, CustomerID = 1, Item = "fishing rod", Price = 100.0],  
+    [OrderID = 2, CustomerID = 1, Item = "1 lb. worms", Price = 5.0],  
+    [OrderID = 3, CustomerID = 2, Item = "fishing net", Price = 25.0]}),  
+    #"Capitalized Each Word" = Table.TransformColumns(Orders, {"Item", Text.Proper})  
+in  
+    #"Capitalized Each Word"
+
+

Full example

+

+    let
+    Source = Sales,
+    LookupTable = #table(
+    type table
+        [
+            #"FROM"=text,
+            #"TO"=text
+        ], 
+        {
+            {"CEE","Central & Eastern Europe"},
+            {"WE","Western Europe"}  
+        }
+    ),
+
+    JT = Table.NestedJoin(
+        Source, 
+        {"Area"}, 
+        LookupTable, 
+        {"FROM"}, 
+        "Map", 
+        JoinKind.LeftOuter
+    ),
+
+    #"Expanded Map" = Table.ExpandTableColumn(
+        JT, 
+        "Map", 
+        {"TO"}, 
+        {"TO"}
+    ),
+
+    #"Replace non-matches with original value" = Table.AddColumn(
+        #"Expanded Map", 
+        "Replaced", 
+        each 
+            if [TO] = null then [Area] 
+            else [TO]
+    ),
+
+    #"Remove original column" = Table.RemoveColumns(
+        #"Replace non-matches with original value",
+        {"Area", "TO"}
+    ),
+
+    #"Renamed replace column to original name" = Table.RenameColumns(
+        #"Remove original column",
+        {{"Replaced", "Area"}}
+    )
+
+in
+    #"Renamed replace column to original name"
+
diff --git a/examples/prism-powershell.html b/examples/prism-powershell.html index e5dba2e025..7028084a78 100644 --- a/examples/prism-powershell.html +++ b/examples/prism-powershell.html @@ -1,6 +1,6 @@

Comments

# This is a comment
-<# This is a
+<# This is a
 multi-line comment #>

Variable Interpolation

@@ -16,4 +16,4 @@

Full Example

$Names | ForEach { SayHello $_ } - \ No newline at end of file + diff --git a/examples/prism-prolog.html b/examples/prism-prolog.html index b231bcae7c..a0df67e5bf 100644 --- a/examples/prism-prolog.html +++ b/examples/prism-prolog.html @@ -21,24 +21,3 @@

Example

N >= 2, N1 is N - 1, N2 is N - 2, fibo(N1, F1), fibo(N2, F2), F is F1 + F2, assert(fibo(N,F):-!). % assert as first clause - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Null-ary predicates are not highlighted

-
halt.
-trace.
-
-:- if(test1).
-section_1.
-:- elif(test2).
-section_2.
-:- elif(test3).
-section_3.
-:- else.
-section_else.
-:- endif.
diff --git a/examples/prism-promql.html b/examples/prism-promql.html new file mode 100644 index 0000000000..5570bbda63 --- /dev/null +++ b/examples/prism-promql.html @@ -0,0 +1,17 @@ +

Examples

+
# These examples are taken from: https://prometheus.io/docs/prometheus/latest/querying/examples/
+
+http_requests_total{job="apiserver", handler="/api/comments"}[5m]
+
+http_requests_total{job=~".*server"}
+
+max_over_time(deriv(rate(distance_covered_total[5s])[30s:5s])[10m:])
+
+sum by (job) (
+  rate(http_requests_total[5m])
+)
+
+sum by (app, proc) (
+  instance_memory_limit_bytes - instance_memory_usage_bytes
+) / 1024 / 1024
+
diff --git a/examples/prism-protobuf.html b/examples/prism-protobuf.html new file mode 100644 index 0000000000..7174552d71 --- /dev/null +++ b/examples/prism-protobuf.html @@ -0,0 +1,25 @@ +

Full example

+
syntax = "proto3";
+
+package foo.generated;
+option java_package = "org.foo.generated";
+option optimize_for = SPEED;
+
+// What's up with all the foo?
+message Foo {
+
+  message Bar {
+
+    optional string key   = 1;
+    optional Foo value = 2;
+    optional string value_raw = 3 [deprecated=true];
+  }
+
+  enum Level {
+    INFO  = 0;
+    WARN  = 1;
+    ERROR = 2;
+  }
+
+  repeated Property property = 1;
+}
diff --git a/examples/prism-psl.html b/examples/prism-psl.html new file mode 100644 index 0000000000..daee2b952c --- /dev/null +++ b/examples/prism-psl.html @@ -0,0 +1,43 @@ +

Strings

+
# PSL Strings are properly rendered
+print("Hello, World!");
+
+# Escaped sequences are highlighted too
+print("Goodbye \H\H\H\H\H\H\H\HHello, World!\n");
+
+# Multi-line strings are supported
+print("multi
+line");
+
+ +

Numbers

+
a = 1;
+b = 2.5;
+c = 0xff;
+
+ +

PSL Built-in Functions

+
p = nthargf(process(".*"), 1, " \t", "\n");
+lock("test");
+execute("OS", "pwd");
+
+ +

PSL Keywords

+
foreach entry (["aaa", "bbb", "ccc"]) {
+	if (grep("[bc]", entry)) {
+		last;
+	}
+}
+
+ +

PSL Constants

+
set("/CLASS/inst/paramA/state", WARN);
+if (true) {
+	PslDebug = -1;
+}
+output = execute("OS", "echo test");
+if (errno) {
+	print(ALARM." with errno=".errno."\n");
+}
+print(trim(output, "\n\r\t ", TRIM_LEADING_AND_TRAILING));
+
\ No newline at end of file diff --git a/examples/prism-pug.html b/examples/prism-pug.html index d37de5caba..ee46c8b0ec 100644 --- a/examples/prism-pug.html +++ b/examples/prism-pug.html @@ -52,7 +52,7 @@

Inline JavaScript

alert('foo'); alert('bar'); - var classes = ['foo', 'bar', 'baz'] -- for (var x = 0; x < 3; x++) +- for (var x = 0; x < 3; x++) li item diff --git a/examples/prism-puppet.html b/examples/prism-puppet.html index 4892ab8972..ff73e81fe4 100644 --- a/examples/prism-puppet.html +++ b/examples/prism-puppet.html @@ -30,7 +30,7 @@

Variables

Functions

require apache
 template('apache/vhost-default.conf.erb')
-[1,20,3].filter |$value| { $value < 10 }
+[1,20,3].filter |$value| { $value < 10 }

All-in-one example

file {'ntp.conf':
@@ -114,10 +114,10 @@ 

All-in-one example

default => 'root', } -User <| groups == 'admin' |> -Concat::Fragment <<| tag == "bacula-storage-dir-${bacula_director}" |>> +User <| groups == 'admin' |> +Concat::Fragment <<| tag == "bacula-storage-dir-${bacula_director}" |>> -Exec <| title == 'update_migrations' |> { +Exec <| title == 'update_migrations' |> { environment => 'RUBYLIB=/usr/lib/ruby/site_ruby/1.8/', } @@ -137,16 +137,3 @@

All-in-one example

target => '/etc/nagios3/conf.d/nagios_service.cfg', notify => Service[$nagios::params::nagios_service], }
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

More than one level of nested braces inside interpolation

-
"Foobar ${foo({
-    bar => {baz => 42}
-    baz => 42
-})} <- broken"
\ No newline at end of file diff --git a/examples/prism-pure.html b/examples/prism-pure.html index d7a0129b12..9bcac74185 100644 --- a/examples/prism-pure.html +++ b/examples/prism-pure.html @@ -24,7 +24,7 @@

Inline code

Inline code requires the desired language to be loaded. On this page, check C, C++ and Fortran before checking Pure should make the examples below work properly.

-
%<
+
%<
 int mygcd(int x, int y)
 {
   if (y == 0)
@@ -34,7 +34,7 @@ 

Inline code

} %> -%< -*- Fortran90 -*- +%< -*- Fortran90 -*- function fact(n) result(p) integer n, p p = 1 @@ -44,7 +44,7 @@

Inline code

end function fact %> -%< -*- C++ -*- +%< -*- C++ -*- #include <pure/runtime.h> #include <string> @@ -112,4 +112,4 @@

Example

safe (i,j) p = ~any (check (i,j)) p; check (i1,j1) (i2,j2) = i1==i2 || j1==j2 || i1+j1==i2+j2 || i1-j1==i2-j2; -end;
\ No newline at end of file +end;
diff --git a/examples/prism-purebasic.html b/examples/prism-purebasic.html new file mode 100644 index 0000000000..379f737dc6 --- /dev/null +++ b/examples/prism-purebasic.html @@ -0,0 +1,30 @@ +

Note: PureBasic Examples.

+ +

Comments

+
; This is a comment
+ +

Strings

+
"This a string."
+ +

Numbers

+
42
+3.14159
+-42
+-3.14159
+.5
+10.
+2E10
+4.2E-14
+-3E+2
+ +

PureBasic example

+
Procedure.s Test(s.s)
+	Protected a$, b$, Result.s
+
+	Result = Mid(s, 1, 3)
+
+	ProcedureReturn Result
+EndProcedure
+
+Test()
+End
diff --git a/examples/prism-purescript.html b/examples/prism-purescript.html new file mode 100644 index 0000000000..0b71ec3823 --- /dev/null +++ b/examples/prism-purescript.html @@ -0,0 +1,57 @@ +

Comments

+
-- Single line comment
+{- Multi-line
+comment -}
+ +

Strings and characters

+
'a'
+'\n'
+'\^A'
+'\^]'
+'\NUL'
+'\23'
+'\o75'
+'\xFE'
+"Here is a backslant \\ as well as \137, \
+    \a numeric escape character, and \^X, a control character."
+ +

Numbers

+
42
+123.456
+123.456e-789
+1e+3
+0o74
+0XAF
+ +

Full example

+
module Codewars.Kata.SumFracts (sumFracts) where
+
+import Prelude
+
+import Data.Foldable (foldl)
+import Data.BigInt (BigInt, fromInt, toString)
+import Data.List (List, length)
+import Data.Tuple (Tuple(..))
+import Data.Maybe (Maybe(..))
+import Data.Ord (abs, signum)
+
+reduce :: Tuple BigInt BigInt -> Tuple BigInt BigInt
+reduce (Tuple num den) =
+  let gcd' = gcd num den
+      den' = den / gcd'
+   in Tuple (num / gcd' * (signum den')) (abs den')
+   
+sumFracts :: List (Tuple Int Int) -> Maybe String
+sumFracts fracts =
+  let fracts' = fracts <#> (\(Tuple n d) -> Tuple (fromInt n) (fromInt d)) >>> reduce
+      
+      den = foldl (\acc (Tuple _ d) -> lcm acc d) one fracts'
+      num = foldl (\acc (Tuple n d) -> acc + n * (den / d)) zero fracts'
+      
+      Tuple n d = reduce $ Tuple num den
+      
+   in if length fracts == 0
+        then Nothing
+        else if d == one
+                then Just $ toString n
+                else Just $ (toString n) >< " " >< (toString d)
diff --git a/examples/prism-python.html b/examples/prism-python.html index a8c383b889..3a63e8bc40 100644 --- a/examples/prism-python.html +++ b/examples/prism-python.html @@ -48,4 +48,4 @@

Full example

return (copy[size/2 - 1] + copy[size/2]) / 2 if __name__ == '__main__': import doctest - doctest.testmod() \ No newline at end of file + doctest.testmod() diff --git a/examples/prism-q.html b/examples/prism-q.html index 58d674f478..85673d3abc 100644 --- a/examples/prism-q.html +++ b/examples/prism-q.html @@ -58,8 +58,8 @@

Dates

Verbs

99+L
-x<42|x>98
-(x<42)|x>98
+x<42|x>98
+(x<42)|x>98
 42~(4 2;(1 0))
 (4 2)~(4; 2*1)
@@ -100,13 +100,3 @@

Example

getCAs exec distinct caType from ca adjust[t;`dividend] / adjust trades for dividends only - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

The global context is highlighted as a verb

-
\d .
\ No newline at end of file diff --git a/examples/prism-qml.html b/examples/prism-qml.html new file mode 100644 index 0000000000..2069d838ed --- /dev/null +++ b/examples/prism-qml.html @@ -0,0 +1,36 @@ +

Full example

+
// https://code.qt.io/cgit/qt/qtdeclarative.git/tree/examples/qml/referenceexamples/valuesource/example.qml?h=5.14
+
+import People 1.0
+import QtQuick 2.0  // For QColor
+
+BirthdayParty {
+	HappyBirthdaySong on announcement { name: "Bob Jones" }
+
+	onPartyStarted: console.log("This party started rockin' at " + time);
+
+
+	host: Boy {
+		name: "Bob Jones"
+		shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 }
+	}
+
+	Boy {
+		name: "Leo Hodges"
+		BirthdayParty.rsvp: "2009-07-06"
+		shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 }
+	}
+	Boy {
+		name: "Jack Smith"
+		shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 }
+	}
+	Girl {
+		name: "Anne Brown"
+		BirthdayParty.rsvp: "2009-07-01"
+		shoe.size: 7
+		shoe.color: "red"
+		shoe.brand: "Marc Jacobs"
+		shoe.price: 699.99
+	}
+
+}
diff --git a/examples/prism-qsharp.html b/examples/prism-qsharp.html new file mode 100644 index 0000000000..eec88a8966 --- /dev/null +++ b/examples/prism-qsharp.html @@ -0,0 +1,33 @@ +

Full example

+
namespace Bell {
+  open Microsoft.Quantum.Canon;
+  open Microsoft.Quantum.Intrinsic;
+
+  operation SetQubitState(desired : Result, target : Qubit) : Unit {
+      if desired != M(target) {
+          X(target);
+      }
+  }
+
+  @EntryPoint()
+  operation TestBellState(count : Int, initial : Result) : (Int, Int) {
+
+      mutable numOnes = 0;
+      use qubit = Qubit();
+      for test in 1..count {
+          SetQubitState(initial, qubit);
+          let res = M(qubit);        
+
+          // Count the number of ones we saw:
+          if res == One {
+                set numOnes += 1;
+          }
+      }
+
+      SetQubitState(Zero, qubit); 
+
+  // Return number of times we saw a |0> and number of times we saw a |1>
+  Message("Test results (# of 0s, # of 1s): ");
+  return (count - numOnes, numOnes);
+  }
+}
diff --git a/examples/prism-racket.html b/examples/prism-racket.html new file mode 100644 index 0000000000..d09509f43f --- /dev/null +++ b/examples/prism-racket.html @@ -0,0 +1,16 @@ +

Full example

+
; Source: https://github.com/mbutterick/pollen/blob/master/pollen/private/to-string.rkt
+
+#lang racket/base
+(provide (all-defined-out))
+
+(define (to-string x)
+  (cond
+    [(string? x) x]
+    [(or (null? x) (void? x)) ""]
+    [(or (symbol? x) (number? x) (path? x) (char? x)) (format "~a" x)]
+    ;; special handling for procedures, because if a procedure reaches this func,
+    ;; it usually indicates a failed attempt to use a tag function.
+    ;; meaning, it's more useful to raise an error.
+    [(procedure? x) (error 'pollen "Can't convert procedure ~a to string" x)]
+    [else (format "~v" x)]))
diff --git a/examples/prism-regex.html b/examples/prism-regex.html new file mode 100644 index 0000000000..41a59c1f76 --- /dev/null +++ b/examples/prism-regex.html @@ -0,0 +1,46 @@ +

The regex languages con be used for inline regex snippets like (?<number>\d+)[-_ ]\k<number> but it mainly adds itself to other languages such as:

+ +

JavaScript

+
Prism.languages.markup = {
+	'comment': /<!--[\s\S]*?-->/,
+	'prolog': /<\?[\s\S]+?\?>/,
+	'doctype': {
+		pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
+		greedy: true
+	},
+	'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
+	'tag': {
+		pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,
+		greedy: true,
+		inside: {
+			'tag': {
+				pattern: /^<\/?[^\s>\/]+/i,
+				inside: {
+					'punctuation': /^<\/?/,
+					'namespace': /^[^\s>\/:]+:/
+				}
+			},
+			'attr-value': {
+				pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,
+				inside: {
+					'punctuation': [
+						/^=/,
+						{
+							pattern: /^(\s*)["']|["']$/,
+							lookbehind: true
+						}
+					]
+				}
+			},
+			'punctuation': /\/?>/,
+			'attr-name': {
+				pattern: /[^\s>\/]+/,
+				inside: {
+					'namespace': /^[^\s>\/:]+:/
+				}
+			}
+
+		}
+	},
+	'entity': /&#?[\da-z]{1,8};/i
+};
diff --git a/examples/prism-rego.html b/examples/prism-rego.html new file mode 100644 index 0000000000..d8050a366e --- /dev/null +++ b/examples/prism-rego.html @@ -0,0 +1,44 @@ +

Full example

+
# Role-based Access Control (RBAC)
+
+# By default, deny requests.
+default allow = false
+
+# Allow admins to do anything.
+allow {
+	user_is_admin
+}
+
+# Allow the action if the user is granted permission to perform the action.
+allow {
+	# Find grants for the user.
+	some grant
+	user_is_granted[grant]
+
+	# Check if the grant permits the action.
+	input.action == grant.action
+	input.type == grant.type
+}
+
+# user_is_admin is true if...
+user_is_admin {
+
+	# for some `i`...
+	some i
+
+	# "admin" is the `i`-th element in the user->role mappings for the identified user.
+	data.user_roles[input.user][i] == "admin"
+}
+
+# user_is_granted is a set of grants for the user identified in the request.
+# The `grant` will be contained if the set `user_is_granted` for every...
+user_is_granted[grant] {
+	some i, j
+
+	# `role` assigned an element of the user_roles for this user...
+	role := data.user_roles[input.user][i]
+
+	# `grant` assigned a single grant from the grants list for 'role'...
+	grant := data.role_grants[role][j]
+}
+
diff --git a/examples/prism-renpy.html b/examples/prism-renpy.html index dffac07c4b..746d215b32 100644 --- a/examples/prism-renpy.html +++ b/examples/prism-renpy.html @@ -1,21 +1,16 @@

Comments

-
-    # This is a comment
-
+
# This is a comment

Strings

-
-    "foo \"bar\" baz"
+
"foo \"bar\" baz"
 'foo \'bar\' baz'
 """ "Multi-line" strings
 are supported."""
 ''' 'Multi-line' strings
-are supported.'''
-
+are supported.'''

Python

-
-    class Dog:
+
class Dog:
 
     tricks = []             # mistaken use of a class variable
 
@@ -23,19 +18,15 @@ 

Python

self.name = name def add_trick(self, trick): - self.tricks.append(trick)
-
+ self.tricks.append(trick)

Properties

-
-    style my_text is text:
+
style my_text is text:
     size 40
-    font "gentium.ttf"
-
+ font "gentium.ttf"

Configuration

-
-    init -1:
+
init -1:
     python hide:
 
         ## Should we enable the use of developer tools? This should be
@@ -52,8 +43,7 @@ 

Configuration

## This controls the title of the window, when Ren'Py is ## running in a window. - config.window_title = u"The Question"
-
+ config.window_title = u"The Question"

Full example

@@ -120,4 +110,4 @@

Full example

"... to ask her later.": - jump later \ No newline at end of file + jump later diff --git a/examples/prism-rest.html b/examples/prism-rest.html index 511e87c9e1..a7288a38b8 100644 --- a/examples/prism-rest.html +++ b/examples/prism-rest.html @@ -308,22 +308,3 @@

Inline markup

See the `Python home page <http://www.python.org>`_ for info. Oh yes, the _`Norwegian Blue`. What's, um, what's wrong with it? - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nothing is highlighted inside table cells

-
+---------------+----------+
-| column 1     | column 2  |
-+--------------+-----------+
-| **bold**?    | *italic*? |
-+--------------+-----------+
- -

The inline markup recognition rules are not as strict as they are in the spec

-

No inline markup should be highlighted in the following code.

-
2 * x a ** b (* BOM32_* ` `` _ __ |
-"*" '|' (*) [*] {*} <*> ‘*’ ‚*‘ ‘*‚ ’*’ ‚*’ “*” „*“ “*„ ”*” „*” »*« ›*‹ «*» »*» ›*›
\ No newline at end of file diff --git a/examples/prism-robotframework.html b/examples/prism-robotframework.html new file mode 100644 index 0000000000..8ddd56c120 --- /dev/null +++ b/examples/prism-robotframework.html @@ -0,0 +1,21 @@ +

Full example

+
*** Settings ***
+Documentation    Example using the space separated plain text format.
+Library          OperatingSystem
+
+*** Variables ***
+${MESSAGE}       Hello, world!
+
+*** Test Cases ***
+My Test
+    [Documentation]    Example test
+    Log    ${MESSAGE}
+    My Keyword    /tmp
+
+Another Test
+    Should Be Equal    ${MESSAGE}    Hello, world!
+
+*** Keywords ***
+My Keyword
+    [Arguments]    ${path}
+    Directory Should Exist    ${path}
diff --git a/examples/prism-ruby.html b/examples/prism-ruby.html index 4f1e3906f7..58d43cd1ea 100644 --- a/examples/prism-ruby.html +++ b/examples/prism-ruby.html @@ -7,7 +7,10 @@

Comments

Strings

"foo \"bar\" baz"
-'foo \'bar\' baz'
+'foo \'bar\' baz' +<<STRING + here's some #{string} contents +STRING

Regular expressions

/foo?[ ]*bar/
diff --git a/examples/prism-rust.html b/examples/prism-rust.html index d447968423..e7b2d1ae44 100644 --- a/examples/prism-rust.html +++ b/examples/prism-rust.html @@ -5,7 +5,7 @@

Comments

comment */

Strings

-
'C'; '\''; '\n'; '\u7FFF'; // Characters
+
'C'; '\''; '\n'; '\u{7FFF}'; // Characters
 "foo \"bar\" baz"; // String
 r##"foo #"bar"# baz"##; // Raw string with # pairs
 b'C'; b'\''; b'\n'; // Bytes
@@ -14,10 +14,7 @@ 

Strings

Numbers

-
123i;                              // type int
-123u;                              // type uint
-123_u;                             // type uint
-0xff_u8;                           // type u8
+
0xff_u8;                           // type u8
 0o70_i16;                          // type i16
 0b1111_1111_1001_0000_i32;         // type i32
 
@@ -32,9 +29,9 @@ 

Booleans

Functions and macros

println!("x is {}", x);
-fn next_two(x: int) -> (int, int) { (x + 1i, x + 2i) }
-next_two(5i);
-vec![1i, 2, 3];
+fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }
+next_two(5);
+vec![1, 2, 3];
 

Attributes

@@ -47,22 +44,6 @@

Attributes

Closure parameters and bitwise OR

let x = a | b;
 let y = c || d;
-let add_one = |x: int| -> int { 1i + x };
+let add_one = |x: i32| -> i32 { 1i + x };
 let printer = || { println!("x is: {}", x); };
 
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nested block comments

-
/* Nested block
-	/* comments
-	are */
-not supported */
- -

Delimiters of parameters for closures that don't use braces

-
|x| x + 1i;
\ No newline at end of file diff --git a/examples/prism-sas.html b/examples/prism-sas.html index 8932ebb036..da2a8b52b8 100644 --- a/examples/prism-sas.html +++ b/examples/prism-sas.html @@ -6,7 +6,7 @@

Comments

Numbers, dates and times

42; 4.5; 4.5e-10; -3; -3.5e2; -4.2e-23;
-0afx; 0123x; abcdefx;
+0afx; 0123x;
 '1jan2013'd; '01jan09'd;
 '9:25't; '9:25:19pm't;
 '01may12:9:30:00'dt; '18jan2003:9:27:05am'dt;
@@ -23,7 +23,7 @@ 

Operators

A**B;
 'foo'||'bar'!!'baz'¦¦'test';
 A<>B><C;
-A~=B¬=C^=D>=E<=F;
+A~=B¬=C^=D>=E<=F;
 a*b/c+d-e<f>g&h|i!j¦k;
 ~a;¬b;^c;
 (a eq b) ne (c gt d) lt e ge f le h;
@@ -31,7 +31,8 @@ 

Operators

not a;

More examples

-
/* Some examples adapted from the documentation (http://support.sas.com/documentation/cdl/en/basess/64003/PDF/default/basess.pdf) */
+
/* Some examples adapted from the documentation
+   http://support.sas.com/documentation/cdl/en/basess/64003/PDF/default/basess.pdf */
 
 data city; * another inline comment;
 
@@ -155,4 +156,4 @@ 

More examples

JD03 switch 383 09jan2013 13.99 BV1E timer 26 03aug2013 34.50 ; -run;
\ No newline at end of file +run;
diff --git a/examples/prism-sass.html b/examples/prism-sass.html index 7200e789cc..a2f0673a2b 100644 --- a/examples/prism-sass.html +++ b/examples/prism-sass.html @@ -26,22 +26,3 @@

Variables

#main width: $width
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Deprecated Sass syntax is not supported

-
.page
-  color = 5px + 9px
-
-!width = 13px
-.icon
-  width = !width
- -

Selectors with pseudo classes are highlighted as property/value pairs

-
a:hover
-  text-decoration: underline
\ No newline at end of file diff --git a/examples/prism-scala.html b/examples/prism-scala.html index 1dc56f8714..b9ed1f1b65 100644 --- a/examples/prism-scala.html +++ b/examples/prism-scala.html @@ -85,16 +85,3 @@

Full example

println("sl2 = " + sl2) } }
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nested block comments

-
/* Nested block
-	/* comments
-	are */
-not supported */
\ No newline at end of file diff --git a/examples/prism-shell-session.html b/examples/prism-shell-session.html new file mode 100644 index 0000000000..07c9ce4c3d --- /dev/null +++ b/examples/prism-shell-session.html @@ -0,0 +1,18 @@ +

Full example

+
$ git checkout master
+Switched to branch 'master'
+Your branch is up-to-date with 'origin/master'.
+$ git push
+Everything up-to-date
+$ echo "Foo
+> Bar"
+Foo
+Bar
+ +

bash and sh console sessions are fully supported.

+ +
foo@bar:/$ cd ~
+foo@bar:~$ sudo -i
+[sudo] password for foo:
+root@bar:~# echo "hello!"
+hello!
diff --git a/examples/prism-smali.html b/examples/prism-smali.html new file mode 100644 index 0000000000..61c07c1893 --- /dev/null +++ b/examples/prism-smali.html @@ -0,0 +1,30 @@ +

Full example

+
# Source: https://github.com/JesusFreke/smali/blob/master/examples/HelloWorld/HelloWorld.smali
+
+.class public LHelloWorld;
+
+#Ye olde hello world application
+#To assemble and run this on a phone or emulator:
+#
+#java -jar smali.jar -o classes.dex HelloWorld.smali
+#zip HelloWorld.zip classes.dex
+#adb push HelloWorld.zip /data/local
+#adb shell dalvikvm -cp /data/local/HelloWorld.zip HelloWorld
+#
+#if you get out of memory type errors when running smali.jar, try
+#java -Xmx512m -jar smali.jar HelloWorld.smali
+#instead
+
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+    .registers 2
+
+    sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+    const-string v1, "Hello World!"
+
+    invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
+
+    return-void
+.end method
diff --git a/examples/prism-smarty.html b/examples/prism-smarty.html index 5e57922fa4..650e6fc1d4 100644 --- a/examples/prism-smarty.html +++ b/examples/prism-smarty.html @@ -69,13 +69,3 @@

Literal section

} {/literal} </style>
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Smarty tag in the middle of an HTML tag

-
<div{if $test} class="test"{/if}></div>
\ No newline at end of file diff --git a/examples/prism-sml.html b/examples/prism-sml.html new file mode 100644 index 0000000000..d5030eb815 --- /dev/null +++ b/examples/prism-sml.html @@ -0,0 +1,43 @@ +

Full example

+
(* source: https://github.com/HarrisonGrodin/ml-numbers/blob/ba35c763092052e391871edf224f17474c6231b1/src/Rational.sml *)
+
+structure Rational :> RATIONAL =
+  struct
+    type t = int * int  (* (a,b) invariant: a,b coprime; b nonnegative *)
+
+    local
+      val rec gcd = fn
+        (m,0) => m
+      | (m,n) => gcd (n, m mod n)
+    in
+      infix 8 //
+      val op // = fn (x,y) => (
+        let
+          val gcd = gcd (x,y)
+        in
+          (x div gcd, y div gcd)
+        end
+      )
+    end
+
+    val show = Fn.id
+
+    val zero = (0,1)
+    val one  = (1,1)
+
+    val eq : t * t -> bool = (op =)
+    val compare = fn ((a,b),(x,y)) => Int.compare (a * y, b * x)
+    val toString = fn (x,y) => Int.toString x ^ " // " ^ Int.toString y
+    val percent =
+      Fn.curry (Fn.flip (op ^)) "%"
+      o Int.toString
+      o (fn (a,b) => (100 * a) div b)
+
+    val op + = fn ((a,b),(x,y)) => (a * y + b * x) // (b * y)
+    val ~ = fn (a,b) => (~a,b)
+    val op - = fn (r1,r2) => r1 + ~r2
+
+    val op * = fn ((a,b),(x,y)) => (a * x) // (b * y)
+    val inv = Fn.flip (op //)
+    val op / = fn (r1,r2) => r1 * inv r2
+  end
diff --git a/examples/prism-solidity.html b/examples/prism-solidity.html new file mode 100644 index 0000000000..f66afca109 --- /dev/null +++ b/examples/prism-solidity.html @@ -0,0 +1,151 @@ +

Full example

+
pragma solidity >=0.4.22 <0.7.0;
+
+/// @title Voting with delegation.
+contract Ballot {
+	// This declares a new complex type which will
+	// be used for variables later.
+	// It will represent a single voter.
+	struct Voter {
+		uint weight; // weight is accumulated by delegation
+		bool voted;  // if true, that person already voted
+		address delegate; // person delegated to
+		uint vote;   // index of the voted proposal
+	}
+
+	// This is a type for a single proposal.
+	struct Proposal {
+		bytes32 name;   // short name (up to 32 bytes)
+		uint voteCount; // number of accumulated votes
+	}
+
+	address public chairperson;
+
+	// This declares a state variable that
+	// stores a `Voter` struct for each possible address.
+	mapping(address => Voter) public voters;
+
+	// A dynamically-sized array of `Proposal` structs.
+	Proposal[] public proposals;
+
+	/// Create a new ballot to choose one of `proposalNames`.
+	constructor(bytes32[] memory proposalNames) public {
+		chairperson = msg.sender;
+		voters[chairperson].weight = 1;
+
+		// For each of the provided proposal names,
+		// create a new proposal object and add it
+		// to the end of the array.
+		for (uint i = 0; i < proposalNames.length; i++) {
+			// `Proposal({...})` creates a temporary
+			// Proposal object and `proposals.push(...)`
+			// appends it to the end of `proposals`.
+			proposals.push(Proposal({
+					name: proposalNames[i],
+					voteCount: 0
+			}));
+		}
+	}
+
+	// Give `voter` the right to vote on this ballot.
+	// May only be called by `chairperson`.
+	function giveRightToVote(address voter) public {
+		// If the first argument of `require` evaluates
+		// to `false`, execution terminates and all
+		// changes to the state and to Ether balances
+		// are reverted.
+		// This used to consume all gas in old EVM versions, but
+		// not anymore.
+		// It is often a good idea to use `require` to check if
+		// functions are called correctly.
+		// As a second argument, you can also provide an
+		// explanation about what went wrong.
+		require(
+			msg.sender == chairperson,
+			"Only chairperson can give right to vote."
+		);
+		require(
+			!voters[voter].voted,
+			"The voter already voted."
+		);
+		require(voters[voter].weight == 0);
+		voters[voter].weight = 1;
+	}
+
+	/// Delegate your vote to the voter `to`.
+	function delegate(address to) public {
+		// assigns reference
+		Voter storage sender = voters[msg.sender];
+		require(!sender.voted, "You already voted.");
+
+		require(to != msg.sender, "Self-delegation is disallowed.");
+
+		// Forward the delegation as long as
+		// `to` also delegated.
+		// In general, such loops are very dangerous,
+		// because if they run too long, they might
+		// need more gas than is available in a block.
+		// In this case, the delegation will not be executed,
+		// but in other situations, such loops might
+		// cause a contract to get "stuck" completely.
+		while (voters[to].delegate != address(0)) {
+			to = voters[to].delegate;
+
+			// We found a loop in the delegation, not allowed.
+			require(to != msg.sender, "Found loop in delegation.");
+		}
+
+		// Since `sender` is a reference, this
+		// modifies `voters[msg.sender].voted`
+		sender.voted = true;
+		sender.delegate = to;
+		Voter storage delegate_ = voters[to];
+		if (delegate_.voted) {
+			// If the delegate already voted,
+			// directly add to the number of votes
+			proposals[delegate_.vote].voteCount += sender.weight;
+		} else {
+			// If the delegate did not vote yet,
+			// add to her weight.
+			delegate_.weight += sender.weight;
+		}
+	}
+
+	/// Give your vote (including votes delegated to you)
+	/// to proposal `proposals[proposal].name`.
+	function vote(uint proposal) public {
+		Voter storage sender = voters[msg.sender];
+		require(sender.weight != 0, "Has no right to vote");
+		require(!sender.voted, "Already voted.");
+		sender.voted = true;
+		sender.vote = proposal;
+
+		// If `proposal` is out of the range of the array,
+		// this will throw automatically and revert all
+		// changes.
+		proposals[proposal].voteCount += sender.weight;
+	}
+
+	/// @dev Computes the winning proposal taking all
+	/// previous votes into account.
+	function winningProposal() public view
+			returns (uint winningProposal_)
+	{
+		uint winningVoteCount = 0;
+		for (uint p = 0; p < proposals.length; p++) {
+			if (proposals[p].voteCount > winningVoteCount) {
+				winningVoteCount = proposals[p].voteCount;
+				winningProposal_ = p;
+			}
+		}
+	}
+
+	// Calls winningProposal() function to get the index
+	// of the winner contained in the proposals array and then
+	// returns the name of the winner
+	function winnerName() public view
+			returns (bytes32 winnerName_)
+	{
+		winnerName_ = proposals[winningProposal()].name;
+	}
+}
diff --git a/examples/prism-solution-file.html b/examples/prism-solution-file.html new file mode 100644 index 0000000000..06de0aa8e7 --- /dev/null +++ b/examples/prism-solution-file.html @@ -0,0 +1,28 @@ +

Full example

+
# https://docs.microsoft.com/en-us/visualstudio/extensibility/internals/solution-dot-sln-file?view=vs-2015&redirectedfrom=MSDN
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29709.97
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Project1", "Project1.vbproj", "{8CDD8387-B905-44A8-B5D5-07BB50E05BEA}"
+EndProject
+Global
+	GlobalSection(SolutionNotes) = postSolution
+	EndGlobalSection
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Debug
+		ConfigName.1 = Release
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Debug.ActiveCfg = Debug|x86
+		{8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Debug.Build.0 = Debug|x86
+		{8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Release.ActiveCfg = Release|x86
+		{8CDD8387-B905-44A8-B5D5-07BB50E05BEA}.Release.Build.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
diff --git a/examples/prism-soy.html b/examples/prism-soy.html index 648b8e5f91..9b43ceb75b 100644 --- a/examples/prism-soy.html +++ b/examples/prism-soy.html @@ -11,7 +11,7 @@

Variable

Commands

{template .helloNames}
   // Greet the person.
-  {call .helloName data="all" /}
+ {call .helloName data="all" /}<br> // Greet the additional people. {foreach $additionalName in $additionalNames} {call .helloName} @@ -33,4 +33,4 @@

Functions and print directives

Literal section

{literal}
 This is not a {$variable}
-{/literal}
\ No newline at end of file +{/literal}
diff --git a/examples/prism-sparql.html b/examples/prism-sparql.html new file mode 100644 index 0000000000..f416c8598c --- /dev/null +++ b/examples/prism-sparql.html @@ -0,0 +1,304 @@ +

Introduction

+ +

The queries shown here can be found in the SPARQL specifications: +https://www.w3.org/TR/sparql11-query/

+ +

query 2.1.6 Examples of Query Syntax

+ +
PREFIX  dc: <http://purl.org/dc/elements/1.1/>
+	SELECT  ?title
+	WHERE   { <http://example.org/book/book1> dc:title ?title }
+
+ +

query 2.1.6-q1 Examples of Query Syntax

+ +
PREFIX  dc: <http://purl.org/dc/elements/1.1/>
+PREFIX  : <http://example.org/book/>
+SELECT  $title
+WHERE   { :book1  dc:title  $title }
+
+ +

query 2.1.6-q2 Examples of Query Syntax

+ +
BASE    <http://example.org/book/>
+PREFIX  dc: <http://purl.org/dc/elements/1.1/>
+SELECT  $title
+WHERE   { <book1>  dc:title  ?title }
+
+ +

query 2.5.3 Example of Basic Graph Pattern Matching

+ +
PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
+SELECT ?mbox
+WHERE
+	{ ?x foaf:name "Johnny Lee Outlaw" .
+		?x foaf:mbox ?mbox }
+
+ +

query 3.1.1 Matching Integers

+ +
SELECT ?v WHERE { ?v ?p 42 }
+ +

query 3.1.2 Matching Arbitrary Datatypes

+ +
SELECT ?v WHERE { ?v ?p "abc"^^<http://example.org/datatype#specialDatatype> }
+ +

query 3.1.3-q1 Matching Language Tags

+ +
SELECT ?x WHERE { ?x ?p "cat"@en }
+ +

query 3.2 Value Constraints

+ +
PREFIX  dc:  <http://purl.org/dc/elements/1.1/>
+PREFIX  ns:  <http://example.org/ns#>
+SELECT  ?title ?price
+WHERE   { ?x ns:price ?price .
+					FILTER (?price < 30) .
+					?x dc:title ?title . }
+
+ +

query 5.5 Nested Optional Graph Patterns

+ +
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
+SELECT ?foafName ?mbox ?gname ?fname
+WHERE
+	{  ?x foaf:name ?foafName .
+		 OPTIONAL { ?x foaf:mbox ?mbox } .
+		 OPTIONAL {  ?x vcard:N ?vc .
+								 ?vc vcard:Given ?gname .
+								 OPTIONAL { ?vc vcard:Family ?fname }
+							}
+	}
+
+ +

query 6.1-q2 Joining Patterns with UNION

+ +
PREFIX dc10:  <http://purl.org/dc/elements/1.1/>
+PREFIX dc11:  <http://purl.org/dc/elements/1.0/>
+
+SELECT ?title ?author
+WHERE  { { ?book dc10:title ?title .  ?book dc10:creator ?author }
+				 UNION
+				 { ?book dc11:title ?title .  ?book dc11:creator ?author }
+			 }
+
+
+ +

query 8.3 Restricting by Bound Variables

+ +
PREFIX  data:  <http://example.org/foaf/>
+PREFIX  foaf:  <http://xmlns.com/foaf/0.1/>
+PREFIX  rdfs:  <http://www.w3.org/2000/01/rdf-schema#>
+
+SELECT ?mbox ?nick ?ppd
+WHERE
+{
+	GRAPH data:aliceFoaf
+	{
+		?alice foaf:mbox <mailto:alice@work.example> ;
+					 foaf:knows ?whom .
+		?whom  foaf:mbox ?mbox ;
+					 rdfs:seeAlso ?ppd .
+		?ppd  a foaf:PersonalProfileDocument .
+	} .
+	GRAPH ?ppd
+	{
+			?w foaf:mbox ?mbox ;
+				 foaf:nick ?nick
+	}
+}
+
+ +

query 9.3 Combining FROM and FROM NAMED

+ +
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc: <http://purl.org/dc/elements/1.1/>
+
+SELECT ?who ?g ?mbox
+FROM <http://example.org/dft.ttl>
+FROM NAMED <http://example.org/alice>
+FROM NAMED <http://example.org/bob>
+WHERE
+{
+	 ?g dc:publisher ?who .
+	 GRAPH ?g { ?x foaf:mbox ?mbox }
+}
+
+ +

query 10.1.2 DISTINCT

+ +

+	PREFIX foaf:    <http://xmlns.com/foaf/0.1//>
+SELECT DISTINCT ?name WHERE { ?x foaf:name ?name }
+
+ +

query 10.1.3-q2 ORDER BY

+ +
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
+
+SELECT ?name
+WHERE { ?x foaf:name ?name ; :empId ?emp }
+ORDER BY ?name DESC(?emp)
+
+ +

query 10.1.5 OFFSET

+ +
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
+
+SELECT  ?name
+WHERE   { ?x foaf:name ?name }
+ORDER BY ?name
+LIMIT   5
+OFFSET  10
+
+ +

query 10.3.1 Templates with Blank Nodes

+ +
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
+PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#>
+
+CONSTRUCT { ?x  vcard:N _:v .
+						_:v vcard:givenName ?gname .
+						_:v vcard:familyName ?fname }
+WHERE
+ {
+		{ ?x foaf:firstname ?gname } UNION  { ?x foaf:givenname   ?gname } .
+		{ ?x foaf:surname   ?fname } UNION  { ?x foaf:family_name ?fname } .
+ }
+
+ +

query 10.3.3 Solution Modifiers and CONSTRUCT

+ +
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX site: <http://example.org/stats#>
+
+CONSTRUCT { [] foaf:name ?name }
+WHERE
+{ [] foaf:name ?name ;
+		 site:hits ?hits .
+}
+ORDER BY desc(?hits)
+LIMIT 2
+ +

query 10.4.3 Descriptions of Resources

+ +
PREFIX ent:  <http://org.example.com/employees#>
+DESCRIBE ?x WHERE { ?x ent:employeeId "1234" }
+
+ +

query 10.5-q1 Asking "yes or no" questions

+ +
PREFIX foaf:    <http://xmlns.com/foaf/0.1/>
+ASK  { ?x foaf:name  "Alice" ;
+					foaf:mbox  <mailto:alice@work.example> }
+
+ +

query 11.4.1 bound

+ +
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+PREFIX dc:   <http://purl.org/dc/elements/1.1/>
+PREFIX xsd:   <http://www.w3.org/2001/XMLSchema#>
+SELECT ?name
+ WHERE { ?x foaf:givenName  ?givenName .
+				 OPTIONAL { ?x dc:date ?date } .
+				 FILTER ( bound(?date) ) }
+ +

query 11.4.3 isBlank

+ +

+PREFIX a:      <http://www.w3.org/2000/10/annotation-ns#>
+PREFIX dc:     <http://purl.org/dc/elements/1.1/>
+PREFIX foaf:   <http://xmlns.com/foaf/0.1/>
+
+SELECT ?given ?family
+WHERE { ?annot  a:annotates  <http://www.w3.org/TR/rdf-sparql-query/> .
+?annot  dc:creator   ?c .
+OPTIONAL { ?c  foaf:given   ?given ; foaf:family  ?family } .
+FILTER isBlank(?c)
+}
+ +

query 11.4.5 str

+ +

+	PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+	SELECT ?name ?mbox
+	 WHERE { ?x foaf:name  ?name ;
+							foaf:mbox  ?mbox .
+FILTER regex(str(?mbox), "@work.example") }
+
+ +

query 11.4.7 datatype

+ +

+	PREFIX foaf: <http://xmlns.com/foaf/0.1/>
+	PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>
+	PREFIX eg:   <http://biometrics.example/ns#>
+	SELECT ?name ?shoeSize
+	 WHERE { ?x foaf:name  ?name ; eg:shoeSize  ?shoeSize .
+					 FILTER ( datatype(?shoeSize) = xsd:integer ) }
+
+ +

query 11.4.10-q1 RDFterm-equal

+ +

+	PREFIX a:      <http://www.w3.org/2000/10/annotation-ns#>
+	PREFIX dc:     <http://purl.org/dc/elements/1.1/>
+	PREFIX xsd:    <http://www.w3.org/2001/XMLSchema#>
+
+	SELECT ?annotates
+	WHERE { ?annot  a:annotates  ?annotates .
+					?annot  dc:date      ?date .
+					FILTER ( ?date = xsd:dateTime("2004-01-01T00:00:00Z") || ?date = xsd:dateTime("2005-01-01T00:00:00Z") ) }
+
+ +

query 11.6-q1 Extensible Value Testing

+ +

+	PREFIX aGeo: <http://example.org/geo#>
+
+	SELECT ?neighbor
+	WHERE { ?a aGeo:placeName "Grenoble" .
+					?a aGeo:location ?axLoc .
+					?a aGeo:location ?ayLoc .
+
+					?b aGeo:placeName ?neighbor .
+					?b aGeo:location ?bxLoc .
+					?b aGeo:location ?byLoc .
+
+					FILTER ( aGeo:distance(?axLoc, ?ayLoc, ?bxLoc, ?byLoc) < 10 ) .
+				}
+
+ +

The final example query is not based on the SPARQL 1.1 queries.

+ +

Full Example query

+ +

+	base <http://example.org/geo#>
+	prefix geo: <http://www.opengis.net/ont/geosparql#>
+	prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+	select ?shape ?shapeColor ?shapeHeight ?shapeName (sample(?shapeLabel) as ?shapeLabel)  {
+		{
+			select * {
+				values (?placeName ?streetName) {
+					"Grenoble" "Paul Mistral"
+				}
+				?place geo:NamePlace ?placeName.
+				?pand geo:hasGeometry/geo:asWKT ?shape;
+			}
+
+		}
+		?pand geo:measuredHeight ?shapeHeight.
+		# Only retrieve buildings larger then 10 meters.
+		FILTER ( ?shapeHeight < 10 ) .
+		BIND(IF(!bound(?EindGeldigheid5), "#22b14c", "#ed1c24" ) AS?tColor)
+		# tekst label
+		bind(concat(str(?streetName),' ',str(?houseNumber),', ',str(?PlaceName)) as ?shapeName)
+		bind("""Multi-line
+		String Element
+		""" as ?shapeLabel)
+	}
+	group by ?shape ?shapeColor ?shapeHeight ?shapeName
+	limit 10
+
diff --git a/examples/prism-splunk-spl.html b/examples/prism-splunk-spl.html new file mode 100644 index 0000000000..8675476323 --- /dev/null +++ b/examples/prism-splunk-spl.html @@ -0,0 +1,7 @@ +

Full example

+
source=monthly_data.csv
+| rename remote_ip AS ip
+| eval isLocal=if(cidrmatch("123.132.32.0/25",ip), "local", "not local")
+| eval error=case(status == 200, "OK", status == 404, "Not found", true(), "Other")
+  `comment("TODO: Add support for more status codes")`
+| sort amount
diff --git a/examples/prism-sqf.html b/examples/prism-sqf.html new file mode 100644 index 0000000000..93639763c4 --- /dev/null +++ b/examples/prism-sqf.html @@ -0,0 +1,100 @@ +

Full example

+
#include "script_component.hpp"
+/*
+ * Author: BaerMitUmlaut
+ * Handles any audible, visual and physical effects of fatigue.
+ *
+ * Arguments:
+ * 0: Unit <OBJECT>
+ * 1: Fatigue <NUMBER>
+ * 2: Speed <NUMBER>
+ * 3: Overexhausted <BOOL>
+ *
+ * Return Value:
+ * None
+ *
+ * Example:
+ * [_player, 0.5, 3.3, true] call ace_advanced_fatigue_fnc_handleEffects
+ *
+ * Public: No
+ */
+params ["_unit", "_fatigue", "_speed", "_overexhausted"];
+
+#ifdef DEBUG_MODE_FULL
+	systemChat str _fatigue;
+	systemChat str vectorMagnitude velocity _unit;
+#endif
+
+// - Audible effects ----------------------------------------------------------
+GVAR(lastBreath) = GVAR(lastBreath) + 1;
+if (_fatigue > 0.4 && {GVAR(lastBreath) > (_fatigue * -10 + 9)} && {!underwater _unit}) then {
+	switch (true) do {
+		case (_fatigue < 0.6): {
+			playSound (QGVAR(breathLow) + str(floor random 6));
+		};
+		case (_fatigue < 0.85): {
+			playSound (QGVAR(breathMid) + str(floor random 6));
+		};
+		default {
+			playSound (QGVAR(breathMax) + str(floor random 6));
+		};
+	};
+	GVAR(lastBreath) = 0;
+};
+
+// - Visual effects -----------------------------------------------------------
+GVAR(ppeBlackoutLast) = GVAR(ppeBlackoutLast) + 1;
+if (GVAR(ppeBlackoutLast) == 1) then {
+	GVAR(ppeBlackout) ppEffectAdjust [1,1,0,[0,0,0,1],[0,0,0,0],[1,1,1,1],[10,10,0,0,0,0.1,0.5]];
+	GVAR(ppeBlackout) ppEffectCommit 1;
+} else {
+	if (_fatigue > 0.85) then {
+		if (GVAR(ppeBlackoutLast) > (100 - _fatigue * 100) / 3) then {
+			GVAR(ppeBlackout) ppEffectAdjust [1,1,0,[0,0,0,1],[0,0,0,0],[1,1,1,1],[2,2,0,0,0,0.1,0.5]];
+			GVAR(ppeBlackout) ppEffectCommit 1;
+			GVAR(ppeBlackoutLast) = 0;
+		};
+	};
+};
+
+// - Physical effects ---------------------------------------------------------
+if (GVAR(isSwimming)) exitWith {
+	if (GVAR(setAnimExclusions) isEqualTo []) then {
+		_unit setAnimSpeedCoef linearConversion [0.7, 0.9, _fatigue, 1, 0.5, true];
+	};
+	if ((isSprintAllowed _unit) && {_fatigue > 0.7}) then {
+		[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
+	} else {
+		if ((!isSprintAllowed _unit) && {_fatigue < 0.7}) then {
+			[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
+		};
+	};
+};
+if ((getAnimSpeedCoef _unit) != 1) then {
+	if (GVAR(setAnimExclusions) isEqualTo []) then {
+		TRACE_1("reset",getAnimSpeedCoef _unit);
+		_unit setAnimSpeedCoef 1;
+	};
+};
+
+if (_overexhausted) then {
+	[_unit, "forceWalk", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
+} else {
+	if (isForcedWalk _unit && {_fatigue < 0.7}) then {
+		[_unit, "forceWalk", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
+	} else {
+		if ((isSprintAllowed _unit) && {_fatigue > 0.7}) then {
+			[_unit, "blockSprint", QUOTE(ADDON), true] call EFUNC(common,statusEffect_set);
+		} else {
+			if ((!isSprintAllowed _unit) && {_fatigue < 0.6}) then {
+				[_unit, "blockSprint", QUOTE(ADDON), false] call EFUNC(common,statusEffect_set);
+			};
+		};
+	};
+};
+
+_unit setVariable [QGVAR(aimFatigue), _fatigue];
+
+private _aimCoef = [missionNamespace, "ACE_setCustomAimCoef", "max"] call EFUNC(common,arithmeticGetResult);
+_unit setCustomAimCoef _aimCoef;
+
diff --git a/examples/prism-squirrel.html b/examples/prism-squirrel.html new file mode 100644 index 0000000000..14ff2d6af3 --- /dev/null +++ b/examples/prism-squirrel.html @@ -0,0 +1,57 @@ +

Full example

+
 // source: http://www.squirrel-lang.org/#look
+
+local table = {
+	a = "10"
+	subtable = {
+		array = [1,2,3]
+	},
+	[10 + 123] = "expression index"
+}
+
+local array=[ 1, 2, 3, { a = 10, b = "string" } ];
+
+foreach (i,val in array)
+{
+	::print("the type of val is"+typeof val);
+}
+
+/////////////////////////////////////////////
+
+class Entity
+{
+	constructor(etype,entityname)
+	{
+		name = entityname;
+		type = etype;
+	}
+
+	x = 0;
+	y = 0;
+	z = 0;
+	name = null;
+	type = null;
+}
+
+function Entity::MoveTo(newx,newy,newz)
+{
+	x = newx;
+	y = newy;
+	z = newz;
+}
+
+class Player extends Entity {
+	constructor(entityname)
+	{
+		base.constructor("Player",entityname)
+	}
+	function DoDomething()
+	{
+		::print("something");
+	}
+
+}
+
+local newplayer = Player("da playar");
+
+newplayer.MoveTo(100,200,300);
diff --git a/examples/prism-stan.html b/examples/prism-stan.html new file mode 100644 index 0000000000..6d7b0ff937 --- /dev/null +++ b/examples/prism-stan.html @@ -0,0 +1,21 @@ +

Full example

+
// source: https://github.com/stan-dev/example-models/blob/8a6964135560f54f52695ccd4d2492a8067f0c30/misc/linear-regression/regression_std.stan
+
+// normal mixture, unknown proportion and means, known variance
+// p(y|mu,theta) = theta * Normal(y|mu[1],1) + (1-theta) * Normal(y|mu[2],1);
+
+data {
+  int<lower=0>  N;
+  real y[N];
+}
+parameters {
+  real<lower=0,upper=1> theta;
+  real mu[2];
+}
+model {
+  theta ~ uniform(0,1); // equivalently, ~ beta(1,1);
+  for (k in 1:2)
+    mu[k] ~ normal(0,10);
+  for (n in 1:N)
+    target += log_mix(theta, normal_lpdf(y[n]|mu[1],1.0), normal_lpdf(y[n]|mu[2],1.0));
+}
diff --git a/examples/prism-swift.html b/examples/prism-swift.html index 98d6eb55e2..e49a0d4a74 100644 --- a/examples/prism-swift.html +++ b/examples/prism-swift.html @@ -29,12 +29,12 @@

Control flow

for _ in 1...power { answer *= base } -while square < finalSquare { +while square < finalSquare { // roll the dice if ++diceRoll == 7 { diceRoll = 1 } // move by the rolled amount square += diceRoll - if square < board.count { + if square < board.count { // if we're still on the board, move up or down for a snake or a ladder square += board[square] } @@ -52,29 +52,16 @@

Control flow

Classes and attributes

class MyViewController: UIViewController {
-    @IBOutlet weak var button: UIButton!
-    @IBOutlet var textFields: [UITextField]!
-    @IBAction func buttonTapped(AnyObject) {
-	    println("button tapped!")
+	@IBOutlet weak var button: UIButton!
+	@IBOutlet var textFields: [UITextField]!
+	@IBAction func buttonTapped(AnyObject) {
+		println("button tapped!")
 	}
 }
 
 @IBDesignable
 class MyCustomView: UIView {
-    @IBInspectable var textColor: UIColor
-    @IBInspectable var iconHeight: CGFloat
-    /* ... */
+	@IBInspectable var textColor: UIColor
+	@IBInspectable var iconHeight: CGFloat
+	/* ... */
 }
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nested block comments

-
/* Nested block
-	/* comments
-	are */
-not supported */
\ No newline at end of file diff --git a/examples/prism-systemd.html b/examples/prism-systemd.html new file mode 100644 index 0000000000..082ff8b54d --- /dev/null +++ b/examples/prism-systemd.html @@ -0,0 +1,20 @@ +

Full example

+
# Source: https://www.freedesktop.org/software/systemd/man/systemd.syntax.html
+
+[Section A]
+KeyOne=value 1
+KeyTwo=value 2
+
+# a comment
+
+[Section B]
+Setting="something" "some thing" "…"
+KeyTwo=value 2 \
+       value 2 continued
+
+[Section C]
+KeyThree=value 3\
+# this line is ignored
+; this line is ignored too
+       value 3 continued
+
diff --git a/examples/prism-t4-cs.html b/examples/prism-t4-cs.html new file mode 100644 index 0000000000..e3651c7708 --- /dev/null +++ b/examples/prism-t4-cs.html @@ -0,0 +1,16 @@ +

Full example

+
<#@ template hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core.dll" #>
+<#@ output extension=".txt" #>
+<#
+    using System.Collections.Generic;
+
+    var numbers = new List<int> { 0, 1, 2, 3, 4, 5, 6, /* 7, */ 8, 9, 10  };
+
+    foreach (var i in numbers)
+    {
+#>
+The square of <#= i #> is <#= i * i #>
+<#
+    }
+#>
diff --git a/examples/prism-t4-vb.html b/examples/prism-t4-vb.html new file mode 100644 index 0000000000..04c999693d --- /dev/null +++ b/examples/prism-t4-vb.html @@ -0,0 +1,16 @@ +

Full example

+
<#@ template hostspecific="false" language="VB" #>
+<#@ assembly name="System.Core.dll" #>
+<#@ output extension=".txt" #>
+<#
+    Imports System.Collections.Generic
+
+    Dim numbers() As Integer = { 0, 1, 2, 3, 4, 5, 6, 8, 9, 10  }
+    ' not including 7
+
+    For Each i In numbers
+#>
+The square of <#= i #> is <#= i * i #>
+<#
+    Next
+#>
diff --git a/examples/prism-tap.html b/examples/prism-tap.html new file mode 100644 index 0000000000..d395678948 --- /dev/null +++ b/examples/prism-tap.html @@ -0,0 +1,7 @@ +

Full example

+
1..48
+ok 1 Description # Directive
+# Diagnostic
+....
+ok 47 Description
+ok 48 Description
diff --git a/examples/prism-textile.html b/examples/prism-textile.html index 4ff4d12798..f195e9673b 100644 --- a/examples/prism-textile.html +++ b/examples/prism-textile.html @@ -156,23 +156,3 @@

Tables

|This|is|a|row| {background:#ddd}. |This|is|grey|row|
- -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nested styles are only partially supported

- -

Only one level of nesting is supported.

- -
*A bold paragraph %containing a span with broken _italic_ inside%!*
- -

HTML inside Textile is not supported

- -

But Textile inside HTML should be just fine.

- -
<strong>This _should_ work properly.</strong>
-*But this is <em>definitely</em> broken.*
\ No newline at end of file diff --git a/examples/prism-toml.html b/examples/prism-toml.html new file mode 100644 index 0000000000..7f68c8ef9b --- /dev/null +++ b/examples/prism-toml.html @@ -0,0 +1,28 @@ +

Full example

+
# This is a comment
+
+key = "value"
+paths.home = 'c:\foo\'
+
+[database.prod]
+server = "192.168.1.1"
+ports = [ 8001, 8001, 8002 ]
+connection_max = 5000
+enabled = true
+
+
+[[users]]
+name = "John"
+bday = 1995-09-22
+bio = ""
+interests = [ "biking", "fishing" ]
+
+[[users]]
+name = "Jane"
+bday = 1989-05-09
+bio = """\
+Hi!
+
+I love programming!\
+"""
+interests = [ "programming" ]
diff --git a/examples/prism-tremor.html b/examples/prism-tremor.html new file mode 100644 index 0000000000..c0c89e2753 --- /dev/null +++ b/examples/prism-tremor.html @@ -0,0 +1,82 @@ +

Comments

+
# Single line comment
+### Module level documentation comment
+## Statement level documentation comment
+# Regular code comment
+
+ +

Strings

+

+# double quote single line strings
+"foo \"bar\" baz"
+
+# heredocs or multiline strings
+"""
+{ "snot": "badger" }
+"""
+
+ +

Variables

+

+# Immutable constants
+const snot = "fleek";
+
+# Mutable variables
+let badger = "flook";
+
+ +

Operators

+

+merge {} of
+  { "snot": "badger" }
+end;
+
+patch {} of
+  insert snot = "badger"
+end;
+
+ +

Functions and keywords

+

+fn fib_(a, b, n) of
+case (a, b, n) when n > 0 => recur(b, a + b, n - 1)
+default => a
+end;
+
+fn fib(n) with
+fib_(0, 1, n)
+end;
+
+fib(event)
+
+ +

Queries

+

+	define script fib
+	script
+        fn fib_(a, b, n) of
+            case (a, b, n) when n > 0 => recur(b, a + b, n - 1)
+            default => a
+        end;
+
+        fn fib(n) with
+            fib_(0, 1, n)
+        end;
+
+		{ "fib": fib(event.n) }
+	end;
+
+	create script fib;
+	select event.n from in into fib;
+	select event from fib into out;
+
+ +

Deployments

+

+define pipeline passthrough
+pipeline
+  select event from in into out;
+end;
+
+deploy pipeline passthrough;
+
\ No newline at end of file diff --git a/examples/prism-tt2.html b/examples/prism-tt2.html new file mode 100644 index 0000000000..1a6711f970 --- /dev/null +++ b/examples/prism-tt2.html @@ -0,0 +1,61 @@ +

Comments

+
[%# this entire directive is ignored no
+    matter how many lines it wraps onto
+%]
+[% # this is a comment
+   theta = 20      # so is this
+   rho   = 30      # <aol>me too!</aol>
+%]
+
+ +

Variables

+
[% text %]
+[% article.title %]
+[%= eat.whitespace.left %]
+[% eat.whitespace.right =%]
+[%= eat.whitespace.both =%]
+[% object.method() %]
+ + +

Conditionals and Loops

+
[% IF foo = bar %]
+this
+[% ELSE %]
+that
+[% END %]
+[% FOREACH post IN q.listPosts(lingua = "de") %]
+  <a href="[% post.permalink %]">[% post.title | html %]</a>
+[% END %]
+ +

Multiple Directives

+
[% IF title;
+      INCLUDE header;
+   ELSE;
+      INCLUDE other/header  title="Some Other Title";
+   END
+%]
+ +

Operators

+
[% FOREACH post IN q.listPosts(lingua => 'de') %]
+  [% post.title | myfilter(foo = "bar") %]
+[% END %]
+ +

Known Limitations

+
    +
  • + Outline tags are not supported.
  • +
  • The arguments to + TAGS + are usually misinterpreted
  • +
  • In TT2, you can use keywords as identifiers where this is + unambiguous. But these keywords will be highlighted as keywords, not + as variables here.
  • +
  • The + ANYCASE + option is not supported.
  • +
  • + Any number of backslashes in front of dollar signs inside of double quoted + strings are ignored since the behavior of Template Toolkit 2.26 seems to be + inconsistent. +
  • +
diff --git a/examples/prism-turtle.html b/examples/prism-turtle.html new file mode 100644 index 0000000000..a64a2a5779 --- /dev/null +++ b/examples/prism-turtle.html @@ -0,0 +1,18 @@ +

Full example

+
@base <http://example.org/> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix rel: <http://www.perceive.net/schemas/relationship/> .
+
+GRAPH <urn:myGraph> {
+<#green-goblin>
+    rel:enemyOf <#spiderman> ;
+    a foaf:Person ;    # in the context of the Marvel universe
+    foaf:name "Green Goblin" .
+
+<#spiderman>
+    rel:enemyOf <#green-goblin> ;
+    a foaf:Person ;
+    foaf:name "Spiderman", "Человек-паук"@ru .
+}
diff --git a/examples/prism-twig.html b/examples/prism-twig.html index 0a7078151d..167ffadd95 100644 --- a/examples/prism-twig.html +++ b/examples/prism-twig.html @@ -23,13 +23,3 @@

Twig embedded in HTML

{% else %} <p>Not foo...</p> {% endif %} - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Tag containing Twig is not highlighted

-
<div{% if foo %} class="bar"{% endif %}></div>
\ No newline at end of file diff --git a/examples/prism-typoscript.html b/examples/prism-typoscript.html new file mode 100644 index 0000000000..2ebcc1373f --- /dev/null +++ b/examples/prism-typoscript.html @@ -0,0 +1,95 @@ +

Typical TypoScript Setup File

+
# import other files
+@import 'EXT:fluid_styled_content/Configuration/TypoScript/setup.typoscript'
+@import 'EXT:sitepackage/Configuration/TypoScript/Helper/DynamicContent.typoscript'
+
+page = PAGE
+page {
+	typeNum = 0
+
+	// setup templates
+	10 = FLUIDTEMPLATE
+	10 {
+		templateName = TEXT
+		templateName.stdWrap.cObject = CASE
+		templateName.stdWrap.cObject {
+			key.data = pagelayout
+
+			pagets__sitepackage_default = TEXT
+			pagets__sitepackage_default.value = Default
+
+			pagets__sitepackage_alternate = TEXT
+			pagets__sitepackage_alternate.value = Alternative
+
+			default = TEXT
+			default.value = Default
+		}
+		
+		templateRootPaths {
+			0 = EXT:sitepackage/Resources/Private/Templates/Page/
+			1 = {$sitepackage.fluidtemplate.templateRootPath}
+		}
+		
+		partialRootPaths {
+			0 = EXT:sitepackage/Resources/Private/Partials/Page/
+			1 = {$sitepackage.fluidtemplate.partialRootPath}
+		}
+		
+		layoutRootPaths {
+			0 = EXT:sitepackage/Resources/Private/Layouts/Page/
+			1 = {$sitepackage.fluidtemplate.layoutRootPath}
+		}
+
+		dataProcessing {
+			10 = TYPO3\CMS\Frontend\DataProcessing\MenuProcessor
+			10 {
+				levels = 1
+				includeSpacer = 1
+				as = mainnavigation
+			}
+		}
+	}
+
+	// include css into head
+	includeCSS {
+		bootstrap = https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css
+		bootstrap.external = 1
+		website = EXT:sitepackage/Resources/Public/Css/styles.css
+	}
+
+	// include js into footer
+	includeJSFooter {
+		jquery = https://code.jquery.com/jquery-3.2.1.slim.min.js
+		jquery.external = 1
+		bootstrap = https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js
+		bootstrap.external = 1
+		website = EXT:sitepackage/Resources/Public/JavaScript/scripts.js
+	}
+}
+
+// global site configuration
+config {
+	absRefPrefix = auto
+	cache_period = 86400
+	debug = 0
+	disablePrefixComment = 1
+	doctype = html5
+	extTarget =
+	index_enable = 1
+	index_externals = 1
+	index_metatags = 1
+	inlineStyle2TempFile = 1
+	intTarget =
+	linkVars = L
+	metaCharset = utf-8
+	no_cache = 0
+	pageTitleFirst = 1
+	prefixLocalAnchors = all
+	removeDefaultJS = 0
+	sendCacheHeaders = 1
+	compressCss = 0
+	compressJs = 0
+	concatenateCss = 0
+	concatenateJs = 0
+}
+
diff --git a/examples/prism-unrealscript.html b/examples/prism-unrealscript.html new file mode 100644 index 0000000000..b4926e6ba7 --- /dev/null +++ b/examples/prism-unrealscript.html @@ -0,0 +1,38 @@ +

Full example

+
// Source: https://github.com/Jusas/XCOM2_ReconSoldierClass/blob/master/ReconOperatorSoldierClass/Src/ReconSoldierClass/Classes/ReconOperator_AcademyUnlocks.uc
+
+class ReconOperator_AcademyUnlocks extends X2StrategyElement;
+
+static function array<X2DataTemplate> CreateTemplates()
+{
+	local array<X2DataTemplate> Templates;
+
+	Templates.AddItem(AdrenalineUnlock());
+
+	return Templates;
+}
+
+static function X2SoldierAbilityUnlockTemplate AdrenalineUnlock()
+{
+	local X2SoldierAbilityUnlockTemplate Template;
+	local ArtifactCost Resources;
+
+	`CREATE_X2TEMPLATE(class'X2SoldierAbilityUnlockTemplate', Template, 'ReconAdrenalineUnlock');
+
+	Template.AllowedClasses.AddItem('ReconSoldierClass');
+	Template.AbilityName = 'ReconAdrenalineSpike';
+	Template.strImage = "img:///UILibrary_ReconOperator.GTS.GTS_adrenaline";
+
+	// Requirements
+	Template.Requirements.RequiredHighestSoldierRank = 5;
+	Template.Requirements.RequiredSoldierClass = 'ReconSoldierClass';
+	Template.Requirements.RequiredSoldierRankClassCombo = true;
+	Template.Requirements.bVisibleIfSoldierRankGatesNotMet = true;
+
+	// Cost
+	Resources.ItemTemplateName = 'Supplies';
+	Resources.Quantity = 75;
+	Template.Cost.ResourceCosts.AddItem(Resources);
+
+	return Template;
+}
diff --git a/examples/prism-uorazor.html b/examples/prism-uorazor.html new file mode 100644 index 0000000000..5c218ff9a0 --- /dev/null +++ b/examples/prism-uorazor.html @@ -0,0 +1,13 @@ +

Full example

+

+# UO Razor Script Highlighting by Jaseowns
+// These two are comments
+// Example script:
+setvar "my_training_target"
+while skill "anatomy" < 100
+    useskill "anatomy"
+    wft 500
+    target "my_training_target"
+    wait 2000
+endwhile
+
diff --git a/examples/prism-uri.html b/examples/prism-uri.html new file mode 100644 index 0000000000..da6dc04bec --- /dev/null +++ b/examples/prism-uri.html @@ -0,0 +1,13 @@ +

Full example

+
https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top
+https://example.com/path/resource.txt#fragment
+ldap://[2001:db8::7]/c=GB?objectClass?one
+mailto:John.Doe@example.com
+news:comp.infosystems.www.servers.unix
+tel:+1-816-555-1212
+telnet://192.0.2.16:80/
+urn:oasis:names:specification:docbook:dtd:xml:4.1.2
+//example.com/path/resource.txt
+/path/resource.txt
+path/resource.txt
+
diff --git a/examples/prism-v.html b/examples/prism-v.html new file mode 100644 index 0000000000..1ddb018263 --- /dev/null +++ b/examples/prism-v.html @@ -0,0 +1,91 @@ +

Comments

+
// This is a comment
+/* This is a comment
+on multiple lines */
+ +

Numbers

+
123
+0x7B
+0b01111011
+0o173
+170141183460469231731687303715884105727
+1_000_000
+0b0_11
+3_122.55
+0xF_F
+0o17_3
+72.40
+072.40
+2.71828
+
+ +

Runes and strings

+
'\t'
+'\000'
+'\x07'
+'\u12e4'
+'\U00101234'
+`abc`
+`multi-line
+string`
+"Hello, world!"
+"multi-line
+string"
+ +

String interpolation

+
'Hello, $name!'
+"age = $user.age"
+'can register = ${user.age > 13}'
+'x = ${x:4.2f}'
+'[${x:10}]'
+'[${int(x):-10}]'
+
+ +

Struct

+
struct Foo {
+	a int   // private immutable (default)
+mut:
+	b int   // private mutable
+	c int   // (you can list multiple fields with the same access modifier)
+pub:
+	d int   // public immutable (readonly)
+pub mut:
+	e int   // public, but mutable only in parent module
+__global:
+	f int   // public and mutable both inside and outside parent module
+}           // (not recommended to use, that's why the 'global' keyword
+			// starts with __)
+
+ +

Functions

+
func(a, b int, z float64) bool { return a*b < int(z) }
+ +

Full example

+

+module mymodule
+
+import external_module
+
+fn sqr(n int) int {
+	return n * n
+}
+
+fn run(value int, op fn (int) int) int {
+	return op(value)
+}
+
+fn main() {
+	println(run(5, sqr)) // "25"
+	// Anonymous functions can be declared inside other functions:
+	double_fn := fn (n int) int {
+		return n + n
+	}
+	println(run(5, double_fn)) // "10"
+	// Functions can be passed around without assigning them to variables:
+	res := run(5, fn (n int) int {
+		return n + n
+	})
+
+	external_module.say_hi()
+}
+
diff --git a/examples/prism-vala.html b/examples/prism-vala.html new file mode 100644 index 0000000000..456bdce2af --- /dev/null +++ b/examples/prism-vala.html @@ -0,0 +1,33 @@ +

Comments

+
// Single line comment
+/** Multi-line
+doc comment */
+ +

Strings

+
"foo \"bar\" baz"
+"Multi-line strings ending with a \
+are supported too."
+"""Verbatim strings
+You can create
+multi-line strings like this too."""
+@"Template string with variables $var1 $(var2 * 2)"
+ +

Regex

+
/foo?[ ]*bar/
+ +

Full example

+
using Gtk;
+
+int main (string[] args) {
+	Gtk.init(ref args);
+
+	var window = new Window();
+
+	var button = new Button.with_label("Click me!");
+
+	window.add(button);
+	window.show_all();
+
+	Gtk.main();
+	return 0;
+}
diff --git a/examples/prism-vbnet.html b/examples/prism-vbnet.html index bc2a376b2e..b5e3081284 100644 --- a/examples/prism-vbnet.html +++ b/examples/prism-vbnet.html @@ -7,10 +7,10 @@

Example

Public Function findValue(ByVal arr() As Double,
     ByVal searchValue As Double) As Double
     Dim i As Integer = 0
-    While i <= UBound(arr) AndAlso arr(i) <> searchValue
+    While i <= UBound(arr) AndAlso arr(i) <> searchValue
         ' If i is greater than UBound(arr), searchValue is not checked.
         i += 1
     End While
     If i > UBound(arr) Then i = -1
     Return i
-End Function
\ No newline at end of file +End Function diff --git a/examples/prism-vhdl.html b/examples/prism-vhdl.html index b495085155..0d3b56f6b9 100644 --- a/examples/prism-vhdl.html +++ b/examples/prism-vhdl.html @@ -5,8 +5,8 @@

Comments

Literals

constant FREEZE : integer := 32;
 constant TEMP : real := 32.0;
-A_INT <= 16#FF#;
-B_INT <= 2#1010_1010#;
+A_INT <= 16#FF#;
+B_INT <= 2#1010_1010#;
 MONEY := 1_000_000.0;
 FACTOR := 2.2E-6;
 constant DEL1 :time := 10 ns;
@@ -17,9 +17,9 @@ 

Literals

signal STATE : T_STATE := IDLE; constant FLAG :bit_vector(0 to 7) := "11111111"; constant MSG : string := "Hello"; -BIT_8_BUS <= B"1111_1111"; -BIT_9_BUS <= O"353"; -BIT_16_BUS <= X"AA55"; +BIT_8_BUS <= B"1111_1111"; +BIT_9_BUS <= O"353"; +BIT_16_BUS <= X"AA55"; constant TWO_LINE_MSG : string := "Hello" & CR & "World";

Full example

@@ -37,8 +37,8 @@

Full example

architecture circuits of fadd is -- full adder stage, body begin -- circuits of fadd - s <= a xor b xor cin after 1 ns; - cout <= (a and b) or (a and cin) or (b and cin) after 1 ns; + s <= a xor b xor cin after 1 ns; + cout <= (a and b) or (a and cin) or (b and cin) after 1 ns; end architecture circuits; -- of fadd library IEEE; diff --git a/examples/prism-warpscript.html b/examples/prism-warpscript.html new file mode 100644 index 0000000000..177d0d57d9 --- /dev/null +++ b/examples/prism-warpscript.html @@ -0,0 +1,22 @@ +

Full example

+
// Source: https://www.warp10.io/content/04_Tutorials/01_WarpScript/05_Best_Practices
+
+//factorial macro. take a number on the stack, push its factorial
+<%
+	'input' STORE
+	1
+	1 $input <% * %> FOR
+%> 'factorial' STORE
+
+//build a map with key from 1 to 10 and value = key!
+{} 'result' STORE
+
+1 10
+<%
+	'key' STORE
+	$result $key @factorial $key PUT
+	DROP //remove the map let by PUT
+%> FOR
+
+//push the result on the stack
+$result
diff --git a/examples/prism-web-idl.html b/examples/prism-web-idl.html new file mode 100644 index 0000000000..7f2c9a91f1 --- /dev/null +++ b/examples/prism-web-idl.html @@ -0,0 +1,28 @@ +

Full example

+
[Exposed=Window]
+interface Paint { };
+
+[Exposed=Window]
+interface SolidColor : Paint {
+	attribute double red;
+	attribute double green;
+	attribute double blue;
+};
+
+[Exposed=Window]
+interface Pattern : Paint {
+	attribute DOMString imageURL;
+};
+
+[Exposed=Window]
+interface GraphicalWindow {
+	constructor();
+	readonly attribute unsigned long width;
+	readonly attribute unsigned long height;
+
+	attribute Paint currentPaint;
+
+	undefined drawRectangle(double x, double y, double width, double height);
+
+	undefined drawText(double x, double y, DOMString text);
+};
diff --git a/examples/prism-wiki.html b/examples/prism-wiki.html index 295eb3f812..99dbd0c618 100644 --- a/examples/prism-wiki.html +++ b/examples/prism-wiki.html @@ -143,23 +143,3 @@

Tables

| |15.00 |} - -

Known failures

-

There are certain edge cases where Prism will fail. - There are always such cases in every regex-based syntax highlighter. - However, Prism dares to be open and honest about them. - If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug. -

- -

Nested magic words are not supported

- -
{{#switch:{{PAGENAME}}
-| L'Aquila = No translation
-| L = Not OK
-| L'Aquila = Entity escaping
-| L'Aquila = Numeric char encoding
-}}
- -

Nesting of bold and italic is not supported

-
''Italic with '''bold''' inside''
- diff --git a/examples/prism-wolfram.html b/examples/prism-wolfram.html new file mode 100644 index 0000000000..a6eeabdbc6 --- /dev/null +++ b/examples/prism-wolfram.html @@ -0,0 +1,31 @@ +

Comments

+

+(* This is a comment *)
+
+ +

Strings

+

+"foo bar baz"
+
+ +

Numbers

+

+7
+3.14
+10.
+.001
+1e100
+3.14e-10
+2147483647
+
+ +

Full example

+

+(* Most operators are supported *)
+f /@ {1, 2, 3};
+f @@ Range[10];
+f @@@ y;
+Module[{x=1}, 
+    Return @ $Failed
+]
+
diff --git a/examples/prism-wren.html b/examples/prism-wren.html new file mode 100644 index 0000000000..bce7637be6 --- /dev/null +++ b/examples/prism-wren.html @@ -0,0 +1,17 @@ +

Full example

+
// Source: https://wren.io/
+
+System.print("Hello, world!")
+
+class Wren {
+  flyTo(city) {
+    System.print("Flying to %(city)")
+  }
+}
+
+var adjectives = Fiber.new {
+  ["small", "clean", "fast"].each {|word| Fiber.yield(word) }
+}
+
+while (!adjectives.isDone) System.print(adjectives.call())
+
diff --git a/examples/prism-xml-doc.html b/examples/prism-xml-doc.html new file mode 100644 index 0000000000..0e815617db --- /dev/null +++ b/examples/prism-xml-doc.html @@ -0,0 +1,14 @@ +

C#

+
/// <summary>
+/// Summary documentation goes here.
+/// </summary>
+ +

F#

+
/// <summary>
+/// Summary documentation goes here.
+/// </summary>
+ +

VB.net

+
''' <summary>
+''' Summary documentation goes here.
+''' </summary>
diff --git a/examples/prism-xojo.html b/examples/prism-xojo.html index 35480744dd..5dd8fc85e5 100644 --- a/examples/prism-xojo.html +++ b/examples/prism-xojo.html @@ -21,8 +21,8 @@

Example

Dim g As Graphics
 Dim yOffSet As Integer
 g = OpenPrinterDialog()
-If g <> Nil Then
-  If MainDishMenu.ListIndex <> -1 Then
+If g <> Nil Then
+  If MainDishMenu.ListIndex <> -1 Then
     g.Bold = True
     g.DrawString("Main Dish:",20,20)
     g.Bold = False
diff --git a/examples/prism-xquery.html b/examples/prism-xquery.html
new file mode 100644
index 0000000000..8166d771c2
--- /dev/null
+++ b/examples/prism-xquery.html
@@ -0,0 +1,47 @@
+

Comments

+
(::)
+(: Comment :)
+(: Multi-line
+comment :)
+(:~
+: The <b>functx:substring-after-last</b> function returns the part
+: of <b>$string</b> that appears after the last occurrence of
+: <b>$delim</b>. If <b>$string</b> does not contain
+: <b>$delim</b>, the entire string is returned.
+:
+: @param $string the string to substring
+: @param $delim the delimiter
+: @return the substring
+:)
+ +

Variables

+
$myProduct
+$foo-bar
+$strings:LetterA
+ +

Functions

+
document-node(schema-element(catalog))
+strings:trim($arg as xs:string?)
+false()
+ +

Keywords

+
xquery version "1.0";
+declare default element namespace "http://datypic.com/cat";
+declare boundary-space preserve;
+declare default collation "http://datypic.com/collation/custom";
+ +

Types

+
xs:anyAtomicType
+element
+xs:double
+ +

Full example

+
<report xmlns="http://datypic.com/report"
+xmlns:cat="http://datypic.com/cat"
+xmlns:prod="http://datypic.com/prod"> {
+for $product in doc("prod_ns.xml")/prod:product
+return <lineItem>
+{$product/prod:number}
+{$product/prod:name}
+</lineItem>
+} </report>
\ No newline at end of file diff --git a/examples/prism-yaml.html b/examples/prism-yaml.html index bea52f8651..58b78f60cc 100644 --- a/examples/prism-yaml.html +++ b/examples/prism-yaml.html @@ -89,7 +89,7 @@

Full example

state : MI postal : 48046 ship-to: - <<: *id001 + <<: *id001 product: - sku : BL394D quantity : 4 diff --git a/examples/prism-yang.html b/examples/prism-yang.html new file mode 100644 index 0000000000..744e4d4261 --- /dev/null +++ b/examples/prism-yang.html @@ -0,0 +1,50 @@ +

Full example

+

Source

+
submodule execd-dns {
+
+	belongs-to execd { prefix execd; }
+
+	import inet-types { prefix inet; }
+
+	include execd-types;
+
+	description
+		"The 'dns' component provides support for configuring the DNS resolver.
+
+		 The 'domain' keyword of /etc/resolv.conf is not supported, since
+		 it is equivalent to 'search' with a single domain. I.e. in terms
+		 of the data model, the domains are always configured as 'search'
+		 elements, even if there is only one. The set of available options
+		 has been limited to those that are generally available across
+		 different resolver implementations, and generally useful.";
+
+	revision "2008-11-04" {
+		description "draft-ietf-netmod-yang-02 compatible.";
+	}
+	revision "2007-08-29" {
+		description "Syntax fixes after pyang validation.";
+	}
+	revision "2007-06-08" {
+		description "Initial revision.";
+	}
+
+	grouping dns {
+		list search {
+			key name;
+			max-elements 3;
+			leaf name      { type int32; }
+			leaf domain    { type inet:host; }
+		}
+		list server {
+			key address;
+			max-elements 3;
+			ordered-by user;
+			leaf address   { type inet:ip-address; }
+		}
+		container options {
+			leaf ndots    { type uint8; }
+			leaf timeout  { type uint8; }
+			leaf attempts { type uint8; }
+		}
+	}
+}
diff --git a/examples/prism-zig.html b/examples/prism-zig.html new file mode 100644 index 0000000000..67bf148cd3 --- /dev/null +++ b/examples/prism-zig.html @@ -0,0 +1,46 @@ +

Full example

+
const std = @import("std");
+
+pub fn main() !void {
+    // If this program is run without stdout attached, exit with an error.
+    const stdout_file = try std.io.getStdOut();
+    // If this program encounters pipe failure when printing to stdout, exit
+    // with an error.
+    try stdout_file.write("Hello, world!\n");
+}
+
+const warn = @import("std").debug.warn;
+
+pub fn main() void {
+    warn("Hello, world!\n");
+}
+
+const assert = @import("std").debug.assert;
+
+test "comments" {
+    // Comments in Zig start with "//" and end at the next LF byte (end of line).
+    // The below line is a comment, and won't be executed.
+
+    //assert(false);
+
+    const x = true;  // another comment
+    assert(x);
+}
+
+/// A structure for storing a timestamp, with nanosecond precision (this is a
+/// multiline doc comment).
+const Timestamp = struct {
+    /// The number of seconds since the epoch (this is also a doc comment).
+    seconds: i64,  // signed so we can represent pre-1970 (not a doc comment)
+    /// The number of nanoseconds past the second (doc comment again).
+    nanos: u32,
+
+    /// Returns a `Timestamp` struct representing the Unix epoch; that is, the
+    /// moment of 1970 Jan 1 00:00:00 UTC (this is a doc comment too).
+    pub fn unixEpoch() Timestamp {
+        return Timestamp{
+            .seconds = 0,
+            .nanos = 0,
+        };
+    }
+};
diff --git a/extending.html b/extending.html index b5a60bbfc1..606c2816fb 100644 --- a/extending.html +++ b/extending.html @@ -3,19 +3,26 @@ - + Extending Prism ▲ Prism - + - + + + - +
-
+

Extending Prism

Prism is awesome out of the box, but it’s even awesomer when it’s customized to your own needs. This section will help you write new language definitions, plugins and all-around Prism hacking.

@@ -53,8 +60,8 @@

Language definitions

alias
This option can be used to define one or more aliases for the matched token. The result will be, that - the styles of the token and its aliases are combined. This can be useful, to combine the styling of a well known - token, which is already supported by most of the themes, with a semantically correct token name. The option + the styles of the token and its aliases are combined. This can be useful, to combine the styling of a standard + token, which is already supported by most of the themes, with a semantically correct token name. The option can be set to a string literal or an array of string literals. In the following example the token name latex-equation is not supported by any theme, but it will be highlighted the same as a string.
{
@@ -86,44 +93,256 @@ 

Language definitions

'tokenname': [ /regex0/, /regex1/, { pattern: /regex2/ } ] ...
-
-

Prism.languages.insertBefore(inside, before, insert, root)

+

Helper functions

+ +

Prism also provides some useful function for creating and modifying language definitions. Prism.languages.insertBefore can be used to modify existing languages definitions. Prism.languages.extend is useful for when your language is very similar to another existing language.

+
+ +
+

Creating a new language definition

+ +

This section will explain the usual workflow of creating a new language definition.

+ +

As an example, we will create the language definition of the fictional Foo's Binary, Artistic Robots™ language or just Foo Bar for short.

+ +
    +
  1. +

    Create a new file components/prism-foo-bar.js.

    + +

    In this example, we choose foo-bar as the id of the new language. The language id has to be unique and should work well with the language-xxxx CSS class name Prism uses to refer to language definitions. Your language id should ideally match the regular expression /^[a-z][a-z\d]*(?:-[a-z][a-z\d]*)*$/.

    +
  2. +
  3. +

    Edit components.json to register the new language by adding it to the languages object. (Please note that all language entries are sorted alphabetically by title.)
    + Our new entry for this example will look like this:

    + +
    "foo-bar": {
    +	"title": "Foo Bar",
    +	"owner": "Your GitHub name"
    +}
    + +

    If your language definition depends any other languages, you have to specify this here as well by adding a "require" property. E.g. "require": "clike", or "require" : ["markup", "css"]. For more information on dependencies read the declaring dependencies section.

    + +

    Note: Any changes made to components.json require a rebuild (see step 3).

    +
  4. +
  5. +

    Rebuild Prism by running npm run build.

    + +

    This will make your language available to the test page, or more precise: your local version of it. You can open your local test.html page in any browser, select your language, and see how your language definition highlights any code you input.

    -

    This is a helper method to ease modifying existing languages. For example, the CSS language definition not only defines CSS highlighting for CSS documents, - but also needs to define highlighting for CSS embedded in HTML through <style> elements. To do this, it needs to modify - Prism.languages.markup and add the appropriate tokens. However, Prism.languages.markup - is a regular JavaScript object literal, so if you do this:

    +

    Note: You have to reload the test page to apply changes made to prism-foo-bar.js but you don't have to rebuild Prism itself. However, if you change components.json (e.g. because you added a dependency) then these changes will not show up on the test page until you rebuild Prism.

    +
  6. +
  7. +

    Write the language definition.

    -
    Prism.languages.markup.style = {
    -	/* tokens */
    -};
    +

    The above section already explains the makeup of language definitions.

    +
  8. +
  9. +

    Adding aliases.

    + +

    Aliases for are useful if your language is known under more than just one name or there are very common abbreviations for your language (e.g. JS for JavaScript). Keep in mind that aliases are very similar to language ids in that they also have to be unique (i.e. there cannot be an alias which is the same as another alias of language id) and work as CSS class names.

    + +

    In this example, we will register the alias foo for foo-bar because Foo Bar code is stored in .foo files.

    + +

    To add the alias, we add this line at the end of prism-foo-bar.js:

    + +
    Prism.languages.foo = Prism.languages['foo-bar'];
    + +

    Aliases also have to be registered in components.json by adding the alias property to the language entry. In this example, the updated entry will look like this:

    + +
    "foo-bar": {
    +	"title": "Foo Bar",
    +	"alias": "foo",
    +	"owner": "Your GitHub name"
    +}
    + +

    Note: alias can also be a string array if you need to register multiple aliases.

    + +

    Using aliasTitles, it's also possible to give aliases specific titles. In this example, this won't be necessary but a good example as to where this is useful is the markup language:

    + +
    "markup": {
    +	"title": "Markup",
    +	"alias": ["html", "xml", "svg", "mathml"],
    +	"aliasTitles": {
    +		"html": "HTML",
    +		"xml": "XML",
    +		"svg": "SVG",
    +		"mathml": "MathML"
    +	},
    +	"option": "default"
    +}
    +
  10. +
  11. +

    Adding tests.

    + +

    Create a folder tests/languages/foo-bar/. This is where your test files will live. The test format and how to run tests is described here.

    + +

    You should add a test for every major feature of your language. Test files should test the common case and certain edge cases (if any). Good examples are the tests of the JavaScript language.

    + +

    You can use this template for new .test files:

    + +
    The code to test.
    +
    +----------------------------------------------------
    +
    +----------------------------------------------------
    +
    +Brief description.
    + +

    For every test file:

    + +
      +
    1. +

      Add the code to test and a brief description.

      +
    2. +
    3. +

      Verify that your language definition correctly highlights the test code. This can be done using your local version of the test page.
      + Note: Using the Show tokens options, you see the token stream your language definition created.

      +
    4. +
    5. +

      Once you carefully checked that the test case is handled correctly (i.e. by using the test page), run the following command:

      + npm run test:languages -- --language=foo-bar --accept +

      This command will take the token stream your language definition currently produces and inserted into the test file. The empty space between the two lines separating the code and the description of test case will be replaced with a simplified version of the token stream.

      +
    6. +
    7. +

      Carefully check that the inserted token stream JSON is what you expect.

      +
    8. +
    9. Re-run npm run test:languages -- --language=foo-bar to verify that the test passes.
    10. +
    +
  12. +
  13. +

    Add an example page.

    + +

    Create a new file examples/prism-foo-bar.html. This will be the template containing the example markup. Just look at other examples to see how these files are structured.
    + We don't have any rules as to what counts as an example, so a single Full example section where you present the highlighting of the major features of the language is enough.

    +
  14. +
  15. +

    Run npm test to check that all tests pass, not just your language tests.
    + This will usually pass without problems. If you can't get all the tests to pass, skip this step.

    +
  16. +
  17. +

    Run npm run build again.

    + +

    Your language definition is now ready!

    +
  18. +
+
-

then the style token will be added (and processed) at the end. Prism.languages.insertBefore allows you to insert - tokens before existing tokens. For the CSS example above, you would use it like this:

-
Prism.languages.insertBefore('markup', 'cdata', {
-	'style': {
-		/* tokens */
+
+

Dependencies

+ +

Languages and plugins can depend on each other, so Prism has its own dependency system to declare and resolve dependencies.

+ +

Declaring dependencies

+ +

You declare a dependency by adding a property to the entry of your language or plugin in the components.json file. The name of the property will be dependency kind and its value will be the component id of the dependee. If multiple languages or plugins are depended upon then you can also declare an array of component ids.

+ +

In the following example, we will use the require dependency kind to declare that a fictional language Foo depends on the JavaScript language and that another fictional language Bar depends on both JavaScript and CSS.

+ +
{
+	"languages": {
+		"javascript": { "title": "JavaScript" },
+		"css": { "title": "CSS" },
+		...,
+		"foo": {
+			"title": "Foo",
+			"require": "javascript"
+		},
+		"bar": {
+			"title": "Bar",
+			"require": ["css", "javascript"]
+		}
 	}
-});
+}
+ +

Dependency kinds

+ +

There are 3 kinds of dependencies:

+ +
+
require
+
+ Prism will ensure that all dependees are loaded before the depender.
+ You are not allowed to modify the dependees unless they are also declared as modify. + +

This kind of dependency is most useful if you e.g. extend another language or dependee as an embedded language (e.g. like PHP is embedded in HTML).

+
+
optional
+
+ Prism will ensure that an optional dependee is loaded before the depender if the dependee is loaded. Unlike require dependencies which also guarantee that the dependees are loaded, optional dependencies only guarantee the order of loaded components.
+ You are not allowed to modify the dependees. If you need to modify the optional dependee, declare it as modify instead. + +

This kind of dependency is useful if you have embedded languages but you want to give the users a choice as to whether they want to include the embedded language. By using optional dependencies, users can better control the bundle size of Prism by only including the languages they need.
+ E.g. HTTP can highlight JSON and XML payloads but it doesn't force the user to include these languages.

+
+
modify
+
+ This is an optional dependency which also declares that the depender might modify the dependees. + +

This kind of dependency is useful if your language modifies another language (e.g. by adding tokens).
+ E.g. CSS Extras adds new tokens to the CSS language.

+
+
-

Parameters

-
-
inside
-
The property of root that contains the object to be modified.
+

To summarize the properties of the different dependency kinds:

+ + + + + + + + + + + + + + + + + +
Non-optionalOptional
Read onlyrequireoptional
Modifiablemodify
+ + + +

Note: You can declare a component as both require and modify

+ +

Resolving dependencies

-
before
-
Key to insert before (String)
+

We consider the dependencies of components an implementation detail, so they may change from release to release. Prism will usually resolve dependencies for you automatically. So you won't have to worry about dependency loading if you download a bundle or use the loadLanguages function in NodeJS, the AutoLoader, or our Babel plugin.

-
insert
-
An object containing the key-value pairs to be inserted
+

If you have to resolve dependencies yourself, use the getLoader function exported by dependencies.js. Example:

+ +
const getLoader = require('prismjs/dependencies');
+const components = require('prismjs/components');
+
+const componentsToLoad = ['markup', 'css', 'php'];
+const loadedComponents = ['clike', 'javascript'];
+
+const loader = getLoader(components, componentsToLoad, loadedComponents);
+loader.load(id => {
+	require(`prismjs/components/prism-${id}.min.js`);
+});
+ +

For more details on the getLoader API, check out the inline documentation.

-
root
-
The root object, i.e. the object that contains the object that will be modified. Optional, default value is Prism.languages.
-
- +

Writing plugins

@@ -137,111 +356,23 @@

Writing plugins

} });

Of course, to understand which hooks to use you would have to read Prism’s source. Imagine where you would add your code and then find the appropriate hook. - If there is no hook you can use, you may request one to be added, detailing why you need it there. + If there is no hook you can use, you may request one to be added, detailing why you need it there.

API documentation

-
-

Prism.highlightAll(async, callback)

-

This is the most high-level function in Prism’s API. It fetches all the elements that have a .language-xxxx class - and then calls Prism.highlightElement() on each one of them.

- -

Parameters

-
-
async
-
- Whether to use Web Workers to improve performance and avoid blocking the UI when highlighting very large - chunks of code. False by default - (why?).
- Note: All language definitions required to highlight the code must be included in the main prism.js - file for the async highlighting to work. You can build your own bundle on the Download page. -
- -
callback
-
- An optional callback to be invoked after the highlighting is done. Mostly useful when async - is true, since in that case, the highlighting is done asynchronously. -
-
-
- -
-

Prism.highlightAllUnder(element, async, callback)

-

Fetches all the descendants of element that have a .language-xxxx class - and then calls Prism.highlightElement() on each one of them.

- -

Parameters

-
-
element
-
The root element, whose descendants that have a .language-xxxx class will be highlighted.
- -
async
-
Same as in Prism.highlightAll()
- -
callback
-
Same as in Prism.highlightAll()
-
-
- -
-

Prism.highlightElement(element, async, callback)

-

Highlights the code inside a single element.

- -

Parameters

-
-
element
-
The element containing the code. It must have a class of language-xxxx to be processed, where xxxx is a valid language identifier.
- -
async
-
Same as in Prism.highlightAll()
-
callback
-
Same as in Prism.highlightAll()
-
-
- -
-

Prism.highlight(text, grammar)

-

Low-level function, only use if you know what you’re doing. - It accepts a string of text as input and the language definitions to use, and returns a string with the HTML produced.

- -

Parameters

-
-
text
-
A string with the code to be highlighted.
-
grammar
-
An object containing the tokens to use. Usually a language definition like Prism.languages.markup
-
- -

Returns

-

The highlighted HTML

-
- -
-

Prism.tokenize(text, grammar)

-

This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input and the language definitions to use, and returns an array with the tokenized code. - When the language definition includes nested tokens, the function is called recursively on each of these tokens. This method could be useful in other contexts as well, as a very crude parser.

- -

Parameters

-
-
text
-
A string with the code to be highlighted.
-
grammar
-
An object containing the tokens to use. Usually a language definition like Prism.languages.markup
-
- -

Returns

-

An array of strings, tokens (class Prism.Token) and other arrays.

-
+

All public and stable parts of Prism's API are documented here.

-
+
+ - + + - + diff --git a/faq.html b/faq.html index 31903a5e52..8dd2a57338 100644 --- a/faq.html +++ b/faq.html @@ -3,9 +3,9 @@ - + FAQ ▲ Prism - + - + - + - +
-
- +
+

FAQ

Frequently Asked Questions, with a few Questions I want people to Frequently Ask.

This page doesn’t work in Opera!

- +

Prism works fine in Opera. However, this page might sometimes appear to not be working in Opera, due to the theme switcher triggering an Opera bug. This will be fixed soon.

Isn’t it bad to do syntax highlighting with regular expressions?

- -

It is true that to correctly handle every possible case of syntax found in the wild, one would need to write a full-blown parser. + +

It is true that to correctly handle every possible case of syntax found in the wild, one would need to write a full-blown parser. However, in most web applications and websites a small error margin is usually acceptable and a rare highlighting failure is not the end of the world. A syntax highlighter based on regular expressions might only be accurate 99% of the time (the actual percentage is just a guess), but in exchange for the small error margin, it offers some very important benefits: - +

  • Smaller filesize. Proper parsers are very big.
  • -
  • Extensibility. Authors can define new languages simply by knowing how to code regular expressions. +
  • Extensibility. Authors can define new languages simply by knowing how to code regular expressions. Writing a correct, unambiguous BNF grammar is a task at least an order of magnitude harder.
  • Graceful error recovery. Parsers fail on incorrect syntax, where regular expressions keep matching.
- +

For this reason, most syntax highlighters on the web and on desktop, are powered by regular expressions. This includes the internal syntax highlighters used by popular native applications like Espresso and Sublime Text, at the time of writing. Of course, not every regex-powered syntax highlighter is created equal. The number and type of failures can be vastly different, depending on - the exact algorithm used. Prism’s known failures are documented in the Examples section.

+ the exact algorithm used. Prism’s known failures are documented on this page..

Why is asynchronous highlighting disabled by default?

- +

Web Workers are good for preventing syntax highlighting of really large code blocks from blocking the main UI thread. In most cases, you will want to highlight reasonably sized chunks of code, and this will not be needed. Furthermore, using Web Workers is actually slower than synchronously highlighting, due to the overhead of creating and terminating the Worker. It just appears faster in these cases because it doesn’t block the main thread. - In addition, since Web Workers operate on files instead of objects, plugins that hook on core parts of Prism (e.g. modify language definitions) + In addition, since Web Workers operate on files instead of objects, plugins that hook on core parts of Prism (e.g. modify language definitions) will not work unless included in the same file (using the builder in the Download page will protect you from this pitfall). Lastly, Web Workers cannot interact with the DOM and most other APIs (e.g. the console), so they are notoriously hard to debug.

@@ -73,14 +73,14 @@

Why is asynchronous highlighting disabled by default?

Why is pre-existing HTML stripped off?

- -

Because it would complicate the code a lot, although it’s not a crucial feature for most people. + +

Because it would complicate the code a lot, although it’s not a crucial feature for most people. If it’s very important to you, you can use the Keep Markup plugin.

If pre-existing HTML is stripped off, how can I highlight certain parts of the code?

- +

There is a number of ways around it. You can always break the block of code into multiple parts, and wrap the HTML around it (or just use a .highlight class). You can see an example of this in action at the “Basic usage” section of the homepage.

Another way around the limitation is to use the Line Highlght plugin, to highlight and link to specific lines and/or line ranges. @@ -88,57 +88,22 @@

If pre-existing HTML is stripped off, how can I highlight certain parts of t

How do I know which tokens I can style for every language?

- -

Every token that is highlighted gets two classes: token and a class with the token type (e.g. comment). - You can find the different types of tokens either by looking at the keys of the object defining the language or by running this snippet in the console: -

function printTokens(o, prefix) { for (var i in o) { console.log((prefix? prefix + ' > ' : '') + i); if (o[i].inside) printTokens(o[i].inside, (prefix? prefix + ' > ' : '') + i); } };
-

Then you can use the function for every language you want to examine. For example, markup:

-
printTokens(Prism.languages.markup);
-

which outputs:

-
comment
-prolog
-doctype
-script
-script > tag
-script > tag > tag
-script > tag > tag > punctuation
-script > tag > tag > namespace
-script > tag > attr-value
-script > tag > attr-value > punctuation
-script > tag > punctuation
-script > tag > attr-name
-script > tag > attr-name > namespace
-script > rest
-style
-style > tag
-style > tag > tag
-style > tag > tag > punctuation
-style > tag > tag > namespace
-style > tag > attr-value
-style > tag > attr-value > punctuation
-style > tag > punctuation
-style > tag > attr-name
-style > tag > attr-name > namespace
-style > rest
-cdata
-tag
-tag > tag
-tag > tag > punctuation
-tag > tag > namespace
-tag > attr-value
-tag > attr-value > punctuation
-tag > punctuation
-tag > attr-name
-tag > attr-name > namespace
-entity
+ +

Every token that is highlighted gets at least two classes: token and a class with the token type (e.g. comment) plus any number of aliases. + Aliases can be seen as additional token types and are used to give specialized tokens a more common class for easier styling. + You can find the different types of tokens either by looking at the keys of the object defining the language or by using the below interface.

+ +

Language:

+
+ +

Additionally, you can find a list of standard tokens on this page.

How can I use different highlighting for tokens with the same name in different languages?

-

Just use a descendant selector, that includes the language class. The default prism.css does this, to have different colors for +

Just use a descendant selector, that includes the language class. The default prism.css does this, to have different colors for JavaScript strings (which are very common) and CSS strings (which are relatively rare). Here’s that code, simplified to illustrate the technique: -


-.token.string {
+	
.token.string {
 	color: #690;
 }
 
@@ -157,11 +122,17 @@ 

How can I use different highlighting for tokens with the same name in differ }

-
+
+ - + + + - - + - \ No newline at end of file + diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 7ae0264253..0000000000 --- a/gulpfile.js +++ /dev/null @@ -1,143 +0,0 @@ -var gulp = require('gulp'), - rename = require('gulp-rename'), - uglify = require('gulp-uglify'), - header = require('gulp-header'), - concat = require('gulp-concat'), - replace = require('gulp-replace'), - fs = require('fs'), - - paths = { - componentsFile: 'components.json', - componentsFileJS: 'components.js', - components: ['components/**/*.js', '!components/index.js', '!components/**/*.min.js'], - main: [ - 'components/prism-core.js', - 'components/prism-markup.js', - 'components/prism-css.js', - 'components/prism-clike.js', - 'components/prism-javascript.js', - 'plugins/file-highlight/prism-file-highlight.js' - ], - plugins: ['plugins/**/*.js', '!plugins/**/*.min.js'], - showLanguagePlugin: 'plugins/show-language/prism-show-language.js', - autoloaderPlugin: 'plugins/autoloader/prism-autoloader.js', - changelog: 'CHANGELOG.md' - }, - - componentsPromise = new Promise(function (resolve, reject) { - fs.readFile(paths.componentsFile, { - encoding: 'utf-8' - }, function (err, data) { - if (!err) { - resolve(JSON.parse(data)); - } else { - reject(err); - } - }); - }); - -gulp.task('components', function() { - return gulp.src(paths.components) - .pipe(uglify()) - .pipe(rename({ suffix: '.min' })) - .pipe(gulp.dest('components')); -}); - -gulp.task('build', function() { - return gulp.src(paths.main) - .pipe(header('\n/* **********************************************\n' + - ' Begin <%= file.relative %>\n' + - '********************************************** */\n\n')) - .pipe(concat('prism.js')) - .pipe(gulp.dest('./')); -}); - -gulp.task('plugins', ['languages-plugins'], function() { - return gulp.src(paths.plugins) - .pipe(uglify()) - .pipe(rename({ suffix: '.min' })) - .pipe(gulp.dest('plugins')); -}); - -gulp.task('components-json', function (cb) { - componentsPromise.then(function (data) { - data = 'var components = ' + JSON.stringify(data) + ';\n' + - 'if (typeof module !== \'undefined\' && module.exports) { module.exports = components; }'; - fs.writeFile(paths.componentsFileJS, data, cb); - }); -}); - -gulp.task('watch', function() { - gulp.watch(paths.components, ['components', 'build']); - gulp.watch(paths.plugins, ['plugins', 'build']); -}); - -gulp.task('languages-plugins', function (cb) { - componentsPromise.then(function (data) { - var languagesMap = {}; - var dependenciesMap = {}; - for (var p in data.languages) { - if (p !== 'meta') { - var title = data.languages[p].displayTitle || data.languages[p].title; - var ucfirst = p.substring(0, 1).toUpperCase() + p.substring(1); - if (title !== ucfirst) { - languagesMap[p] = title; - } - - for (var name in data.languages[p].aliasTitles) { - languagesMap[name] = data.languages[p].aliasTitles[name]; - } - - if(data.languages[p].require) { - dependenciesMap[p] = data.languages[p].require; - } - } - } - - var jsonLanguagesMap = JSON.stringify(languagesMap); - var jsonDependenciesMap = JSON.stringify(dependenciesMap); - - var tasks = [ - {plugin: paths.showLanguagePlugin, map: jsonLanguagesMap}, - {plugin: paths.autoloaderPlugin, map: jsonDependenciesMap} - ]; - - var cpt = 0; - var l = tasks.length; - var done = function() { - cpt++; - if(cpt === l) { - cb && cb(); - } - }; - - tasks.forEach(function(task) { - var stream = gulp.src(task.plugin) - .pipe(replace( - /\/\*languages_placeholder\[\*\/[\s\S]*?\/\*\]\*\//, - '/*languages_placeholder[*/' + task.map + '/*]*/' - )) - .pipe(gulp.dest(task.plugin.substring(0, task.plugin.lastIndexOf('/')))); - - stream.on('error', done); - stream.on('end', done); - }); - }); -}); - -gulp.task('changelog', function (cb) { - return gulp.src(paths.changelog) - .pipe(replace( - /#(\d+)(?![\d\]])/g, - '[#$1](https://github.com/PrismJS/prism/issues/$1)' - )) - .pipe(replace( - /\[[\da-f]+(?:, *[\da-f]+)*\]/g, - function (match) { - return match.replace(/([\da-f]{7})[\da-f]*/g, '[`$1`](https://github.com/PrismJS/prism/commit/$1)'); - } - )) - .pipe(gulp.dest('.')); -}); - -gulp.task('default', ['components', 'components-json', 'plugins', 'build']); diff --git a/gulpfile.js/changelog.js b/gulpfile.js/changelog.js new file mode 100644 index 0000000000..88597ba336 --- /dev/null +++ b/gulpfile.js/changelog.js @@ -0,0 +1,395 @@ +'use strict'; + +const { src, dest } = require('gulp'); + +const replace = require('gulp-replace'); +const pump = require('pump'); +const git = require('simple-git/promise')(__dirname); + +const { changelog } = require('./paths'); + + +const ISSUE_RE = /#(\d+)(?![\d\]])/g; +const ISSUE_SUB = '[#$1](https://github.com/PrismJS/prism/issues/$1)'; + +function linkify(cb) { + return pump([ + src(changelog), + replace(ISSUE_RE, ISSUE_SUB), + replace( + /\[[\da-f]+(?:, *[\da-f]+)*\]/g, + m => m.replace(/([\da-f]{7})[\da-f]*/g, '[`$1`](https://github.com/PrismJS/prism/commit/$1)') + ), + dest('.') + ], cb); +} + +/** + * Creates an array which iterates its items in the order given by `compareFn`. + * + * The array may not be sorted at all times. + * + * @param {(a: T, b: T) => number} compareFn + * @returns {T[]} + * @template T + */ +function createSortedArray(compareFn) { + /** @type {T[]} */ + const a = []; + + a['sort'] = function () { + return Array.prototype.sort.call(this, compareFn); + }; + a[Symbol.iterator] = function () { + return this.slice().sort(compareFn)[Symbol.iterator](); + }; + + return a; +} + +/** + * Parses the given log line and adds the list of the changed files to the output. + * + * @param {string} line A one-liner log line consisting of the commit hash and the commit message. + * @returns {Promise} + * + * @typedef {{ message: string, hash: string, changes: CommitChange[] }} CommitInfo + * @typedef {{ file: string, mode: ChangeMode }} CommitChange + * @typedef {"A" | "C" | "D" | "M" | "R" | "T" | "U" | "X" | "B"} ChangeMode + */ +async function getCommitInfo(line) { + // eslint-disable-next-line regexp/no-super-linear-backtracking + const [, hash, message] = /^([a-f\d]+)\s+(.*)$/i.exec(line); + + /* The output looks like this: + * + * M components.js + * M components.json + * + * or nothing for e.g. reverts. + */ + const output = await git.raw(['diff-tree', '--no-commit-id', '--name-status', '-r', hash]); + + const changes = !output ? [] : output.trim().split(/\n/g).map(line => { + const [, mode, file] = /(\w)\s+(.+)/.exec(line); + return { mode: /** @type {ChangeMode} */ (mode), file }; + }); + + return { hash, message, changes }; +} + +/** + * Parses the output of `git log` with the given revision range. + * + * @param {string | Promise} range The revision range in which the log will be parsed. + * @returns {Promise} + */ +async function getLog(range) { + /* The output looks like this: + * + * bfbe4464 Invoke `callback` after `after-highlight` hook (#1588) + * b41fb8f1 Fixes regex for JS examples (#1591) + */ + const output = await git.raw(['log', await Promise.resolve(range), '--oneline']); + + if (output) { + const commits = output.trim().split(/\n/g); + return Promise.all(commits.map(getCommitInfo)); + } else { + return []; + } +} + +const revisionRanges = { + nextRelease() { + return git.raw(['describe', '--abbrev=0', '--tags']).then(res => `${res.trim()}..HEAD`); + } +}; +const strCompare = (a, b) => a.localeCompare(b, 'en'); + +async function changes() { + const { languages, plugins } = require('../components.js'); + + const infos = await getLog(revisionRanges.nextRelease()); + + const entries = { + 'TODO:': {}, + 'New components': { + ['']: createSortedArray(strCompare) + }, + 'Updated components': {}, + 'Updated plugins': {}, + 'Updated themes': {}, + 'Other': {}, + }; + /** + * + * @param {string} category + * @param {string | { message: string, hash: string }} info + */ + function addEntry(category, info) { + const path = category.split(/\s*>>\s*/); + if (path[path.length - 1] !== '') { + path.push(''); + } + + let current = entries; + for (const key of path) { + if (key) { + current = current[key] = current[key] || {}; + } else { + (current[key] = current[key] || []).push(info); + } + } + } + + + /** @param {CommitChange} change */ + function notGenerated(change) { + return !change.file.endsWith('.min.js') + && !change.file.startsWith('docs/') + && ['prism.js', 'components.js', 'package-lock.json'].indexOf(change.file) === -1; + } + /** @param {CommitChange} change */ + function notPartlyGenerated(change) { + return change.file !== 'plugins/autoloader/prism-autoloader.js' && + change.file !== 'plugins/show-language/prism-show-language.js'; + } + /** @param {CommitChange} change */ + function notTests(change) { + return !/^tests\//.test(change.file); + } + /** @param {CommitChange} change */ + function notExamples(change) { + return !/^examples\//.test(change.file); + } + /** @param {CommitChange} change */ + function notFailures(change) { + return !/^known-failures.html$/.test(change.file); + } + /** @param {CommitChange} change */ + function notComponentsJSON(change) { + return change.file !== 'components.json'; + } + + /** + * @param {((e: T, index: number) => boolean)[]} filters + * @returns {(e: T, index: number) => boolean} + * @template T + */ + function and(...filters) { + return (e, index) => { + for (let i = 0, l = filters.length; i < l; i++) { + if (!filters[i](e, index)) { + return false; + } + } + return true; + }; + } + + /** + * Some commit message have the format `component changed: actual message`. + * This function can be used to remove this prefix. + * + * @param {string} prefix + * @param {CommitInfo} info + * @returns {{ message: string, hash: string }} + */ + function removeMessagePrefix(prefix, info) { + const source = String.raw`^${prefix.replace(/([^-\w\s])/g, '\\$1').replace(/[-\s]/g, '[-\\s]')}:\s*`; + const patter = RegExp(source, 'i'); + return { + message: info.message.replace(patter, ''), + hash: info.hash + }; + } + + + /** + * @type {((info: CommitInfo) => boolean)[]} + */ + const commitSorters = [ + + function rebuild(info) { + if (info.changes.length > 0 && info.changes.filter(notGenerated).length === 0) { + console.log('Rebuild found: ' + info.message); + return true; + } + }, + + function addedComponent(info) { + let relevantChanges = info.changes.filter(and(notGenerated, notTests, notExamples, notFailures)); + + // `components.json` has to be modified + if (relevantChanges.some(c => c.file === 'components.json')) { + relevantChanges = relevantChanges.filter(and(notComponentsJSON, notPartlyGenerated)); + + // now, only the newly added JS should be left + if (relevantChanges.length === 1) { + const change = relevantChanges[0]; + if (change.mode === 'A' && change.file.startsWith('components/prism-')) { + const lang = change.file.match(/prism-([\w-]+)\.js$/)[1]; + const entry = languages[lang] || { + title: 'REMOVED LANGUAGE ' + lang, + }; + const titles = [entry.title]; + if (entry.aliasTitles) { + titles.push(...Object.values(entry.aliasTitles)); + } + addEntry('New components', `__${titles.join('__ & __')}__: ${infoToString(info)}`); + return true; + } + } + } + }, + + function changedComponentOrCore(info) { + let relevantChanges = info.changes.filter(and(notGenerated, notTests, notExamples, notFailures)); + + // if `components.json` changed, then autoloader and show-language also change + if (relevantChanges.some(c => c.file === 'components.json')) { + relevantChanges = relevantChanges.filter(and(notComponentsJSON, notPartlyGenerated)); + } + + if (relevantChanges.length === 1) { + const change = relevantChanges[0]; + if (change.mode === 'M' && change.file.startsWith('components/prism-')) { + const lang = change.file.match(/prism-([\w-]+)\.js$/)[1]; + if (lang === 'core') { + addEntry('Other >> Core', removeMessagePrefix('Core', info)); + } else { + const title = languages[lang].title; + addEntry('Updated components >> ' + title, removeMessagePrefix(title, info)); + } + return true; + } + } + }, + + function changedPlugin(info) { + let relevantChanges = info.changes.filter(and(notGenerated, notTests, notExamples, c => !/\.(?:css|html)$/.test(c.file))); + + if (relevantChanges.length > 0 && + relevantChanges.every(c => c.mode === 'M' && /^plugins\/.*\.js$/.test(c.file))) { + + if (relevantChanges.length === 1) { + const change = relevantChanges[0]; + const id = change.file.match(/\/prism-([\w-]+)\.js/)[1]; + const title = plugins[id].title || plugins[id]; + addEntry('Updated plugins >> ' + title, removeMessagePrefix(title, info)); + } else { + addEntry('Updated plugins', info); + } + return true; + } + }, + + function changedTheme(info) { + if (info.changes.length > 0 && info.changes.every(c => { + return /themes\/.*\.css/.test(c.file) && c.mode === 'M'; + })) { + if (info.changes.length === 1) { + const change = info.changes[0]; + let name = (change.file.match(/prism-(\w+)\.css$/) || [, 'Default'])[1]; + name = name[0].toUpperCase() + name.substr(1); + addEntry('Updated themes >> ' + name, removeMessagePrefix(name, info)); + } else { + addEntry('Updated themes', info); + } + return true; + } + }, + + function changedInfrastructure(info) { + let relevantChanges = info.changes.filter(notGenerated); + + if (relevantChanges.length > 0 && relevantChanges.every(c => { + if (/^(?:gulpfile.js|tests)\//.test(c.file)) { + // gulp tasks or tests + return true; + } + if (/^\.[\w.]+$/.test(c.file)) { + // a .something file + return true; + } + return ['bower.json', 'CNAME', 'composer.json', 'package.json', 'package-lock.json'].indexOf(c.file) >= 0; + })) { + addEntry('Other >> Infrastructure', info); + return true; + } + + // or dependencies.js + const excludeTests = info.changes.filter(notTests); + if (excludeTests.length === 1 && excludeTests[0].file === 'dependencies.js') { + addEntry('Other >> Infrastructure', info); + return true; + } + }, + + function changedWebsite(info) { + if (info.changes.length > 0 && info.changes.every(c => { + return /[\w-]+\.html$/.test(c.file) || /^(?:assets|docs)\//.test(c.file); + })) { + addEntry('Other >> Website', info); + return true; + } + }, + + function otherChanges(info) { + // detect changes of the Github setup + // This assumes that .md files are related to GitHub + if (info.changes.length > 0 && info.changes.every(c => /\.md$/i.test(c.file))) { + addEntry('Other', info); + return true; + } + }, + + ]; + + for (const info of infos) { + if (!commitSorters.some(sorter => sorter(info))) { + addEntry('TODO:', info); + } + } + + + let md = ''; + + /** + * Stringifies the given commit info. + * + * @param {string | CommitInfo} info + * @returns {string} + */ + function infoToString(info) { + if (typeof info === 'string') { + return info; + } + return `${info.message} [\`${info.hash}\`](https://github.com/PrismJS/prism/commit/${info.hash})`; + } + function printCategory(category, indentation = '') { + for (const subCategory of Object.keys(category).sort(strCompare)) { + if (subCategory) { + md += `${indentation}* __${subCategory}__\n`; + printCategory(category[subCategory], indentation + ' '); + } else { + for (const info of category['']) { + md += `${indentation}* ${infoToString(info)}\n`; + } + } + } + } + + for (const category of Object.keys(entries)) { + md += `\n### ${category}\n\n`; + printCategory(entries[category]); + } + console.log(md); +} + + +module.exports = { + linkify, + changes +}; diff --git a/gulpfile.js/docs.js b/gulpfile.js/docs.js new file mode 100644 index 0000000000..7b23cafbe8 --- /dev/null +++ b/gulpfile.js/docs.js @@ -0,0 +1,71 @@ +'use strict'; + +const { src, dest, series } = require('gulp'); +const replace = require('gulp-replace'); +const jsdoc = require('gulp-jsdoc3'); +const pump = require('pump'); +const del = require('del'); + +const jsDoc = { + config: '../.jsdoc.json', + readme: 'README.md', + files: ['components/prism-core.js'], + junk: ['docs/fonts/Source-Sans-Pro', 'docs/**/Apache-License-2.0.txt'] +}; + + +function docsClean() { + return del([ + // everything in the docs folder + 'docs/**/*', + // except for our CSS overwrites + '!docs/styles', + '!docs/styles/overwrites.css', + ]); +} + +function docsCreate(cb) { + let config = require(jsDoc.config); + let files = [jsDoc.readme].concat(jsDoc.files); + src(files, { read: false }).pipe(jsdoc(config, cb)); +} + +function docsAddFavicon(cb) { + return pump([ + src('docs/*.html'), + replace( + /\s*<\/head>/, + '\n $&' + ), + dest('docs/') + ], cb); +} + +function docsRemoveExcessFiles() { + return del(jsDoc.junk); +} + +function docsFixLineEnds(cb) { + // https://github.com/jsdoc/jsdoc/issues/1837 + return pump([ + src('docs/*.html'), + replace(/\r\n?|\n/g, '\n'), + dest('docs/') + ], cb); +} + +const docs = series(docsClean, docsCreate, docsRemoveExcessFiles, docsAddFavicon, docsFixLineEnds); + +module.exports = { + docs, + handlers: { + jsdocCommentFound(comment) { + // This is a hack. + // JSDoc doesn't support TS' type import syntax (e.g. `@type {import("./my-file.js").Type}`) and throws an + // error if used. So we just replace the "function" with some literal that JSDoc will interpret as a + // namespace. Not pretty but it works. + comment.comment = comment.comment + .replace(/\bimport\s*\(\s*(?:"(?:[^"\r\n\\]|\\.)*"|'(?:[^'\r\n\\]|\\.)*')\s*\)/g, '__dyn_import__'); + } + } +}; diff --git a/gulpfile.js/index.js b/gulpfile.js/index.js new file mode 100644 index 0000000000..be62e8175e --- /dev/null +++ b/gulpfile.js/index.js @@ -0,0 +1,295 @@ +'use strict'; + +const { src, dest, series, parallel, watch } = require('gulp'); + +const rename = require('gulp-rename'); +const uglify = require('gulp-uglify'); +const header = require('gulp-header'); +const concat = require('gulp-concat'); +const replace = require('gulp-replace'); +const cleanCSS = require('gulp-clean-css'); +const webfont = require('webfont').default; +const pump = require('pump'); +const util = require('util'); +const fs = require('fs'); + +const paths = require('./paths'); +const { changes, linkify } = require('./changelog'); +const { docs } = require('./docs'); + + +const componentsPromise = new Promise((resolve, reject) => { + fs.readFile(paths.componentsFile, { + encoding: 'utf-8' + }, (err, data) => { + if (!err) { + resolve(JSON.parse(data)); + } else { + reject(err); + } + }); +}); + +function inlineRegexSource() { + return replace( + /\/((?:[^\n\r[\\\/]|\\.|\[(?:[^\n\r\\\]]|\\.)*\])+)\/\s*\.\s*source\b/g, + (m, source) => { + // escape backslashes + source = source.replace(/\\(.)|\[(?:\\s\\S|\\S\\s)\]/g, function (m, g1) { + if (g1) { + // characters like /\n/ can just be kept as "\n" instead of being escaped to "\\n" + if (/[nrt0/]/.test(g1)) { + return m; + } + if ('\\' == g1) { + return '\\\\\\\\'; // escape using 4 backslashes + } + return '\\\\' + g1; + } else { + return '[^]'; + } + }); + // escape single quotes + source = source.replace(/'/g, "\\'"); + // wrap source in single quotes + return "'" + source + "'"; + } + ); +} + +function minifyJS() { + return [ + inlineRegexSource(), + uglify() + ]; +} + + +function minifyComponents(cb) { + pump([src(paths.components), ...minifyJS(), rename({ suffix: '.min' }), dest('components')], cb); +} +function minifyPlugins(cb) { + pump([src(paths.plugins), ...minifyJS(), rename({ suffix: '.min' }), dest('plugins')], cb); +} +function minifyPluginCSS(cb) { + pump([src(paths.pluginsCSS), cleanCSS(), rename({ suffix: '.min' }), dest('plugins')], cb); +} +function minifyThemes(cb) { + pump([src(paths.themes), cleanCSS(), rename({ suffix: '.min' }), dest('themes')], cb); +} +function build(cb) { + pump([src(paths.main), header(` +/* ********************************************** + Begin <%= file.relative %> +********************************************** */ + +`), concat('prism.js'), dest('./')], cb); +} + +async function componentsJsonToJs() { + const data = await componentsPromise; + const js = `var components = ${JSON.stringify(data)}; +if (typeof module !== 'undefined' && module.exports) { module.exports = components; }`; + return util.promisify(fs.writeFile)(paths.componentsFileJS, js); +} + +function watchComponentsAndPlugins() { + watch(paths.components, parallel(minifyComponents, build)); + watch(paths.plugins, parallel(minifyPlugins, build)); +} + +async function languagePlugins() { + const data = await componentsPromise; + /** @type {Record} */ + const languagesMap = {}; + const dependenciesMap = {}; + const aliasMap = {}; + + /** + * Tries to guess the name of a language given its id. + * + * From `prism-show-language.js`. + * + * @param {string} id The language id. + * @returns {string} + */ + function guessTitle(id) { + if (!id) { + return id; + } + return (id.substring(0, 1).toUpperCase() + id.substring(1)).replace(/s(?=cript)/, 'S'); + } + + /** + * @param {string} key + * @param {string} title + */ + function addLanguageTitle(key, title) { + if (!(key in languagesMap)) { + if (guessTitle(key) === title) { + languagesMap[key] = null; + } else { + languagesMap[key] = title; + } + } + } + + for (const id in data.languages) { + if (id !== 'meta') { + const language = data.languages[id]; + const title = language.displayTitle || language.title; + + addLanguageTitle(id, title); + + for (const name in language.aliasTitles) { + addLanguageTitle(name, language.aliasTitles[name]); + } + + if (language.alias) { + if (typeof language.alias === 'string') { + aliasMap[language.alias] = id; + addLanguageTitle(language.alias, title); + } else { + language.alias.forEach(function (alias) { + aliasMap[alias] = id; + addLanguageTitle(alias, title); + }); + } + } + + if (language.require) { + dependenciesMap[id] = language.require; + } + } + } + + function formattedStringify(json) { + return JSON.stringify(json, null, '\t').replace(/\n/g, '\n\t'); + } + + /** @type {Record} */ + const nonNullLanguageMap = { + 'none': 'Plain text', + 'plain': 'Plain text', + 'plaintext': 'Plain text', + 'text': 'Plain text', + 'txt': 'Plain text' + }; + for (const id in languagesMap) { + const title = languagesMap[id]; + if (title) { + nonNullLanguageMap[id] = title; + } + } + + const jsonLanguagesMap = formattedStringify(nonNullLanguageMap); + const jsonDependenciesMap = formattedStringify(dependenciesMap); + const jsonAliasMap = formattedStringify(aliasMap); + + const tasks = [ + { + plugin: paths.showLanguagePlugin, + maps: { languages: jsonLanguagesMap } + }, + { + plugin: paths.autoloaderPlugin, + maps: { aliases: jsonAliasMap, dependencies: jsonDependenciesMap } + } + ]; + + // TODO: Use `Promise.allSettled` (https://github.com/tc39/proposal-promise-allSettled) + const taskResults = await Promise.all(tasks.map(async task => { + try { + const value = await new Promise((resolve, reject) => { + const stream = src(task.plugin) + .pipe(replace( + /\/\*(\w+)_placeholder\[\*\/[\s\S]*?\/\*\]\*\//g, + (m, mapName) => `/*${mapName}_placeholder[*/${task.maps[mapName]}/*]*/` + )) + .pipe(dest(task.plugin.substring(0, task.plugin.lastIndexOf('/')))); + + stream.on('error', reject); + stream.on('end', resolve); + }); + return { status: 'fulfilled', value }; + } catch (error) { + return { status: 'rejected', reason: error }; + } + })); + + const rejectedTasks = taskResults.filter(/** @returns {r is {status: 'rejected', reason: any}} */ r => r.status === 'rejected'); + if (rejectedTasks.length > 0) { + throw rejectedTasks.map(r => r.reason); + } +} + +async function treeviewIconFont() { + // List of all icons + // Add new icons to the end of the list. + const iconList = [ + 'file', 'folder', + 'image', 'audio', 'video', + 'text', 'code', + 'archive', 'pdf', + 'excel', 'powerpoint', 'word' + ]; + const fontName = 'PrismTreeview'; + + // generate the font + const result = await webfont({ + files: iconList.map(n => `plugins/treeview/icons/${n}.svg`), + formats: ['woff'], + fontName, + sort: false + }); + + /** @type {Buffer} */ + const woff = result.woff; + /** + * @type {{ contents: string; srcPath: string; metadata: Metadata }[]} + * @typedef Metadata + * @property {string} path + * @property {string} name + * @property {string[]} unicode + * @property {boolean} renamed + * @property {number} width + * @property {number} height + * */ + const glyphsData = result.glyphsData; + + const fontFace = ` +/* @GENERATED-FONT */ +@font-face { + font-family: "${fontName}"; + /** + * This font is generated from the .svg files in the \`icons\` folder. See the \`treeviewIconFont\` function in + * \`gulpfile.js/index.js\` for more information. + * + * Use the following escape sequences to refer to a specific icon: + * + * - ${glyphsData.map(({ metadata }) => { + const codePoint = metadata.unicode[0].codePointAt(0); + return `\\${codePoint.toString(16)} ${metadata.name}`; + }).join('\n\t * - ')} + */ + src: url("data:application/font-woff;base64,${woff.toString('base64')}") + format("woff"); +} +`.trim(); + + const cssPath = 'plugins/treeview/prism-treeview.css'; + const fontFaceRegex = /\/\*\s*@GENERATED-FONT\s*\*\/\s*@font-face\s*\{(?:[^{}/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\}/; + + const css = fs.readFileSync(cssPath, 'utf-8'); + fs.writeFileSync(cssPath, css.replace(fontFaceRegex, fontFace), 'utf-8'); +} + +const components = minifyComponents; +const plugins = series(languagePlugins, treeviewIconFont, minifyPlugins, minifyPluginCSS); + +module.exports = { + watch: watchComponentsAndPlugins, + default: series(parallel(components, plugins, minifyThemes, componentsJsonToJs, build), docs), + linkify, + changes +}; diff --git a/gulpfile.js/paths.js b/gulpfile.js/paths.js new file mode 100644 index 0000000000..4f8389d1bc --- /dev/null +++ b/gulpfile.js/paths.js @@ -0,0 +1,21 @@ +'use strict'; + +module.exports = { + componentsFile: 'components.json', + componentsFileJS: 'components.js', + components: ['components/**/*.js', '!components/index.js', '!components/**/*.min.js'], + themes: ['themes/*.css', '!themes/*.min.css'], + main: [ + 'components/prism-core.js', + 'components/prism-markup.js', + 'components/prism-css.js', + 'components/prism-clike.js', + 'components/prism-javascript.js', + 'plugins/file-highlight/prism-file-highlight.js' + ], + plugins: ['plugins/**/*.js', '!plugins/**/*.min.js'], + pluginsCSS: ['plugins/**/*.css', '!plugins/**/*.min.css'], + showLanguagePlugin: 'plugins/show-language/prism-show-language.js', + autoloaderPlugin: 'plugins/autoloader/prism-autoloader.js', + changelog: 'CHANGELOG.md' +}; diff --git a/index.html b/index.html index 83f8317931..71f64e5f88 100644 --- a/index.html +++ b/index.html @@ -7,11 +7,11 @@ window.console && console.log('foo'); - + Prism - + - + @@ -19,7 +19,7 @@
-
+
  • @@ -57,14 +57,15 @@

    Used By

    Prism is used on several websites, small and large. Some of them are:

    - Smashing Magazine - A List Apart - Mozilla Developer Network (MDN) - CSS-Tricks - SitePoint - Drupal - React - Stripe + Smashing Magazine + A List Apart + Mozilla Developer Network (MDN) + CSS-Tricks + SitePoint + Drupal + React + Stripe + MySQL

@@ -75,13 +76,13 @@

Examples


 
 	

This page’s CSS code, highlighted with Prism:

-

+	

 
 	

This page’s HTML, highlighted with Prism:


 
 	

This page’s logo (SVG), highlighted with Prism:

-

+	

 
 	

If you’re still not sold, you can view more examples or try it out for yourself.

@@ -95,19 +96,23 @@

Full list of features

Prism forces you to use the correct element for marking up code: <code>. On its own for inline code, or inside a <pre> for blocks of code. In addition, the language is defined through the way recommended in the HTML5 draft: through a language-xxxx class. -
  • The language definition is inherited. This means that if multiple code snippets have the same language, you can just define it once, in one of their common ancestors.
  • -
  • Supports parallelism with Web Workers, if available. Disabled by default (why?).
  • -
  • Very easy to extend without modifying the code, due to Prism’s plugin architecture. Multiple hooks are scattered throughout the source.
  • -
  • Very easy to define new languages. Only thing you need is a good understanding of regular expressions
  • -
  • All styling is done through CSS, with sensible class names rather than ugly namespaced abbreviated nonsense.
  • -
  • Wide browser support: IE9+, Firefox, Chrome, Safari, Opera, most Mobile browsers
  • -
  • Highlights embedded languages (e.g. CSS inside HTML, JavaScript inside HTML)
  • -
  • Highlights inline code as well, not just code blocks
  • -
  • Highlights nested languages (CSS in HTML, JavaScript in HTML)
  • -
  • It doesn’t force you to use any Prism-specific markup, not even a Prism-specific class name, only standard markup you should be using anyway. So, you can just try it for a while, remove it if you don’t like it and leave no traces behind.
  • -
  • Highlight specific lines and/or line ranges (requires plugin)
  • -
  • Show invisible characters like tabs, line breaks etc (requires plugin)
  • -
  • Autolink URLs and emails, use Markdown links in comments (requires plugin)
  • +
  • The language-xxxx class is inherited. + This means that if multiple code snippets have the same language, you can just define it once,in one of their common ancestors.
  • +
  • Supports parallelism with Web Workers, if available. + Disabled by default (why?).
  • +
  • Very easy to extend without modifying the code, due to Prism’s plugin architecture. + Multiple hooks are scattered throughout the source.
  • +
  • Very easy to define new languages. + The only thing you need is a good understanding of regular expressions.
  • +
  • All styling is done through CSS, with sensible class names rather than ugly, namespaced, abbreviated nonsense.
  • +
  • Wide browser support: Edge, IE11, Firefox, Chrome, Safari, Opera, most mobile browsers.
  • +
  • Highlights embedded languages (e.g. CSS inside HTML, JavaScript inside HTML).
  • +
  • Highlights inline code as well, not just code blocks.
  • +
  • It doesn’t force you to use any Prism-specific markup, not even a Prism-specific class name, only standard markup you should be using anyway. + So, you can just try it for a while, remove it if you don’t like it and leave no traces behind.
  • +
  • Highlight specific lines and/or line ranges (requires plugin).
  • +
  • Show invisible characters like tabs, line breaks etc (requires plugin).
  • +
  • Autolink URLs and emails, use Markdown links in comments (requires plugin).
  • @@ -115,87 +120,154 @@

    Full list of features

    Limitations

    • Any pre-existing HTML in the code will be stripped off. There are ways around it though.
    • -
    • Regex-based so it *will* fail on certain edge cases, which are documented in the Examples section.
    • -
    • No IE 6-8 support. If someone can read code, they are probably in the 85% of the population with a modern browser.
    • +
    • Regex-based so it *will* fail on certain edge cases, which are documented in the known failures page.
    • +
    • Some of our themes have problems with certain layouts. Known cases are documented here.
    • +
    • No IE 6-10 support. If someone can read code, they are probably in the 95% of the population with a modern browser.

    Basic usage

    -

    You will need to include the prism.css and prism.js files you downloaded in your page. Example: +

    You will need to include the prism.css and prism.js files you downloaded in your page. Example:

    <!DOCTYPE html>
     <html>
     <head>
    -	...
    -	<link href="themes/prism.css" rel="stylesheet" />
    -</head>
    +	...
    +	<link href="themes/prism.css" rel="stylesheet" />
    +</head>
     <body>
    -	...
    -	<script src="prism.js"></script>
    -</body>
    +	...
    +	<script src="prism.js"></script>
    +</body>
     </html>

    Prism does its best to encourage good authoring practices. Therefore, it only works with <code> elements, since marking up code without a <code> element is semantically invalid. According to the HTML5 spec, the recommended way to define a code language is a language-xxxx class, which is what Prism uses. Alternatively, Prism also supports a shorter version: lang-xxxx.

    -

    To make things easier however, Prism assumes that this language definition is inherited. Therefore, if multiple <code> elements have the same language, you can add the language-xxxx class on one of their common ancestors. - This way, you can also define a document-wide default language, by adding a language-xxxx class on the <body> or <html> element.

    - -

    If you want to opt-out of highlighting for a <code> element that is a descendant of an element with a declared code language, you can add the class language-none to it (or any non-existing language, really).

    The recommended way to mark up a code block (both for semantics and for Prism) is a <pre> element with a <code> element inside, like so:

    +
    <pre><code class="language-css">p { color: red }</code></pre>
    +

    If you use that pattern, the <pre> will automatically get the language-xxxx class (if it doesn’t already have it) and will be styled as a code block.

    -

    If you want to prevent any elements from being automatically highlighted, you can use the attribute data-manual on the <script> element you used for prism and use the API. +

    Inline code snippets are done like this:

    + +
    <code class="language-css">p { color: red }</code>
    + +

    Note: You have to escape all < and & characters inside <code> elements (code blocks and inline snippets) with &lt; and &amp; respectively, or else the browser might interpret them as an HTML tag or entity. If you have large portions of HTML code, you can use the Unescaped Markup plugin to work around this.

    + +

    Language inheritance

    + +

    To make things easier however, Prism assumes that the language class is inherited. Therefore, if multiple <code> elements have the same language, you can add the language-xxxx class on one of their common ancestors. + This way, you can also define a document-wide default language, by adding a language-xxxx class on the <body> or <html> element.

    + +

    If you want to opt-out of highlighting a <code> element that inherits its language, you can add the language-none class to it. The none language can also be inherited to disable highlighting for the element with the class and all of its descendants.

    + +

    If you want to opt-out of highlighting but still use plugins like Show Invisibles, add use language-plain class instead.

    + +

    Manual highlighting

    + +

    If you want to prevent any elements from being automatically highlighted and instead use the API, you can set Prism.manual to true before the DOMContentLoaded event is fired. By setting the data-manual attribute on the <script> element containing Prism core, this will be done automatically. Example:

    +
    <script src="prism.js" data-manual></script>
    -

    If you want to use Prism on the server or through the command line, Prism can be used with Node.js as well. - This might be useful if you're trying to generate static HTML pages with highlighted code for environments that don't support browser-side JS, like AMP pages.

    +

    or

    + +
    <script>
    +window.Prism = window.Prism || {};
    +window.Prism.manual = true;
    +</script>
    +<script src="prism.js"></script>
    -

    You can install Prism for Node.js by running:

    -
    $ npm install prismjs
    +

    Usage with CDNs

    -

    Example:

    -
    var Prism = require('prismjs');
    +	

    In combination with CDNs, we recommend using the Autoloader plugin which automatically loads languages when necessary.

    + +

    The setup of the Autoloader, will look like the following. You can also add your own themes of course.

    + +
    <!DOCTYPE html>
    +<html>
    +<head>
    +	...
    +	<link href="https://{{cdn}}/prismjs@v1.x/themes/prism.css" rel="stylesheet" />
    +</head>
    +<body>
    +	...
    +	<script src="https://{{cdn}}/prismjs@v1.x/components/prism-core.min.js"></script>
    +	<script src="https://{{cdn}}/prismjs@v1.x/plugins/autoloader/prism-autoloader.min.js"></script>
    +</body>
    +</html>
    + +

    Please note that links in the above code sample serve as placeholders. You have to replace them with valid links to the CDN of your choice.

    + +

    CDNs which provide PrismJS are e.g. cdnjs, jsDelivr, and UNPKG.

    + +

    Usage with Webpack, Browserify, & Other Bundlers

    + +

    If you want to use Prism with a bundler, install Prism with npm:

    + +
    $ npm install prismjs
    + +

    You can then import into your bundle:

    + +
    import Prism from 'prismjs';
    + +

    To make it easy to configure your Prism instance with only the languages and plugins you need, use the babel plugin, + babel-plugin-prismjs. This will allow you to load + the minimum number of languages and plugins to satisfy your needs. + See that plugin's documentation for configuration details.

    + +

    Usage with Node

    + +

    If you want to use Prism on the server or through the command line, Prism can be used with Node.js as well. + This might be useful if you're trying to generate static HTML pages with highlighted code for environments that don't support browser-side JS, like AMP pages.

    + +

    Example:

    +
    const Prism = require('prismjs');
     
     // The code snippet you want to highlight, as a string
    -var code = "var data = 1;";
    +const code = `var data = 1;`;
     
     // Returns a highlighted HTML string
    -var html = Prism.highlight(code, Prism.languages.javascript, 'javascript');
    +const html = Prism.highlight(code, Prism.languages.javascript, 'javascript');

    Requiring prismjs will load the default languages: markup, css, - clike and javascript. You can load more languages separately by requiring them - directly from the components folder. Or you can use the loadLanguages() utility, that - will automatically handle any required dependencies.

    + clike and javascript. You can load more languages with the + loadLanguages() utility, which will automatically handle any required dependencies.

    Example:

    -
    var Prism = require('prismjs');
    -var loadLanguages = require('prismjs/components/index.js');
    +	
    const Prism = require('prismjs');
    +const loadLanguages = require('prismjs/components/');
     loadLanguages(['haml']);
     
     // The code snippet you want to highlight, as a string
    -var code = "= ['hi', 'there', 'reader!'].join \" \"";
    +const code = `= ['hi', 'there', 'reader!'].join " "`;
     
     // Returns a highlighted HTML string
    -var html = Prism.highlight(code, Prism.languages.haml, 'haml');
    +const html = Prism.highlight(code, Prism.languages.haml, 'haml');
    + +

    Note: Do not use loadLanguages() with Webpack or another bundler, as this will cause Webpack to include all languages and plugins. Use the babel plugin described above.

    + +

    Note: loadLanguages() will ignore unknown languages and log warning messages to the console. You can prevent the warnings by setting loadLanguages.silent = true.

    -
    +

    Supported languages

    This is the list of all languages currently supported by Prism, with their corresponding alias, to use in place of xxxx in the language-xxxx (or lang-xxxx) class:

    +
    +

    Couldn’t find the language you were looking for? Request it!

    Plugins

    Plugins are additional scripts (and CSS code) that extend Prism’s functionality. Many of the following plugins are official, but are released as plugins to keep the Prism Core small for those who don’t need the extra functionality.

    -
      +

        No assembly required to use them. Just select them in the download page.

        It’s very easy to write your own Prism plugins. Did you write a plugin for Prism that you want added to this list? Send a pull request!

        @@ -206,6 +278,7 @@

        Third-party language definitions

        @@ -215,15 +288,20 @@

        Third-party tutorials

        Several tutorials have been written by members of the community to help you integrate Prism into multiple different website types and configurations:

        Please note that the tutorials listed here are not verified to contain correct information. Read at your risk and always check the official documentation here if something doesn’t work :)

        @@ -234,20 +312,21 @@

        Third-party tutorials

        Credits

        -
        +
        + - + - + + + + + + + +
        +
        + +

        Known failures

        +

        A list of rare edge cases where Prism highlights code incorrectly.

        +
        + +
        +

        There are certain edge cases where Prism will fail. There are always such cases in every regex-based syntax highlighter.
        + However, Prism dares to be open and honest about them. If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug.

        +
        + + +
        + +

        Comments only support one level of nesting

        +
        (* Nested block
        +	(* comments
        +		(* on more than
        +		2 levels *)
        +	are *)
        +not supported *)
        + +
        + + +
        + +

        Nested block comments

        +
        #cs
        +	#cs
        +		foo()
        +	#ce
        +#ce
        + +
        + + +
        + +

        Two levels of nesting inside C section

        +
        {
        +	if($1) {
        +		if($2) {
        +
        +		}
        +	}
        +} // <- Broken
        +%%
        +%%
        + +
        + + +
        + +

        Comments only support one level of nesting

        +
        /+ /+ /+ this does not work +/ +/ +/
        + +

        Token strings only support one level of nesting

        +
        q{ q{ q{ this does not work } } }
        + +
        + + +
        + +

        String interpolation in single-quoted strings

        +
        '#{:atom} <- this should not be highligted'
        + +
        + + +
        + +

        Two divisions on the same line

        +
        2 / 3 / 4
        + +
        + + +
        + +

        Names starting with a number

        +
        The box 1A is a container
        + +
        + + +
        + +

        String interpolation containing a closing brace

        +
        `${ /* } */ a + b }`
        +`${ '}' }`
        + +

        String interpolation with deeply nested braces

        +
        `${foo({ a: { b: { c: true } } })}`
        + +
        + + +
        + +

        At-rules looking like variables

        +
        @import "some file.less";
        + +

        At-rules containing interpolation

        +
        @import "@{themes}/tidal-wave.less";
        + +

        extend is not highlighted consistently

        +
        nav ul {
        +  &:extend(.inline);
        +  background: blue;
        +}
        +.a:extend(.b) {}
        + +
        + + +
        + +

        Functions with a single string parameter not using parentheses are not highlighted

        +
        foobar"param";
        + +
        + + +
        + +

        Numbers with underscores

        +
        mov     ax,1100_1000b
        +mov     ax,1100_1000y
        +mov     ax,0b1100_1000
        +mov     ax,0y1100_1000
        +
        +dd    1.222_222_222
        + +
        + + +
        + +

        Code block starting with a comment

        +
        # Doesn't work
        +# Does work
        +
         # Does work when prefixed with a space
        + +

        Comments inside expressions break literals and operators

        +
        ^if(
        +    $age>=4  # not too young
        +    && $age<=80  # and not too old
        +)
        + +
        + + +
        + +

        Null-ary predicates are not highlighted

        +
        halt.
        +trace.
        +
        +:- if(test1).
        +section_1.
        +:- elif(test2).
        +section_2.
        +:- elif(test3).
        +section_3.
        +:- else.
        +section_else.
        +:- endif.
        + +
        + + +
        + +

        More than one level of nested braces inside interpolation

        +
        "Foobar ${foo({
        +    bar => {baz => 42}
        +    baz => 42
        +})} <- broken"
        + +
        + + +
        + +

        Interpolation expressions containing strings with { or }

        +
        f"{'}'}"
        + +
        + + +
        + +

        The global context is highlighted as a verb

        +
        \d .
        + +
        + + +
        + +

        Nothing is highlighted inside table cells

        +
        +---------------+----------+
        +| column 1     | column 2  |
        ++--------------+-----------+
        +| **bold**?    | *italic*? |
        ++--------------+-----------+
        + +

        The inline markup recognition rules are not as strict as they are in the spec

        +

        No inline markup should be highlighted in the following code.

        +
        2 * x a ** b (* BOM32_* ` `` _ __ |
        +"*" '|' (*) [*] {*} <*> ‘*’ ‚*‘ ‘*‚ ’*’ ‚*’ “*” „*“ “*„ ”*” „*” »*« ›*‹ «*» »*» ›*›
        + +
        + + +
        + +

        Nested block comments

        +
        /* Nested block
        +	/* comments
        +	are */
        +not supported */
        + +

        Delimiters of parameters for closures that don't use braces

        +
        |x| x + 1i;
        + +
        + + +
        + +

        Deprecated Sass syntax is not supported

        +
        .page
        +  color = 5px + 9px
        +
        +!width = 13px
        +.icon
        +  width = !width
        + +

        Selectors with pseudo classes are highlighted as property/value pairs

        +
        a:hover
        +  text-decoration: underline
        + +
        + + +
        + +

        Nested block comments

        +
        /* Nested block
        +	/* comments
        +	are */
        +not supported */
        + +
        + + +
        + +

        The first argument of case-lambda argument lists are highlighted as functions

        +
        (define plus
        +	(case-lambda
        +		(() 0)
        +		((x) x)
        +		((x y) (+ x y))
        +		((x y z) (+ (+ x y) z))
        +		(args (apply + args))))
        + +
        + + +
        + +

        Nested block comments

        +
        /* Nested block
        +	/* comments
        +	are */
        +not supported */
        + +
        + + +
        + +

        HTML inside Textile is not supported

        + +

        But Textile inside HTML should be just fine.

        + +
        <strong>This _should_ work properly.</strong>
        +*But this is <em>definitely</em> broken.*
        + +
        + + +
        + +

        Tag containing Twig is not highlighted

        +
        <div{% if foo %} class="bar"{% endif %}></div>
        + +
        + + +
        + +

        Nested magic words are not supported

        + +
        {{#switch:{{PAGENAME}}
        +| L'Aquila = No translation
        +| L = Not OK
        +| L'Aquila = Entity escaping
        +| L'Aquila = Numeric char encoding
        +}}
        + +

        Nesting of bold and italic is not supported

        +
        ''Italic with '''bold''' inside''
        + +
        + + +
        + +

        Themes

        + +

        Some of our themes are not compatible with certain layouts.

        + +

        Coy

        + +

        Coy's shadows and background might not wrap around the code correctly if combined with float of flexbox layouts.

        + + + +

        Workarounds

        + +

        There are 2 possible workarounds:

        + +

        The first workaround is setting display: flex-root; for the pre element. This will fix the issue but flex-root has limited browser support.

        + +

        The second is adding clear: both; to the style of the pre element. This will fix the issue but it will change the way code blocks behave when overlapping with other elements.

        + +
        + + +
        + + + + + + + + + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..51f76b340c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8545 @@ +{ + "name": "prismjs", + "version": "1.27.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.3.tgz", + "integrity": "sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA==", + "dev": true + }, + "@babel/polyfill": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", + "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", + "dev": true, + "requires": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.4" + } + }, + "@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@octokit/auth-token": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.2.tgz", + "integrity": "sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ==", + "dev": true, + "requires": { + "@octokit/types": "^5.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.8.tgz", + "integrity": "sha512-MuRrgv+bM4Q+e9uEvxAB/Kf+Sj0O2JAOBA131uo1o6lgdq1iS8ejKwtqHgdfY91V3rN9R/hdGKFiQYMzVzVBEQ==", + "dev": true, + "requires": { + "@octokit/types": "^5.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + } + } + }, + "@octokit/plugin-paginate-rest": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", + "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.1" + }, + "dependencies": { + "@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + } + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz", + "integrity": "sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg==", + "dev": true + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", + "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.1", + "deprecation": "^2.3.1" + }, + "dependencies": { + "@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + } + } + }, + "@octokit/request": { + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.9.tgz", + "integrity": "sha512-CzwVvRyimIM1h2n9pLVYfTDmX9m+KHSgCpqPsY8F1NdEK8IaWqXhSBXsdjOBFZSpEcxNEeg4p0UO9cQ8EnOCLA==", + "dev": true, + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^5.0.0", + "deprecation": "^2.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "once": "^1.4.0", + "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "@octokit/request-error": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.2.tgz", + "integrity": "sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw==", + "dev": true, + "requires": { + "@octokit/types": "^5.0.1", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "@octokit/request-error": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", + "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", + "dev": true, + "requires": { + "@octokit/types": "^2.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "dependencies": { + "@octokit/types": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", + "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + } + } + }, + "@octokit/rest": { + "version": "16.43.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz", + "integrity": "sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==", + "dev": true, + "requires": { + "@octokit/auth-token": "^2.4.0", + "@octokit/plugin-paginate-rest": "^1.1.1", + "@octokit/plugin-request-log": "^1.0.0", + "@octokit/plugin-rest-endpoint-methods": "2.4.0", + "@octokit/request": "^5.2.0", + "@octokit/request-error": "^1.0.2", + "atob-lite": "^2.0.0", + "before-after-hook": "^2.0.0", + "btoa-lite": "^1.0.0", + "deprecation": "^2.0.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2", + "lodash.uniq": "^4.5.0", + "octokit-pagination-methods": "^1.1.0", + "once": "^1.4.0", + "universal-user-agent": "^4.0.0" + } + }, + "@octokit/types": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz", + "integrity": "sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ==", + "dev": true, + "requires": { + "@types/node": ">= 8" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.2.tgz", + "integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==", + "dev": true + }, + "@types/node-fetch": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz", + "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true + }, + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "acorn": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", + "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "dev": true + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } + } + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-retry": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", + "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", + "dev": true, + "requires": { + "retry": "0.12.0" + } + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "atob-lite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", + "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", + "dev": true + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "basic-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", + "dev": true + }, + "beeper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-2.0.0.tgz", + "integrity": "sha512-+ShExQEewPvKdTUOtCAJmkUAgEyNF0QqgiAhPRE5xLvoFkIPt8xuHKaz1gMLzSMS73beHWs9gbRBngdH61nVWw==", + "dev": true, + "requires": { + "delay": "^4.1.0" + } + }, + "before-after-hook": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", + "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==", + "dev": true + }, + "benchmark": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", + "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", + "dev": true, + "requires": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "binaryextensions": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz", + "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", + "dev": true + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "catharsis": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "comment-parser": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.2.tgz", + "integrity": "sha512-AOdq0i8ghZudnYv8RUnHrhTgafUGs61Rdz9jemU5x2lnZwAWyOq7vySo626K59e1fVKH1xSRorJwPVRLSWOoAQ==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-props": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "dev": true, + "requires": { + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + } + } + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "cubic2quad": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cubic2quad/-/cubic2quad-1.1.1.tgz", + "integrity": "sha1-abGcYaP1tB7PLx1fro+wNBWqixU=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "danger": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/danger/-/danger-10.5.0.tgz", + "integrity": "sha512-KUqwc8WFmW4JqPpgG4cssOZQE1aYRj/If/ZX+XNOsMRhxJH5cY9ij6VQH7C/pP64UGqmMNNV6jSsbxOOAWMy4w==", + "dev": true, + "requires": { + "@babel/polyfill": "^7.2.5", + "@octokit/rest": "^16.43.1", + "async-retry": "1.2.3", + "chalk": "^2.3.0", + "commander": "^2.18.0", + "debug": "^4.1.1", + "fast-json-patch": "^3.0.0-1", + "get-stdin": "^6.0.0", + "gitlab": "^10.0.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "hyperlinker": "^1.0.0", + "json5": "^2.1.0", + "jsonpointer": "^4.0.1", + "jsonwebtoken": "^8.4.0", + "lodash.find": "^4.6.0", + "lodash.includes": "^4.3.0", + "lodash.isobject": "^3.0.2", + "lodash.keys": "^4.0.8", + "lodash.mapvalues": "^4.6.0", + "lodash.memoize": "^4.1.2", + "memfs-or-file-map-to-github-branch": "^1.1.0", + "micromatch": "^3.1.10", + "node-cleanup": "^2.1.2", + "node-fetch": "2.6.1", + "override-require": "^1.1.1", + "p-limit": "^2.1.0", + "parse-diff": "^0.7.0", + "parse-git-config": "^2.0.3", + "parse-github-url": "^1.0.2", + "parse-link-header": "^1.0.1", + "pinpoint": "^1.1.0", + "prettyjson": "^1.2.1", + "readline-sync": "^1.4.9", + "require-from-string": "^2.0.2", + "supports-hyperlinks": "^1.0.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + } + } + }, + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "dev": true + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "dependencies": { + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "deepmerge": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz", + "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==", + "dev": true + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "delay": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-4.3.0.tgz", + "integrity": "sha512-Lwaf3zVFDMBop1yDuFZ19F9WyGcZcGacsbdlZtWjQmM50tOcMntm1njF/Nb/Vjij3KaSvCF+sEYGKrrjObu2NA==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "docdash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/docdash/-/docdash-1.2.0.tgz", + "integrity": "sha512-IYZbgYthPTspgqYeciRJNPhSwL51yer7HAwDXhF5p+H7mTDbPvY3PCk/QDjNxdPCpWkaJVFC4t7iCNB/t9E5Kw==", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, + "domhandler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", + "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1" + } + }, + "domutils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.0.0.tgz", + "integrity": "sha512-n5SelJ1axbO636c2yUtOGia/IcJtVtlhQbFiVDBZHKV5ReJO1ViX7sFEemtuyoAnBxk5meNSYgA8V4s0271efg==", + "dev": true, + "requires": { + "dom-serializer": "^0.2.1", + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0" + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "dev": true, + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + } + } + }, + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "eslint": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz", + "integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "eslint-plugin-jsdoc": { + "version": "32.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-32.3.0.tgz", + "integrity": "sha512-zyx7kajDK+tqS1bHuY5sapkad8P8KT0vdd/lE55j47VPG2MeenSYuIY/M/Pvmzq5g0+3JB+P3BJGUXmHxtuKPQ==", + "dev": true, + "requires": { + "comment-parser": "1.1.2", + "debug": "^4.3.1", + "jsdoctypeparser": "^9.0.0", + "lodash": "^4.17.20", + "regextras": "^0.7.1", + "semver": "^7.3.4", + "spdx-expression-parse": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + } + } + }, + "eslint-plugin-regexp": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-1.4.0.tgz", + "integrity": "sha512-H+APSyKFrhPOaVAdsLa3qLPD6SgkzNPypxM+lnx5fwbUY9Pcw5XV3bJkxt7JIjdsL1B5NMdQXOhN3N8LtyVa5A==", + "dev": true, + "requires": { + "comment-parser": "^1.1.2", + "eslint-utils": "^3.0.0", + "grapheme-splitter": "^1.0.4", + "jsdoctypeparser": "^9.0.0", + "refa": "^0.9.0", + "regexp-ast-analysis": "^0.3.0", + "regexpp": "^3.2.0", + "scslre": "^0.1.6" + }, + "dependencies": { + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + }, + "regexp-ast-analysis": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.3.0.tgz", + "integrity": "sha512-11PlbBSUxwWpdj6BdZUKfhDdV9g+cveqHB+BqBQDBD7ZermDBVgtyowUaXTvT0dO3tZYo2bDIr/GoED6X1aYSA==", + "dev": true, + "requires": { + "refa": "^0.9.0", + "regexpp": "^3.2.0" + } + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fast-json-patch": { + "version": "3.0.0-1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.0.0-1.tgz", + "integrity": "sha512-6pdFb07cknxvPzCeLsFHStEy+MysPJPgZQ9LbQ/2O67unQF93SNqfdSqnPPl71YMHX+AD8gbl7iuoGFzHEdDuw==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fetch-blob": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", + "integrity": "sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA==", + "dev": true, + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + } + } + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "requires": { + "fetch-blob": "^3.1.2" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "geometry-interfaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz", + "integrity": "sha512-qD6OdkT6NcES9l4Xx3auTpwraQruU7dARbQPVO71MKvkGYw5/z/oIiGymuFXrRaEQa5Y67EIojUpaLeGEa5hGA==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + } + } + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "git-config-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz", + "integrity": "sha1-bTP37WPbDQ4RgTFQO6s6ykfVRmQ=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "homedir-polyfill": "^1.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "gitlab": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/gitlab/-/gitlab-10.2.1.tgz", + "integrity": "sha512-z+DxRF1C9uayVbocs9aJkJz+kGy14TSm1noB/rAIEBbXOkOYbjKxyuqJzt+0zeFpXFdgA0yq6DVVbvM7HIfGwg==", + "dev": true, + "requires": { + "form-data": "^2.5.0", + "humps": "^2.0.1", + "ky": "^0.12.0", + "ky-universal": "^0.3.0", + "li": "^1.3.0", + "query-string": "^6.8.2", + "universal-url": "^2.0.0" + }, + "dependencies": { + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + } + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", + "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "gulp-cli": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" + } + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + } + } + }, + "gulp-clean-css": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-4.3.0.tgz", + "integrity": "sha512-mGyeT3qqFXTy61j0zOIciS4MkYziF2U594t2Vs9rUnpkEHqfu6aDITMp8xOvZcvdX61Uz3y1mVERRYmjzQF5fg==", + "dev": true, + "requires": { + "clean-css": "4.2.3", + "plugin-error": "1.0.1", + "through2": "3.0.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "through2": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", + "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "dev": true, + "requires": { + "readable-stream": "2 || 3" + } + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } + }, + "gulp-header": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-2.0.7.tgz", + "integrity": "sha512-qppGkYGQZnt/mRJiiR5wYZIUwNUn47Xpg4+6tHYDVeAW5IDLbHBQwbw7axfMLWGE+gKQpB+yXLeslHMw1/Haog==", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.1.0", + "lodash.template": "^4.4.0", + "map-stream": "0.0.7", + "through2": "^2.0.0" + } + }, + "gulp-jsdoc3": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-jsdoc3/-/gulp-jsdoc3-3.0.0.tgz", + "integrity": "sha512-rE2jAwCPA8XFi9g4V3Z3LPhZNjxuMTIYQVMjdqZAQpRfJITLVaUK3xfmiiNTMc7j+fT7pL8Q5yj7ZPRdwCJWNg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1", + "beeper": "^2.0.0", + "debug": "^4.1.1", + "fancy-log": "^1.3.3", + "ink-docstrap": "^1.3.2", + "jsdoc": "^3.6.3", + "map-stream": "0.0.7", + "tmp": "0.1.0" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "gulp-rename": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", + "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "dev": true + }, + "gulp-replace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", + "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", + "dev": true, + "requires": { + "istextorbinary": "2.2.1", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" + } + }, + "gulp-uglify": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hasurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hasurl/-/hasurl-1.0.0.tgz", + "integrity": "sha512-43ypUd3DbwyCT01UYpA99AEZxZ4aKtRxWGBHEIbjcOsUghd9YUON0C+JF6isNjaiwC/UF5neaUudy6JS9jZPZQ==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "htmlparser2": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.0.0.tgz", + "integrity": "sha512-cChwXn5Vam57fyXajDtPXL1wTYc8JtLbr2TN76FYu05itVVVealxLowe2B3IEznJG4p9HAYn/0tJaRlGuEglFQ==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "http-server": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", + "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", + "dev": true, + "requires": { + "basic-auth": "^1.0.3", + "colors": "^1.4.0", + "corser": "^2.0.1", + "ecstatic": "^3.3.2", + "http-proxy": "^1.18.0", + "minimist": "^1.2.5", + "opener": "^1.5.1", + "portfinder": "^1.0.25", + "secure-compare": "3.0.1", + "union": "~0.5.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "humps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", + "integrity": "sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=", + "dev": true + }, + "hyperlinker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", + "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + }, + "ink-docstrap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ink-docstrap/-/ink-docstrap-1.3.2.tgz", + "integrity": "sha512-STx5orGQU1gfrkoI/fMU7lX6CSP7LBGO10gXNgOZhwKhUqbtNjCkYSewJtNnLmWP1tAGN6oyEpG1HFPw5vpa5Q==", + "dev": true, + "requires": { + "moment": "^2.14.1", + "sanitize-html": "^1.13.0" + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true + }, + "is-path-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.1.0.tgz", + "integrity": "sha512-Sc5j3/YnM8tDeyCsVeKlm/0p95075DyLmDEIkSgQ7mXkrOX+uTCtmQFm0CYzVyJwcCCmO3k8qfJt17SxQwB5Zw==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "requires": { + "xmlcreate": "^2.0.3" + } + }, + "jsdoc": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.4.tgz", + "integrity": "sha512-3G9d37VHv7MFdheviDCjUfQoIjdv4TC5zTTf5G9VODLtOnVS6La1eoYBDlbWfsRT3/Xo+j2MIqki2EV12BZfwA==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^0.8.2", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.10.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", + "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "dev": true + } + } + }, + "jsdoctypeparser": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz", + "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==", + "dev": true + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + } + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonpointer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz", + "integrity": "sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg==", + "dev": true + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dev": true, + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "ky": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.12.0.tgz", + "integrity": "sha512-t9b7v3V2fGwAcQnnDDQwKQGF55eWrf4pwi1RN08Fy8b/9GEwV7Ea0xQiaSW6ZbeghBHIwl8kgnla4vVo9seepQ==", + "dev": true + }, + "ky-universal": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.3.0.tgz", + "integrity": "sha512-CM4Bgb2zZZpsprcjI6DNYTaH3oGHXL2u7BU4DK+lfCuC4snkt9/WRpMYeKbBbXscvKkeqBwzzjFX2WwmKY5K/A==", + "dev": true, + "requires": { + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "li": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/li/-/li-1.3.0.tgz", + "integrity": "sha1-IsWbyu+qmo7zWc91l4TkvxBq6hs=", + "dev": true + }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", + "dev": true + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", + "dev": true + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=", + "dev": true + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=", + "dev": true + }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz", + "integrity": "sha1-oIYCrBLk+4P5H8H7ejYKTZujUgU=", + "dev": true + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true + }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "macos-release": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.1.tgz", + "integrity": "sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg==", + "dev": true + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "dev": true, + "requires": { + "make-error": "^1.2.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true + }, + "marked": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", + "dev": true + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "mem": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memfs-or-file-map-to-github-branch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.2.0.tgz", + "integrity": "sha512-PloI9AkRXrLQuBU1s7eYQpl+4hkL0U0h23lddMaJ3ZGUufn8pdNRxd1kCfBqL5gISCFQs78ttXS15e4/f5vcTA==", + "dev": true, + "requires": { + "@octokit/rest": "^16.43.1" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "microbuffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/microbuffer/-/microbuffer-1.0.0.tgz", + "integrity": "sha1-izgy7UDIfVH0e7I0kTppinVtGdI=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", + "dev": true + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "dev": true, + "requires": { + "mime-db": "~1.38.0" + } + }, + "mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "yargs-parser": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neatequal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/neatequal/-/neatequal-1.0.0.tgz", + "integrity": "sha1-LuEhG8n6bkxVcV/SELsFYC6xrjs=", + "dev": true, + "requires": { + "varstream": "^0.3.2" + } + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-cleanup": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", + "integrity": "sha1-esGavSl+Caf3KnFUXZUbUX5N3iw=", + "dev": true + }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true + }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "node-fetch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.1.1.tgz", + "integrity": "sha512-SMk+vKgU77PYotRdWzqZGTZeuFKlsJ0hu4KPviQKkfY+N3vn2MIzr0rvpnYpR8MtB3IEuhlEcuOLbGvLRlA+yg==", + "dev": true, + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.3", + "formdata-polyfill": "^4.0.10" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nunjucks": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.2.tgz", + "integrity": "sha512-KUi85OoF2NMygwODAy28Lh9qHmq5hO3rBlbkYoC8v377h4l8Pt5qFjILl0LWpMbOrZ18CzfVVUvIHUIrtED3sA==", + "dev": true, + "requires": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "chokidar": "^3.3.0", + "commander": "^5.1.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "dev": true + }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "octokit-pagination-methods": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", + "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "dev": true, + "requires": { + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" + } + }, + "override-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/override-require/-/override-require-1.1.1.tgz", + "integrity": "sha1-auIvresfhQ/7DPTCD/e4fl62UN8=", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, + "parse-diff": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.7.1.tgz", + "integrity": "sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg==", + "dev": true + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-git-config": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-2.0.3.tgz", + "integrity": "sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "git-config-path": "^1.0.1", + "ini": "^1.3.5" + } + }, + "parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-link-header": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-link-header/-/parse-link-header-1.0.1.tgz", + "integrity": "sha1-vt/g0hGK64S+deewJUGeyKYRQKc=", + "dev": true, + "requires": { + "xtend": "~4.0.1" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "optional": true + }, + "pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pinpoint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pinpoint/-/pinpoint-1.1.0.tgz", + "integrity": "sha1-DPd1eml38b9/ajIge3CeN3OI6HQ=", + "dev": true + }, + "platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "dev": true + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "prettyjson": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.1.tgz", + "integrity": "sha1-/P+rQdGcq0365eV15kJGYZsS0ok=", + "dev": true, + "requires": { + "colors": "^1.1.2", + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "query-string": { + "version": "6.13.6", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.6.tgz", + "integrity": "sha512-/WWZ7d9na6s2wMEGdVCVgKWE9Rt7nYyNIf7k8xmHXcesPMlEzicWo3lbYwHyA4wBktI2KrXxxZeACLbE84hvSQ==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "dev": true + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "refa": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/refa/-/refa-0.9.1.tgz", + "integrity": "sha512-egU8LgFq2VXlAfUi8Jcbr5X38wEOadMFf8tCbshgcpVCYlE7k84pJOSlnvXF+muDB4igkdVMq7Z/kiNPqDT9TA==", + "dev": true, + "requires": { + "regexpp": "^3.2.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp-ast-analysis": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.2.4.tgz", + "integrity": "sha512-8L7kOZQaKPxKKAwGuUZxTQtlO3WZ+tiXy4s6G6PKL6trbOXcZoumwC3AOHHFtI/xoSbNxt7jgLvCnP1UADLWqg==", + "dev": true, + "requires": { + "refa": "^0.9.0", + "regexpp": "^3.2.0" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "regextras": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.7.1.tgz", + "integrity": "sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==", + "dev": true + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sanitize-html": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.0.tgz", + "integrity": "sha512-U1btucGeYVpg0GoK43jPpe/bDCV4cBOGuxzv5NBd0bOjyZdMKY0n98S/vNlO1wVwre0VCj8H3hbzE7gD2+RjKA==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "htmlparser2": "^4.1.0", + "lodash": "^4.17.15", + "postcss": "^7.0.27", + "srcset": "^2.0.1", + "xtend": "^4.0.1" + }, + "dependencies": { + "htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "scslre": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/scslre/-/scslre-0.1.6.tgz", + "integrity": "sha512-JORxVRlQTfjvlOAaiQKebgFElyAm5/W8b50lgaZ0OkEnKnagJW2ufDh3xRfU75UD9z3FGIu1gL1IyR3Poa6Qmw==", + "dev": true, + "requires": { + "refa": "^0.9.0", + "regexp-ast-analysis": "^0.2.3", + "regexpp": "^3.2.0" + } + }, + "secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-git": { + "version": "1.110.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.110.0.tgz", + "integrity": "sha512-UYY0rQkknk0P5eb+KW+03F4TevZ9ou0H+LoGaj7iiVgpnZH4wdj/HTViy/1tNNkmIPcmtxuBqXWiYt2YwlRKOQ==", + "dev": true, + "requires": { + "debug": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "srcset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-2.0.1.tgz", + "integrity": "sha512-00kZI87TdRKwt+P8jj8UZxbfp7mK2ufxcIMWvhAOZNJTRROimpHeruWrGvCZneiuVDLqdyHefVp748ECTnyUBQ==", + "dev": true + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.fromcodepoint": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.fromcodepoint/-/string.fromcodepoint-0.2.1.tgz", + "integrity": "sha1-jZeDM8C8klOPUPOD5IiPPlYZ1lM=", + "dev": true + }, + "string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==", + "dev": true + }, + "string.prototype.padend": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.2.tgz", + "integrity": "sha512-/AQFLdYvePENU3W5rgurfWSMU6n+Ww8n/3cUt7E+vPBB/D7YDG8x+qjoFs4M/alR2bW7Qg6xMjVwWUOvuQ0XpQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", + "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", + "dev": true, + "requires": { + "has-flag": "^2.0.0", + "supports-color": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + } + } + } + } + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "svg-pathdata": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-5.0.5.tgz", + "integrity": "sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==", + "dev": true + }, + "svg2ttf": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/svg2ttf/-/svg2ttf-4.3.0.tgz", + "integrity": "sha512-LZ0B7zzHWLWbzLzwaKGHQvPOuxCXLReIb3LSxFSGUy1gMw2Utk6KGNbTmbmRL6Rk1qDSmTixnDrQgnXaL9n0CA==", + "dev": true, + "requires": { + "argparse": "^1.0.6", + "cubic2quad": "^1.0.0", + "lodash": "^4.17.10", + "microbuffer": "^1.0.0", + "svgpath": "^2.1.5", + "xmldom": "~0.1.22" + } + }, + "svgicons2svgfont": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-9.1.1.tgz", + "integrity": "sha512-iOj7lqHP/oMrLg7S2Iv89LOJUfmIuePefXcs5ul4IsKwcYvL/T/Buahz+nQQJygyuvEMBBXqnCRmnvJggHeJzA==", + "dev": true, + "requires": { + "commander": "^2.12.2", + "geometry-interfaces": "^1.1.4", + "glob": "^7.1.2", + "neatequal": "^1.0.0", + "readable-stream": "^2.3.3", + "sax": "^1.2.4", + "string.fromcodepoint": "^0.2.1", + "string.prototype.codepointat": "^0.2.0", + "svg-pathdata": "^5.0.0", + "transformation-matrix-js": "^2.7.1" + } + }, + "svgpath": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.3.0.tgz", + "integrity": "sha512-N/4UDu3Y2ICik0daMmFW1tplw0XPs1nVIEVYkTiQfj9/JQZeEtAKaSYwheCwje1I4pQ5r22fGpoaNIvGgsyJyg==", + "dev": true + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "table": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", + "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", + "dev": true, + "requires": { + "ajv": "^7.0.2", + "lodash": "^4.17.20", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ajv": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.4.tgz", + "integrity": "sha512-nBeQgg/ZZA3u3SYxyaDvpvDtgZ/EZPF547ARgZBrG9Bhu1vKDwAIjtIf+sDtJUKa2zOcEbmRLBRSyMraS/Oy1A==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "textextensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", + "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "transformation-matrix-js": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/transformation-matrix-js/-/transformation-matrix-js-2.7.6.tgz", + "integrity": "sha512-1CxDIZmCQ3vA0GGnkdMQqxUXVm3xXAFmglPYRS1hr37LzSg22TC7QAWOT38OmdUvMEs/rqcnkFoAsqvzdiluDg==", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "ttf2eot": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-2.0.0.tgz", + "integrity": "sha1-jmM3pYWr0WCKDISVirSDzmn2ZUs=", + "dev": true, + "requires": { + "argparse": "^1.0.6", + "microbuffer": "^1.0.0" + } + }, + "ttf2woff": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ttf2woff/-/ttf2woff-2.0.2.tgz", + "integrity": "sha512-X68badwBjAy/+itU49scLjXUL094up+rHuYk+YAOTTBYSUMOmLZ7VyhZJuqQESj1gnyLAC2/5V8Euv+mExmyPA==", + "dev": true, + "requires": { + "argparse": "^1.0.6", + "microbuffer": "^1.0.0", + "pako": "^1.0.0" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "uglify-js": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.2.tgz", + "integrity": "sha512-imog1WIsi9Yb56yRt5TfYVxGmnWs3WSGU73ieSOlMVFwhJCA9W8fqFFMMj4kgDqiS/80LGdsYnWL7O9UcjEBlg==", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + } + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "dev": true + }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, + "union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, + "requires": { + "qs": "^6.4.0" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "universal-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universal-url/-/universal-url-2.0.0.tgz", + "integrity": "sha512-3DLtXdm/G1LQMCnPj+Aw7uDoleQttNHp2g5FnNQKR6cP6taNWS1b/Ehjjx4PVyvejKi3TJyu8iBraKM4q3JQPg==", + "dev": true, + "requires": { + "hasurl": "^1.0.0", + "whatwg-url": "^7.0.0" + } + }, + "universal-user-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", + "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", + "dev": true, + "requires": { + "os-name": "^3.1.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "varstream": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/varstream/-/varstream-0.3.2.tgz", + "integrity": "sha1-GKxklHZfP/GjWtmkvgU77BiKXeE=", + "dev": true, + "requires": { + "readable-stream": "^1.0.33" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + } + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "wawoff2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wawoff2/-/wawoff2-1.0.2.tgz", + "integrity": "sha512-qxuTwf5tAP/XojrRc6cmR0hGvqgD3XUxv2fzfzURKPDfE7AeHmtRuankVxdJ4DRdSKXaE5QlyJT49yBis2vb6Q==", + "dev": true, + "requires": { + "argparse": "^1.0.6" + } + }, + "web-streams-polyfill": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", + "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", + "dev": true + }, + "webfont": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/webfont/-/webfont-9.0.0.tgz", + "integrity": "sha512-Sn8KnTXroWAbBHYKUXCUq2rKwqbluupUd7krYqluT+kFGV4dvMuKXaL84Fm/Kfv+5rz2S81jNRvcyQ6ySBiC2Q==", + "dev": true, + "requires": { + "cosmiconfig": "^5.2.0", + "deepmerge": "^3.2.0", + "fs-extra": "^7.0.1", + "globby": "^9.2.0", + "meow": "^5.0.0", + "nunjucks": "^3.2.0", + "p-limit": "^2.2.0", + "resolve-from": "^5.0.0", + "svg2ttf": "^4.0.0", + "svgicons2svgfont": "^9.0.3", + "ttf2eot": "^2.0.0", + "ttf2woff": "^2.0.0", + "wawoff2": "^1.0.2", + "xml2js": "^0.4.17" + }, + "dependencies": { + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + } + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "windows-release": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz", + "integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==", + "dev": true, + "requires": { + "execa": "^1.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } +} diff --git a/package.json b/package.json old mode 100755 new mode 100644 index cba9283b3a..201c71bac1 --- a/package.json +++ b/package.json @@ -1,47 +1,87 @@ { - "name": "prismjs", - "version": "1.14.0", - "description": "Lightweight, robust, elegant syntax highlighting. A spin-off project from Dabblet.", - "main": "prism.js", - "style": "themes/prism.css", - "scripts": { - "test": "mocha tests/testrunner-tests.js && mocha tests/run.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/LeaVerou/prism.git" - }, - "keywords": [ - "prism", - "highlight" - ], - "author": "Lea Verou", - "license": "MIT", - "readmeFilename": "README.md", - "optionalDependencies": { - "clipboard": "^2.0.0" - }, - "devDependencies": { - "chai": "^2.3.0", - "gulp": "^3.8.6", - "gulp-concat": "^2.3.4", - "gulp-header": "^1.0.5", - "gulp-rename": "^1.2.0", - "gulp-uglify": "^0.3.1", - "gulp-replace": "^0.5.4", - "mocha": "^2.2.5", - "yargs": "^3.26.0" - }, - "jspm": { - "main": "prism", - "registry": "jspm", - "jspmPackage": true, - "format": "global", - "files": [ - "components/**/*.js", - "plugins/**/*", - "themes/*.css", - "prism.js" - ] - } + "name": "prismjs", + "version": "1.27.0", + "description": "Lightweight, robust, elegant syntax highlighting. A spin-off project from Dabblet.", + "main": "prism.js", + "style": "themes/prism.css", + "engines": { + "node": ">=6" + }, + "scripts": { + "benchmark": "node benchmark/benchmark.js", + "build": "gulp", + "start": "http-server -c-1", + "lint": "eslint . --cache", + "lint:fix": "npm run lint -- --fix", + "lint:ci": "eslint . --max-warnings 0", + "regex-coverage": "mocha tests/coverage.js", + "test:aliases": "mocha tests/aliases-test.js", + "test:core": "mocha tests/core/**/*.js", + "test:dependencies": "mocha tests/dependencies-test.js", + "test:examples": "mocha tests/examples-test.js", + "test:identifiers": "mocha tests/identifier-test.js", + "test:languages": "mocha tests/run.js", + "test:patterns": "mocha tests/pattern-tests.js", + "test:plugins": "mocha tests/plugins/**/*.js", + "test:runner": "mocha tests/testrunner-tests.js", + "test": "npm-run-all test:*" + }, + "repository": { + "type": "git", + "url": "https://github.com/PrismJS/prism.git" + }, + "keywords": [ + "prism", + "highlight" + ], + "author": "Lea Verou", + "license": "MIT", + "readmeFilename": "README.md", + "devDependencies": { + "@types/node-fetch": "^2.5.5", + "benchmark": "^2.1.4", + "chai": "^4.2.0", + "danger": "^10.5.0", + "del": "^4.1.1", + "docdash": "^1.2.0", + "eslint": "^7.22.0", + "eslint-plugin-jsdoc": "^32.3.0", + "eslint-plugin-regexp": "^1.4.0", + "gulp": "^4.0.2", + "gulp-clean-css": "^4.3.0", + "gulp-concat": "^2.3.4", + "gulp-header": "^2.0.7", + "gulp-jsdoc3": "^3.0.0", + "gulp-rename": "^1.2.0", + "gulp-replace": "^1.0.0", + "gulp-uglify": "^3.0.1", + "gzip-size": "^5.1.1", + "htmlparser2": "^4.0.0", + "http-server": "^0.12.3", + "jsdom": "^16.7.0", + "mocha": "^6.2.0", + "node-fetch": "^3.1.1", + "npm-run-all": "^4.1.5", + "prettier": "^2.4.1", + "pump": "^3.0.0", + "refa": "^0.9.1", + "regexp-ast-analysis": "^0.2.4", + "regexpp": "^3.2.0", + "scslre": "^0.1.6", + "simple-git": "^1.107.0", + "webfont": "^9.0.0", + "yargs": "^13.2.2" + }, + "jspm": { + "main": "prism", + "registry": "jspm", + "jspmPackage": true, + "format": "global", + "files": [ + "components/**/*.js", + "plugins/**/*", + "themes/*.css", + "prism.js" + ] + } } diff --git a/plugins/autolinker/index.html b/plugins/autolinker/index.html index d6200b5e34..b4e4a282c7 100644 --- a/plugins/autolinker/index.html +++ b/plugins/autolinker/index.html @@ -3,68 +3,63 @@ - + Autolinker ▲ Prism plugins - + - + - + -
        -
        - -

        Autolinker

        -

        Converts URLs and emails in code to clickable links. Parses Markdown links in comments.

        -
        +

        How to use

        URLs and emails will be linked automatically, you don’t need to do anything. To link some text inside a comment to a certain URL, - you may use the Markdown syntax: + you may use the Markdown syntax:

        [Text you want to see](http://url-goes-here.com)

        Examples

        - +

        JavaScript

        /**
          * Prism: Lightweight, robust, elegant syntax highlighting
          * MIT license http://www.opensource.org/licenses/mit-license.php/
        - * @author Lea Verou http://lea.verou.me 
        + * @author Lea Verou http://lea.verou.me
          * Reach Lea at fake@email.com (no, not really)
          * And this is [a Markdown link](http://prismjs.com). Sweet, huh?
          */
         var foo = 5;
         // And a single line comment http://google.com
        - -

        CSS

        -
        @font-face {
        +
        +	

        CSS

        +
        @font-face {
         	src: url(http://lea.verou.me/logo.otf);
         	font-family: 'LeaVerou';
         }
        - +

        HTML

        <!-- Links in HTML, woo!
         Lea Verou http://lea.verou.me or, with Markdown, [Lea Verou](http://lea.verou.me) -->
        -<img src="http://prismjs.com/img/spectrum.png" alt="In attributes too!" />
        +<img src="https://prismjs.com/assets/img/spectrum.png" alt="In attributes too!" />
         <p>Autolinking in raw text: http://prismjs.com</p>
        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/autolinker/prism-autolinker.js b/plugins/autolinker/prism-autolinker.js index 3913c98adb..7846dba519 100644 --- a/plugins/autolinker/prism-autolinker.js +++ b/plugins/autolinker/prism-autolinker.js @@ -1,81 +1,76 @@ -(function(){ +(function () { -if ( - typeof self !== 'undefined' && !self.Prism || - typeof global !== 'undefined' && !global.Prism -) { - return; -} + if (typeof Prism === 'undefined') { + return; + } + + var url = /\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~/.:=&@]+(?:\?[\w\-+%~/.:=?&!$'()*,;@]*)?(?:#[\w\-+%~/.:#=?&!$'()*,;@]*)?/; + var email = /\b\S+@[\w.]+[a-z]{2}/; + var linkMd = /\[([^\]]+)\]\(([^)]+)\)/; -var url = /\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~/.:=&]+(?:\?[\w\-+%~/.:#=?&!$'()*,;]*)?(?:#[\w\-+%~/.:#=?&!$'()*,;]*)?/, - email = /\b\S+@[\w.]+[a-z]{2}/, - linkMd = /\[([^\]]+)]\(([^)]+)\)/, - // Tokens that may contain URLs and emails - candidates = ['comment', 'url', 'attr-value', 'string']; + var candidates = ['comment', 'url', 'attr-value', 'string']; -Prism.plugins.autolinker = { - processGrammar: function (grammar) { - // Abort if grammar has already been processed - if (!grammar || grammar['url-link']) { - return; - } - Prism.languages.DFS(grammar, function (key, def, type) { - if (candidates.indexOf(type) > -1 && Prism.util.type(def) !== 'Array') { - if (!def.pattern) { - def = this[key] = { - pattern: def - }; - } + Prism.plugins.autolinker = { + processGrammar: function (grammar) { + // Abort if grammar has already been processed + if (!grammar || grammar['url-link']) { + return; + } + Prism.languages.DFS(grammar, function (key, def, type) { + if (candidates.indexOf(type) > -1 && !Array.isArray(def)) { + if (!def.pattern) { + def = this[key] = { + pattern: def + }; + } - def.inside = def.inside || {}; + def.inside = def.inside || {}; - if (type == 'comment') { - def.inside['md-link'] = linkMd; - } - if (type == 'attr-value') { - Prism.languages.insertBefore('inside', 'punctuation', { 'url-link': url }, def); - } - else { - def.inside['url-link'] = url; + if (type == 'comment') { + def.inside['md-link'] = linkMd; + } + if (type == 'attr-value') { + Prism.languages.insertBefore('inside', 'punctuation', { 'url-link': url }, def); + } else { + def.inside['url-link'] = url; + } + + def.inside['email-link'] = email; } + }); + grammar['url-link'] = url; + grammar['email-link'] = email; + } + }; - def.inside['email-link'] = email; + Prism.hooks.add('before-highlight', function (env) { + Prism.plugins.autolinker.processGrammar(env.grammar); + }); + + Prism.hooks.add('wrap', function (env) { + if (/-link$/.test(env.type)) { + env.tag = 'a'; + + var href = env.content; + + if (env.type == 'email-link' && href.indexOf('mailto:') != 0) { + href = 'mailto:' + href; + } else if (env.type == 'md-link') { + // Markdown + var match = env.content.match(linkMd); + + href = match[2]; + env.content = match[1]; } - }); - grammar['url-link'] = url; - grammar['email-link'] = email; - } -}; -Prism.hooks.add('before-highlight', function(env) { - Prism.plugins.autolinker.processGrammar(env.grammar); -}); + env.attributes.href = href; -Prism.hooks.add('wrap', function(env) { - if (/-link$/.test(env.type)) { - env.tag = 'a'; - - var href = env.content; - - if (env.type == 'email-link' && href.indexOf('mailto:') != 0) { - href = 'mailto:' + href; - } - else if (env.type == 'md-link') { - // Markdown - var match = env.content.match(linkMd); - - href = match[2]; - env.content = match[1]; + // Silently catch any error thrown by decodeURIComponent (#1186) + try { + env.content = decodeURIComponent(env.content); + } catch (e) { /* noop */ } } - - env.attributes.href = href; - } - - // Silently catch any error thrown by decodeURIComponent (#1186) - try { - env.content = decodeURIComponent(env.content); - } catch(e) {} -}); + }); -})(); +}()); diff --git a/plugins/autolinker/prism-autolinker.min.css b/plugins/autolinker/prism-autolinker.min.css new file mode 100644 index 0000000000..3c54381d78 --- /dev/null +++ b/plugins/autolinker/prism-autolinker.min.css @@ -0,0 +1 @@ +.token a{color:inherit} \ No newline at end of file diff --git a/plugins/autolinker/prism-autolinker.min.js b/plugins/autolinker/prism-autolinker.min.js index 9fdced9560..731c4a0c21 100644 --- a/plugins/autolinker/prism-autolinker.min.js +++ b/plugins/autolinker/prism-autolinker.min.js @@ -1 +1 @@ -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~\/.:=&]+(?:\?[\w\-+%~\/.:#=?&!$'()*,;]*)?(?:#[\w\-+%~\/.:#=?&!$'()*,;]*)?/,n=/\b\S+@[\w.]+[a-z]{2}/,e=/\[([^\]]+)]\(([^)]+)\)/,t=["comment","url","attr-value","string"];Prism.plugins.autolinker={processGrammar:function(r){r&&!r["url-link"]&&(Prism.languages.DFS(r,function(r,a,l){t.indexOf(l)>-1&&"Array"!==Prism.util.type(a)&&(a.pattern||(a=this[r]={pattern:a}),a.inside=a.inside||{},"comment"==l&&(a.inside["md-link"]=e),"attr-value"==l?Prism.languages.insertBefore("inside","punctuation",{"url-link":i},a):a.inside["url-link"]=i,a.inside["email-link"]=n)}),r["url-link"]=i,r["email-link"]=n)}},Prism.hooks.add("before-highlight",function(i){Prism.plugins.autolinker.processGrammar(i.grammar)}),Prism.hooks.add("wrap",function(i){if(/-link$/.test(i.type)){i.tag="a";var n=i.content;if("email-link"==i.type&&0!=n.indexOf("mailto:"))n="mailto:"+n;else if("md-link"==i.type){var t=i.content.match(e);n=t[2],i.content=t[1]}i.attributes.href=n}try{i.content=decodeURIComponent(i.content)}catch(r){}})}}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism){var e=/\b([a-z]{3,7}:\/\/|tel:)[\w\-+%~/.:=&@]+(?:\?[\w\-+%~/.:=?&!$'()*,;@]*)?(?:#[\w\-+%~/.:#=?&!$'()*,;@]*)?/,r=/\b\S+@[\w.]+[a-z]{2}/,a=/\[([^\]]+)\]\(([^)]+)\)/,l=["comment","url","attr-value","string"];Prism.plugins.autolinker={processGrammar:function(i){i&&!i["url-link"]&&(Prism.languages.DFS(i,function(i,n,t){-1 - + Autoloader ▲ Prism plugins - + - + - + -
        -
        - -

        Autoloader

        -

        Automatically loads the needed languages to highlight the code blocks.

        -
        +

        How to use

        The plugin will automatically handle missing grammars and load them for you. - To do this, you need to provide it with a directory of all the grammars you want. + To do this, you need to provide a URL to a directory of all the grammars you want. + This can be the path to a local directory with all grammars or a CDN URL.

        You can download all the available grammars by clicking on the following link: .
        Alternatively, you can also clone the GitHub repo and take the components folder from there. + Read our usage section to use a CDN.

        You can then download Prism core and any plugins from the Download page, without checking any languages (or just check the languages you want to load by default, e.g. if you're using a language a lot, then you probably want to save the extra HTTP request). @@ -63,6 +60,10 @@

        Specifying the grammars path

        Prism.plugins.autoloader.languages_path = 'path/to/grammars/';
        +

        + Note: Autoloader is pretty good at guessing this path. You most likely won't have to change this path. +

        +

        Using development versions

        @@ -109,6 +110,9 @@

        Examples

        Basic usage with some Perl code:

        my ($class, $filename) = @_;
        +

        Alias support with TypeScript's ts:

        +
        const a: number = 0;
        +

        The Less filter used in Pug:

        :less
         	foo {
        @@ -117,17 +121,39 @@ 

        Examples

        -
        +
        +

        Markdown

        + +

        Markdown will use the Autoloader to automatically load missing languages.

        +
        The C# code will be highlighted __after__ the rest of this document.
        +
        +```csharp
        +public class Foo : IBar<int> {
        +	public string Baz { get; set; } = "foo";
        +}
        +```
        +
        +The CSS code will be highlighted with this document because CSS has already been loaded.
        +
        +```css
        +a:hover {
        +	color: green !important;
        +}
        +```
        + +
        + +
        - - + + - + - - - + + + + - + -
        -
        - -

        Command Line

        -

        Display a command line with a prompt and, optionally, the output/response from the commands.

        -
        +

        How to use

        @@ -54,6 +49,14 @@

        How to use

        Optional: To automatically present some lines as output, you can prefix those lines with any string and specify the prefix using the data-filter-output attribute on the <pre> element. For example, data-filter-output="(out)" will treat lines beginning with (out) as output and remove the prefix.

        + +

        Output lines are user selectable by default, so if you select the whole content of the code block, it will select the shell commands and any output lines. This may not be desireable if you want to copy/paste just the commands and not the output. If you want to make the output not user selectable then add the following to your CSS:

        + +
        .command-line span.token.output {
        +	user-select: none;
        +}
        + +

        Optional: For multi-line commands you can specify the data-continuation-str attribute on the <pre> element. For example, data-continuation-str="\" will treat lines ending with \ as being continued on the following line. Continued lines will have a prompt as set by the attribute data-continuation-prompt or a default of >.

        @@ -95,17 +98,37 @@

        Windows PowerShell With Output

        d-r-- 10/14/2015 5:06 PM Searches d-r-- 10/14/2015 5:06 PM Videos
        +

        Line continuation with Output (bash)

        +
        echo "hello"
        +(out)hello
        +echo one \
        +two \
        +three
        +(out)one two three
        +(out)
        +echo "goodbye"
        +(out)goodbye
        + +

        Line continuation with Output (PowerShell)

        +
        Write-Host `
        +'Hello' `
        +'from' `
        +'PowerShell!'
        +(out)Hello from PowerShell!
        +Write-Host 'Goodbye from PowerShell!'
        +(out)Goodbye from PowerShell!
        +
        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/command-line/prism-command-line.css b/plugins/command-line/prism-command-line.css index 153a87076a..984a718c1f 100644 --- a/plugins/command-line/prism-command-line.css +++ b/plugins/command-line/prism-command-line.css @@ -6,6 +6,7 @@ letter-spacing: -1px; margin-right: 1em; pointer-events: none; + text-align: right; -webkit-user-select: none; -moz-user-select: none; @@ -14,7 +15,7 @@ } .command-line-prompt > span:before { - color: #999; + opacity: 0.4; content: ' '; display: block; padding-right: 0.8em; @@ -31,3 +32,12 @@ .command-line-prompt > span[data-prompt]:before { content: attr(data-prompt); } + +.command-line-prompt > span[data-continuation-prompt]:before { + content: attr(data-continuation-prompt); +} + +.command-line span.token.output { + /* Make shell output lines a bit lighter to distinguish them from shell commands */ + opacity: 0.7; +} diff --git a/plugins/command-line/prism-command-line.js b/plugins/command-line/prism-command-line.js index b8595d72b7..415ac5dc95 100644 --- a/plugins/command-line/prism-command-line.js +++ b/plugins/command-line/prism-command-line.js @@ -1,139 +1,228 @@ -(function() { +(function () { -if (typeof self === 'undefined' || !self.Prism || !self.document) { - return; -} + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } -var clsReg = /\s*\bcommand-line\b\s*/; + var CLASS_PATTERN = /(?:^|\s)command-line(?:\s|$)/; + var PROMPT_CLASS = 'command-line-prompt'; -Prism.hooks.add('before-highlight', function (env) { - env.vars = env.vars || {}; - env.vars['command-line'] = env.vars['command-line'] || {}; + /** @type {(str: string, prefix: string) => boolean} */ + var startsWith = ''.startsWith + ? function (s, p) { return s.startsWith(p); } + : function (s, p) { return s.indexOf(p) === 0; }; - if (env.vars['command-line'].complete || !env.code) { - env.vars['command-line'].complete = true; - return; + // Support for IE11 that has no endsWith() + /** @type {(str: string, suffix: string) => boolean} */ + var endsWith = ''.endsWith + ? function (str, suffix) { + return str.endsWith(suffix); + } + : function (str, suffix) { + var len = str.length; + return str.substring(len - suffix.length, len) === suffix; + }; + + /** + * Returns whether the given hook environment has a command line info object. + * + * @param {any} env + * @returns {boolean} + */ + function hasCommandLineInfo(env) { + var vars = env.vars = env.vars || {}; + return 'command-line' in vars; } - - // Works only for wrapped inside
         (not inline).
        -	var pre = env.element.parentNode;
        -	if (!pre || !/pre/i.test(pre.nodeName) || // Abort only if neither the 
         nor the  have the class
        -		(!clsReg.test(pre.className) && !clsReg.test(env.element.className))) {
        -		env.vars['command-line'].complete = true;
        -		return;
        +	/**
        +	 * Returns the command line info object from the given hook environment.
        +	 *
        +	 * @param {any} env
        +	 * @returns {CommandLineInfo}
        +	 *
        +	 * @typedef CommandLineInfo
        +	 * @property {boolean} [complete]
        +	 * @property {number} [numberOfLines]
        +	 * @property {string[]} [outputLines]
        +	 */
        +	function getCommandLineInfo(env) {
        +		var vars = env.vars = env.vars || {};
        +		return vars['command-line'] = vars['command-line'] || {};
         	}
         
        -	if (env.element.querySelector('.command-line-prompt')) { // Abort if prompt already exists.
        -		env.vars['command-line'].complete = true;
        -		return;
        -	}
         
        -	var codeLines = env.code.split('\n');
        -	env.vars['command-line'].numberOfLines = codeLines.length;
        -	env.vars['command-line'].outputLines = [];
        -
        -	var outputSections = pre.getAttribute('data-output');
        -	var outputFilter = pre.getAttribute('data-filter-output');
        -	if (outputSections || outputSections === '') { // The user specified the output lines. -- cwells
        -		outputSections = outputSections.split(',');
        -		for (var i = 0; i < outputSections.length; i++) { // Parse the output sections into start/end ranges. -- cwells
        -			var range = outputSections[i].split('-');
        -			var outputStart = parseInt(range[0], 10);
        -			var outputEnd = (range.length === 2 ? parseInt(range[1], 10) : outputStart);
        -
        -			if (!isNaN(outputStart) && !isNaN(outputEnd)) {
        -				if (outputStart < 1) {
        -					outputStart = 1;
        +	Prism.hooks.add('before-highlight', function (env) {
        +		var commandLine = getCommandLineInfo(env);
        +
        +		if (commandLine.complete || !env.code) {
        +			commandLine.complete = true;
        +			return;
        +		}
        +
        +		// Works only for  wrapped inside 
         (not inline).
        +		var pre = env.element.parentElement;
        +		if (!pre || !/pre/i.test(pre.nodeName) || // Abort only if neither the 
         nor the  have the class
        +			(!CLASS_PATTERN.test(pre.className) && !CLASS_PATTERN.test(env.element.className))) {
        +			commandLine.complete = true;
        +			return;
        +		}
        +
        +		// The element might be highlighted multiple times, so we just remove the previous prompt
        +		var existingPrompt = env.element.querySelector('.' + PROMPT_CLASS);
        +		if (existingPrompt) {
        +			existingPrompt.remove();
        +		}
        +
        +		var codeLines = env.code.split('\n');
        +
        +		var continuationLineIndicies = commandLine.continuationLineIndicies = new Set();
        +		var lineContinuationStr = pre.getAttribute('data-continuation-str');
        +
        +		// Identify code lines that are a continuation line and thus don't need
        +		// a prompt
        +		if (lineContinuationStr && codeLines.length > 1) {
        +			for (var j = 1; j < codeLines.length; j++) {
        +				if (codeLines.hasOwnProperty(j - 1)
        +						&& endsWith(codeLines[j - 1], lineContinuationStr)) {
        +					// Mark this line as being a continuation line
        +					continuationLineIndicies.add(j);
         				}
        -				if (outputEnd > codeLines.length) {
        -					outputEnd = codeLines.length;
        +			}
        +		}
        +
        +		commandLine.numberOfLines = codeLines.length;
        +		/** @type {string[]} */
        +		var outputLines = commandLine.outputLines = [];
        +
        +		var outputSections = pre.getAttribute('data-output');
        +		var outputFilter = pre.getAttribute('data-filter-output');
        +		if (outputSections !== null) { // The user specified the output lines. -- cwells
        +			outputSections.split(',').forEach(function (section) {
        +				var range = section.split('-');
        +				var outputStart = parseInt(range[0], 10);
        +				var outputEnd = range.length === 2 ? parseInt(range[1], 10) : outputStart;
        +
        +				if (!isNaN(outputStart) && !isNaN(outputEnd)) {
        +					if (outputStart < 1) {
        +						outputStart = 1;
        +					}
        +					if (outputEnd > codeLines.length) {
        +						outputEnd = codeLines.length;
        +					}
        +					// Convert start and end to 0-based to simplify the arrays. -- cwells
        +					outputStart--;
        +					outputEnd--;
        +					// Save the output line in an array and clear it in the code so it's not highlighted. -- cwells
        +					for (var j = outputStart; j <= outputEnd; j++) {
        +						outputLines[j] = codeLines[j];
        +						codeLines[j] = '';
        +					}
         				}
        -				// Convert start and end to 0-based to simplify the arrays. -- cwells
        -				outputStart--;
        -				outputEnd--;
        -				// Save the output line in an array and clear it in the code so it's not highlighted. -- cwells
        -				for (var j = outputStart; j <= outputEnd; j++) {
        -					env.vars['command-line'].outputLines[j] = codeLines[j];
        -					codeLines[j] = '';
        +			});
        +		} else if (outputFilter) { // Treat lines beginning with this string as output. -- cwells
        +			for (var i = 0; i < codeLines.length; i++) {
        +				if (startsWith(codeLines[i], outputFilter)) { // This line is output. -- cwells
        +					outputLines[i] = codeLines[i].slice(outputFilter.length);
        +					codeLines[i] = '';
         				}
         			}
         		}
        -	} else if (outputFilter) { // Treat lines beginning with this string as output. -- cwells
        -		for (var i = 0; i < codeLines.length; i++) {
        -			if (codeLines[i].indexOf(outputFilter) === 0) { // This line is output. -- cwells
        -				env.vars['command-line'].outputLines[i] = codeLines[i].slice(outputFilter.length);
        -				codeLines[i] = '';
        +
        +		env.code = codeLines.join('\n');
        +	});
        +
        +	Prism.hooks.add('before-insert', function (env) {
        +		var commandLine = getCommandLineInfo(env);
        +
        +		if (commandLine.complete) {
        +			return;
        +		}
        +
        +		// Reinsert the output lines into the highlighted code. -- cwells
        +		var codeLines = env.highlightedCode.split('\n');
        +		var outputLines = commandLine.outputLines || [];
        +		for (var i = 0, l = codeLines.length; i < l; i++) {
        +			// Add spans to allow distinction of input/output text for styling
        +			if (outputLines.hasOwnProperty(i)) {
        +				// outputLines were removed from codeLines so missed out on escaping
        +				// of markup so do it here.
        +				codeLines[i] = ''
        +					+ Prism.util.encode(outputLines[i]) + '';
        +			} else {
        +				codeLines[i] = ''
        +					+ codeLines[i] + '';
         			}
         		}
        -	}
        +		env.highlightedCode = codeLines.join('\n');
        +	});
         
        -	env.code = codeLines.join('\n');
        -});
        +	Prism.hooks.add('complete', function (env) {
        +		if (!hasCommandLineInfo(env)) {
        +			// the previous hooks never ran
        +			return;
        +		}
         
        -Prism.hooks.add('before-insert', function (env) {
        -	env.vars = env.vars || {};
        -	env.vars['command-line'] = env.vars['command-line'] || {};
        -	if (env.vars['command-line'].complete) {
        -		return;
        -	}
        +		var commandLine = getCommandLineInfo(env);
         
        -	// Reinsert the output lines into the highlighted code. -- cwells
        -	var codeLines = env.highlightedCode.split('\n');
        -	for (var i = 0; i < env.vars['command-line'].outputLines.length; i++) {
        -		if (env.vars['command-line'].outputLines.hasOwnProperty(i)) {
        -			codeLines[i] = env.vars['command-line'].outputLines[i];
        +		if (commandLine.complete) {
        +			return;
         		}
        -	}
        -	env.highlightedCode = codeLines.join('\n');
        -});
         
        -Prism.hooks.add('complete', function (env) {
        -	env.vars = env.vars || {};
        -	env.vars['command-line'] = env.vars['command-line'] || {};
        -	if (env.vars['command-line'].complete) {
        -		return;
        -	}
        +		var pre = env.element.parentElement;
        +		if (CLASS_PATTERN.test(env.element.className)) { // Remove the class "command-line" from the 
        +			env.element.className = env.element.className.replace(CLASS_PATTERN, ' ');
        +		}
        +		if (!CLASS_PATTERN.test(pre.className)) { // Add the class "command-line" to the 
        +			pre.className += ' command-line';
        +		}
         
        -	var pre = env.element.parentNode;
        -	if (clsReg.test(env.element.className)) { // Remove the class "command-line" from the 
        -		env.element.className = env.element.className.replace(clsReg, ' ');
        -	}
        -	if (!clsReg.test(pre.className)) { // Add the class "command-line" to the 
        -		pre.className += ' command-line';
        -	}
        +		function getAttribute(key, defaultValue) {
        +			return (pre.getAttribute(key) || defaultValue).replace(/"/g, '"');
        +		}
         
        -	var getAttribute = function(key, defaultValue) {
        -		return (pre.getAttribute(key) || defaultValue).replace(/"/g, '"');
        -	};
        -
        -	// Create the "rows" that will become the command-line prompts. -- cwells
        -	var promptLines = new Array(env.vars['command-line'].numberOfLines + 1);
        -	var promptText = getAttribute('data-prompt', '');
        -	if (promptText !== '') {
        -		promptLines = promptLines.join('');
        -	} else {
        -		var user = getAttribute('data-user', 'user');
        -		var host = getAttribute('data-host', 'localhost');
        -		promptLines = promptLines.join('');
        -	}
        +		// Create the "rows" that will become the command-line prompts. -- cwells
        +		var promptLines = '';
        +		var rowCount = commandLine.numberOfLines || 0;
        +		var promptText = getAttribute('data-prompt', '');
        +		var promptLine;
        +		if (promptText !== '') {
        +			promptLine = '';
        +		} else {
        +			var user = getAttribute('data-user', 'user');
        +			var host = getAttribute('data-host', 'localhost');
        +			promptLine = '';
        +		}
         
        -	// Create the wrapper element. -- cwells
        -	var prompt = document.createElement('span');
        -	prompt.className = 'command-line-prompt';
        -	prompt.innerHTML = promptLines;
        +		var continuationLineIndicies = commandLine.continuationLineIndicies || new Set();
        +		var continuationPromptText = getAttribute('data-continuation-prompt', '>');
        +		var continuationPromptLine = '';
         
        -	// Remove the prompt from the output lines. -- cwells
        -	for (var i = 0; i < env.vars['command-line'].outputLines.length; i++) {
        -		if (env.vars['command-line'].outputLines.hasOwnProperty(i)) {
        -			var node = prompt.children[i];
        -			node.removeAttribute('data-user');
        -			node.removeAttribute('data-host');
        -			node.removeAttribute('data-prompt');
        +		// Assemble all the appropriate prompt/continuation lines
        +		for (var j = 0; j < rowCount; j++) {
        +			if (continuationLineIndicies.has(j)) {
        +				promptLines += continuationPromptLine;
        +			} else {
        +				promptLines += promptLine;
        +			}
        +		}
        +
        +		// Create the wrapper element. -- cwells
        +		var prompt = document.createElement('span');
        +		prompt.className = PROMPT_CLASS;
        +		prompt.innerHTML = promptLines;
        +
        +		// Remove the prompt from the output lines. -- cwells
        +		var outputLines = commandLine.outputLines || [];
        +		for (var i = 0, l = outputLines.length; i < l; i++) {
        +			if (outputLines.hasOwnProperty(i)) {
        +				var node = prompt.children[i];
        +				node.removeAttribute('data-user');
        +				node.removeAttribute('data-host');
        +				node.removeAttribute('data-prompt');
        +			}
         		}
        -	}
         
        -	env.element.insertBefore(prompt, env.element.firstChild);
        -	env.vars['command-line'].complete = true;
        -});
        +		env.element.insertBefore(prompt, env.element.firstChild);
        +		commandLine.complete = true;
        +	});
         
         }());
        diff --git a/plugins/command-line/prism-command-line.min.css b/plugins/command-line/prism-command-line.min.css
        new file mode 100644
        index 0000000000..5e5c875d7e
        --- /dev/null
        +++ b/plugins/command-line/prism-command-line.min.css
        @@ -0,0 +1 @@
        +.command-line-prompt{border-right:1px solid #999;display:block;float:left;font-size:100%;letter-spacing:-1px;margin-right:1em;pointer-events:none;text-align:right;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.command-line-prompt>span:before{opacity:.4;content:' ';display:block;padding-right:.8em}.command-line-prompt>span[data-user]:before{content:"[" attr(data-user) "@" attr(data-host) "] $"}.command-line-prompt>span[data-user=root]:before{content:"[" attr(data-user) "@" attr(data-host) "] #"}.command-line-prompt>span[data-prompt]:before{content:attr(data-prompt)}.command-line-prompt>span[data-continuation-prompt]:before{content:attr(data-continuation-prompt)}.command-line span.token.output{opacity:.7}
        \ No newline at end of file
        diff --git a/plugins/command-line/prism-command-line.min.js b/plugins/command-line/prism-command-line.min.js
        index 159f4094f5..fb2e402b04 100644
        --- a/plugins/command-line/prism-command-line.min.js
        +++ b/plugins/command-line/prism-command-line.min.js
        @@ -1 +1 @@
        -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e=/\s*\bcommand-line\b\s*/;Prism.hooks.add("before-highlight",function(a){if(a.vars=a.vars||{},a.vars["command-line"]=a.vars["command-line"]||{},a.vars["command-line"].complete||!a.code)return a.vars["command-line"].complete=!0,void 0;var n=a.element.parentNode;if(!n||!/pre/i.test(n.nodeName)||!e.test(n.className)&&!e.test(a.element.className))return a.vars["command-line"].complete=!0,void 0;if(a.element.querySelector(".command-line-prompt"))return a.vars["command-line"].complete=!0,void 0;var t=a.code.split("\n");a.vars["command-line"].numberOfLines=t.length,a.vars["command-line"].outputLines=[];var r=n.getAttribute("data-output"),s=n.getAttribute("data-filter-output");if(r||""===r){r=r.split(",");for(var o=0;oi&&(i=1),l>t.length&&(l=t.length),i--,l--;for(var d=i;l>=d;d++)a.vars["command-line"].outputLines[d]=t[d],t[d]=""}}}else if(s)for(var o=0;o');else{var o=t("data-user","user"),m=t("data-host","localhost");r=r.join('')}var i=document.createElement("span");i.className="command-line-prompt",i.innerHTML=r;for(var l=0;li.length&&(a=i.length),a--;for(var r=--n;r<=a;r++)l[r]=i[r],i[r]=""}});else if(u)for(var c=0;c'+Prism.util.encode(a[r])+"":n[r]=''+n[r]+"";e.highlightedCode=n.join("\n")}}),Prism.hooks.add("complete",function(e){if(function(e){return"command-line"in(e.vars=e.vars||{})}(e)){var t=N(e);if(!t.complete){var n=e.element.parentElement;v.test(e.element.className)&&(e.element.className=e.element.className.replace(v," ")),v.test(n.className)||(n.className+=" command-line");var a,r="",i=t.numberOfLines||0,s=h("data-prompt","");if(""!==s)a='';else a='';for(var o=t.continuationLineIndicies||new Set,l='")+'">',m=0;m
         
         	
        -	
        +	
         	Copy to Clipboard ▲ Prism plugins
         	
        -	
        +	
         	
         	
        -	
        +	
         
         	
        -	
        +	
         
        -
        +
         
        -
        -
        - -

        Copy to Clipboard

        -

        Add a button that copies the code block to the clipboard when clicked.

        -
        +

        How to use

        -

        In addition to including the plugin file with your PrismJS build, ensure Clipboard.js is loaded before the plugin.

        -

        The simplest way to include Clipboard.js is to use any of the - recommended CDNs. If you're using Browserify, Clipboard.js will be loaded auotmatically - if it's included in your package.json. - If you don't load Clipboard.js yourself, the plugin will load it from a CDN for you.

        +

        The plugin depends on the Prism Toolbar plugin. In addition to including the plugin file with your PrismJS build, ensure it is loaded before the plugin.

        +
        + +
        +

        Settings

        + +

        By default, the plugin shows messages in English and sets a 5-second timeout after a click. You can use the following HTML5 data attributes to override the default settings:

        + +
          +
        • data-prismjs-copy — default message displayed by Copy to Clipboard;
        • +
        • data-prismjs-copy-error — a message displayed after failing copying, prompting the user to press Ctrl+C;
        • +
        • data-prismjs-copy-success — a message displayed after a successful copying;
        • +
        • data-prismjs-copy-timeout — a timeout (in milliseconds) after copying. Once the timeout passed, the success or error message will revert back to the default message. The value should be a non-negative integer.
        • +
        + +

        The plugin traverses up the DOM tree to find each of these attributes. The search starts at every pre code element and stops at the closest ancestor element that has a desired attribute or at the worst case, at the html element.

        + +

        Warning! Although possible, you definitely shouldn't add these attributes to the html element, because a human-readable text should be placed after the character encoding declaration (<meta charset="...">), and the latter must be serialized completely within the first 512 (in older browsers) or 1024 bytes of the document. Consider using the body element or one of its descendants.

        +
        + +
        +

        Styling

        + +

        This plugin supports customizing the style of the copy button. To understand how this is done, let's look at the HTML structure of the copy button:

        + +
        <button class="copy-to-clipboard-button" type="button" data-copy-state="copy">
        +	<span>Copy</span>
        +</button>
        + +

        The copy-to-clipboard-button class can be used to select the button. The data-copy-state attribute indicates the current state of the plugin with the 3 possible states being:

        + +
          +
        • data-copy-state="copy" — default state;
        • +
        • data-copy-state="copy-error" — the state after failing copying;
        • +
        • data-copy-state="copy-success" — the state after successful copying;
        • +
        + +

        These 3 states should be conveyed to the user either by different styling or displaying the button text.

        +
        + +
        +

        Examples

        + +

        Sharing

        + +

        The following code blocks show modified messages and both use a half-second timeout. The other settings are set to default.

        + +

        Source code:

        + +
        <body data-prismjs-copy-timeout="500">
        +	<pre><code class="language-js" data-prismjs-copy="Copy the JavaScript snippet!">console.log('Hello, world!');</code></pre>
        +
        +	<pre><code class="language-c" data-prismjs-copy="Copy the C snippet!">int main() {
        +	return 0;
        +}</code></pre>
        +</body>
        + +

        Output:

        + +
        +
        console.log('Hello, world!');
        + +
        int main() {
        +	return 0;
        +}
        +
        + +

        Inheritance

        + +

        The plugin always use the closest ancestor element that has a desired attribute, so it's possible to override any setting on any descendant. In the following example, the baz message is used. The other settings are set to default.

        + +

        Source code:

        + +
        <body data-prismjs-copy="foo">
        +	<main data-prismjs-copy="bar">
        +		<pre><code class="language-c" data-prismjs-copy="baz">int main() {
        +	return 0;
        +}</code></pre>
        +	</main>
        +</body>
        + +

        Output:

        + +
        +
        +
        int main() {
        +	return 0;
        +}
        +
        +
        + +

        i18n

        + +

        You can use the data attributes for internationalization.

        + +

        The following code blocks use shared messages in Russian and the default 5-second timeout.

        + +

        Source code:

        + +
        <!DOCTYPE html>
        +<html lang="ru">
        +<!-- The head is omitted. -->
        +<body
        +	data-prismjs-copy="Скопировать"
        +	data-prismjs-copy-error="Нажмите Ctrl+C, чтобы скопировать"
        +	data-prismjs-copy-success="Скопировано!"
        +>
        +	<pre><code class="language-c">int main() {
        +	return 0;
        +}</code></pre>
        +
        +	<pre><code class="language-js">console.log('Hello, world!');</code></pre>
        +</body>
        +</html>
        + +

        Output:

        + +
        +
        int main() {
        +	return 0;
        +}
        + +
        console.log('Hello, world!');
        +
        + +

        The next HTML document is in English, but some code blocks show messages in Russian and simplified Mainland Chinese. The other settings are set to default.

        + +

        Source code:

        + +
        <!DOCTYPE html>
        +<html lang="en"><!-- The head is omitted. -->
        +<body>
        +	<pre><code class="language-js">console.log('Hello, world!');</code></pre>
        +
        +	<pre
        +		lang="ru"
        +		data-prismjs-copy="Скопировать"
        +		data-prismjs-copy-error="Нажмите Ctrl+C, чтобы скопировать"
        +		data-prismjs-copy-success="Скопировано!"
        +	><code class="language-js">console.log('Привет, мир!');</code></pre>
        +
        +	<pre
        +		lang="zh-Hans-CN"
        +		data-prismjs-copy="复制文本"
        +		data-prismjs-copy-error="按Ctrl+C复制"
        +		data-prismjs-copy-success="文本已复制!"
        +	><code class="language-js">console.log('你好,世界!');</code></pre>
        +</body>
        +</html>
        + +

        Output:

        + +
        +
        console.log('Hello, world!');
        + +
        console.log('Привет, мир!');
        -
        
        +		
        console.log('你好,世界!');
        +
        -
        +
        + - + - + - \ No newline at end of file + diff --git a/plugins/copy-to-clipboard/prism-copy-to-clipboard.js b/plugins/copy-to-clipboard/prism-copy-to-clipboard.js index 0b185f4734..f6cac476ac 100644 --- a/plugins/copy-to-clipboard/prism-copy-to-clipboard.js +++ b/plugins/copy-to-clipboard/prism-copy-to-clipboard.js @@ -1,5 +1,6 @@ -(function(){ - if (typeof self === 'undefined' || !self.Prism || !self.document) { +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { return; } @@ -9,67 +10,151 @@ return; } - var ClipboardJS = window.ClipboardJS || undefined; - - if (!ClipboardJS && typeof require === 'function') { - ClipboardJS = require('clipboard'); + /** + * When the given elements is clicked by the user, the given text will be copied to clipboard. + * + * @param {HTMLElement} element + * @param {CopyInfo} copyInfo + * + * @typedef CopyInfo + * @property {() => string} getText + * @property {() => void} success + * @property {(reason: unknown) => void} error + */ + function registerClipboard(element, copyInfo) { + element.addEventListener('click', function () { + copyTextToClipboard(copyInfo); + }); } - var callbacks = []; + // https://stackoverflow.com/a/30810322/7595472 + + /** @param {CopyInfo} copyInfo */ + function fallbackCopyTextToClipboard(copyInfo) { + var textArea = document.createElement('textarea'); + textArea.value = copyInfo.getText(); - if (!ClipboardJS) { - var script = document.createElement('script'); - var head = document.querySelector('head'); + // Avoid scrolling to bottom + textArea.style.top = '0'; + textArea.style.left = '0'; + textArea.style.position = 'fixed'; - script.onload = function() { - ClipboardJS = window.ClipboardJS; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); - if (ClipboardJS) { - while (callbacks.length) { - callbacks.pop()(); + try { + var successful = document.execCommand('copy'); + setTimeout(function () { + if (successful) { + copyInfo.success(); + } else { + copyInfo.error(); } - } + }, 1); + } catch (err) { + setTimeout(function () { + copyInfo.error(err); + }, 1); + } + + document.body.removeChild(textArea); + } + /** @param {CopyInfo} copyInfo */ + function copyTextToClipboard(copyInfo) { + if (navigator.clipboard) { + navigator.clipboard.writeText(copyInfo.getText()).then(copyInfo.success, function () { + // try the fallback in case `writeText` didn't work + fallbackCopyTextToClipboard(copyInfo); + }); + } else { + fallbackCopyTextToClipboard(copyInfo); + } + } + + /** + * Selects the text content of the given element. + * + * @param {Element} element + */ + function selectElementText(element) { + // https://stackoverflow.com/a/20079910/7595472 + window.getSelection().selectAllChildren(element); + } + + /** + * Traverses up the DOM tree to find data attributes that override the default plugin settings. + * + * @param {Element} startElement An element to start from. + * @returns {Settings} The plugin settings. + * @typedef {Record<"copy" | "copy-error" | "copy-success" | "copy-timeout", string | number>} Settings + */ + function getSettings(startElement) { + /** @type {Settings} */ + var settings = { + 'copy': 'Copy', + 'copy-error': 'Press Ctrl+C to copy', + 'copy-success': 'Copied!', + 'copy-timeout': 5000 }; - script.src = 'https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js'; - head.appendChild(script); + var prefix = 'data-prismjs-'; + for (var key in settings) { + var attr = prefix + key; + var element = startElement; + while (element && !element.hasAttribute(attr)) { + element = element.parentElement; + } + if (element) { + settings[key] = element.getAttribute(attr); + } + } + return settings; } Prism.plugins.toolbar.registerButton('copy-to-clipboard', function (env) { - var linkCopy = document.createElement('a'); - linkCopy.textContent = 'Copy'; + var element = env.element; - if (!ClipboardJS) { - callbacks.push(registerClipboard); - } else { - registerClipboard(); - } + var settings = getSettings(element); - return linkCopy; + var linkCopy = document.createElement('button'); + linkCopy.className = 'copy-to-clipboard-button'; + linkCopy.setAttribute('type', 'button'); + var linkSpan = document.createElement('span'); + linkCopy.appendChild(linkSpan); - function registerClipboard() { - var clip = new ClipboardJS(linkCopy, { - 'text': function () { - return env.code; - } - }); + setState('copy'); - clip.on('success', function() { - linkCopy.textContent = 'Copied!'; + registerClipboard(linkCopy, { + getText: function () { + return element.textContent; + }, + success: function () { + setState('copy-success'); resetText(); - }); - clip.on('error', function () { - linkCopy.textContent = 'Press Ctrl+C to copy'; + }, + error: function () { + setState('copy-error'); + + setTimeout(function () { + selectElementText(element); + }, 1); resetText(); - }); - } + } + }); + + return linkCopy; function resetText() { - setTimeout(function () { - linkCopy.textContent = 'Copy'; - }, 5000); + setTimeout(function () { setState('copy'); }, settings['copy-timeout']); + } + + /** @param {"copy" | "copy-error" | "copy-success"} state */ + function setState(state) { + linkSpan.textContent = settings[state]; + linkCopy.setAttribute('data-copy-state', state); } }); -})(); +}()); diff --git a/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js b/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js index aa5742db56..4604e93994 100644 --- a/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js +++ b/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js @@ -1 +1 @@ -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){if(!Prism.plugins.toolbar)return console.warn("Copy to Clipboard plugin loaded before Toolbar plugin."),void 0;var o=window.ClipboardJS||void 0;o||"function"!=typeof require||(o=require("clipboard"));var e=[];if(!o){var t=document.createElement("script"),n=document.querySelector("head");t.onload=function(){if(o=window.ClipboardJS)for(;e.length;)e.pop()()},t.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js",n.appendChild(t)}Prism.plugins.toolbar.registerButton("copy-to-clipboard",function(t){function n(){var e=new o(i,{text:function(){return t.code}});e.on("success",function(){i.textContent="Copied!",r()}),e.on("error",function(){i.textContent="Press Ctrl+C to copy",r()})}function r(){setTimeout(function(){i.textContent="Copy"},5e3)}var i=document.createElement("a");return i.textContent="Copy",o?n():e.push(n),i})}}(); \ No newline at end of file +!function(){function u(t,e){t.addEventListener("click",function(){!function(t){navigator.clipboard?navigator.clipboard.writeText(t.getText()).then(t.success,function(){o(t)}):o(t)}(e)})}function o(e){var t=document.createElement("textarea");t.value=e.getText(),t.style.top="0",t.style.left="0",t.style.position="fixed",document.body.appendChild(t),t.focus(),t.select();try{var o=document.execCommand("copy");setTimeout(function(){o?e.success():e.error()},1)}catch(t){setTimeout(function(){e.error(t)},1)}document.body.removeChild(t)}"undefined"!=typeof Prism&&"undefined"!=typeof document&&(Prism.plugins.toolbar?Prism.plugins.toolbar.registerButton("copy-to-clipboard",function(t){var e=t.element,o=function(t){var e={copy:"Copy","copy-error":"Press Ctrl+C to copy","copy-success":"Copied!","copy-timeout":5e3};for(var o in e){for(var n="data-prismjs-"+o,c=t;c&&!c.hasAttribute(n);)c=c.parentElement;c&&(e[o]=c.getAttribute(n))}return e}(e),n=document.createElement("button");n.className="copy-to-clipboard-button",n.setAttribute("type","button");var c=document.createElement("span");return n.appendChild(c),i("copy"),u(n,{getText:function(){return e.textContent},success:function(){i("copy-success"),r()},error:function(){i("copy-error"),setTimeout(function(){!function(t){window.getSelection().selectAllChildren(t)}(e)},1),r()}}),n;function r(){setTimeout(function(){i("copy")},o["copy-timeout"])}function i(t){c.textContent=o[t],n.setAttribute("data-copy-state",t)}}):console.warn("Copy to Clipboard plugin loaded before Toolbar plugin."))}(); \ No newline at end of file diff --git a/plugins/custom-class/index.html b/plugins/custom-class/index.html index 81af18587d..ec94c122d8 100644 --- a/plugins/custom-class/index.html +++ b/plugins/custom-class/index.html @@ -3,23 +3,18 @@ - + Custom Class ▲ Prism plugins - + - + - + -
        -
        - -

        Custom Class

        -

        This plugin allows you to prefix Prism default classes (.comment will become .namespace--comment) or replace them with your defined ones (like .editor__comment or .comment_7sh3a).

        -
        +

        Motivation

        @@ -28,7 +23,7 @@

        Motivation

        • - You want to add namespace for all of them (like .prism--comment) to avoid conflict with your existing classes. + You want to add namespace for all of them (like .prism--comment) to avoid conflict with your existing classes.
        • You use a naming convention (like BEM). You want to write classes like .editor__comment. @@ -36,26 +31,54 @@

          Motivation

        • You use CSS Modules. You want to use your hashed classes, like .comment_7sh3a.
        • +
        • You need more granular control about the classes of certain tokens. + You can define functions which will add new classes to tokens, so selectively change the highlighting of certain parts of your code. +
        +
        -

        Features

        - -

        This plugin currently provides 2 features:

        +
        +

        How to use

        -

        1. Prefix all Prism classes with a string

        +

        Prefix all Prism classes

        - Prism.plugins.customClass.prefix('prism--') +
        Prism.plugins.customClass.prefix('prism--')
        -

        2. Replace some Prism classes with your defined ones via an object

        +

        Replace some Prism classes with ones you defined

        Prism.plugins.customClass.map({
         	keyword: 'special-keyword',
         	string: 'string_ch29s',
         	comment: 'comment_93jsa'
        -})
        +});
        + +

        Object's keys are the classes you want to replace (eg: comment), with their values being the classes you want to use (eg: my-comment). Classes which are not specified will stay as they are.

        + +

        Alternatively you can also pass a function that takes the original class and returns the mapped class. This function can also be used implement language specific mapped classes.
        Example:

        + +
        Prism.plugins.customClass.map((className, language) => {
        +	if (language === 'css') {
        +		return cssSpecificMap[className] || className;
        +	} else {
        +		return className;
        +	}
        +});
        + +

        Add new classes

        + +

        You can add new classes with per-token and per-language precision.

        + +
        Prism.plugins.customClass.add(({content, type, language}) => {
        +	if (content === 'content' && type === 'property' && language === 'css') {
        +		return 'content-property';
        +	}
        +});
        + +

        Note: The given content is the inner HTML of the current token. All < and & characters are escaped and it might contain the HTML code of nested tokens.

        -

        Object's keys are the tokens you want to replace (eg: comment), with their values being the classes you want to use (eg: my-comment). Tokens which are not specified will stay the same.

        +
        +

        Notes

          @@ -63,9 +86,9 @@

          Notes

          Feature functions must be called AFTER Prism and this plugin. For example:

          <!-- 1. load prism -->
          -<script src="prism.js"></script>
          +<script src="prism.js"></script>
           <!-- 2. load the plugin if you don't include it inside prism when download -->
          -<script src="plugins/custom-class/custom-class.js"></script>
          +<script src="plugins/custom-class/custom-class.js"></script>
           <!-- 3. call the feature you want to use -->
           <script>
           	Prism.plugins.customClass.map(myClassMap);
          @@ -86,48 +109,78 @@ 

          CSS Modules Usage:

          import classMap from 'styles/editor-class-map.css'; Prism.plugins.customClass.map(classMap)
          +

          Note: This plugin only affects generated token elements (usually of the form span.token). The classes of code and pre elements as well as all elements generated by other plugins (e.g. Toolbar elements and line number elements) will not be changed.

        Example

        -

        Input

        -
        <pre class="language-javascript"><code>
        +	

        Prefix and map classes

        + +

        Input

        +
        <pre class="language-javascript"><code>
         	var foo = 'bar';
         </code></pre>
        -

        Options

        +

        Options

        Prism.plugins.customClass.map({
         	keyword: 'special-keyword',
         	string: 'my-string'
         });
         Prism.plugins.customClass.prefix('pr-');
        -

        Output

        -
        <pre class="language-javascript"><code>
        -	<span class="pr-token pr-special-keyword">var</span>
        +	

        Output

        +
        <pre class="language-javascript"><code class="language-markup">
        +	<span class="pr-token pr-special-keyword">var</span>
         	foo
        -	<span class="pr-token pr-operator">=</span>
        -	<span class="pr-my-string">'bar'</span>
        -	<span class="pr-token pr-punctuation">;</span>
        +	<span class="pr-token pr-operator">=</span>
        +	<span class="pr-token pr-my-string">'bar'</span>
        +	<span class="pr-token pr-punctuation">;</span>
         </code></pre>
        -
        -
        -

        Todo

        - +

        Note that this plugin only affects tokens. The classes of the code and pre elements won't be prefixed.

        + +

        Add new classes

        + +

        Input

        +
        <pre class="language-css"><code>
        +a::after {
        +	content: '\2b00 ';
        +	opacity: .7;
        +}
        +</code></pre>
        + +

        Options

        +
        Prism.plugins.customClass.add(({language, type, content}) => {
        +	if (content === 'content' && type === 'property' && language === 'css') {
        +		return 'content-property';
        +	}
        +});
        + +

        Output

        +
        <pre class=" language-css"><code class=" language-css">
        +<span class="token selector">a::after</span>
        +<span class="token punctuation">{</span>
        +	<span class="token property content-property">content</span>
        +	<span class="token punctuation">:</span>
        +	<span class="token string">'\2b00 '</span>
        +	<span class="token punctuation">;</span>
        +	<span class="token property">opacity</span>
        +	<span class="token punctuation">:</span>
        +	 .7
        +	<span class="token punctuation">;</span>
        +<span class="token punctuation">}</span>
        +</code></pre>
        +
        -
        +
        - + - + diff --git a/plugins/custom-class/prism-custom-class.js b/plugins/custom-class/prism-custom-class.js index bb5bd6a6eb..a8dca48f98 100644 --- a/plugins/custom-class/prism-custom-class.js +++ b/plugins/custom-class/prism-custom-class.js @@ -1,31 +1,110 @@ -(function(){ - -if ( - (typeof self === 'undefined' || !self.Prism) && - (typeof global === 'undefined' || !global.Prism) -) { - return; -} - -var options = { - classMap: {} -}; -Prism.plugins.customClass = { - map: function map(cm) { - options.classMap = cm; - }, - prefix: function prefix(string) { - options.prefixString = string; - } -} +(function () { -Prism.hooks.add('wrap', function (env) { - if (!options.classMap && !options.prefixString) { + if (typeof Prism === 'undefined') { return; } - env.classes = env.classes.map(function(c) { - return (options.prefixString || '') + (options.classMap[c] || c); + + /** + * @callback ClassMapper + * @param {string} className + * @param {string} language + * @returns {string} + * + * @callback ClassAdder + * @param {ClassAdderEnvironment} env + * @returns {undefined | string | string[]} + * + * @typedef ClassAdderEnvironment + * @property {string} language + * @property {string} type + * @property {string} content + */ + + // options + + /** @type {ClassAdder | undefined} */ + var adder; + /** @type {ClassMapper | undefined} */ + var mapper; + /** @type {string} */ + var prefixString = ''; + + + /** + * @param {string} className + * @param {string} language + */ + function apply(className, language) { + return prefixString + (mapper ? mapper(className, language) : className); + } + + + Prism.plugins.customClass = { + /** + * Sets the function which can be used to add custom aliases to any token. + * + * @param {ClassAdder} classAdder + */ + add: function (classAdder) { + adder = classAdder; + }, + /** + * Maps all class names using the given object or map function. + * + * This does not affect the prefix. + * + * @param {Object | ClassMapper} classMapper + */ + map: function map(classMapper) { + if (typeof classMapper === 'function') { + mapper = classMapper; + } else { + mapper = function (className) { + return classMapper[className] || className; + }; + } + }, + /** + * Adds the given prefix to all class names. + * + * @param {string} string + */ + prefix: function prefix(string) { + prefixString = string || ''; + }, + /** + * Applies the current mapping and prefix to the given class name. + * + * @param {string} className A single class name. + * @param {string} language The language of the code that contains this class name. + * + * If the language is unknown, pass `"none"`. + */ + apply: apply + }; + + Prism.hooks.add('wrap', function (env) { + if (adder) { + var result = adder({ + content: env.content, + type: env.type, + language: env.language + }); + + if (Array.isArray(result)) { + env.classes.push.apply(env.classes, result); + } else if (result) { + env.classes.push(result); + } + } + + if (!mapper && !prefixString) { + return; + } + + env.classes = env.classes.map(function (c) { + return apply(c, env.language); + }); }); -}); -})(); +}()); diff --git a/plugins/custom-class/prism-custom-class.min.js b/plugins/custom-class/prism-custom-class.min.js index f22063f557..e6331f932a 100644 --- a/plugins/custom-class/prism-custom-class.min.js +++ b/plugins/custom-class/prism-custom-class.min.js @@ -1 +1 @@ -!function(){if("undefined"!=typeof self&&self.Prism||"undefined"!=typeof global&&global.Prism){var s={classMap:{}};Prism.plugins.customClass={map:function(i){s.classMap=i},prefix:function(i){s.prefixString=i}},Prism.hooks.add("wrap",function(i){(s.classMap||s.prefixString)&&(i.classes=i.classes.map(function(i){return(s.prefixString||"")+(s.classMap[i]||i)}))})}}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism){var a,t,e="";Prism.plugins.customClass={add:function(n){a=n},map:function(s){t="function"==typeof s?s:function(n){return s[n]||n}},prefix:function(n){e=n||""},apply:u},Prism.hooks.add("wrap",function(s){if(a){var n=a({content:s.content,type:s.type,language:s.language});Array.isArray(n)?s.classes.push.apply(s.classes,n):n&&s.classes.push(n)}(t||e)&&(s.classes=s.classes.map(function(n){return u(n,s.language)}))})}function u(n,s){return e+(t?t(n,s):n)}}(); \ No newline at end of file diff --git a/plugins/data-uri-highlight/index.html b/plugins/data-uri-highlight/index.html index ac817e44b3..0c986aae69 100644 --- a/plugins/data-uri-highlight/index.html +++ b/plugins/data-uri-highlight/index.html @@ -3,25 +3,20 @@ - + Data-URI Highlight ▲ Prism plugins - + - + - + -
        -
        - -

        Data-URI Highlight

        -

        Highlights data-URI contents.

        -
        +

        How to use

        @@ -31,7 +26,7 @@

        How to use

        Example

        - +
        div {
             border: 40px solid transparent;
             border-image: 33.334% url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30"> \
        @@ -47,14 +42,14 @@ 

        Example

        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/data-uri-highlight/prism-data-uri-highlight.js b/plugins/data-uri-highlight/prism-data-uri-highlight.js index 7ff8d1fd5f..ea1f4b3a34 100644 --- a/plugins/data-uri-highlight/prism-data-uri-highlight.js +++ b/plugins/data-uri-highlight/prism-data-uri-highlight.js @@ -1,9 +1,6 @@ (function () { - if ( - typeof self !== 'undefined' && !self.Prism || - typeof global !== 'undefined' && !global.Prism - ) { + if (typeof Prism === 'undefined') { return; } @@ -47,7 +44,7 @@ } Prism.languages.DFS(grammar, function (key, def, type) { - if (candidates.indexOf(type) > -1 && Prism.util.type(def) !== 'Array') { + if (candidates.indexOf(type) > -1 && !Array.isArray(def)) { if (!def.pattern) { def = this[key] = { pattern: def @@ -60,8 +57,7 @@ Prism.languages.insertBefore('inside', def.inside['url-link'] ? 'url-link' : 'punctuation', { 'data-uri': dataURI }, def); - } - else { + } else { if (def.inside['url-link']) { Prism.languages.insertBefore('inside', 'url-link', { 'data-uri': dataURI @@ -95,4 +91,4 @@ Prism.plugins.dataURIHighlight.processGrammar(env.grammar); }); -}()); \ No newline at end of file +}()); diff --git a/plugins/data-uri-highlight/prism-data-uri-highlight.min.js b/plugins/data-uri-highlight/prism-data-uri-highlight.min.js index 479828d93f..7f6a2137de 100644 --- a/plugins/data-uri-highlight/prism-data-uri-highlight.min.js +++ b/plugins/data-uri-highlight/prism-data-uri-highlight.min.js @@ -1 +1 @@ -!function(){if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){var i=function(i){return Prism.plugins.autolinker&&Prism.plugins.autolinker.processGrammar(i),i},a={pattern:/(.)\bdata:[^\/]+\/[^,]+,(?:(?!\1)[\s\S]|\\\1)+(?=\1)/,lookbehind:!0,inside:{"language-css":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?css,)[\s\S]+/,lookbehind:!0},"language-javascript":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?javascript,)[\s\S]+/,lookbehind:!0},"language-json":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?json,)[\s\S]+/,lookbehind:!0},"language-markup":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?(?:html|xml),)[\s\S]+/,lookbehind:!0}}},n=["url","attr-value","string"];Prism.plugins.dataURIHighlight={processGrammar:function(i){i&&!i["data-uri"]&&(Prism.languages.DFS(i,function(i,e,r){n.indexOf(r)>-1&&"Array"!==Prism.util.type(e)&&(e.pattern||(e=this[i]={pattern:e}),e.inside=e.inside||{},"attr-value"==r?Prism.languages.insertBefore("inside",e.inside["url-link"]?"url-link":"punctuation",{"data-uri":a},e):e.inside["url-link"]?Prism.languages.insertBefore("inside","url-link",{"data-uri":a},e):e.inside["data-uri"]=a)}),i["data-uri"]=a)}},Prism.hooks.add("before-highlight",function(n){if(a.pattern.test(n.code))for(var e in a.inside)if(a.inside.hasOwnProperty(e)&&!a.inside[e].inside&&a.inside[e].pattern.test(n.code)){var r=e.match(/^language-(.+)/)[1];Prism.languages[r]&&(a.inside[e].inside={rest:i(Prism.languages[r])})}Prism.plugins.dataURIHighlight.processGrammar(n.grammar)})}}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism){var e={pattern:/(.)\bdata:[^\/]+\/[^,]+,(?:(?!\1)[\s\S]|\\\1)+(?=\1)/,lookbehind:!0,inside:{"language-css":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?css,)[\s\S]+/,lookbehind:!0},"language-javascript":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?javascript,)[\s\S]+/,lookbehind:!0},"language-json":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?json,)[\s\S]+/,lookbehind:!0},"language-markup":{pattern:/(data:[^\/]+\/(?:[^+,]+\+)?(?:html|xml),)[\s\S]+/,lookbehind:!0}}},r=["url","attr-value","string"];Prism.plugins.dataURIHighlight={processGrammar:function(i){i&&!i["data-uri"]&&(Prism.languages.DFS(i,function(i,a,n){-1 + + + + + + Diff Highlight ▲ Prism plugins + + + + + + + + + + + + +
        + +
        +

        How to use

        + +

        Replace the language-diff of your code block with a language-diff-xxxx class to enable syntax highlighting for diff blocks.

        + +

        + Optional:
        + You can add the diff-highlight class to your code block to indicate changes using the background color of a line rather than the color of the text. +

        + +

        Autoloader

        + +

        The Autoloader plugin understands the language-diff-xxxx format and will ensure that the language definitions for both Diff and the code language are loaded.

        +
        + +
        +

        Example

        + +

        Using class="language-diff":

        + +
        @@ -4,6 +4,5 @@
        +-    let foo = bar.baz([1, 2, 3]);
        +-    foo = foo + 1;
        ++    const foo = bar.baz([1, 2, 3]) + 1;
        +     console.log(`foo: ${foo}`);
        + +

        Using class="language-diff diff-highlight":

        + +
        @@ -4,6 +4,5 @@
        +-    let foo = bar.baz([1, 2, 3]);
        +-    foo = foo + 1;
        ++    const foo = bar.baz([1, 2, 3]) + 1;
        +     console.log(`foo: ${foo}`);
        + +

        Using class="language-diff-javascript":

        + +
        @@ -4,6 +4,5 @@
        +-    let foo = bar.baz([1, 2, 3]);
        +-    foo = foo + 1;
        ++    const foo = bar.baz([1, 2, 3]) + 1;
        +     console.log(`foo: ${foo}`);
        + +

        Using class="language-diff-javascript diff-highlight":

        + +
        @@ -4,6 +4,5 @@
        +-    let foo = bar.baz([1, 2, 3]);
        +-    foo = foo + 1;
        ++    const foo = bar.baz([1, 2, 3]) + 1;
        +     console.log(`foo: ${foo}`);
        + +

        + Using class="language-diff-rust diff-highlight":
        + (Autoloader is used to load the Rust language definition.) +

        + +
        @@ -111,6 +114,9 @@
        +         nasty_btree_map.insert(i, MyLeafNode(i));
        +     }
        +
        ++    let mut zst_btree_map: BTreeMap<(), ()> = BTreeMap::new();
        ++    zst_btree_map.insert((), ());
        ++
        +     // VecDeque
        +     let mut vec_deque = VecDeque::new();
        +     vec_deque.push_back(5);
        +
        + +
        + + + + + + + + + + + diff --git a/plugins/diff-highlight/prism-diff-highlight.css b/plugins/diff-highlight/prism-diff-highlight.css new file mode 100644 index 0000000000..0d9eb0c52b --- /dev/null +++ b/plugins/diff-highlight/prism-diff-highlight.css @@ -0,0 +1,13 @@ +pre.diff-highlight > code .token.deleted:not(.prefix), +pre > code.diff-highlight .token.deleted:not(.prefix) { + background-color: rgba(255, 0, 0, .1); + color: inherit; + display: block; +} + +pre.diff-highlight > code .token.inserted:not(.prefix), +pre > code.diff-highlight .token.inserted:not(.prefix) { + background-color: rgba(0, 255, 128, .1); + color: inherit; + display: block; +} diff --git a/plugins/diff-highlight/prism-diff-highlight.js b/plugins/diff-highlight/prism-diff-highlight.js new file mode 100644 index 0000000000..aa7bcf3f3f --- /dev/null +++ b/plugins/diff-highlight/prism-diff-highlight.js @@ -0,0 +1,90 @@ +(function () { + + if (typeof Prism === 'undefined') { + return; + } + + + var LANGUAGE_REGEX = /^diff-([\w-]+)/i; + var HTML_TAG = /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g; + //this will match a line plus the line break while ignoring the line breaks HTML tags may contain. + var HTML_LINE = RegExp(/(?:__|[^\r\n<])*(?:\r\n?|\n|(?:__|[^\r\n<])(?![^\r\n]))/.source.replace(/__/g, function () { return HTML_TAG.source; }), 'gi'); + + var warningLogged = false; + + Prism.hooks.add('before-sanity-check', function (env) { + var lang = env.language; + if (LANGUAGE_REGEX.test(lang) && !env.grammar) { + env.grammar = Prism.languages[lang] = Prism.languages.diff; + } + }); + Prism.hooks.add('before-tokenize', function (env) { + if (!warningLogged && !Prism.languages.diff && !Prism.plugins.autoloader) { + warningLogged = true; + console.warn("Prism's Diff Highlight plugin requires the Diff language definition (prism-diff.js)." + + "Make sure the language definition is loaded or use Prism's Autoloader plugin."); + } + + var lang = env.language; + if (LANGUAGE_REGEX.test(lang) && !Prism.languages[lang]) { + Prism.languages[lang] = Prism.languages.diff; + } + }); + + Prism.hooks.add('wrap', function (env) { + var diffLanguage; var diffGrammar; + + if (env.language !== 'diff') { + var langMatch = LANGUAGE_REGEX.exec(env.language); + if (!langMatch) { + return; // not a language specific diff + } + + diffLanguage = langMatch[1]; + diffGrammar = Prism.languages[diffLanguage]; + } + + var PREFIXES = Prism.languages.diff && Prism.languages.diff.PREFIXES; + + // one of the diff tokens without any nested tokens + if (PREFIXES && env.type in PREFIXES) { + /** @type {string} */ + var content = env.content.replace(HTML_TAG, ''); // remove all HTML tags + + /** @type {string} */ + var decoded = content.replace(/</g, '<').replace(/&/g, '&'); + + // remove any one-character prefix + var code = decoded.replace(/(^|[\r\n])./g, '$1'); + + // highlight, if possible + var highlighted; + if (diffGrammar) { + highlighted = Prism.highlight(code, diffGrammar, diffLanguage); + } else { + highlighted = Prism.util.encode(code); + } + + // get the HTML source of the prefix token + var prefixToken = new Prism.Token('prefix', PREFIXES[env.type], [/\w+/.exec(env.type)[0]]); + var prefix = Prism.Token.stringify(prefixToken, env.language); + + // add prefix + var lines = []; var m; + HTML_LINE.lastIndex = 0; + while ((m = HTML_LINE.exec(highlighted))) { + lines.push(prefix + m[0]); + } + if (/(?:^|[\r\n]).$/.test(decoded)) { + // because both "+a\n+" and "+a\n" will map to "a\n" after the line prefixes are removed + lines.push(prefix); + } + env.content = lines.join(''); + + if (diffGrammar) { + env.classes.push('language-' + diffLanguage); + } + } + }); + +}()); diff --git a/plugins/diff-highlight/prism-diff-highlight.min.css b/plugins/diff-highlight/prism-diff-highlight.min.css new file mode 100644 index 0000000000..9b8f6a7528 --- /dev/null +++ b/plugins/diff-highlight/prism-diff-highlight.min.css @@ -0,0 +1 @@ +pre.diff-highlight>code .token.deleted:not(.prefix),pre>code.diff-highlight .token.deleted:not(.prefix){background-color:rgba(255,0,0,.1);color:inherit;display:block}pre.diff-highlight>code .token.inserted:not(.prefix),pre>code.diff-highlight .token.inserted:not(.prefix){background-color:rgba(0,255,128,.1);color:inherit;display:block} \ No newline at end of file diff --git a/plugins/diff-highlight/prism-diff-highlight.min.js b/plugins/diff-highlight/prism-diff-highlight.min.js new file mode 100644 index 0000000000..a6cf1c2fce --- /dev/null +++ b/plugins/diff-highlight/prism-diff-highlight.min.js @@ -0,0 +1 @@ +!function(){if("undefined"!=typeof Prism){var m=/^diff-([\w-]+)/i,d=/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g,c=RegExp("(?:__|[^\r\n<])*(?:\r\n?|\n|(?:__|[^\r\n<])(?![^\r\n]))".replace(/__/g,function(){return d.source}),"gi"),a=!1;Prism.hooks.add("before-sanity-check",function(e){var i=e.language;m.test(i)&&!e.grammar&&(e.grammar=Prism.languages[i]=Prism.languages.diff)}),Prism.hooks.add("before-tokenize",function(e){a||Prism.languages.diff||Prism.plugins.autoloader||(a=!0,console.warn("Prism's Diff Highlight plugin requires the Diff language definition (prism-diff.js).Make sure the language definition is loaded or use Prism's Autoloader plugin."));var i=e.language;m.test(i)&&!Prism.languages[i]&&(Prism.languages[i]=Prism.languages.diff)}),Prism.hooks.add("wrap",function(e){var i,a;if("diff"!==e.language){var s=m.exec(e.language);if(!s)return;i=s[1],a=Prism.languages[i]}var r=Prism.languages.diff&&Prism.languages.diff.PREFIXES;if(r&&e.type in r){var n,g=e.content.replace(d,"").replace(/</g,"<").replace(/&/g,"&"),f=g.replace(/(^|[\r\n])./g,"$1");n=a?Prism.highlight(f,a,i):Prism.util.encode(f);var u,l=new Prism.Token("prefix",r[e.type],[/\w+/.exec(e.type)[0]]),t=Prism.Token.stringify(l,e.language),o=[];for(c.lastIndex=0;u=c.exec(n);)o.push(t+u[0]);/(?:^|[\r\n]).$/.test(g)&&o.push(t),e.content=o.join(""),a&&e.classes.push("language-"+i)}})}}(); \ No newline at end of file diff --git a/plugins/download-button/index.html b/plugins/download-button/index.html new file mode 100644 index 0000000000..2f7c29c91f --- /dev/null +++ b/plugins/download-button/index.html @@ -0,0 +1,53 @@ + + + + + + +Download Button ▲ Prism plugins + + + + + + + + + + + +
        + +
        +

        How to use

        + +

        Use the data-src and data-download-link attribute on a <pre> elements similar to Autoloader, like so:

        + +
        <pre data-src="myfile.js" data-download-link></pre>
        + +

        Optionally, the text of the button can also be customized by using a data-download-link-label attribute.

        +
        <pre data-src="myfile.js" data-download-link data-download-link-label="Download this file"></pre>
        +
        + +
        +

        Examples

        + +

        The plugin’s JS code:

        +
        
        +
        +	

        This page:

        +
        
        +
        + +
        + + + + + + + + + + + diff --git a/plugins/download-button/prism-download-button.js b/plugins/download-button/prism-download-button.js new file mode 100644 index 0000000000..8a5bd90539 --- /dev/null +++ b/plugins/download-button/prism-download-button.js @@ -0,0 +1,20 @@ +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined' || !document.querySelector) { + return; + } + + Prism.plugins.toolbar.registerButton('download-file', function (env) { + var pre = env.element.parentNode; + if (!pre || !/pre/i.test(pre.nodeName) || !pre.hasAttribute('data-src') || !pre.hasAttribute('data-download-link')) { + return; + } + var src = pre.getAttribute('data-src'); + var a = document.createElement('a'); + a.textContent = pre.getAttribute('data-download-link-label') || 'Download'; + a.setAttribute('download', ''); + a.href = src; + return a; + }); + +}()); diff --git a/plugins/download-button/prism-download-button.min.js b/plugins/download-button/prism-download-button.min.js new file mode 100644 index 0000000000..57e5879e75 --- /dev/null +++ b/plugins/download-button/prism-download-button.min.js @@ -0,0 +1 @@ +"undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector&&Prism.plugins.toolbar.registerButton("download-file",function(t){var e=t.element.parentNode;if(e&&/pre/i.test(e.nodeName)&&e.hasAttribute("data-src")&&e.hasAttribute("data-download-link")){var n=e.getAttribute("data-src"),a=document.createElement("a");return a.textContent=e.getAttribute("data-download-link-label")||"Download",a.setAttribute("download",""),a.href=n,a}}); \ No newline at end of file diff --git a/plugins/file-highlight/index.html b/plugins/file-highlight/index.html index 5154de1be9..2033ef017a 100644 --- a/plugins/file-highlight/index.html +++ b/plugins/file-highlight/index.html @@ -3,44 +3,40 @@ - + File Highlight ▲ Prism plugins - + - - + + - + -
        -
        - -

        File Highlight

        -

        Fetch external files and highlight them with Prism. Used on the Prism website itself.

        -
        +

        How to use

        - +

        Use the data-src attribute on empty <pre> elements, like so:

        - +
        <pre data-src="myfile.js"></pre>
        - +

        You don’t need to specify the language, it’s automatically determined by the file extension. If, however, the language cannot be determined from the file extension or the file extension is incorrect, you may specify a language as well (with the usual class name way).

        - -

        Please note that the files are fetched with XMLHttpRequest. This means that if the file is on a different origin, fetching it will fail, unless CORS is enabled on that website.

        -

        - When used in conjunction with the Toolbar plugin, this plugin can also display a button to download the file. - To use it, add a data-download-link attribute on the <pre> element.
        - Optionally, the text can also be customized by using a data-download-link-label attribute. -

        -
        <pre data-src="myfile.js" data-download-link data-download-link-label="Download this file"></pre>
        +

        Use the data-range attribute to display only a selected range of lines from the file, like so:

        + +
        <pre data-src="myfile.js" data-range="1,5"></pre>
        + +

        Lines start at 1, so "1,5" will display line 1 up to and including line 5. It's also possible to specify just a single line (e.g. "5" for just line 5) and open ranges (e.g. "3," for all lines starting at line 3). Negative integers can be used to specify the n-th last line, e.g. -2 for the second last line.

        + +

        When data-range is used in conjunction with the Line Numbers plugin, this plugin will add the proper data-start according to the specified range. This behavior can be overridden by setting the data-start attribute manually.

        + +

        Please note that the files are fetched with XMLHttpRequest. This means that if the file is on a different origin, fetching it will fail, unless CORS is enabled on that website.

        @@ -48,28 +44,28 @@

        Examples

        The plugin’s JS code:

        
        -	
        +
         	

        This page:

        
         
         	

        File that doesn’t exist:

        
         
        -	

        With a download button:

        -
        
        +	

        With line numbers, and data-range="12,111":

        +
        
         
         	

        For more examples, browse around the Prism website. Most large code samples are actually files fetched with this plugin.

        -
        +
        - - + + - + - \ No newline at end of file + diff --git a/plugins/file-highlight/prism-file-highlight.js b/plugins/file-highlight/prism-file-highlight.js index a2deb65157..1247e19fae 100644 --- a/plugins/file-highlight/prism-file-highlight.js +++ b/plugins/file-highlight/prism-file-highlight.js @@ -1,85 +1,195 @@ (function () { - if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { return; } - self.Prism.fileHighlight = function() { - - var Extensions = { - 'js': 'javascript', - 'py': 'python', - 'rb': 'ruby', - 'ps1': 'powershell', - 'psm1': 'powershell', - 'sh': 'bash', - 'bat': 'batch', - 'h': 'c', - 'tex': 'latex' - }; + // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill + if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; + } - Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) { - var src = pre.getAttribute('data-src'); + var LOADING_MESSAGE = 'Loading…'; + var FAILURE_MESSAGE = function (status, message) { + return '✖ Error ' + status + ' while fetching file: ' + message; + }; + var FAILURE_EMPTY_MESSAGE = '✖ Error: File does not exist or is empty'; + + var EXTENSIONS = { + 'js': 'javascript', + 'py': 'python', + 'rb': 'ruby', + 'ps1': 'powershell', + 'psm1': 'powershell', + 'sh': 'bash', + 'bat': 'batch', + 'h': 'c', + 'tex': 'latex' + }; - var language, parent = pre; - var lang = /\blang(?:uage)?-(?!\*)([\w-]+)\b/i; - while (parent && !lang.test(parent.className)) { - parent = parent.parentNode; + var STATUS_ATTR = 'data-src-status'; + var STATUS_LOADING = 'loading'; + var STATUS_LOADED = 'loaded'; + var STATUS_FAILED = 'failed'; + + var SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '="' + STATUS_LOADED + '"])' + + ':not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])'; + + /** + * Loads the given file. + * + * @param {string} src The URL or path of the source file to load. + * @param {(result: string) => void} success + * @param {(reason: string) => void} error + */ + function loadFile(src, success, error) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', src, true); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + if (xhr.status < 400 && xhr.responseText) { + success(xhr.responseText); + } else { + if (xhr.status >= 400) { + error(FAILURE_MESSAGE(xhr.status, xhr.statusText)); + } else { + error(FAILURE_EMPTY_MESSAGE); + } + } } + }; + xhr.send(null); + } - if (parent) { - language = (pre.className.match(lang) || [, ''])[1]; + /** + * Parses the given range. + * + * This returns a range with inclusive ends. + * + * @param {string | null | undefined} range + * @returns {[number, number | undefined] | undefined} + */ + function parseRange(range) { + var m = /^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(range || ''); + if (m) { + var start = Number(m[1]); + var comma = m[2]; + var end = m[3]; + + if (!comma) { + return [start, start]; } - - if (!language) { - var extension = (src.match(/\.(\w+)$/) || [, ''])[1]; - language = Extensions[extension] || extension; + if (!end) { + return [start, undefined]; } + return [start, Number(end)]; + } + return undefined; + } - var code = document.createElement('code'); - code.className = 'language-' + language; + Prism.hooks.add('before-highlightall', function (env) { + env.selector += ', ' + SELECTOR; + }); - pre.textContent = ''; + Prism.hooks.add('before-sanity-check', function (env) { + var pre = /** @type {HTMLPreElement} */ (env.element); + if (pre.matches(SELECTOR)) { + env.code = ''; // fast-path the whole thing and go to complete - code.textContent = 'Loading…'; + pre.setAttribute(STATUS_ATTR, STATUS_LOADING); // mark as loading - pre.appendChild(code); + // add code element with loading message + var code = pre.appendChild(document.createElement('CODE')); + code.textContent = LOADING_MESSAGE; - var xhr = new XMLHttpRequest(); + var src = pre.getAttribute('data-src'); - xhr.open('GET', src, true); + var language = env.language; + if (language === 'none') { + // the language might be 'none' because there is no language set; + // in this case, we want to use the extension as the language + var extension = (/\.(\w+)$/.exec(src) || [, 'none'])[1]; + language = EXTENSIONS[extension] || extension; + } - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { + // set language classes + Prism.util.setLanguage(code, language); + Prism.util.setLanguage(pre, language); - if (xhr.status < 400 && xhr.responseText) { - code.textContent = xhr.responseText; + // preload the language + var autoloader = Prism.plugins.autoloader; + if (autoloader) { + autoloader.loadLanguages(language); + } - Prism.highlightElement(code); - } - else if (xhr.status >= 400) { - code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText; - } - else { - code.textContent = '✖ Error: File does not exist or is empty'; + // load file + loadFile( + src, + function (text) { + // mark as loaded + pre.setAttribute(STATUS_ATTR, STATUS_LOADED); + + // handle data-range + var range = parseRange(pre.getAttribute('data-range')); + if (range) { + var lines = text.split(/\r\n?|\n/g); + + // the range is one-based and inclusive on both ends + var start = range[0]; + var end = range[1] == null ? lines.length : range[1]; + + if (start < 0) { start += lines.length; } + start = Math.max(0, Math.min(start - 1, lines.length)); + if (end < 0) { end += lines.length; } + end = Math.max(0, Math.min(end, lines.length)); + + text = lines.slice(start, end).join('\n'); + + // add data-start for line numbers + if (!pre.hasAttribute('data-start')) { + pre.setAttribute('data-start', String(start + 1)); + } } - } - }; - - if (pre.hasAttribute('data-download-link') && Prism.plugins.toolbar) { - Prism.plugins.toolbar.registerButton('download-file', function () { - var a = document.createElement('a'); - a.textContent = pre.getAttribute('data-download-link-label') || 'Download'; - a.setAttribute('download', ''); - a.href = src; - return a; - }); - } - xhr.send(null); - }); + // highlight code + code.textContent = text; + Prism.highlightElement(code); + }, + function (error) { + // mark as failed + pre.setAttribute(STATUS_ATTR, STATUS_FAILED); + code.textContent = error; + } + ); + } + }); + + Prism.plugins.fileHighlight = { + /** + * Executes the File Highlight plugin for all matching `pre` elements under the given container. + * + * Note: Elements which are already loaded or currently loading will not be touched by this method. + * + * @param {ParentNode} [container=document] + */ + highlight: function highlight(container) { + var elements = (container || document).querySelectorAll(SELECTOR); + + for (var i = 0, element; (element = elements[i++]);) { + Prism.highlightElement(element); + } + } }; - document.addEventListener('DOMContentLoaded', self.Prism.fileHighlight); + var logged = false; + /** @deprecated Use `Prism.plugins.fileHighlight.highlight` instead. */ + Prism.fileHighlight = function () { + if (!logged) { + console.warn('Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.'); + logged = true; + } + Prism.plugins.fileHighlight.highlight.apply(this, arguments); + }; -})(); +}()); diff --git a/plugins/file-highlight/prism-file-highlight.min.js b/plugins/file-highlight/prism-file-highlight.min.js index 593de3e181..23bacb136e 100644 --- a/plugins/file-highlight/prism-file-highlight.min.js +++ b/plugins/file-highlight/prism-file-highlight.min.js @@ -1 +1 @@ -!function(){"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(){var t={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"};Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(e){for(var n,a=e.getAttribute("data-src"),o=e,r=/\blang(?:uage)?-(?!\*)([\w-]+)\b/i;o&&!r.test(o.className);)o=o.parentNode;if(o&&(n=(e.className.match(r)||[,""])[1]),!n){var s=(a.match(/\.(\w+)$/)||[,""])[1];n=t[s]||s}var l=document.createElement("code");l.className="language-"+n,e.textContent="",l.textContent="Loading…",e.appendChild(l);var i=new XMLHttpRequest;i.open("GET",a,!0),i.onreadystatechange=function(){4==i.readyState&&(i.status<400&&i.responseText?(l.textContent=i.responseText,Prism.highlightElement(l)):l.textContent=i.status>=400?"✖ Error "+i.status+" while fetching file: "+i.statusText:"✖ Error: File does not exist or is empty")},e.hasAttribute("data-download-link")&&Prism.plugins.toolbar&&Prism.plugins.toolbar.registerButton("download-file",function(){var t=document.createElement("a");return t.textContent=e.getAttribute("data-download-link-label")||"Download",t.setAttribute("download",""),t.href=a,t}),i.send(null)})},document.addEventListener("DOMContentLoaded",self.Prism.fileHighlight))}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector);var l={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"},o="data-src-status",h="loading",g="loaded",u="pre[data-src]:not(["+o+'="'+g+'"]):not(['+o+'="'+h+'"])';Prism.hooks.add("before-highlightall",function(t){t.selector+=", "+u}),Prism.hooks.add("before-sanity-check",function(t){var r=t.element;if(r.matches(u)){t.code="",r.setAttribute(o,h);var s=r.appendChild(document.createElement("CODE"));s.textContent="Loading…";var e=r.getAttribute("data-src"),i=t.language;if("none"===i){var n=(/\.(\w+)$/.exec(e)||[,"none"])[1];i=l[n]||n}Prism.util.setLanguage(s,i),Prism.util.setLanguage(r,i);var a=Prism.plugins.autoloader;a&&a.loadLanguages(i),function(t,e,i){var n=new XMLHttpRequest;n.open("GET",t,!0),n.onreadystatechange=function(){4==n.readyState&&(n.status<400&&n.responseText?e(n.responseText):400<=n.status?i(function(t,e){return"✖ Error "+t+" while fetching file: "+e}(n.status,n.statusText)):i("✖ Error: File does not exist or is empty"))},n.send(null)}(e,function(t){r.setAttribute(o,g);var e=function(t){var e=/^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(t||"");if(e){var i=Number(e[1]),n=e[2],a=e[3];return n?a?[i,Number(a)]:[i,void 0]:[i,i]}}(r.getAttribute("data-range"));if(e){var i=t.split(/\r\n?|\n/g),n=e[0],a=null==e[1]?i.length:e[1];n<0&&(n+=i.length),n=Math.max(0,Math.min(n-1,i.length)),a<0&&(a+=i.length),a=Math.max(0,Math.min(a,i.length)),t=i.slice(n,a).join("\n"),r.hasAttribute("data-start")||r.setAttribute("data-start",String(n+1))}s.textContent=t,Prism.highlightElement(s)},function(t){r.setAttribute(o,"failed"),s.textContent=t})}});var t=!(Prism.plugins.fileHighlight={highlight:function(t){for(var e,i=(t||document).querySelectorAll(u),n=0;e=i[n++];)Prism.highlightElement(e)}});Prism.fileHighlight=function(){t||(console.warn("Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead."),t=!0),Prism.plugins.fileHighlight.highlight.apply(this,arguments)}}}(); \ No newline at end of file diff --git a/plugins/filter-highlight-all/index.html b/plugins/filter-highlight-all/index.html new file mode 100644 index 0000000000..58523c593e --- /dev/null +++ b/plugins/filter-highlight-all/index.html @@ -0,0 +1,146 @@ + + + + + + + Filter highlightAll ▲ Prism plugins + + + + + + + + + + + +
        + +
        +

        How to use

        + +

        Filter highlightAll provides you with ways to filter the element the highlightAll and highlightAllUnder methods actually highlight. This can be very useful when you use Prism's automatic highlighting when loading the page but want to exclude certain code blocks.

        +
        + +
        +

        API

        + +

        In Prism.plugins.filterHighlightAll you can find the following:

        + +
        +
        add(condition: (value: { element, language: string }) => boolean): void
        +
        + Adds a new filter which will only allow an element to be highlighted if the given function returns true for that element.
        + This can be used to define a custom language filter. +
        + +
        addSelector(selector: string): void
        +
        + Adds a new filter which will only allow an element to be highlighted if the element matches the given CSS selector. +
        + +
        reject.add(condition: (value: { element, language: string }) => boolean): void
        +
        + Same as add, but only elements which do not fulfill the condition will be highlighted. +
        + +
        reject.addSelector(selector: string): void
        +
        + Same as addSelector, but only elements which do not match the selector will be highlighted. +
        + +
        filterKnown: boolean = false
        +
        + Set this to true to only allow known languages. + Code blocks without a set language or an unknown language will not be highlighted. +
        +
        + +

        An element will only be highlighted by the highlightAll and highlightAllUnder methods if all of the above accept the element.

        + +

        Attributes

        + +

        You can also add the following data-* attributes to the script which contains the Filter highlightAll plugin.

        + +
        +
        <script src="..." data-filter-selector="<css selector>">
        +
        + This attribute is a shorthand for Prism.plugins.filterHighlightAll.addSelector. + The value of the attribute will be passed as is to the addSelector function. +
        + +
        <script src="..." data-reject-selector="<css selector>">
        +
        + This attribute is a shorthand for Prism.plugins.filterHighlightAll.reject.addSelector. + The value of the attribute will be passed as is to the rejectSelector function. +
        + +
        <script src="..." data-filter-known>
        +
        + This attribute can be used to set the value of Prism.plugins.filterHighlightAll.filterKnown. + filterKnown will be set to true if the attribute is present, false otherwise. +
        +
        + +
        + +
        +

        Examples

        + +

        The following code is used to define a filter on this page.

        + +
        // <code> elements with a .no-highlight class will be ignored
        +Prism.plugins.filterHighlightAll.reject.addSelector('code.no-highlight');
        +Prism.plugins.filterHighlightAll.reject.addSelector('pre.no-highlight > code');
        +
        +// don't highlight CSS code
        +Prism.plugins.filterHighlightAll.add(function (env) {
        +	return env.language !== 'css';
        +});
        + +

        The results:

        + +
        let foo = "I'm not being highlighted";
        + +
        a.link::after {
        +	content: 'also not being highlighted';
        +	color: #F00;
        +}
        + +

        Prism will ignore these blocks, so you can even define your own static highlighting which Prism would normally remove.

        + +
        a.link::before {
        +	content: 'I just do my own highlighting';
        +	color: #F00;
        +}
        + +
        + +
        + + + + + + + + + + + + diff --git a/plugins/filter-highlight-all/prism-filter-highlight-all.js b/plugins/filter-highlight-all/prism-filter-highlight-all.js new file mode 100644 index 0000000000..03d61d8db5 --- /dev/null +++ b/plugins/filter-highlight-all/prism-filter-highlight-all.js @@ -0,0 +1,127 @@ +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } + + // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill + if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; + } + + var script = Prism.util.currentScript(); + + + /** + * @type {Array<(element: HTMLElement) => boolean>} + */ + var filters = []; + + var config = Prism.plugins.filterHighlightAll = { + + /** + * Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements for + * which the given function returns `true` will be highlighted. + * + * @param {(value: { element: HTMLElement, language: string }) => boolean} condition + */ + add: function (condition) { + filters.push(function (element) { + return condition({ + element: element, + language: Prism.util.getLanguage(element) + }); + }); + }, + + /** + * Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements that + * match the given CSS selection will be highlighted. + * + * @param {string} selector + */ + addSelector: function (selector) { + filters.push(function (element) { + return element.matches(selector); + }); + }, + + reject: { + + /** + * Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements for + * which the given function returns `false` will be highlighted. + * + * @param {(value: { element: HTMLElement, language: string }) => boolean} condition + */ + add: function (condition) { + filters.push(function (element) { + return !condition({ + element: element, + language: Prism.util.getLanguage(element) + }); + }); + }, + + /** + * Adds a new filter for the elements of `highlightAll` and `highlightAllUnder` such that only elements that do + * not match the given CSS selection will be highlighted. + * + * @param {string} selector + */ + addSelector: function (selector) { + filters.push(function (element) { + return !element.matches(selector); + }); + }, + + }, + + /** + * Filters the elements of `highlightAll` and `highlightAllUnder` such that only elements with a known language + * will be highlighted. All elements with an unset or unknown language will be ignored. + * + * __Note:__ This will effectively disable the AutoLoader plugin. + * + * @type {boolean} + */ + filterKnown: !!script && script.hasAttribute('data-filter-known') + }; + + config.add(function filterKnown(env) { + return !config.filterKnown || typeof Prism.languages[env.language] === 'object'; + }); + + if (script) { + var attr; + attr = script.getAttribute('data-filter-selector'); + if (attr) { + config.addSelector(attr); + } + attr = script.getAttribute('data-reject-selector'); + if (attr) { + config.reject.addSelector(attr); + } + } + + /** + * Applies all filters to the given element and returns true if and only if every filter returned true on the + * given element. + * + * @param {HTMLElement} element + * @returns {boolean} + */ + function combinedFilter(element) { + for (var i = 0, l = filters.length; i < l; i++) { + if (!filters[i](element)) { + return false; + } + } + return true; + } + + Prism.hooks.add('before-all-elements-highlight', function (env) { + env.elements = env.elements.filter(combinedFilter); + }); + +}()); diff --git a/plugins/filter-highlight-all/prism-filter-highlight-all.min.js b/plugins/filter-highlight-all/prism-filter-highlight-all.min.js new file mode 100644 index 0000000000..1e311d345a --- /dev/null +++ b/plugins/filter-highlight-all/prism-filter-highlight-all.min.js @@ -0,0 +1 @@ +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector);var e,t=Prism.util.currentScript(),r=[],n=Prism.plugins.filterHighlightAll={add:function(t){r.push(function(e){return t({element:e,language:Prism.util.getLanguage(e)})})},addSelector:function(t){r.push(function(e){return e.matches(t)})},reject:{add:function(t){r.push(function(e){return!t({element:e,language:Prism.util.getLanguage(e)})})},addSelector:function(t){r.push(function(e){return!e.matches(t)})}},filterKnown:!!t&&t.hasAttribute("data-filter-known")};if(n.add(function(e){return!n.filterKnown||"object"==typeof Prism.languages[e.language]}),t)(e=t.getAttribute("data-filter-selector"))&&n.addSelector(e),(e=t.getAttribute("data-reject-selector"))&&n.reject.addSelector(e);Prism.hooks.add("before-all-elements-highlight",function(e){e.elements=e.elements.filter(i)})}function i(e){for(var t=0,n=r.length;t - + Highlight Keywords ▲ Prism plugins - + - + - + - + -
        -
        +
        -

        Highlight Keywords

        -

        This plugin adds special CSS classes for each keyword matched in the code. For example, the keyword if will have the class keyword-if as well. You can have fine grained control over the appearance of each keyword by providing your own CSS rules.

        -
        +
        +

        How to use

        + +

        This plugin adds a special class for every keyword, so keyword-specific styles can be applied. These special classes allow for fine-grained control over the appearance of keywords using your own CSS rules.

        + +

        For example, the keyword if will have the class keyword-if added. A CSS rule used to apply special highlighting could look like this:

        + +
        .token.keyword.keyword-if { /* styles for 'if' */ }
        + +

        Note: This plugin does not come with CSS styles. You have to define the keyword-specific CSS rules yourself.

        +

        Examples

        +

        This example shows the plugin in action. The keywords if and return will be highlighted in red. The color of all other keywords will be determined by the current theme. The CSS rules used to implement the keyword-specific highlighting can be seen in the HTML file below.

        +

        JavaScript

        
         
         	

        HTML (Markup)

        
         
        -
        +
        - + - + diff --git a/plugins/highlight-keywords/prism-highlight-keywords.js b/plugins/highlight-keywords/prism-highlight-keywords.js index 32b2812273..523fc964fe 100644 --- a/plugins/highlight-keywords/prism-highlight-keywords.js +++ b/plugins/highlight-keywords/prism-highlight-keywords.js @@ -1,17 +1,14 @@ -(function(){ +(function () { -if ( - typeof self !== 'undefined' && !self.Prism || - typeof global !== 'undefined' && !global.Prism -) { - return; -} - -Prism.hooks.add('wrap', function(env) { - if (env.type !== "keyword") { + if (typeof Prism === 'undefined') { return; } - env.classes.push('keyword-' + env.content); -}); -})(); + Prism.hooks.add('wrap', function (env) { + if (env.type !== 'keyword') { + return; + } + env.classes.push('keyword-' + env.content); + }); + +}()); diff --git a/plugins/highlight-keywords/prism-highlight-keywords.min.js b/plugins/highlight-keywords/prism-highlight-keywords.min.js index c4326feadb..b0d8d9adb5 100644 --- a/plugins/highlight-keywords/prism-highlight-keywords.min.js +++ b/plugins/highlight-keywords/prism-highlight-keywords.min.js @@ -1 +1 @@ -!function(){"undefined"!=typeof self&&!self.Prism||"undefined"!=typeof global&&!global.Prism||Prism.hooks.add("wrap",function(e){"keyword"===e.type&&e.classes.push("keyword-"+e.content)})}(); \ No newline at end of file +"undefined"!=typeof Prism&&Prism.hooks.add("wrap",function(e){"keyword"===e.type&&e.classes.push("keyword-"+e.content)}); \ No newline at end of file diff --git a/plugins/index.html b/plugins/index.html index e0e6cf23ea..cdab97fbb0 100644 --- a/plugins/index.html +++ b/plugins/index.html @@ -3,21 +3,21 @@ - + Plugins ▲ Prism - + - + - +
        -
        +
        @@ -30,13 +30,13 @@

        Contribute

        Writing Prism plugins is easy! Read how at the “Extending Prism” section.

        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/inline-color/index.html b/plugins/inline-color/index.html new file mode 100644 index 0000000000..3639e065cf --- /dev/null +++ b/plugins/inline-color/index.html @@ -0,0 +1,75 @@ + + + + + + +Inline color ▲ Prism plugins + + + + + + + + + + + + + +
        + +
        +

        Examples

        + +

        CSS

        +
        span.foo {
        +	background-color: navy;
        +	color: #BFD;
        +}
        +
        +span.bar {
        +	background: rgba(105, 0, 12, .38);
        +	color: hsl(30, 100%, 50%);
        +	border-color: transparent;
        +}
        + +
        
        +
        +	

        HTML (Markup)

        +
        <!DOCTYPE html>
        +<html lang="en">
        +<head>
        +
        +<meta charset="utf-8" />
        +<title>Example</title>
        +<style>
        +/* Also works here */
        +a.not-a-class {
        +	color: red;
        +}
        +</style>
        +<body style="color: black">
        +
        +</body>
        +</html>
        + +
        +
        + + + + + + + + + + + diff --git a/plugins/inline-color/prism-inline-color.css b/plugins/inline-color/prism-inline-color.css new file mode 100644 index 0000000000..d83787461e --- /dev/null +++ b/plugins/inline-color/prism-inline-color.css @@ -0,0 +1,33 @@ +span.inline-color-wrapper { + /* + * The background image is the following SVG inline in base 64: + * + * + * + * + * + * + * SVG-inlining explained: + * https://stackoverflow.com/a/21626701/7595472 + */ + background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyIDIiPjxwYXRoIGZpbGw9ImdyYXkiIGQ9Ik0wIDBoMnYySDB6Ii8+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0wIDBoMXYxSDB6TTEgMWgxdjFIMXoiLz48L3N2Zz4="); + /* This is to prevent visual glitches where one pixel from the repeating pattern could be seen. */ + background-position: center; + background-size: 110%; + + display: inline-block; + height: 1.333ch; + width: 1.333ch; + margin: 0 .333ch; + box-sizing: border-box; + border: 1px solid white; + outline: 1px solid rgba(0,0,0,.5); + overflow: hidden; +} + +span.inline-color { + display: block; + /* To prevent visual glitches again */ + height: 120%; + width: 120%; +} diff --git a/plugins/inline-color/prism-inline-color.js b/plugins/inline-color/prism-inline-color.js new file mode 100644 index 0000000000..6e7b9edaa7 --- /dev/null +++ b/plugins/inline-color/prism-inline-color.js @@ -0,0 +1,105 @@ +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } + + // Copied from the markup language definition + var HTML_TAG = /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g; + + // a regex to validate hexadecimal colors + var HEX_COLOR = /^#?((?:[\da-f]){3,4}|(?:[\da-f]{2}){3,4})$/i; + + /** + * Parses the given hexadecimal representation and returns the parsed RGBA color. + * + * If the format of the given string is invalid, `undefined` will be returned. + * Valid formats are: `RGB`, `RGBA`, `RRGGBB`, and `RRGGBBAA`. + * + * Hexadecimal colors are parsed because they are not fully supported by older browsers, so converting them to + * `rgba` functions improves browser compatibility. + * + * @param {string} hex + * @returns {string | undefined} + */ + function parseHexColor(hex) { + var match = HEX_COLOR.exec(hex); + if (!match) { + return undefined; + } + hex = match[1]; // removes the leading "#" + + // the width and number of channels + var channelWidth = hex.length >= 6 ? 2 : 1; + var channelCount = hex.length / channelWidth; + + // the scale used to normalize 4bit and 8bit values + var scale = channelWidth == 1 ? 1 / 15 : 1 / 255; + + // normalized RGBA channels + var channels = []; + for (var i = 0; i < channelCount; i++) { + var int = parseInt(hex.substr(i * channelWidth, channelWidth), 16); + channels.push(int * scale); + } + if (channelCount == 3) { + channels.push(1); // add alpha of 100% + } + + // output + var rgb = channels.slice(0, 3).map(function (x) { + return String(Math.round(x * 255)); + }).join(','); + var alpha = String(Number(channels[3].toFixed(3))); // easy way to round 3 decimal places + + return 'rgba(' + rgb + ',' + alpha + ')'; + } + + /** + * Validates the given Color using the current browser's internal implementation. + * + * @param {string} color + * @returns {string | undefined} + */ + function validateColor(color) { + var s = new Option().style; + s.color = color; + return s.color ? color : undefined; + } + + /** + * An array of function which parse a given string representation of a color. + * + * These parser serve as validators and as a layer of compatibility to support color formats which the browser + * might not support natively. + * + * @type {((value: string) => (string|undefined))[]} + */ + var parsers = [ + parseHexColor, + validateColor + ]; + + + Prism.hooks.add('wrap', function (env) { + if (env.type === 'color' || env.classes.indexOf('color') >= 0) { + var content = env.content; + + // remove all HTML tags inside + var rawText = content.split(HTML_TAG).join(''); + + var color; + for (var i = 0, l = parsers.length; i < l && !color; i++) { + color = parsers[i](rawText); + } + + if (!color) { + return; + } + + var previewElement = ''; + env.content = previewElement + content; + } + }); + +}()); diff --git a/plugins/inline-color/prism-inline-color.min.css b/plugins/inline-color/prism-inline-color.min.css new file mode 100644 index 0000000000..c161187fe4 --- /dev/null +++ b/plugins/inline-color/prism-inline-color.min.css @@ -0,0 +1 @@ +span.inline-color-wrapper{background:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyIDIiPjxwYXRoIGZpbGw9ImdyYXkiIGQ9Ik0wIDBoMnYySDB6Ii8+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0wIDBoMXYxSDB6TTEgMWgxdjFIMXoiLz48L3N2Zz4=);background-position:center;background-size:110%;display:inline-block;height:1.333ch;width:1.333ch;margin:0 .333ch;box-sizing:border-box;border:1px solid #fff;outline:1px solid rgba(0,0,0,.5);overflow:hidden}span.inline-color{display:block;height:120%;width:120%} \ No newline at end of file diff --git a/plugins/inline-color/prism-inline-color.min.js b/plugins/inline-color/prism-inline-color.min.js new file mode 100644 index 0000000000..c64c1572f6 --- /dev/null +++ b/plugins/inline-color/prism-inline-color.min.js @@ -0,0 +1 @@ +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var a=/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g,c=/^#?((?:[\da-f]){3,4}|(?:[\da-f]{2}){3,4})$/i,l=[function(n){var r=c.exec(n);if(r){for(var o=6<=(n=r[1]).length?2:1,s=n.length/o,e=1==o?1/15:1/255,t=[],i=0;i';n.content=i+o}})}}(); \ No newline at end of file diff --git a/plugins/jsonp-highlight/index.html b/plugins/jsonp-highlight/index.html index d70d375e80..14b0278ee7 100644 --- a/plugins/jsonp-highlight/index.html +++ b/plugins/jsonp-highlight/index.html @@ -3,47 +3,42 @@ - + JSONP Highlight ▲ Prism plugins - + - + - + -
        -
        - -

        JSONP Highlight

        -

        Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).

        -
        +

        How to use

        - +

        Use the data-jsonp attribute on <pre> elements, like so:

        - +
        <pre
        -  class="language-javascript"
        -  data-jsonp="https://api.github.com/repos/leaverou/prism/contents/prism.js">
        +	class="language-javascript"
        +	data-jsonp="https://api.github.com/repos/leaverou/prism/contents/prism.js">
         </pre>
        - +

        - Don't specifiy the callback query parameter in the URL; this will be added + Don't specify the callback query parameter in the URL; this will be added automatically. If the API expects a different callback parameter name however, use the data-callback parameter to specify the name:

        - +
        <pre class="…" data-jsonp="…" data-callback="cb"></pre>

        The next trick is of course actually extracting something from the JSONP response worth highlighting, which means processing the response to extract the interesting data. -

        +

        The following JSONP APIs are automatically detected and parsed:

        @@ -62,16 +57,16 @@

        How to use

      • Register your adapter function by calling - Prism.plugins.jsonphighlight.registerAdapter(function(rsp) { … }). + Prism.plugins.jsonphighlight.registerAdapter(function(rsp) { … }). It will be added to the list of inbuilt adapters and used if no other registered - adapater (e.g. GitHub/Bitbucket) can parse the response. + adapter (e.g. GitHub/Bitbucket) can parse the response.
      • - +

        In either case, the function must accept at least a single parameter (the JSONP response) and returns a string of the content to highlight. If your adapter cannot parse the response, you - must return null. The DOM node that will contain the highlighted code will also + must return null. The DOM node that will contain the highlighted code will also be passed in as the second argument, incase you need to use it to query any extra information (maybe you wish to inspect the class or data-jsonp attributes to assist in parsing the response). @@ -79,7 +74,7 @@

        How to use

        The following example demonstrates both methods of using a custom adapter, to simply return - the stringyfied JSONP response (i.e highlight the entire JSONP data): + the stringified JSONP response (i.e highlight the entire JSONP data):

        <!-- perhaps this is in a .js file elsewhere -->
        @@ -139,36 +134,36 @@ 

        Caveat for Gists

        Examples

        - +

        The plugin’s JS code (from GitHub):

        -
        
        +	
        
         
         	

        GitHub Gist (gist contains a single file, automatically selected):

        -
        
        +	
        
         
         	

        GitHub Gist (gist contains a multiple files, file to load specified):

        -
        
        +	
        
         
        - 	

        Bitbucket API:

        +

        Bitbucket API:

        
        - 	
        - 	

        Custom adapter (JSON.stringify showing GitHub status):

        -
        
        +
        +	

        Custom adapter (JSON.stringify showing the GitHub REST API for Prism's repository):

        +
        
         
         	

        Registered adapter (as above, but without explicitly declaring the data-adapter attribute):

        -
        
        +	
        
         
        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/jsonp-highlight/prism-jsonp-highlight.js b/plugins/jsonp-highlight/prism-jsonp-highlight.js index 4ce5ca5081..28541a3f3d 100644 --- a/plugins/jsonp-highlight/prism-jsonp-highlight.js +++ b/plugins/jsonp-highlight/prism-jsonp-highlight.js @@ -1,151 +1,303 @@ -(function() { - if ( !self.Prism || !self.document || !document.querySelectorAll || ![].filter) return; +(function () { + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } + + /** + * @callback Adapter + * @param {any} response + * @param {HTMLPreElement} [pre] + * @returns {string | null} + */ + + /** + * The list of adapter which will be used if `data-adapter` is not specified. + * + * @type {Array<{adapter: Adapter, name: string}>} + */ var adapters = []; - function registerAdapter(adapter) { - if (typeof adapter === "function" && !getAdapter(adapter)) { - adapters.push(adapter); + + /** + * Adds a new function to the list of adapters. + * + * If the given adapter is already registered or not a function or there is an adapter with the given name already, + * nothing will happen. + * + * @param {Adapter} adapter The adapter to be registered. + * @param {string} [name] The name of the adapter. Defaults to the function name of `adapter`. + */ + function registerAdapter(adapter, name) { + name = name || adapter.name; + if (typeof adapter === 'function' && !getAdapter(adapter) && !getAdapter(name)) { + adapters.push({ adapter: adapter, name: name }); } } + /** + * Returns the given adapter itself, if registered, or a registered adapter with the given name. + * + * If no fitting adapter is registered, `null` will be returned. + * + * @param {string|Function} adapter The adapter itself or the name of an adapter. + * @returns {Adapter} A registered adapter or `null`. + */ function getAdapter(adapter) { - if (typeof adapter === "function") { - return adapters.filter(function(fn) { return fn.valueOf() === adapter.valueOf()})[0]; - } - else if (typeof adapter === "string" && adapter.length > 0) { - return adapters.filter(function(fn) { return fn.name === adapter})[0]; + if (typeof adapter === 'function') { + for (var i = 0, item; (item = adapters[i++]);) { + if (item.adapter.valueOf() === adapter.valueOf()) { + return item.adapter; + } + } + } else if (typeof adapter === 'string') { + // eslint-disable-next-line no-redeclare + for (var i = 0, item; (item = adapters[i++]);) { + if (item.name === adapter) { + return item.adapter; + } + } } return null; } + /** + * Remove the given adapter or the first registered adapter with the given name from the list of + * registered adapters. + * + * @param {string|Function} adapter The adapter itself or the name of an adapter. + */ function removeAdapter(adapter) { - if (typeof adapter === "string") + if (typeof adapter === 'string') { adapter = getAdapter(adapter); - if (typeof adapter === "function") { - var index = adapters.indexOf(adapter); - if (index >=0) { - adapters.splice(index,1); + } + if (typeof adapter === 'function') { + var index = adapters.findIndex(function (item) { + return item.adapter === adapter; + }); + if (index >= 0) { + adapters.splice(index, 1); } } } - Prism.plugins.jsonphighlight = { - registerAdapter: registerAdapter, - removeAdapter: removeAdapter, - highlight: highlight - }; - registerAdapter(function github(rsp, el) { - if ( rsp && rsp.meta && rsp.data ) { - if ( rsp.meta.status && rsp.meta.status >= 400 ) { - return "Error: " + ( rsp.data.message || rsp.meta.status ); - } - else if ( typeof(rsp.data.content) === "string" ) { - return typeof(atob) === "function" - ? atob(rsp.data.content.replace(/\s/g, "")) - : "Your browser cannot decode base64"; + registerAdapter(function github(rsp) { + if (rsp && rsp.meta && rsp.data) { + if (rsp.meta.status && rsp.meta.status >= 400) { + return 'Error: ' + (rsp.data.message || rsp.meta.status); + } else if (typeof (rsp.data.content) === 'string') { + return typeof (atob) === 'function' + ? atob(rsp.data.content.replace(/\s/g, '')) + : 'Your browser cannot decode base64'; } } return null; - }); + }, 'github'); registerAdapter(function gist(rsp, el) { - if ( rsp && rsp.meta && rsp.data && rsp.data.files ) { - if ( rsp.meta.status && rsp.meta.status >= 400 ) { - return "Error: " + ( rsp.data.message || rsp.meta.status ); + if (rsp && rsp.meta && rsp.data && rsp.data.files) { + if (rsp.meta.status && rsp.meta.status >= 400) { + return 'Error: ' + (rsp.data.message || rsp.meta.status); } - else { - var filename = el.getAttribute("data-filename"); - if (filename == null) { - // Maybe in the future we can somehow render all files - // But the standard + - + - + -
        -
        - -

        Keep markup

        -

        Prevents custom markup from being dropped out during highlighting.

        -
        +

        How to use

        -

        You have nothing to do. With this plugin loaded, all markup inside code will be kept.

        + +

        You have nothing to do. The plugin is active by default. With this plugin loaded, all markup inside code will be kept.

        + +

        However, you can deactivate the plugin for certain code element by adding the no-keep-markup class to it. You can also deactivate the plugin for the whole page by adding the no-keep-markup class to the body of the page and then selectively activate it again by adding the keep-markup class to code elements.

        + +

        Double highlighting

        + +

        Some plugins (e.g. Autoloader) need to re-highlight code blocks. This is a problem for Keep Markup because it will keep the markup of the first highlighting pass resulting in a lot of unnecessary DOM nodes and causing problems for themes and other plugins.

        + +

        This problem can be fixed by adding a drop-tokens class to a code block or any of its ancestors. If drop-tokens is present, Keep Markup will ignore all span.token elements created by Prism.

        Examples

        @@ -68,13 +72,13 @@

        Examples

        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/keep-markup/prism-keep-markup.js b/plugins/keep-markup/prism-keep-markup.js index bc136c6720..c160faa88f 100644 --- a/plugins/keep-markup/prism-keep-markup.js +++ b/plugins/keep-markup/prism-keep-markup.js @@ -1,6 +1,6 @@ (function () { - if (typeof self === 'undefined' || !self.Prism || !self.document || !document.createRange) { + if (typeof Prism === 'undefined' || typeof document === 'undefined' || !document.createRange) { return; } @@ -11,38 +11,64 @@ return; } + if (!Prism.util.isActive(env.element, 'keep-markup', true)) { + return; + } + + var dropTokens = Prism.util.isActive(env.element, 'drop-tokens', false); + /** + * Returns whether the given element should be kept. + * + * @param {HTMLElement} element + * @returns {boolean} + */ + function shouldKeep(element) { + if (dropTokens && element.nodeName.toLowerCase() === 'span' && element.classList.contains('token')) { + return false; + } + return true; + } + var pos = 0; var data = []; - var f = function (elt, baseNode) { - var o = {}; - if (!baseNode) { - // Clone the original tag to keep all attributes - o.clone = elt.cloneNode(false); - o.posOpen = pos; - data.push(o); + function processElement(element) { + if (!shouldKeep(element)) { + // don't keep this element and just process its children + processChildren(element); + return; } - for (var i = 0, l = elt.childNodes.length; i < l; i++) { - var child = elt.childNodes[i]; + + var o = { + // Clone the original tag to keep all attributes + clone: element.cloneNode(false), + posOpen: pos + }; + data.push(o); + + processChildren(element); + + o.posClose = pos; + } + function processChildren(element) { + for (var i = 0, l = element.childNodes.length; i < l; i++) { + var child = element.childNodes[i]; if (child.nodeType === 1) { // element - f(child); - } else if(child.nodeType === 3) { // text + processElement(child); + } else if (child.nodeType === 3) { // text pos += child.data.length; } } - if (!baseNode) { - o.posClose = pos; - } - }; - f(env.element, true); + } + processChildren(env.element); - if (data && data.length) { + if (data.length) { // data is an array of all existing tags env.keepMarkup = data; } }); Prism.hooks.add('after-highlight', function (env) { - if(env.keepMarkup && env.keepMarkup.length) { + if (env.keepMarkup && env.keepMarkup.length) { var walk = function (elt, nodeState) { for (var i = 0, l = elt.childNodes.length; i < l; i++) { @@ -55,12 +81,12 @@ } } else if (child.nodeType === 3) { // text - if(!nodeState.nodeStart && nodeState.pos + child.data.length > nodeState.node.posOpen) { + if (!nodeState.nodeStart && nodeState.pos + child.data.length > nodeState.node.posOpen) { // We found the start position nodeState.nodeStart = child; nodeState.nodeStartPos = nodeState.node.posOpen - nodeState.pos; } - if(nodeState.nodeStart && nodeState.pos + child.data.length >= nodeState.node.posClose) { + if (nodeState.nodeStart && nodeState.pos + child.data.length >= nodeState.node.posClose) { // We found the end position nodeState.nodeEnd = child; nodeState.nodeEndPos = nodeState.node.posClose - nodeState.pos; diff --git a/plugins/keep-markup/prism-keep-markup.min.js b/plugins/keep-markup/prism-keep-markup.min.js index 7f54d27680..6bea9d2efd 100644 --- a/plugins/keep-markup/prism-keep-markup.min.js +++ b/plugins/keep-markup/prism-keep-markup.min.js @@ -1 +1 @@ -!function(){"undefined"!=typeof self&&self.Prism&&self.document&&document.createRange&&(Prism.plugins.KeepMarkup=!0,Prism.hooks.add("before-highlight",function(e){if(e.element.children.length){var n=0,o=[],t=function(e,d){var r={};d||(r.clone=e.cloneNode(!1),r.posOpen=n,o.push(r));for(var a=0,s=e.childNodes.length;s>a;a++){var l=e.childNodes[a];1===l.nodeType?t(l):3===l.nodeType&&(n+=l.data.length)}d||(r.posClose=n)};t(e.element,!0),o&&o.length&&(e.keepMarkup=o)}}),Prism.hooks.add("after-highlight",function(e){if(e.keepMarkup&&e.keepMarkup.length){var n=function(e,o){for(var t=0,d=e.childNodes.length;d>t;t++){var r=e.childNodes[t];if(1===r.nodeType){if(!n(r,o))return!1}else 3===r.nodeType&&(!o.nodeStart&&o.pos+r.data.length>o.node.posOpen&&(o.nodeStart=r,o.nodeStartPos=o.node.posOpen-o.pos),o.nodeStart&&o.pos+r.data.length>=o.node.posClose&&(o.nodeEnd=r,o.nodeEndPos=o.node.posClose-o.pos),o.pos+=r.data.length);if(o.nodeStart&&o.nodeEnd){var a=document.createRange();return a.setStart(o.nodeStart,o.nodeStartPos),a.setEnd(o.nodeEnd,o.nodeEndPos),o.node.clone.appendChild(a.extractContents()),a.insertNode(o.node.clone),a.detach(),!1}}return!0};e.keepMarkup.forEach(function(o){n(e.element,{node:o,pos:0})}),e.highlightedCode=e.element.innerHTML}}))}(); \ No newline at end of file +"undefined"!=typeof Prism&&"undefined"!=typeof document&&document.createRange&&(Prism.plugins.KeepMarkup=!0,Prism.hooks.add("before-highlight",function(e){if(e.element.children.length&&Prism.util.isActive(e.element,"keep-markup",!0)){var o=Prism.util.isActive(e.element,"drop-tokens",!1),d=0,t=[];s(e.element),t.length&&(e.keepMarkup=t)}function r(e){if(function(e){return!o||"span"!==e.nodeName.toLowerCase()||!e.classList.contains("token")}(e)){var n={clone:e.cloneNode(!1),posOpen:d};t.push(n),s(e),n.posClose=d}else s(e)}function s(e){for(var n=0,o=e.childNodes.length;nn.node.posOpen&&(n.nodeStart=d,n.nodeStartPos=n.node.posOpen-n.pos),n.nodeStart&&n.pos+d.data.length>=n.node.posClose&&(n.nodeEnd=d,n.nodeEndPos=n.node.posClose-n.pos),n.pos+=d.data.length);if(n.nodeStart&&n.nodeEnd){var r=document.createRange();return r.setStart(n.nodeStart,n.nodeStartPos),r.setEnd(n.nodeEnd,n.nodeEndPos),n.node.clone.appendChild(r.extractContents()),r.insertNode(n.node.clone),r.detach(),!1}}return!0};n.keepMarkup.forEach(function(e){s(n.element,{node:e,pos:0})}),n.highlightedCode=n.element.innerHTML}})); \ No newline at end of file diff --git a/plugins/line-highlight/index.html b/plugins/line-highlight/index.html index 91eec0df0e..f06b5a53a1 100644 --- a/plugins/line-highlight/index.html +++ b/plugins/line-highlight/index.html @@ -3,31 +3,27 @@ - + Line highlight ▲ Prism plugins - + - + + - + -
        -
        - -

        Line highlight

        -

        Highlights specific lines and/or line ranges.

        -
        +

        How to use

        - +

        Obviously, this only works on code blocks (<pre><code>) and not for inline code. - +

        You specify the lines to be highlighted through the data-line attribute on the <pre> element, in the following simple format:

        • A single number refers to the line with that number
        • @@ -35,54 +31,68 @@

          How to use

        • Multiple line numbers or ranges are separated by commas.
        • Whitespace is allowed anywhere and will be stripped off.
        - +

        Examples:

        5
        The 5th line
        - +
        1-5
        Lines 1 through 5
        - +
        1,4
        Line 1 and line 4
        - +
        1-2, 5, 9-20
        Lines 1 through 2, line 5, lines 9 through 20
        - +

        In case you want the line numbering to be offset by a certain number (for example, you want the 1st line to be number 41 instead of 1, which is an offset of 40), you can additionally use the data-line-offset attribute. - -

        You can also link to specific lines on any code snippet, by using the following as a url hash: #{element-id}.{lines} where + +

        You can also link to specific lines on any code snippet, by using the following as a url hash: #{element-id}.{lines} where {element-id} is the id of the <pre> element and {lines} is one or more lines or line ranges that follow the format outlined above. For example, if there is an element with id="play" on the page, you can link to lines 5-6 by linking to #play.5-6

        + +

        If line numbers are also enabled for a code block and the <pre> element has an id, you can add the linkable-line-numbers class to the <pre> element. This will make all line numbers clickable and when clicking any line number, it will change the hash of the current page to link to that specific line.

        Examples

        - +

        Line 2

        
        -	
        +
         	

        Lines 15-25

        
        -	
        +
         	

        Line 1 and lines 3-4 and line 42

        
        -	
        +
         	

        Line 43, starting from line 41

        
        -	
        +
         	

        Linking example

        + +

        Compatible with Line numbers

        +
        
        +
        +	

        Even with some extra content before the code element.

        +
        Some content

        + + +

        With linkable line numbers

        +
        
        +
         
        -
        +
        - + + - + - \ No newline at end of file + diff --git a/plugins/line-highlight/prism-line-highlight.css b/plugins/line-highlight/prism-line-highlight.css index 6058db44ac..ae47c89a28 100644 --- a/plugins/line-highlight/prism-line-highlight.css +++ b/plugins/line-highlight/prism-line-highlight.css @@ -19,6 +19,17 @@ pre[data-line] { white-space: pre; } +@media print { + .line-highlight { + /* + * This will prevent browsers from replacing the background color with white. + * It's necessary because the element is layered on top of the displayed code. + */ + -webkit-print-color-adjust: exact; + color-adjust: exact; + } +} + .line-highlight:before, .line-highlight[data-end]:after { content: attr(data-start); @@ -47,3 +58,13 @@ pre[data-line] { .line-numbers .line-highlight:after { content: none; } + +pre[id].linkable-line-numbers span.line-numbers-rows { + pointer-events: all; +} +pre[id].linkable-line-numbers span.line-numbers-rows > span:before { + cursor: pointer; +} +pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before { + background-color: rgba(128, 128, 128, .2); +} diff --git a/plugins/line-highlight/prism-line-highlight.js b/plugins/line-highlight/prism-line-highlight.js index 5d919ae6c3..1e615c2f49 100644 --- a/plugins/line-highlight/prism-line-highlight.js +++ b/plugins/line-highlight/prism-line-highlight.js @@ -1,181 +1,339 @@ -(function(){ - -if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) { - return; -} - -function $$(expr, con) { - return Array.prototype.slice.call((con || document).querySelectorAll(expr)); -} - -function hasClass(element, className) { - className = " " + className + " "; - return (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1 -} - -// Some browsers round the line-height, others don't. -// We need to test for it to position the elements properly. -var isLineHeightRounded = (function() { - var res; - return function() { - if(typeof res === 'undefined') { - var d = document.createElement('div'); - d.style.fontSize = '13px'; - d.style.lineHeight = '1.5'; - d.style.padding = 0; - d.style.border = 0; - d.innerHTML = ' 
         '; - document.body.appendChild(d); - // Browsers that round the line-height should have offsetHeight === 38 - // The others should have 39. - res = d.offsetHeight === 38; - document.body.removeChild(d); - } - return res; +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined' || !document.querySelector) { + return; } -}()); -function highlightLines(pre, lines, classes) { - lines = typeof lines === 'string' ? lines : pre.getAttribute('data-line'); - - var ranges = lines.replace(/\s+/g, '').split(','), - offset = +pre.getAttribute('data-line-offset') || 0; + var LINE_NUMBERS_CLASS = 'line-numbers'; + var LINKABLE_LINE_NUMBERS_CLASS = 'linkable-line-numbers'; - var parseMethod = isLineHeightRounded() ? parseInt : parseFloat; - var lineHeight = parseMethod(getComputedStyle(pre).lineHeight); - var hasLineNumbers = hasClass(pre, 'line-numbers'); + /** + * @param {string} selector + * @param {ParentNode} [container] + * @returns {HTMLElement[]} + */ + function $$(selector, container) { + return Array.prototype.slice.call((container || document).querySelectorAll(selector)); + } - for (var i=0, currentRange; currentRange = ranges[i++];) { - var range = currentRange.split('-'); + /** + * Returns whether the given element has the given class. + * + * @param {Element} element + * @param {string} className + * @returns {boolean} + */ + function hasClass(element, className) { + return element.classList.contains(className); + } - var start = +range[0], - end = +range[1] || start; + /** + * Calls the given function. + * + * @param {() => any} func + * @returns {void} + */ + function callFunction(func) { + func(); + } - var line = pre.querySelector('.line-highlight[data-range="' + currentRange + '"]') || document.createElement('div'); + // Some browsers round the line-height, others don't. + // We need to test for it to position the elements properly. + var isLineHeightRounded = (function () { + var res; + return function () { + if (typeof res === 'undefined') { + var d = document.createElement('div'); + d.style.fontSize = '13px'; + d.style.lineHeight = '1.5'; + d.style.padding = '0'; + d.style.border = '0'; + d.innerHTML = ' 
         '; + document.body.appendChild(d); + // Browsers that round the line-height should have offsetHeight === 38 + // The others should have 39. + res = d.offsetHeight === 38; + document.body.removeChild(d); + } + return res; + }; + }()); - line.setAttribute('aria-hidden', 'true'); - line.setAttribute('data-range', currentRange); - line.className = (classes || '') + ' line-highlight'; + /** + * Returns the top offset of the content box of the given parent and the content box of one of its children. + * + * @param {HTMLElement} parent + * @param {HTMLElement} child + */ + function getContentBoxTopOffset(parent, child) { + var parentStyle = getComputedStyle(parent); + var childStyle = getComputedStyle(child); + + /** + * Returns the numeric value of the given pixel value. + * + * @param {string} px + */ + function pxToNumber(px) { + return +px.substr(0, px.length - 2); + } - //if the line-numbers plugin is enabled, then there is no reason for this plugin to display the line numbers - if(hasLineNumbers && Prism.plugins.lineNumbers) { - var startNode = Prism.plugins.lineNumbers.getLine(pre, start); - var endNode = Prism.plugins.lineNumbers.getLine(pre, end); - - if (startNode) { - line.style.top = startNode.offsetTop + 'px'; - } - - if (endNode) { - line.style.height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px'; - } - } else { - line.setAttribute('data-start', start); + return child.offsetTop + + pxToNumber(childStyle.borderTopWidth) + + pxToNumber(childStyle.paddingTop) + - pxToNumber(parentStyle.paddingTop); + } - if(end > start) { - line.setAttribute('data-end', end); - } - - line.style.top = (start - offset - 1) * lineHeight + 'px'; + /** + * Returns whether the Line Highlight plugin is active for the given element. + * + * If this function returns `false`, do not call `highlightLines` for the given element. + * + * @param {HTMLElement | null | undefined} pre + * @returns {boolean} + */ + function isActiveFor(pre) { + if (!pre || !/pre/i.test(pre.nodeName)) { + return false; + } - line.textContent = new Array(end - start + 2).join(' \n'); + if (pre.hasAttribute('data-line')) { + return true; } - //allow this to play nicely with the line-numbers plugin - if(hasLineNumbers) { - //need to attack to pre as when line-numbers is enabled, the code tag is relatively which screws up the positioning - pre.appendChild(line); - } else { - (pre.querySelector('code') || pre).appendChild(line); + if (pre.id && Prism.util.isActive(pre, LINKABLE_LINE_NUMBERS_CLASS)) { + // Technically, the line numbers plugin is also necessary but this plugin doesn't control the classes of + // the line numbers plugin, so we can't assume that they are present. + return true; } + + return false; } -} -function applyHash() { - var hash = location.hash.slice(1); + var scrollIntoView = true; + + Prism.plugins.lineHighlight = { + /** + * Highlights the lines of the given pre. + * + * This function is split into a DOM measuring and mutate phase to improve performance. + * The returned function mutates the DOM when called. + * + * @param {HTMLElement} pre + * @param {string | null} [lines] + * @param {string} [classes=''] + * @returns {() => void} + */ + highlightLines: function highlightLines(pre, lines, classes) { + lines = typeof lines === 'string' ? lines : (pre.getAttribute('data-line') || ''); + + var ranges = lines.replace(/\s+/g, '').split(',').filter(Boolean); + var offset = +pre.getAttribute('data-line-offset') || 0; + + var parseMethod = isLineHeightRounded() ? parseInt : parseFloat; + var lineHeight = parseMethod(getComputedStyle(pre).lineHeight); + var hasLineNumbers = Prism.util.isActive(pre, LINE_NUMBERS_CLASS); + var codeElement = pre.querySelector('code'); + var parentElement = hasLineNumbers ? pre : codeElement || pre; + var mutateActions = /** @type {(() => void)[]} */ ([]); + + /** + * The top offset between the content box of the element and the content box of the parent element of + * the line highlight element (either `
        ` or ``).
        +			 *
        +			 * This offset might not be zero for some themes where the  element has a top margin. Some plugins
        +			 * (or users) might also add element above the  element. Because the line highlight is aligned relative
        +			 * to the 
         element, we have to take this into account.
        +			 *
        +			 * This offset will be 0 if the parent element of the line highlight element is the `` element.
        +			 */
        +			var codePreOffset = !codeElement || parentElement == codeElement ? 0 : getContentBoxTopOffset(pre, codeElement);
        +
        +			ranges.forEach(function (currentRange) {
        +				var range = currentRange.split('-');
        +
        +				var start = +range[0];
        +				var end = +range[1] || start;
        +
        +				/** @type {HTMLElement} */
        +				var line = pre.querySelector('.line-highlight[data-range="' + currentRange + '"]') || document.createElement('div');
        +
        +				mutateActions.push(function () {
        +					line.setAttribute('aria-hidden', 'true');
        +					line.setAttribute('data-range', currentRange);
        +					line.className = (classes || '') + ' line-highlight';
        +				});
        +
        +				// if the line-numbers plugin is enabled, then there is no reason for this plugin to display the line numbers
        +				if (hasLineNumbers && Prism.plugins.lineNumbers) {
        +					var startNode = Prism.plugins.lineNumbers.getLine(pre, start);
        +					var endNode = Prism.plugins.lineNumbers.getLine(pre, end);
        +
        +					if (startNode) {
        +						var top = startNode.offsetTop + codePreOffset + 'px';
        +						mutateActions.push(function () {
        +							line.style.top = top;
        +						});
        +					}
        +
        +					if (endNode) {
        +						var height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px';
        +						mutateActions.push(function () {
        +							line.style.height = height;
        +						});
        +					}
        +				} else {
        +					mutateActions.push(function () {
        +						line.setAttribute('data-start', String(start));
        +
        +						if (end > start) {
        +							line.setAttribute('data-end', String(end));
        +						}
        +
        +						line.style.top = (start - offset - 1) * lineHeight + codePreOffset + 'px';
        +
        +						line.textContent = new Array(end - start + 2).join(' \n');
        +					});
        +				}
        +
        +				mutateActions.push(function () {
        +					line.style.width = pre.scrollWidth + 'px';
        +				});
        +
        +				mutateActions.push(function () {
        +					// allow this to play nicely with the line-numbers plugin
        +					// need to attack to pre as when line-numbers is enabled, the code tag is relatively which screws up the positioning
        +					parentElement.appendChild(line);
        +				});
        +			});
        +
        +			var id = pre.id;
        +			if (hasLineNumbers && Prism.util.isActive(pre, LINKABLE_LINE_NUMBERS_CLASS) && id) {
        +				// This implements linkable line numbers. Linkable line numbers use Line Highlight to create a link to a
        +				// specific line. For this to work, the pre element has to:
        +				//  1) have line numbers,
        +				//  2) have the `linkable-line-numbers` class or an ascendant that has that class, and
        +				//  3) have an id.
        +
        +				if (!hasClass(pre, LINKABLE_LINE_NUMBERS_CLASS)) {
        +					// add class to pre
        +					mutateActions.push(function () {
        +						pre.classList.add(LINKABLE_LINE_NUMBERS_CLASS);
        +					});
        +				}
        +
        +				var start = parseInt(pre.getAttribute('data-start') || '1');
        +
        +				// iterate all line number spans
        +				$$('.line-numbers-rows > span', pre).forEach(function (lineSpan, i) {
        +					var lineNumber = i + start;
        +					lineSpan.onclick = function () {
        +						var hash = id + '.' + lineNumber;
        +
        +						// this will prevent scrolling since the span is obviously in view
        +						scrollIntoView = false;
        +						location.hash = hash;
        +						setTimeout(function () {
        +							scrollIntoView = true;
        +						}, 1);
        +					};
        +				});
        +			}
         
        -	// Remove pre-existing temporary lines
        -	$$('.temporary.line-highlight').forEach(function (line) {
        -		line.parentNode.removeChild(line);
        -	});
        +			return function () {
        +				mutateActions.forEach(callFunction);
        +			};
        +		}
        +	};
         
        -	var range = (hash.match(/\.([\d,-]+)$/) || [,''])[1];
         
        -	if (!range || document.getElementById(hash)) {
        -		return;
        -	}
        +	function applyHash() {
        +		var hash = location.hash.slice(1);
         
        -	var id = hash.slice(0, hash.lastIndexOf('.')),
        -	    pre = document.getElementById(id);
        +		// Remove pre-existing temporary lines
        +		$$('.temporary.line-highlight').forEach(function (line) {
        +			line.parentNode.removeChild(line);
        +		});
         
        -	if (!pre) {
        -		return;
        -	}
        +		var range = (hash.match(/\.([\d,-]+)$/) || [, ''])[1];
         
        -	if (!pre.hasAttribute('data-line')) {
        -		pre.setAttribute('data-line', '');
        -	}
        +		if (!range || document.getElementById(hash)) {
        +			return;
        +		}
         
        -	highlightLines(pre, range, 'temporary ');
        +		var id = hash.slice(0, hash.lastIndexOf('.'));
        +		var pre = document.getElementById(id);
         
        -	document.querySelector('.temporary.line-highlight').scrollIntoView();
        -}
        +		if (!pre) {
        +			return;
        +		}
         
        -var fakeTimer = 0; // Hack to limit the number of times applyHash() runs
        +		if (!pre.hasAttribute('data-line')) {
        +			pre.setAttribute('data-line', '');
        +		}
         
        -Prism.hooks.add('before-sanity-check', function(env) {
        -	var pre = env.element.parentNode;
        -	var lines = pre && pre.getAttribute('data-line');
        +		var mutateDom = Prism.plugins.lineHighlight.highlightLines(pre, range, 'temporary ');
        +		mutateDom();
         
        -	if (!pre || !lines || !/pre/i.test(pre.nodeName)) {
        -		return;
        -	}
        -	
        -	/*
        -	* Cleanup for other plugins (e.g. autoloader).
        -	 *
        -	 * Sometimes  blocks are highlighted multiple times. It is necessary
        -	 * to cleanup any left-over tags, because the whitespace inside of the 
        - * tags change the content of the tag. - */ - var num = 0; - $$('.line-highlight', pre).forEach(function (line) { - num += line.textContent.length; - line.parentNode.removeChild(line); - }); - // Remove extra whitespace - if (num && /^( \n)+$/.test(env.code.slice(-num))) { - env.code = env.code.slice(0, -num); + if (scrollIntoView) { + document.querySelector('.temporary.line-highlight').scrollIntoView(); + } } -}); -Prism.hooks.add('complete', function completeHook(env) { - var pre = env.element.parentNode; - var lines = pre && pre.getAttribute('data-line'); + var fakeTimer = 0; // Hack to limit the number of times applyHash() runs - if (!pre || !lines || !/pre/i.test(pre.nodeName)) { - return; - } + Prism.hooks.add('before-sanity-check', function (env) { + var pre = env.element.parentElement; + if (!isActiveFor(pre)) { + return; + } - clearTimeout(fakeTimer); + /* + * Cleanup for other plugins (e.g. autoloader). + * + * Sometimes blocks are highlighted multiple times. It is necessary + * to cleanup any left-over tags, because the whitespace inside of the
        + * tags change the content of the tag. + */ + var num = 0; + $$('.line-highlight', pre).forEach(function (line) { + num += line.textContent.length; + line.parentNode.removeChild(line); + }); + // Remove extra whitespace + if (num && /^(?: \n)+$/.test(env.code.slice(-num))) { + env.code = env.code.slice(0, -num); + } + }); - var hasLineNumbers = Prism.plugins.lineNumbers; - var isLineNumbersLoaded = env.plugins && env.plugins.lineNumbers; + Prism.hooks.add('complete', function completeHook(env) { + var pre = env.element.parentElement; + if (!isActiveFor(pre)) { + return; + } - if (hasClass(pre, 'line-numbers') && hasLineNumbers && !isLineNumbersLoaded) { - Prism.hooks.add('line-numbers', completeHook); - } else { - highlightLines(pre, lines); - fakeTimer = setTimeout(applyHash, 1); - } -}); + clearTimeout(fakeTimer); + + var hasLineNumbers = Prism.plugins.lineNumbers; + var isLineNumbersLoaded = env.plugins && env.plugins.lineNumbers; + + if (hasClass(pre, LINE_NUMBERS_CLASS) && hasLineNumbers && !isLineNumbersLoaded) { + Prism.hooks.add('line-numbers', completeHook); + } else { + var mutateDom = Prism.plugins.lineHighlight.highlightLines(pre); + mutateDom(); + fakeTimer = setTimeout(applyHash, 1); + } + }); window.addEventListener('hashchange', applyHash); window.addEventListener('resize', function () { - var preElements = document.querySelectorAll('pre[data-line]'); - Array.prototype.forEach.call(preElements, function (pre) { - highlightLines(pre); - }); + var actions = $$('pre') + .filter(isActiveFor) + .map(function (pre) { + return Prism.plugins.lineHighlight.highlightLines(pre); + }); + actions.forEach(callFunction); }); -})(); \ No newline at end of file +}()); diff --git a/plugins/line-highlight/prism-line-highlight.min.css b/plugins/line-highlight/prism-line-highlight.min.css new file mode 100644 index 0000000000..6cd87723b4 --- /dev/null +++ b/plugins/line-highlight/prism-line-highlight.min.css @@ -0,0 +1 @@ +pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)} \ No newline at end of file diff --git a/plugins/line-highlight/prism-line-highlight.min.js b/plugins/line-highlight/prism-line-highlight.min.js index 6c87091459..c1f640b45c 100644 --- a/plugins/line-highlight/prism-line-highlight.min.js +++ b/plugins/line-highlight/prism-line-highlight.min.js @@ -1 +1 @@ -!function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){n="string"==typeof n?n:e.getAttribute("data-line");for(var o,l=n.replace(/\s+/g,"").split(","),a=+e.getAttribute("data-line-offset")||0,s=r()?parseInt:parseFloat,d=s(getComputedStyle(e).lineHeight),u=t(e,"line-numbers"),c=0;o=l[c++];){var p=o.split("-"),m=+p[0],f=+p[1]||m,h=e.querySelector('.line-highlight[data-range="'+o+'"]')||document.createElement("div");if(h.setAttribute("aria-hidden","true"),h.setAttribute("data-range",o),h.className=(i||"")+" line-highlight",u&&Prism.plugins.lineNumbers){var g=Prism.plugins.lineNumbers.getLine(e,m),y=Prism.plugins.lineNumbers.getLine(e,f);g&&(h.style.top=g.offsetTop+"px"),y&&(h.style.height=y.offsetTop-g.offsetTop+y.offsetHeight+"px")}else h.setAttribute("data-start",m),f>m&&h.setAttribute("data-end",f),h.style.top=(m-a-1)*d+"px",h.textContent=new Array(f-m+2).join(" \n");u?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML=" 
         ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function l(e){var r=e.element.parentNode,a=r&&r.getAttribute("data-line");if(r&&a&&/pre/i.test(r.nodeName)){clearTimeout(o);var s=Prism.plugins.lineNumbers,d=e.plugins&&e.plugins.lineNumbers;t(r,"line-numbers")&&s&&!d?Prism.hooks.add("line-numbers",l):(n(r,a),o=setTimeout(i,1))}}),window.addEventListener("hashchange",i),window.addEventListener("resize",function(){var e=document.querySelectorAll("pre[data-line]");Array.prototype.forEach.call(e,function(e){n(e)})})}}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector){var t,o="line-numbers",s="linkable-line-numbers",l=function(){if(void 0===t){var e=document.createElement("div");e.style.fontSize="13px",e.style.lineHeight="1.5",e.style.padding="0",e.style.border="0",e.innerHTML=" 
         ",document.body.appendChild(e),t=38===e.offsetHeight,document.body.removeChild(e)}return t},a=!0;Prism.plugins.lineHighlight={highlightLines:function(u,e,c){var t=(e="string"==typeof e?e:u.getAttribute("data-line")||"").replace(/\s+/g,"").split(",").filter(Boolean),d=+u.getAttribute("data-line-offset")||0,h=(l()?parseInt:parseFloat)(getComputedStyle(u).lineHeight),f=Prism.util.isActive(u,o),i=u.querySelector("code"),p=f?u:i||u,g=[],m=i&&p!=i?function(e,t){var i=getComputedStyle(e),n=getComputedStyle(t);function r(e){return+e.substr(0,e.length-2)}return t.offsetTop+r(n.borderTopWidth)+r(n.paddingTop)-r(i.paddingTop)}(u,i):0;t.forEach(function(e){var t=e.split("-"),i=+t[0],n=+t[1]||i,r=u.querySelector('.line-highlight[data-range="'+e+'"]')||document.createElement("div");if(g.push(function(){r.setAttribute("aria-hidden","true"),r.setAttribute("data-range",e),r.className=(c||"")+" line-highlight"}),f&&Prism.plugins.lineNumbers){var o=Prism.plugins.lineNumbers.getLine(u,i),s=Prism.plugins.lineNumbers.getLine(u,n);if(o){var l=o.offsetTop+m+"px";g.push(function(){r.style.top=l})}if(s){var a=s.offsetTop-o.offsetTop+s.offsetHeight+"px";g.push(function(){r.style.height=a})}}else g.push(function(){r.setAttribute("data-start",String(i)),i span",u).forEach(function(e,t){var i=t+r;e.onclick=function(){var e=n+"."+i;a=!1,location.hash=e,setTimeout(function(){a=!0},1)}})}return function(){g.forEach(b)}}};var u=0;Prism.hooks.add("before-sanity-check",function(e){var t=e.element.parentElement;if(c(t)){var i=0;v(".line-highlight",t).forEach(function(e){i+=e.textContent.length,e.parentNode.removeChild(e)}),i&&/^(?: \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}}),Prism.hooks.add("complete",function e(t){var i=t.element.parentElement;if(c(i)){clearTimeout(u);var n=Prism.plugins.lineNumbers,r=t.plugins&&t.plugins.lineNumbers;if(y(i,o)&&n&&!r)Prism.hooks.add("line-numbers",e);else Prism.plugins.lineHighlight.highlightLines(i)(),u=setTimeout(d,1)}}),window.addEventListener("hashchange",d),window.addEventListener("resize",function(){v("pre").filter(c).map(function(e){return Prism.plugins.lineHighlight.highlightLines(e)}).forEach(b)})}function v(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function y(e,t){return e.classList.contains(t)}function b(e){e()}function c(e){return!(!e||!/pre/i.test(e.nodeName))&&(!!e.hasAttribute("data-line")||!(!e.id||!Prism.util.isActive(e,s)))}function d(){var e=location.hash.slice(1);v(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var i=e.slice(0,e.lastIndexOf(".")),n=document.getElementById(i);if(n)n.hasAttribute("data-line")||n.setAttribute("data-line",""),Prism.plugins.lineHighlight.highlightLines(n,t,"temporary ")(),a&&document.querySelector(".temporary.line-highlight").scrollIntoView()}}}(); \ No newline at end of file diff --git a/plugins/line-numbers/index.html b/plugins/line-numbers/index.html index 145376277c..a6c93b1ace 100644 --- a/plugins/line-numbers/index.html +++ b/plugins/line-numbers/index.html @@ -3,43 +3,57 @@ - + Line Numbers ▲ Prism plugins - + - + - + - + -
        -
        - -

        Line Numbers

        -

        Line number at the beginning of code lines.

        -
        +

        How to use

        Obviously, this is supposed to work only for code blocks (<pre><code>) and not for inline code.

        -

        Add class line-numbers to your desired <pre> and line-numbers plugin will take care.

        +

        Add the line-numbers class to your desired <pre> or any of its ancestors, and the Line Numbers plugin will take care of the rest. To give all code blocks line numbers, add the line-numbers class to the <body> of the page. This is part of a general activation mechanism where adding the line-numbers (or no-line-numbers) class to any element will enable (or disable) the Line Numbers plugin for all code blocks in that element.
        Example:

        + +
        <body class="line-numbers"> <!-- enabled for the whole page -->
        +
        +	<!-- with line numbers -->
        +	<pre><code>...</code></pre>
        +	<!-- disabled for a specific element - without line numbers -->
        +	<pre class="no-line-numbers"><code>...</code></pre>
        +
        +	<div class="no-line-numbers"> <!-- disabled for this subtree -->
        +
        +		<!-- without line numbers -->
        +		<pre><code>...</code></pre>
        +		<!-- enabled for a specific element - with line numbers -->
        +		<pre class="line-numbers"><code>...</code></pre>
        +
        +	</div>
        +</body>
        +

        Optional: You can specify the data-start (Number) attribute on the <pre> element. It will shift the line counter.

        -

        Optional: To support multiline line numbers using soft wrap add css white-space to pre-line or pre-wrap.

        +

        Optional: To support multiline line numbers using soft wrap, apply the CSS white-space: pre-line; or white-space: pre-wrap; to your desired <pre>.

        -
        +

        Examples

        JavaScript

        
         
           

        CSS

        -
        
        +  

        Please note that this <pre> does not have the line-numbers class but its parent does.

        +
        
         
           

        HTML

        Please note the data-start="-5" in the code below.

        @@ -49,21 +63,22 @@

        Unknown languages

        This raw text
         is not highlighted
         but it still has
        -lines numbers
        +line numbers

        Soft wrap support

        +

        Please note the style="white-space:pre-wrap;" in the code below.

        
         
         
        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/line-numbers/prism-line-numbers.css b/plugins/line-numbers/prism-line-numbers.css index d5cbfd3fd5..57705307cb 100644 --- a/plugins/line-numbers/prism-line-numbers.css +++ b/plugins/line-numbers/prism-line-numbers.css @@ -1,12 +1,12 @@ -pre.line-numbers { +pre[class*="language-"].line-numbers { position: relative; padding-left: 3.8em; counter-reset: linenumber; } -pre.line-numbers > code { +pre[class*="language-"].line-numbers > code { position: relative; - white-space: inherit; + white-space: inherit; } .line-numbers .line-numbers-rows { @@ -27,7 +27,6 @@ pre.line-numbers > code { } .line-numbers-rows > span { - pointer-events: none; display: block; counter-increment: linenumber; } @@ -38,4 +37,4 @@ pre.line-numbers > code { display: block; padding-right: 0.8em; text-align: right; - } \ No newline at end of file + } diff --git a/plugins/line-numbers/prism-line-numbers.js b/plugins/line-numbers/prism-line-numbers.js index e9e684fe94..71e8b6963a 100644 --- a/plugins/line-numbers/prism-line-numbers.js +++ b/plugins/line-numbers/prism-line-numbers.js @@ -1,32 +1,108 @@ (function () { - if (typeof self === 'undefined' || !self.Prism || !self.document) { + if (typeof Prism === 'undefined' || typeof document === 'undefined') { return; } /** * Plugin name which is used as a class name for
         which is activating the plugin
        -	 * @type {String}
        +	 *
        +	 * @type {string}
         	 */
         	var PLUGIN_NAME = 'line-numbers';
        -	
        +
         	/**
         	 * Regular expression used for determining line breaks
        +	 *
         	 * @type {RegExp}
         	 */
         	var NEW_LINE_EXP = /\n(?!$)/g;
         
        +
        +	/**
        +	 * Global exports
        +	 */
        +	var config = Prism.plugins.lineNumbers = {
        +		/**
        +		 * Get node for provided line number
        +		 *
        +		 * @param {Element} element pre element
        +		 * @param {number} number line number
        +		 * @returns {Element|undefined}
        +		 */
        +		getLine: function (element, number) {
        +			if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
        +				return;
        +			}
        +
        +			var lineNumberRows = element.querySelector('.line-numbers-rows');
        +			if (!lineNumberRows) {
        +				return;
        +			}
        +			var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
        +			var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
        +
        +			if (number < lineNumberStart) {
        +				number = lineNumberStart;
        +			}
        +			if (number > lineNumberEnd) {
        +				number = lineNumberEnd;
        +			}
        +
        +			var lineIndex = number - lineNumberStart;
        +
        +			return lineNumberRows.children[lineIndex];
        +		},
        +
        +		/**
        +		 * Resizes the line numbers of the given element.
        +		 *
        +		 * This function will not add line numbers. It will only resize existing ones.
        +		 *
        +		 * @param {HTMLElement} element A `
        ` element with line numbers.
        +		 * @returns {void}
        +		 */
        +		resize: function (element) {
        +			resizeElements([element]);
        +		},
        +
        +		/**
        +		 * Whether the plugin can assume that the units font sizes and margins are not depended on the size of
        +		 * the current viewport.
        +		 *
        +		 * Setting this to `true` will allow the plugin to do certain optimizations for better performance.
        +		 *
        +		 * Set this to `false` if you use any of the following CSS units: `vh`, `vw`, `vmin`, `vmax`.
        +		 *
        +		 * @type {boolean}
        +		 */
        +		assumeViewportIndependence: true
        +	};
        +
         	/**
        -	 * Resizes line numbers spans according to height of line of code
        -	 * @param {Element} element 
         element
        +	 * Resizes the given elements.
        +	 *
        +	 * @param {HTMLElement[]} elements
         	 */
        -	var _resizeElement = function (element) {
        -		var codeStyles = getStyles(element);
        -		var whiteSpace = codeStyles['white-space'];
        +	function resizeElements(elements) {
        +		elements = elements.filter(function (e) {
        +			var codeStyles = getStyles(e);
        +			var whiteSpace = codeStyles['white-space'];
        +			return whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line';
        +		});
        +
        +		if (elements.length == 0) {
        +			return;
        +		}
         
        -		if (whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line') {
        +		var infos = elements.map(function (element) {
         			var codeElement = element.querySelector('code');
         			var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
        +			if (!codeElement || !lineNumbersWrapper) {
        +				return undefined;
        +			}
        +
        +			/** @type {HTMLElement} */
         			var lineNumberSizer = element.querySelector('.line-numbers-sizer');
         			var codeLines = codeElement.textContent.split(NEW_LINE_EXP);
         
        @@ -37,33 +113,85 @@
         				codeElement.appendChild(lineNumberSizer);
         			}
         
        +			lineNumberSizer.innerHTML = '0';
         			lineNumberSizer.style.display = 'block';
         
        -			codeLines.forEach(function (line, lineNumber) {
        -				lineNumberSizer.textContent = line || '\n';
        -				var lineSize = lineNumberSizer.getBoundingClientRect().height;
        -				lineNumbersWrapper.children[lineNumber].style.height = lineSize + 'px';
        +			var oneLinerHeight = lineNumberSizer.getBoundingClientRect().height;
        +			lineNumberSizer.innerHTML = '';
        +
        +			return {
        +				element: element,
        +				lines: codeLines,
        +				lineHeights: [],
        +				oneLinerHeight: oneLinerHeight,
        +				sizer: lineNumberSizer,
        +			};
        +		}).filter(Boolean);
        +
        +		infos.forEach(function (info) {
        +			var lineNumberSizer = info.sizer;
        +			var lines = info.lines;
        +			var lineHeights = info.lineHeights;
        +			var oneLinerHeight = info.oneLinerHeight;
        +
        +			lineHeights[lines.length - 1] = undefined;
        +			lines.forEach(function (line, index) {
        +				if (line && line.length > 1) {
        +					var e = lineNumberSizer.appendChild(document.createElement('span'));
        +					e.style.display = 'block';
        +					e.textContent = line;
        +				} else {
        +					lineHeights[index] = oneLinerHeight;
        +				}
         			});
        +		});
        +
        +		infos.forEach(function (info) {
        +			var lineNumberSizer = info.sizer;
        +			var lineHeights = info.lineHeights;
        +
        +			var childIndex = 0;
        +			for (var i = 0; i < lineHeights.length; i++) {
        +				if (lineHeights[i] === undefined) {
        +					lineHeights[i] = lineNumberSizer.children[childIndex++].getBoundingClientRect().height;
        +				}
        +			}
        +		});
        +
        +		infos.forEach(function (info) {
        +			var lineNumberSizer = info.sizer;
        +			var wrapper = info.element.querySelector('.line-numbers-rows');
         
        -			lineNumberSizer.textContent = '';
         			lineNumberSizer.style.display = 'none';
        -		}
        -	};
        +			lineNumberSizer.innerHTML = '';
        +
        +			info.lineHeights.forEach(function (height, lineNumber) {
        +				wrapper.children[lineNumber].style.height = height + 'px';
        +			});
        +		});
        +	}
         
         	/**
         	 * Returns style declarations for the element
        +	 *
         	 * @param {Element} element
         	 */
        -	var getStyles = function (element) {
        +	function getStyles(element) {
         		if (!element) {
         			return null;
         		}
         
         		return window.getComputedStyle ? getComputedStyle(element) : (element.currentStyle || null);
        -	};
        +	}
         
        +	var lastWidth = undefined;
         	window.addEventListener('resize', function () {
        -		Array.prototype.forEach.call(document.querySelectorAll('pre.' + PLUGIN_NAME), _resizeElement);
        +		if (config.assumeViewportIndependence && lastWidth === window.innerWidth) {
        +			return;
        +		}
        +		lastWidth = window.innerWidth;
        +
        +		resizeElements(Array.prototype.slice.call(document.querySelectorAll('pre.' + PLUGIN_NAME)));
         	});
         
         	Prism.hooks.add('complete', function (env) {
        @@ -71,37 +199,34 @@
         			return;
         		}
         
        +		var code = /** @type {Element} */ (env.element);
        +		var pre = /** @type {HTMLElement} */ (code.parentNode);
        +
         		// works only for  wrapped inside 
         (not inline)
        -		var pre = env.element.parentNode;
        -		var clsReg = /\s*\bline-numbers\b\s*/;
        -		if (
        -			!pre || !/pre/i.test(pre.nodeName) ||
        -			// Abort only if nor the 
         nor the  have the class
        -			(!clsReg.test(pre.className) && !clsReg.test(env.element.className))
        -		) {
        +		if (!pre || !/pre/i.test(pre.nodeName)) {
         			return;
         		}
         
        -		if (env.element.querySelector('.line-numbers-rows')) {
        -			// Abort if line numbers already exists
        +		// Abort if line numbers already exists
        +		if (code.querySelector('.line-numbers-rows')) {
         			return;
         		}
         
        -		if (clsReg.test(env.element.className)) {
        -			// Remove the class 'line-numbers' from the 
        -			env.element.className = env.element.className.replace(clsReg, ' ');
        -		}
        -		if (!clsReg.test(pre.className)) {
        -			// Add the class 'line-numbers' to the 
        -			pre.className += ' line-numbers';
        +		// only add line numbers if  or one of its ancestors has the `line-numbers` class
        +		if (!Prism.util.isActive(code, PLUGIN_NAME)) {
        +			return;
         		}
         
        +		// Remove the class 'line-numbers' from the 
        +		code.classList.remove(PLUGIN_NAME);
        +		// Add the class 'line-numbers' to the 
        +		pre.classList.add(PLUGIN_NAME);
        +
         		var match = env.code.match(NEW_LINE_EXP);
         		var linesNum = match ? match.length + 1 : 1;
         		var lineNumbersWrapper;
         
        -		var lines = new Array(linesNum + 1);
        -		lines = lines.join('');
        +		var lines = new Array(linesNum + 1).join('');
         
         		lineNumbersWrapper = document.createElement('span');
         		lineNumbersWrapper.setAttribute('aria-hidden', 'true');
        @@ -114,7 +239,7 @@
         
         		env.element.appendChild(lineNumbersWrapper);
         
        -		_resizeElement(pre);
        +		resizeElements([pre]);
         
         		Prism.hooks.run('line-numbers', env);
         	});
        @@ -123,37 +248,5 @@
         		env.plugins = env.plugins || {};
         		env.plugins.lineNumbers = true;
         	});
        -	
        -	/**
        -	 * Global exports
        -	 */
        -	Prism.plugins.lineNumbers = {
        -		/**
        -		 * Get node for provided line number
        -		 * @param {Element} element pre element
        -		 * @param {Number} number line number
        -		 * @return {Element|undefined}
        -		 */
        -		getLine: function (element, number) {
        -			if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
        -				return;
        -			}
        -
        -			var lineNumberRows = element.querySelector('.line-numbers-rows');
        -			var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
        -			var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
        -
        -			if (number < lineNumberStart) {
        -				number = lineNumberStart;
        -			}
        -			if (number > lineNumberEnd) {
        -				number = lineNumberEnd;
        -			}
        -
        -			var lineIndex = number - lineNumberStart;
        -
        -			return lineNumberRows.children[lineIndex];
        -		}
        -	};
         
        -}());
        \ No newline at end of file
        +}());
        diff --git a/plugins/line-numbers/prism-line-numbers.min.css b/plugins/line-numbers/prism-line-numbers.min.css
        new file mode 100644
        index 0000000000..8170f64670
        --- /dev/null
        +++ b/plugins/line-numbers/prism-line-numbers.min.css
        @@ -0,0 +1 @@
        +pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}
        \ No newline at end of file
        diff --git a/plugins/line-numbers/prism-line-numbers.min.js b/plugins/line-numbers/prism-line-numbers.min.js
        index 5291216f69..9ccb6da910 100644
        --- a/plugins/line-numbers/prism-line-numbers.min.js
        +++ b/plugins/line-numbers/prism-line-numbers.min.js
        @@ -1 +1 @@
        -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var e="line-numbers",t=/\n(?!$)/g,n=function(e){var n=r(e),s=n["white-space"];if("pre-wrap"===s||"pre-line"===s){var l=e.querySelector("code"),i=e.querySelector(".line-numbers-rows"),a=e.querySelector(".line-numbers-sizer"),o=l.textContent.split(t);a||(a=document.createElement("span"),a.className="line-numbers-sizer",l.appendChild(a)),a.style.display="block",o.forEach(function(e,t){a.textContent=e||"\n";var n=a.getBoundingClientRect().height;i.children[t].style.height=n+"px"}),a.textContent="",a.style.display="none"}},r=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null};window.addEventListener("resize",function(){Array.prototype.forEach.call(document.querySelectorAll("pre."+e),n)}),Prism.hooks.add("complete",function(e){if(e.code){var r=e.element.parentNode,s=/\s*\bline-numbers\b\s*/;if(r&&/pre/i.test(r.nodeName)&&(s.test(r.className)||s.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){s.test(e.element.className)&&(e.element.className=e.element.className.replace(s," ")),s.test(r.className)||(r.className+=" line-numbers");var l,i=e.code.match(t),a=i?i.length+1:1,o=new Array(a+1);o=o.join(""),l=document.createElement("span"),l.setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=o,r.hasAttribute("data-start")&&(r.style.counterReset="linenumber "+(parseInt(r.getAttribute("data-start"),10)-1)),e.element.appendChild(l),n(r),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}),Prism.plugins.lineNumbers={getLine:function(t,n){if("PRE"===t.tagName&&t.classList.contains(e)){var r=t.querySelector(".line-numbers-rows"),s=parseInt(t.getAttribute("data-start"),10)||1,l=s+(r.children.length-1);s>n&&(n=s),n>l&&(n=l);var i=n-s;return r.children[i]}}}}}();
        \ No newline at end of file
        +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var o="line-numbers",a=/\n(?!$)/g,e=Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(o)){var t=e.querySelector(".line-numbers-rows");if(t){var i=parseInt(e.getAttribute("data-start"),10)||1,r=i+(t.children.length-1);n");(i=document.createElement("span")).setAttribute("aria-hidden","true"),i.className="line-numbers-rows",i.innerHTML=l,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(i),u([t]),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function u(e){if(0!=(e=e.filter(function(e){var n=function(e){return e?window.getComputedStyle?getComputedStyle(e):e.currentStyle||null:null}(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-rows");if(n&&t){var i=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(a);i||((i=document.createElement("span")).className="line-numbers-sizer",n.appendChild(i)),i.innerHTML="0",i.style.display="block";var s=i.getBoundingClientRect().height;return i.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:s,sizer:i}}}).filter(Boolean);n.forEach(function(e){var i=e.sizer,n=e.lines,r=e.lineHeights,s=e.oneLinerHeight;r[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1
        +
        +
        +
        +
        +
        +Match braces ▲ Prism plugins
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + +
        +

        How to use

        + +

        To enable this plugin add the match-braces class to a code block:

        + +
        <pre><code class="language-xxxx match-braces">...</pre></code>
        + +

        Just like language-xxxx, the match-braces class is inherited, so you can add the class to the <body> to enable the plugin for the whole page.

        + +

        The plugin will highlight brace pairs when the cursor hovers over one of the braces. The highlighting effect will disappear as soon as the cursor leaves the brace pair.
        + The hover effect can be disabled by adding the no-brace-hover to the code block. This class can also be inherited.

        + +

        You can also click on a brace to select the brace pair. To deselect the pair, click anywhere within the code block or select another pair.
        + The selection effect can be disabled by adding the no-brace-select to the code block. This class can also be + inherited.

        + +

        Rainbow braces 🌈

        + +

        To enable rainbow braces, simply add the rainbow-braces class to a code block. This class can also get inherited.

        +
        + +
        +

        Examples

        + +

        JavaScript

        +
        
        +	
        const func = (a, b) => {
        +	return `${a}:${b}`;
        +}
        + +

        Lisp

        +
        (defun factorial (n)
        +	(if (= n 0) 1
        +		(* n (factorial (- n 1)))))
        + +

        Lisp with rainbow braces 🌈 but without hover

        +
        (defun factorial (n)
        +	(if (= n 0) 1
        +		(* n (factorial (- n 1)))))
        +
        + +
        + + + + + + + + + + + diff --git a/plugins/match-braces/prism-match-braces.css b/plugins/match-braces/prism-match-braces.css new file mode 100644 index 0000000000..9ca6981da3 --- /dev/null +++ b/plugins/match-braces/prism-match-braces.css @@ -0,0 +1,29 @@ +.token.punctuation.brace-hover, +.token.punctuation.brace-selected { + outline: solid 1px; +} + +.rainbow-braces .token.punctuation.brace-level-1, +.rainbow-braces .token.punctuation.brace-level-5, +.rainbow-braces .token.punctuation.brace-level-9 { + color: #E50; + opacity: 1; +} +.rainbow-braces .token.punctuation.brace-level-2, +.rainbow-braces .token.punctuation.brace-level-6, +.rainbow-braces .token.punctuation.brace-level-10 { + color: #0B3; + opacity: 1; +} +.rainbow-braces .token.punctuation.brace-level-3, +.rainbow-braces .token.punctuation.brace-level-7, +.rainbow-braces .token.punctuation.brace-level-11 { + color: #26F; + opacity: 1; +} +.rainbow-braces .token.punctuation.brace-level-4, +.rainbow-braces .token.punctuation.brace-level-8, +.rainbow-braces .token.punctuation.brace-level-12 { + color: #E0E; + opacity: 1; +} diff --git a/plugins/match-braces/prism-match-braces.js b/plugins/match-braces/prism-match-braces.js new file mode 100644 index 0000000000..478f344ff3 --- /dev/null +++ b/plugins/match-braces/prism-match-braces.js @@ -0,0 +1,190 @@ +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } + + function mapClassName(name) { + var customClass = Prism.plugins.customClass; + if (customClass) { + return customClass.apply(name, 'none'); + } else { + return name; + } + } + + var PARTNER = { + '(': ')', + '[': ']', + '{': '}', + }; + + // The names for brace types. + // These names have two purposes: 1) they can be used for styling and 2) they are used to pair braces. Only braces + // of the same type are paired. + var NAMES = { + '(': 'brace-round', + '[': 'brace-square', + '{': 'brace-curly', + }; + + // A map for brace aliases. + // This is useful for when some braces have a prefix/suffix as part of the punctuation token. + var BRACE_ALIAS_MAP = { + '${': '{', // JS template punctuation (e.g. `foo ${bar + 1}`) + }; + + var LEVEL_WARP = 12; + + var pairIdCounter = 0; + + var BRACE_ID_PATTERN = /^(pair-\d+-)(close|open)$/; + + /** + * Returns the brace partner given one brace of a brace pair. + * + * @param {HTMLElement} brace + * @returns {HTMLElement} + */ + function getPartnerBrace(brace) { + var match = BRACE_ID_PATTERN.exec(brace.id); + return document.querySelector('#' + match[1] + (match[2] == 'open' ? 'close' : 'open')); + } + + /** + * @this {HTMLElement} + */ + function hoverBrace() { + if (!Prism.util.isActive(this, 'brace-hover', true)) { + return; + } + + [this, getPartnerBrace(this)].forEach(function (e) { + e.classList.add(mapClassName('brace-hover')); + }); + } + /** + * @this {HTMLElement} + */ + function leaveBrace() { + [this, getPartnerBrace(this)].forEach(function (e) { + e.classList.remove(mapClassName('brace-hover')); + }); + } + /** + * @this {HTMLElement} + */ + function clickBrace() { + if (!Prism.util.isActive(this, 'brace-select', true)) { + return; + } + + [this, getPartnerBrace(this)].forEach(function (e) { + e.classList.add(mapClassName('brace-selected')); + }); + } + + Prism.hooks.add('complete', function (env) { + + /** @type {HTMLElement} */ + var code = env.element; + var pre = code.parentElement; + + if (!pre || pre.tagName != 'PRE') { + return; + } + + // find the braces to match + /** @type {string[]} */ + var toMatch = []; + if (Prism.util.isActive(code, 'match-braces')) { + toMatch.push('(', '[', '{'); + } + + if (toMatch.length == 0) { + // nothing to match + return; + } + + if (!pre.__listenerAdded) { + // code blocks might be highlighted more than once + pre.addEventListener('mousedown', function removeBraceSelected() { + // the code element might have been replaced + var code = pre.querySelector('code'); + var className = mapClassName('brace-selected'); + Array.prototype.slice.call(code.querySelectorAll('.' + className)).forEach(function (e) { + e.classList.remove(className); + }); + }); + Object.defineProperty(pre, '__listenerAdded', { value: true }); + } + + /** @type {HTMLSpanElement[]} */ + var punctuation = Array.prototype.slice.call( + code.querySelectorAll('span.' + mapClassName('token') + '.' + mapClassName('punctuation')) + ); + + /** @type {{ index: number, open: boolean, element: HTMLElement }[]} */ + var allBraces = []; + + toMatch.forEach(function (open) { + var close = PARTNER[open]; + var name = mapClassName(NAMES[open]); + + /** @type {[number, number][]} */ + var pairs = []; + /** @type {number[]} */ + var openStack = []; + + for (var i = 0; i < punctuation.length; i++) { + var element = punctuation[i]; + if (element.childElementCount == 0) { + var text = element.textContent; + text = BRACE_ALIAS_MAP[text] || text; + if (text === open) { + allBraces.push({ index: i, open: true, element: element }); + element.classList.add(name); + element.classList.add(mapClassName('brace-open')); + openStack.push(i); + } else if (text === close) { + allBraces.push({ index: i, open: false, element: element }); + element.classList.add(name); + element.classList.add(mapClassName('brace-close')); + if (openStack.length) { + pairs.push([i, openStack.pop()]); + } + } + } + } + + pairs.forEach(function (pair) { + var pairId = 'pair-' + (pairIdCounter++) + '-'; + + var opening = punctuation[pair[0]]; + var closing = punctuation[pair[1]]; + + opening.id = pairId + 'open'; + closing.id = pairId + 'close'; + + [opening, closing].forEach(function (e) { + e.addEventListener('mouseenter', hoverBrace); + e.addEventListener('mouseleave', leaveBrace); + e.addEventListener('click', clickBrace); + }); + }); + }); + + var level = 0; + allBraces.sort(function (a, b) { return a.index - b.index; }); + allBraces.forEach(function (brace) { + if (brace.open) { + brace.element.classList.add(mapClassName('brace-level-' + (level % LEVEL_WARP + 1))); + level++; + } else { + level = Math.max(0, level - 1); + brace.element.classList.add(mapClassName('brace-level-' + (level % LEVEL_WARP + 1))); + } + }); + }); + +}()); diff --git a/plugins/match-braces/prism-match-braces.min.css b/plugins/match-braces/prism-match-braces.min.css new file mode 100644 index 0000000000..367b166b5a --- /dev/null +++ b/plugins/match-braces/prism-match-braces.min.css @@ -0,0 +1 @@ +.token.punctuation.brace-hover,.token.punctuation.brace-selected{outline:solid 1px}.rainbow-braces .token.punctuation.brace-level-1,.rainbow-braces .token.punctuation.brace-level-5,.rainbow-braces .token.punctuation.brace-level-9{color:#e50;opacity:1}.rainbow-braces .token.punctuation.brace-level-10,.rainbow-braces .token.punctuation.brace-level-2,.rainbow-braces .token.punctuation.brace-level-6{color:#0b3;opacity:1}.rainbow-braces .token.punctuation.brace-level-11,.rainbow-braces .token.punctuation.brace-level-3,.rainbow-braces .token.punctuation.brace-level-7{color:#26f;opacity:1}.rainbow-braces .token.punctuation.brace-level-12,.rainbow-braces .token.punctuation.brace-level-4,.rainbow-braces .token.punctuation.brace-level-8{color:#e0e;opacity:1} \ No newline at end of file diff --git a/plugins/match-braces/prism-match-braces.min.js b/plugins/match-braces/prism-match-braces.min.js new file mode 100644 index 0000000000..8b523abaaa --- /dev/null +++ b/plugins/match-braces/prism-match-braces.min.js @@ -0,0 +1 @@ +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var d={"(":")","[":"]","{":"}"},u={"(":"brace-round","[":"brace-square","{":"brace-curly"},f={"${":"{"},h=0,n=/^(pair-\d+-)(close|open)$/;Prism.hooks.add("complete",function(e){var t=e.element,n=t.parentElement;if(n&&"PRE"==n.tagName){var r=[];if(Prism.util.isActive(t,"match-braces")&&r.push("(","[","{"),0!=r.length){n.__listenerAdded||(n.addEventListener("mousedown",function(){var e=n.querySelector("code"),t=p("brace-selected");Array.prototype.slice.call(e.querySelectorAll("."+t)).forEach(function(e){e.classList.remove(t)})}),Object.defineProperty(n,"__listenerAdded",{value:!0}));var o=Array.prototype.slice.call(t.querySelectorAll("span."+p("token")+"."+p("punctuation"))),l=[];r.forEach(function(e){for(var t=d[e],n=p(u[e]),r=[],c=[],s=0;s - + Normalize Whitespace ▲ Prism plugins - + - + - + -
        -
        - -

        Normalize Whitespace

        -

        Supports multiple operations to normalize whitespace in code blocks.

        -
        +

        How to use

        @@ -167,14 +162,14 @@

        Examples

        -
        +
        - + - + diff --git a/plugins/normalize-whitespace/prism-normalize-whitespace.js b/plugins/normalize-whitespace/prism-normalize-whitespace.js index 0b66de03a0..c8bc361bbd 100644 --- a/plugins/normalize-whitespace/prism-normalize-whitespace.js +++ b/plugins/normalize-whitespace/prism-normalize-whitespace.js @@ -1,190 +1,198 @@ -(function() { +(function () { -var assign = Object.assign || function (obj1, obj2) { - for (var name in obj2) { - if (obj2.hasOwnProperty(name)) - obj1[name] = obj2[name]; + if (typeof Prism === 'undefined') { + return; } - return obj1; -} -function NormalizeWhitespace(defaults) { - this.defaults = assign({}, defaults); -} + var assign = Object.assign || function (obj1, obj2) { + for (var name in obj2) { + if (obj2.hasOwnProperty(name)) { + obj1[name] = obj2[name]; + } + } + return obj1; + }; -function toCamelCase(value) { - return value.replace(/-(\w)/g, function(match, firstChar) { - return firstChar.toUpperCase(); - }); -} + function NormalizeWhitespace(defaults) { + this.defaults = assign({}, defaults); + } -function tabLen(str) { - var res = 0; - for (var i = 0; i < str.length; ++i) { - if (str.charCodeAt(i) == '\t'.charCodeAt(0)) - res += 3; + function toCamelCase(value) { + return value.replace(/-(\w)/g, function (match, firstChar) { + return firstChar.toUpperCase(); + }); } - return str.length + res; -} - -NormalizeWhitespace.prototype = { - setDefaults: function (defaults) { - this.defaults = assign(this.defaults, defaults); - }, - normalize: function (input, settings) { - settings = assign(this.defaults, settings); - - for (var name in settings) { - var methodName = toCamelCase(name); - if (name !== "normalize" && methodName !== 'setDefaults' && - settings[name] && this[methodName]) { - input = this[methodName].call(this, input, settings[name]); + + function tabLen(str) { + var res = 0; + for (var i = 0; i < str.length; ++i) { + if (str.charCodeAt(i) == '\t'.charCodeAt(0)) { + res += 3; } } + return str.length + res; + } - return input; - }, - - /* - * Normalization methods - */ - leftTrim: function (input) { - return input.replace(/^\s+/, ''); - }, - rightTrim: function (input) { - return input.replace(/\s+$/, ''); - }, - tabsToSpaces: function (input, spaces) { - spaces = spaces|0 || 4; - return input.replace(/\t/g, new Array(++spaces).join(' ')); - }, - spacesToTabs: function (input, spaces) { - spaces = spaces|0 || 4; - return input.replace(new RegExp(' {' + spaces + '}', 'g'), '\t'); - }, - removeTrailing: function (input) { - return input.replace(/\s*?$/gm, ''); - }, - // Support for deprecated plugin remove-initial-line-feed - removeInitialLineFeed: function (input) { - return input.replace(/^(?:\r?\n|\r)/, ''); - }, - removeIndent: function (input) { - var indents = input.match(/^[^\S\n\r]*(?=\S)/gm); - - if (!indents || !indents[0].length) - return input; + NormalizeWhitespace.prototype = { + setDefaults: function (defaults) { + this.defaults = assign(this.defaults, defaults); + }, + normalize: function (input, settings) { + settings = assign(this.defaults, settings); - indents.sort(function(a, b){return a.length - b.length; }); + for (var name in settings) { + var methodName = toCamelCase(name); + if (name !== 'normalize' && methodName !== 'setDefaults' && + settings[name] && this[methodName]) { + input = this[methodName].call(this, input, settings[name]); + } + } - if (!indents[0].length) return input; + }, + + /* + * Normalization methods + */ + leftTrim: function (input) { + return input.replace(/^\s+/, ''); + }, + rightTrim: function (input) { + return input.replace(/\s+$/, ''); + }, + tabsToSpaces: function (input, spaces) { + spaces = spaces|0 || 4; + return input.replace(/\t/g, new Array(++spaces).join(' ')); + }, + spacesToTabs: function (input, spaces) { + spaces = spaces|0 || 4; + return input.replace(RegExp(' {' + spaces + '}', 'g'), '\t'); + }, + removeTrailing: function (input) { + return input.replace(/\s*?$/gm, ''); + }, + // Support for deprecated plugin remove-initial-line-feed + removeInitialLineFeed: function (input) { + return input.replace(/^(?:\r?\n|\r)/, ''); + }, + removeIndent: function (input) { + var indents = input.match(/^[^\S\n\r]*(?=\S)/gm); + + if (!indents || !indents[0].length) { + return input; + } + + indents.sort(function (a, b) { return a.length - b.length; }); + + if (!indents[0].length) { + return input; + } - return input.replace(new RegExp('^' + indents[0], 'gm'), ''); - }, - indent: function (input, tabs) { - return input.replace(/^[^\S\n\r]*(?=\S)/gm, new Array(++tabs).join('\t') + '$&'); - }, - breakLines: function (input, characters) { - characters = (characters === true) ? 80 : characters|0 || 80; - - var lines = input.split('\n'); - for (var i = 0; i < lines.length; ++i) { - if (tabLen(lines[i]) <= characters) - continue; - - var line = lines[i].split(/(\s+)/g), - len = 0; - - for (var j = 0; j < line.length; ++j) { - var tl = tabLen(line[j]); - len += tl; - if (len > characters) { - line[j] = '\n' + line[j]; - len = tl; + return input.replace(RegExp('^' + indents[0], 'gm'), ''); + }, + indent: function (input, tabs) { + return input.replace(/^[^\S\n\r]*(?=\S)/gm, new Array(++tabs).join('\t') + '$&'); + }, + breakLines: function (input, characters) { + characters = (characters === true) ? 80 : characters|0 || 80; + + var lines = input.split('\n'); + for (var i = 0; i < lines.length; ++i) { + if (tabLen(lines[i]) <= characters) { + continue; } + + var line = lines[i].split(/(\s+)/g); + var len = 0; + + for (var j = 0; j < line.length; ++j) { + var tl = tabLen(line[j]); + len += tl; + if (len > characters) { + line[j] = '\n' + line[j]; + len = tl; + } + } + lines[i] = line.join(''); } - lines[i] = line.join(''); + return lines.join('\n'); } - return lines.join('\n'); - } -}; - -// Support node modules -if (typeof module !== 'undefined' && module.exports) { - module.exports = NormalizeWhitespace; -} - -// Exit if prism is not loaded -if (typeof Prism === 'undefined') { - return; -} - -Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({ - 'remove-trailing': true, - 'remove-indent': true, - 'left-trim': true, - 'right-trim': true, - /*'break-lines': 80, - 'indent': 2, - 'remove-initial-line-feed': false, - 'tabs-to-spaces': 4, - 'spaces-to-tabs': 4*/ -}); - -Prism.hooks.add('before-sanity-check', function (env) { - var Normalizer = Prism.plugins.NormalizeWhitespace; - - // Check settings - if (env.settings && env.settings['whitespace-normalization'] === false) { - return; - } + }; - // Simple mode if there is no env.element - if ((!env.element || !env.element.parentNode) && env.code) { - env.code = Normalizer.normalize(env.code, env.settings); - return; + // Support node modules + if (typeof module !== 'undefined' && module.exports) { + module.exports = NormalizeWhitespace; } - // Normal mode - var pre = env.element.parentNode; - var clsReg = /\bno-whitespace-normalization\b/; - if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre' || - clsReg.test(pre.className) || clsReg.test(env.element.className)) - return; + Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({ + 'remove-trailing': true, + 'remove-indent': true, + 'left-trim': true, + 'right-trim': true, + /*'break-lines': 80, + 'indent': 2, + 'remove-initial-line-feed': false, + 'tabs-to-spaces': 4, + 'spaces-to-tabs': 4*/ + }); - var children = pre.childNodes, - before = '', - after = '', - codeFound = false; - - // Move surrounding whitespace from the
         tag into the  tag
        -	for (var i = 0; i < children.length; ++i) {
        -		var node = children[i];
        -
        -		if (node == env.element) {
        -			codeFound = true;
        -		} else if (node.nodeName === "#text") {
        -			if (codeFound) {
        -				after += node.nodeValue;
        -			} else {
        -				before += node.nodeValue;
        -			}
        +	Prism.hooks.add('before-sanity-check', function (env) {
        +		var Normalizer = Prism.plugins.NormalizeWhitespace;
         
        -			pre.removeChild(node);
        -			--i;
        +		// Check settings
        +		if (env.settings && env.settings['whitespace-normalization'] === false) {
        +			return;
         		}
        -	}
         
        -	if (!env.element.children.length || !Prism.plugins.KeepMarkup) {
        -		env.code = before + env.code + after;
        -		env.code = Normalizer.normalize(env.code, env.settings);
        -	} else {
        -		// Preserve markup for keep-markup plugin
        -		var html = before + env.element.innerHTML + after;
        -		env.element.innerHTML = Normalizer.normalize(html, env.settings);
        -		env.code = env.element.textContent;
        -	}
        -});
        +		// Check classes
        +		if (!Prism.util.isActive(env.element, 'whitespace-normalization', true)) {
        +			return;
        +		}
        +
        +		// Simple mode if there is no env.element
        +		if ((!env.element || !env.element.parentNode) && env.code) {
        +			env.code = Normalizer.normalize(env.code, env.settings);
        +			return;
        +		}
        +
        +		// Normal mode
        +		var pre = env.element.parentNode;
        +		if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre') {
        +			return;
        +		}
        +
        +		var children = pre.childNodes;
        +		var before = '';
        +		var after = '';
        +		var codeFound = false;
        +
        +		// Move surrounding whitespace from the 
         tag into the  tag
        +		for (var i = 0; i < children.length; ++i) {
        +			var node = children[i];
        +
        +			if (node == env.element) {
        +				codeFound = true;
        +			} else if (node.nodeName === '#text') {
        +				if (codeFound) {
        +					after += node.nodeValue;
        +				} else {
        +					before += node.nodeValue;
        +				}
        +
        +				pre.removeChild(node);
        +				--i;
        +			}
        +		}
        +
        +		if (!env.element.children.length || !Prism.plugins.KeepMarkup) {
        +			env.code = before + env.code + after;
        +			env.code = Normalizer.normalize(env.code, env.settings);
        +		} else {
        +			// Preserve markup for keep-markup plugin
        +			var html = before + env.element.innerHTML + after;
        +			env.element.innerHTML = Normalizer.normalize(html, env.settings);
        +			env.code = env.element.textContent;
        +		}
        +	});
         
        -}());
        \ No newline at end of file
        +}());
        diff --git a/plugins/normalize-whitespace/prism-normalize-whitespace.min.js b/plugins/normalize-whitespace/prism-normalize-whitespace.min.js
        index b38d064c25..36353c9b62 100644
        --- a/plugins/normalize-whitespace/prism-normalize-whitespace.min.js
        +++ b/plugins/normalize-whitespace/prism-normalize-whitespace.min.js
        @@ -1 +1 @@
        -!function(){function e(e){this.defaults=r({},e)}function n(e){return e.replace(/-(\w)/g,function(e,n){return n.toUpperCase()})}function t(e){for(var n=0,t=0;tn&&(o[s]="\n"+o[s],a=l)}r[i]=o.join("")}return r.join("\n")}},"undefined"!=typeof module&&module.exports&&(module.exports=e),"undefined"!=typeof Prism&&(Prism.plugins.NormalizeWhitespace=new e({"remove-trailing":!0,"remove-indent":!0,"left-trim":!0,"right-trim":!0}),Prism.hooks.add("before-sanity-check",function(e){var n=Prism.plugins.NormalizeWhitespace;if(!e.settings||e.settings["whitespace-normalization"]!==!1){if((!e.element||!e.element.parentNode)&&e.code)return e.code=n.normalize(e.code,e.settings),void 0;var t=e.element.parentNode,r=/\bno-whitespace-normalization\b/;if(e.code&&t&&"pre"===t.nodeName.toLowerCase()&&!r.test(t.className)&&!r.test(e.element.className)){for(var i=t.childNodes,o="",a="",s=!1,l=0;l
         
         	
        -	
        +	
         	Previewers ▲ Prism plugins
         	
        -	
        +	
         	
         	
        -	
        +	
         
         	
        -	
        +	
         
         
         
        -
        -
        - -

        Previewers

        -

        Previewers for angles, colors, gradients, easing and time.

        -
        +

        How to use

        @@ -43,11 +38,11 @@

        Examples

        CSS

        .example-gradient {
        -	background: -moz-linear-gradient(left,  #cb60b3 0%, #c146a1 50%, #a80077 51%, #db36a4 100%); /* FF3.6+ */
        -	background: -webkit-linear-gradient(left,  #cb60b3 0%,#c146a1 50%,#a80077 51%,#db36a4 100%); /* Chrome10+,Safari5.1+ */
        -	background: -o-linear-gradient(left,  #cb60b3 0%,#c146a1 50%,#a80077 51%,#db36a4 100%); /* Opera 11.10+ */
        -	background: -ms-linear-gradient(left,  #cb60b3 0%,#c146a1 50%,#a80077 51%,#db36a4 100%); /* IE10+ */
        -	background: linear-gradient(to right,  #cb60b3 0%,#c146a1 50%,#a80077 51%,#db36a4 100%); /* W3C */
        +	background: -webkit-linear-gradient(left,     #cb60b3 0%, #c146a1 50%, #a80077 51%, #db36a4 100%); /* Chrome10+, Safari5.1+ */
        +	background:    -moz-linear-gradient(left,     #cb60b3 0%, #c146a1 50%, #a80077 51%, #db36a4 100%); /* FF3.6+ */
        +	background:     -ms-linear-gradient(left,     #cb60b3 0%, #c146a1 50%, #a80077 51%, #db36a4 100%); /* IE10+ */
        +	background:      -o-linear-gradient(left,     #cb60b3 0%, #c146a1 50%, #a80077 51%, #db36a4 100%); /* Opera 11.10+ */
        +	background:         linear-gradient(to right, #cb60b3 0%, #c146a1 50%, #a80077 51%, #db36a4 100%); /* W3C */
         }
         .example-angle {
         	transform: rotate(10deg);
        @@ -55,7 +50,7 @@ 

        CSS

        .example-color { color: rgba(255, 0, 0, 0.2); background: purple; - border: 1px solid hsl(100,70%,40%); + border: 1px solid hsl(100, 70%, 40%); } .example-easing { transition-timing-function: linear; @@ -69,13 +64,13 @@

        Markup attributes

        <tr style="background: lightblue;">

        Less

        -
        @gradient: linear-gradient(135deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%);
        +	
        @gradient: linear-gradient(135deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%);
         .example-gradient {
        -	background: -moz-linear-gradient(-45deg,  #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* FF3.6+ */
        -	background: -webkit-linear-gradient(-45deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* Chrome10+,Safari5.1+ */
        -	background: -o-linear-gradient(-45deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* Opera 11.10+ */
        -	background: -ms-linear-gradient(-45deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* IE10+ */
        -	background: linear-gradient(135deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* W3C */
        +	background: -webkit-linear-gradient(-45deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* Chrome10+, Safari5.1+ */
        +	background:    -moz-linear-gradient(-45deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* FF3.6+ */
        +	background:     -ms-linear-gradient(-45deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* IE10+ */
        +	background:      -o-linear-gradient(-45deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* Opera 11.10+ */
        +	background:         linear-gradient(135deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* W3C */
         }
         @angle: 3rad;
         .example-angle {
        @@ -85,7 +80,7 @@ 

        Less

        .example-color { color: hsla(102, 53%, 42%, 0.4); } -@easing: cubic-bezier(0.1,0.3,1,.4); +@easing: cubic-bezier(0.1, 0.3, 1, .4); .example-easing { transition-timing-function: ease; } @@ -95,10 +90,10 @@

        Less

        }

        Sass

        -
        $gradient: linear-gradient(135deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%)
        +	
        $gradient: linear-gradient(135deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%)
         @mixin example-gradient
        -	background: -moz-radial-gradient(center, ellipse cover,  #f2f6f8 0%, #d8e1e7 50%, #b5c6d0 51%, #e0eff9 100%)
        -	background: radial-gradient(ellipse at center,  #f2f6f8 0%,#d8e1e7 50%,#b5c6d0 51%,#e0eff9 100%)
        +	background: -moz-radial-gradient(center, ellipse cover, #f2f6f8 0%, #d8e1e7 50%, #b5c6d0 51%, #e0eff9 100%)
        +	background: radial-gradient(ellipse at center, #f2f6f8 0%, #d8e1e7 50%, #b5c6d0 51%, #e0eff9 100%)
         $angle: 380grad
         @mixin example-angle
         	transform: rotate(-120deg)
        @@ -106,9 +101,9 @@ 

        Sass

        transform: rotate(18rad) $color: blue @mixin example-color - color: rgba(147, 32, 34, 0.8) + color: rgba(147, 32, 34, 0.8) .example-color - color: pink + color: pink $easing: ease-out .example-easing transition-timing-function: ease-in-out @@ -120,10 +115,10 @@

        Sass

        Scss

        -
        $gradient: linear-gradient(135deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%);
        +	
        $gradient: linear-gradient(135deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%);
         $attr: background;
         .example-gradient {
        -    #{$attr}-image: repeating-linear-gradient(10deg, rgba(255,0,0,0), rgba(255,0,0,1) 10px, rgba(255,0,0,0) 20px);
        +	#{$attr}-image: repeating-linear-gradient(10deg, rgba(255, 0, 0, 0), rgba(255, 0, 0, 1) 10px, rgba(255, 0, 0, 0) 20px);
         }
         $angle: 1.8turn;
         .example-angle {
        @@ -131,11 +126,11 @@ 

        Scss

        } $color: blue; .example-color { - #{$attr}-color: rgba(255,255,0,0.75); + #{$attr}-color: rgba(255, 255, 0, 0.75); } $easing: linear; .example-easing { - transition-timing-function: cubic-bezier(0.9,0.1,.2,.4); + transition-timing-function: cubic-bezier(0.9, 0.1, .2, .4); } $time: 1s; .example-time { @@ -143,9 +138,9 @@

        Scss

        }

        Stylus

        -
        gradient = linear-gradient(135deg,  #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%)
        +	
        gradient = linear-gradient(135deg, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%)
         .example-gradient
        -	background-image: repeating-radial-gradient(circle, rgba(255,0,0,0), rgba(255,0,0,1) 10px, rgba(255,0,0,0) 20px)
        +	background-image: repeating-radial-gradient(circle, rgba(255, 0, 0, 0), rgba(255, 0, 0, 1) 10px, rgba(255, 0, 0, 0) 20px)
         angle = 357deg
         .example-angle
         	transform: rotate(100grad)
        @@ -166,15 +161,16 @@ 

        Disabling a previewer

        can be added on a code block or any ancestor. Its value should be a space-separated list of previewers representing the subset.

        For example:

        -
        <pre class="language-css" data-previewers="color"><code>div {
        -	/* Only the previewer for colors is enabled */
        +	
        <pre class="language-css" data-previewers="color time"><code>div {
        +	/* Only the previewer for color and time are enabled */
         	color: red;
        +	transition-duration: 1s;
         	/* The previewer for angles is not enabled. */
         	transform: rotate(10deg);
         }</code></pre>

        will give the following result:

        div {
        -	/* Only the previewers color and time are enabled */
        +	/* Only the previewers for color and time are enabled */
         	color: red;
         	transition-duration: 1s;
         	/* The previewer for angles is not enabled. */
        @@ -184,30 +180,30 @@ 

        Disabling a previewer

        API

        -

        This plugins provides a constructor that can be accessed through Prism.plugins.Previewer.

        +

        This plugins provides a constructor that can be accessed through Prism.plugins.Previewer.

        Once a previewer has been instantiated, an HTML element is appended to the document body. This element will appear when specific tokens are hovered.

        -

        new Prism.plugins.Previewer(type, updater, supportedLanguages)

        +

        new Prism.plugins.Previewer(type, updater, supportedLanguages)

        • -

          type: the token type this previewer is associated to. +

          type: the token type this previewer is associated to. The previewer will be shown when hovering tokens of this type.

        • -

          updater: the function that will be called each time an associated token is hovered. +

          updater: the function that will be called each time an associated token is hovered. This function takes the text content of the token as its only parameter. - The previewer HTML element can be accessed through the keyword this. - This function must return true for the previewer to be shown.

          + The previewer HTML element can be accessed through the keyword this. + This function must return true for the previewer to be shown.

        • -

          supportedLanguages: an optional array of supported languages. +

          supportedLanguages: an optional array of supported languages. The previewer will be available only for those. - Defaults to '*', which means every languages.

          + Defaults to '*', which means every languages.

        • -

          initializer: an optional function. +

          initializer: an optional function. This function will be called when the previewer is initialized, right after the HTML element has been appended to the document body.

        • @@ -215,18 +211,19 @@

          new Prism.plugins.Previewer(type, updater, supportedLanguages)<

        -
        +
        + - + - + - \ No newline at end of file + diff --git a/plugins/previewers/prism-previewers.css b/plugins/previewers/prism-previewers.css index b36988c2bf..2d5e9570c0 100644 --- a/plugins/previewers/prism-previewers.css +++ b/plugins/previewers/prism-previewers.css @@ -13,6 +13,7 @@ width: 32px; height: 32px; margin-left: -16px; + z-index: 10; opacity: 0; -webkit-transition: opacity .25s; diff --git a/plugins/previewers/prism-previewers.js b/plugins/previewers/prism-previewers.js index 8c2feb164d..89ac73f029 100644 --- a/plugins/previewers/prism-previewers.js +++ b/plugins/previewers/prism-previewers.js @@ -1,9 +1,6 @@ -(function() { +(function () { - if ( - typeof self !== 'undefined' && !self.Prism || - !self.document || !Function.prototype.bind - ) { + if (typeof Prism === 'undefined' || typeof document === 'undefined' || !Function.prototype.bind) { return; } @@ -18,15 +15,16 @@ /** * Returns a W3C-valid linear gradient + * * @param {string} prefix Vendor prefix if any ("-moz-", "-webkit-", etc.) * @param {string} func Gradient function name ("linear-gradient") * @param {string[]} values Array of the gradient function parameters (["0deg", "red 0%", "blue 100%"]) */ - var convertToW3CLinearGradient = function(prefix, func, values) { + var convertToW3CLinearGradient = function (prefix, func, values) { // Default value for angle var angle = '180deg'; - if (/^(?:-?\d*\.?\d+(?:deg|rad)|to\b|top|right|bottom|left)/.test(values[0])) { + if (/^(?:-?(?:\d+(?:\.\d+)?|\.\d+)(?:deg|rad)|to\b|top|right|bottom|left)/.test(values[0])) { angle = values.shift(); if (angle.indexOf('to ') < 0) { // Angle uses old keywords @@ -67,11 +65,12 @@ /** * Returns a W3C-valid radial gradient + * * @param {string} prefix Vendor prefix if any ("-moz-", "-webkit-", etc.) * @param {string} func Gradient function name ("linear-gradient") * @param {string[]} values Array of the gradient function parameters (["0deg", "red 0%", "blue 100%"]) */ - var convertToW3CRadialGradient = function(prefix, func, values) { + var convertToW3CRadialGradient = function (prefix, func, values) { if (values[0].indexOf('at') < 0) { // Looks like old syntax @@ -80,12 +79,12 @@ var shape = 'ellipse'; var size = 'farthest-corner'; - if (/\bcenter|top|right|bottom|left\b|^\d+/.test(values[0])) { + if (/\b(?:bottom|center|left|right|top)\b|^\d+/.test(values[0])) { // Found a position // Remove angle value, if any - position = values.shift().replace(/\s*-?\d+(?:rad|deg)\s*/, ''); + position = values.shift().replace(/\s*-?\d+(?:deg|rad)\s*/, ''); } - if (/\bcircle|ellipse|closest|farthest|contain|cover\b/.test(values[0])) { + if (/\b(?:circle|closest|contain|cover|ellipse|farthest)\b/.test(values[0])) { // Found a shape and/or size var shapeSizeParts = values.shift().split(/\s+/); if (shapeSizeParts[0] && (shapeSizeParts[0] === 'circle' || shapeSizeParts[0] === 'ellipse')) { @@ -111,9 +110,10 @@ /** * Converts a gradient to a W3C-valid one * Does not support old webkit syntax (-webkit-gradient(linear...) and -webkit-gradient(radial...)) + * * @param {string} gradient The CSS gradient */ - var convertToW3CGradient = function(gradient) { + var convertToW3CGradient = function (gradient) { if (cache[gradient]) { return cache[gradient]; } @@ -134,7 +134,7 @@ }; return function () { - new Prism.plugins.Previewer('gradient', function(value) { + new Prism.plugins.Previewer('gradient', function (value) { this.firstChild.style.backgroundImage = ''; this.firstChild.style.backgroundImage = convertToW3CGradient(value); return !!this.firstChild.style.backgroundImage; @@ -145,7 +145,7 @@ }()), tokens: { 'gradient': { - pattern: /(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\((?:(?:rgb|hsl)a?\(.+?\)|[^\)])+\)/gi, + pattern: /(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\((?:(?:hsl|rgb)a?\(.+?\)|[^\)])+\)/gi, inside: { 'function': /[\w-]+(?=\()/, 'punctuation': /[(),]/ @@ -188,16 +188,16 @@ }, 'angle': { create: function () { - new Prism.plugins.Previewer('angle', function(value) { + new Prism.plugins.Previewer('angle', function (value) { var num = parseFloat(value); var unit = value.match(/[a-z]+$/i); - var max, percentage; + var max; var percentage; if (!num || !unit) { return false; } unit = unit[0]; - switch(unit) { + switch (unit) { case 'deg': max = 360; break; @@ -211,10 +211,10 @@ max = 1; } - percentage = 100 * num/max; + percentage = 100 * num / max; percentage %= 100; - this[(num < 0? 'set' : 'remove') + 'Attribute']('data-negative', ''); + this[(num < 0 ? 'set' : 'remove') + 'Attribute']('data-negative', ''); this.querySelector('circle').style.strokeDasharray = Math.abs(percentage) + ',500'; return true; }, '*', function () { @@ -224,7 +224,7 @@ }); }, tokens: { - 'angle': /(?:\b|\B-|(?=\B\.))\d*\.?\d+(?:deg|g?rad|turn)\b/i + 'angle': /(?:\b|\B-|(?=\B\.))(?:\d+(?:\.\d+)?|\.\d+)(?:deg|g?rad|turn)\b/i }, languages: { 'css': true, @@ -267,23 +267,18 @@ }, 'color': { create: function () { - new Prism.plugins.Previewer('color', function(value) { + new Prism.plugins.Previewer('color', function (value) { this.style.backgroundColor = ''; this.style.backgroundColor = value; return !!this.style.backgroundColor; }); }, tokens: { - 'color': { - pattern: /\B#(?:[0-9a-f]{3}){1,2}\b|\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B|\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGray|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGray|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGray|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gray|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGray|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGray|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGray|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i, - inside: { - 'function': /[\w-]+(?=\()/, - 'punctuation': /[(),]/ - } - } + 'color': [Prism.languages.css['hexcode']].concat(Prism.languages.css['color']) }, languages: { - 'css': true, + // CSS extras is required, so css and scss are not necessary + 'css': false, 'less': true, 'markup': { lang: 'markup', @@ -304,7 +299,7 @@ root: Prism.languages.sass && Prism.languages.sass['property-line'] } ], - 'scss': true, + 'scss': false, 'stylus': [ { lang: 'stylus', @@ -330,13 +325,13 @@ 'ease': '.25,.1,.25,1', 'ease-in': '.42,0,1,1', 'ease-out': '0,0,.58,1', - 'ease-in-out':'.42,0,.58,1' + 'ease-in-out': '.42,0,.58,1' }[value] || value; - var p = value.match(/-?\d*\.?\d+/g); + var p = value.match(/-?(?:\d+(?:\.\d+)?|\.\d+)/g); - if(p.length === 4) { - p = p.map(function(p, i) { return (i % 2? 1 - p : p) * 100; }); + if (p.length === 4) { + p = p.map(function (p, i) { return (i % 2 ? 1 - p : p) * 100; }); this.querySelector('path').setAttribute('d', 'M0,100 C' + p[0] + ',' + p[1] + ', ' + p[2] + ',' + p[3] + ', 100,0'); @@ -358,14 +353,14 @@ '' + '' + '' + - '' + - '' + + '' + + '' + ''; }); }, tokens: { 'easing': { - pattern: /\bcubic-bezier\((?:-?\d*\.?\d+,\s*){3}-?\d*\.?\d+\)\B|\b(?:linear|ease(?:-in)?(?:-out)?)(?=\s|[;}]|$)/i, + pattern: /\bcubic-bezier\((?:-?(?:\d+(?:\.\d+)?|\.\d+),\s*){3}-?(?:\d+(?:\.\d+)?|\.\d+)\)\B|\b(?:ease(?:-in)?(?:-out)?|linear)(?=\s|[;}]|$)/i, inside: { 'function': /[\w-]+(?=\()/, 'punctuation': /[(),]/ @@ -408,7 +403,7 @@ 'time': { create: function () { - new Prism.plugins.Previewer('time', function(value) { + new Prism.plugins.Previewer('time', function (value) { var num = parseFloat(value); var unit = value.match(/[a-z]+$/i); if (!num || !unit) { @@ -424,7 +419,7 @@ }); }, tokens: { - 'time': /(?:\b|\B-|(?=\B\.))\d*\.?\d+m?s\b/i + 'time': /(?:\b|\B-|(?=\B\.))(?:\d+(?:\.\d+)?|\.\d+)m?s\b/i }, languages: { 'css': true, @@ -469,50 +464,44 @@ /** * Returns the absolute X, Y offsets for an element + * * @param {HTMLElement} element - * @returns {{top: number, right: number, bottom: number, left: number}} + * @returns {{top: number, right: number, bottom: number, left: number, width: number, height: number}} */ var getOffset = function (element) { - var left = 0, top = 0, el = element; - - if (el.parentNode) { - do { - left += el.offsetLeft; - top += el.offsetTop; - } while ((el = el.offsetParent) && el.nodeType < 9); - - el = element; - - do { - left -= el.scrollLeft; - top -= el.scrollTop; - } while ((el = el.parentNode) && !/body/i.test(el.nodeName)); - } + var elementBounds = element.getBoundingClientRect(); + var left = elementBounds.left; + var top = elementBounds.top; + var documentBounds = document.documentElement.getBoundingClientRect(); + left -= documentBounds.left; + top -= documentBounds.top; return { top: top, - right: innerWidth - left - element.offsetWidth, - bottom: innerHeight - top - element.offsetHeight, - left: left + right: innerWidth - left - elementBounds.width, + bottom: innerHeight - top - elementBounds.height, + left: left, + width: elementBounds.width, + height: elementBounds.height }; }; - var tokenRegexp = /(?:^|\s)token(?=$|\s)/; - var activeRegexp = /(?:^|\s)active(?=$|\s)/g; - var flippedRegexp = /(?:^|\s)flipped(?=$|\s)/g; + var TOKEN_CLASS = 'token'; + var ACTIVE_CLASS = 'active'; + var FLIPPED_CLASS = 'flipped'; /** * Previewer constructor + * * @param {string} type Unique previewer type - * @param {function} updater Function that will be called on mouseover. - * @param {string[]|string=} supportedLanguages Aliases of the languages this previewer must be enabled for. Defaults to "*", all languages. - * @param {function=} initializer Function that will be called on initialization. - * @constructor + * @param {Function} updater Function that will be called on mouseover. + * @param {string[]|string} [supportedLanguages] Aliases of the languages this previewer must be enabled for. Defaults to "*", all languages. + * @param {Function} [initializer] Function that will be called on initialization. + * @class */ var Previewer = function (type, updater, supportedLanguages, initializer) { this._elt = null; this._type = type; - this._clsRegexp = RegExp('(?:^|\\s)' + type + '(?=$|\\s)'); this._token = null; this.updater = updater; this._mouseout = this.mouseout.bind(this); @@ -523,7 +512,7 @@ if (!supportedLanguages) { supportedLanguages = ['*']; } - if (Prism.util.type(supportedLanguages) !== 'Array') { + if (!Array.isArray(supportedLanguages)) { supportedLanguages = [supportedLanguages]; } supportedLanguages.forEach(function (lang) { @@ -550,34 +539,39 @@ this._elt = document.createElement('div'); this._elt.className = 'prism-previewer prism-previewer-' + this._type; document.body.appendChild(this._elt); - if(this.initializer) { + if (this.initializer) { this.initializer(); } }; + /** + * @param {Element} token + * @returns {boolean} + */ Previewer.prototype.isDisabled = function (token) { do { if (token.hasAttribute && token.hasAttribute('data-previewers')) { var previewers = token.getAttribute('data-previewers'); return (previewers || '').split(/\s+/).indexOf(this._type) === -1; } - } while(token = token.parentNode); + } while ((token = token.parentNode)); return false; }; /** * Checks the class name of each hovered element - * @param token + * + * @param {Element} token */ Previewer.prototype.check = function (token) { - if (tokenRegexp.test(token.className) && this.isDisabled(token)) { + if (token.classList.contains(TOKEN_CLASS) && this.isDisabled(token)) { return; } do { - if (tokenRegexp.test(token.className) && this._clsRegexp.test(token.className)) { + if (token.classList && token.classList.contains(TOKEN_CLASS) && token.classList.contains(this._type)) { break; } - } while(token = token.parentNode); + } while ((token = token.parentNode)); if (token && token !== this._token) { this._token = token; @@ -588,7 +582,7 @@ /** * Called on mouseout */ - Previewer.prototype.mouseout = function() { + Previewer.prototype.mouseout = function () { this._token.removeEventListener('mouseout', this._mouseout, false); this._token = null; this.hide(); @@ -609,19 +603,19 @@ this._token.addEventListener('mouseout', this._mouseout, false); var offset = getOffset(this._token); - this._elt.className += ' active'; + this._elt.classList.add(ACTIVE_CLASS); if (offset.top - this._elt.offsetHeight > 0) { - this._elt.className = this._elt.className.replace(flippedRegexp, ''); + this._elt.classList.remove(FLIPPED_CLASS); this._elt.style.top = offset.top + 'px'; this._elt.style.bottom = ''; } else { - this._elt.className += ' flipped'; + this._elt.classList.add(FLIPPED_CLASS); this._elt.style.bottom = offset.bottom + 'px'; this._elt.style.top = ''; } - this._elt.style.left = offset.left + Math.min(200, this._token.offsetWidth / 2) + 'px'; + this._elt.style.left = offset.left + Math.min(200, offset.width / 2) + 'px'; } else { this.hide(); } @@ -631,23 +625,26 @@ * Hides the previewer. */ Previewer.prototype.hide = function () { - this._elt.className = this._elt.className.replace(activeRegexp, ''); + this._elt.classList.remove(ACTIVE_CLASS); }; /** * Map of all registered previewers by language + * * @type {{}} */ Previewer.byLanguages = {}; /** * Map of all registered previewers by type + * * @type {{}} */ Previewer.byType = {}; /** * Initializes the mouseover event on the code block. + * * @param {HTMLElement} elt The code block (env.element) * @param {string} lang The language (env.language) */ @@ -673,11 +670,11 @@ var languages = previewers[previewer].languages; if (env.language && languages[env.language] && !languages[env.language].initialized) { var lang = languages[env.language]; - if (Prism.util.type(lang) !== 'Array') { + if (!Array.isArray(lang)) { lang = [lang]; } lang.forEach(function (lang) { - var before, inside, root, skip; + var before; var inside; var root; var skip; if (lang === true) { before = 'important'; inside = env.language; @@ -694,7 +691,7 @@ Prism.languages.insertBefore(inside, before, previewers[previewer].tokens, root); env.grammar = Prism.languages[lang]; - languages[env.language] = {initialized: true}; + languages[env.language] = { initialized: true }; } }); } @@ -703,7 +700,7 @@ // Initialize the previewers only when needed Prism.hooks.add('after-highlight', function (env) { - if(Previewer.byLanguages['*'] || Previewer.byLanguages[env.language]) { + if (Previewer.byLanguages['*'] || Previewer.byLanguages[env.language]) { Previewer.initEvents(env.element, env.language); } }); @@ -712,4 +709,4 @@ previewers[previewer].create(); } -}()); \ No newline at end of file +}()); diff --git a/plugins/previewers/prism-previewers.min.css b/plugins/previewers/prism-previewers.min.css new file mode 100644 index 0000000000..8ba1b5b301 --- /dev/null +++ b/plugins/previewers/prism-previewers.min.css @@ -0,0 +1 @@ +.prism-previewer,.prism-previewer:after,.prism-previewer:before{position:absolute;pointer-events:none}.prism-previewer,.prism-previewer:after{left:50%}.prism-previewer{margin-top:-48px;width:32px;height:32px;margin-left:-16px;z-index:10;opacity:0;-webkit-transition:opacity .25s;-o-transition:opacity .25s;transition:opacity .25s}.prism-previewer.flipped{margin-top:0;margin-bottom:-48px}.prism-previewer:after,.prism-previewer:before{content:'';position:absolute;pointer-events:none}.prism-previewer:before{top:-5px;right:-5px;left:-5px;bottom:-5px;border-radius:10px;border:5px solid #fff;box-shadow:0 0 3px rgba(0,0,0,.5) inset,0 0 10px rgba(0,0,0,.75)}.prism-previewer:after{top:100%;width:0;height:0;margin:5px 0 0 -7px;border:7px solid transparent;border-color:rgba(255,0,0,0);border-top-color:#fff}.prism-previewer.flipped:after{top:auto;bottom:100%;margin-top:0;margin-bottom:5px;border-top-color:rgba(255,0,0,0);border-bottom-color:#fff}.prism-previewer.active{opacity:1}.prism-previewer-angle:before{border-radius:50%;background:#fff}.prism-previewer-angle:after{margin-top:4px}.prism-previewer-angle svg{width:32px;height:32px;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.prism-previewer-angle[data-negative] svg{-webkit-transform:scaleX(-1) rotate(-90deg);-moz-transform:scaleX(-1) rotate(-90deg);-ms-transform:scaleX(-1) rotate(-90deg);-o-transform:scaleX(-1) rotate(-90deg);transform:scaleX(-1) rotate(-90deg)}.prism-previewer-angle circle{fill:transparent;stroke:#2d3438;stroke-opacity:.9;stroke-width:32;stroke-dasharray:0,500}.prism-previewer-gradient{background-image:linear-gradient(45deg,#bbb 25%,transparent 25%,transparent 75%,#bbb 75%,#bbb),linear-gradient(45deg,#bbb 25%,#eee 25%,#eee 75%,#bbb 75%,#bbb);background-size:10px 10px;background-position:0 0,5px 5px;width:64px;margin-left:-32px}.prism-previewer-gradient:before{content:none}.prism-previewer-gradient div{position:absolute;top:-5px;left:-5px;right:-5px;bottom:-5px;border-radius:10px;border:5px solid #fff;box-shadow:0 0 3px rgba(0,0,0,.5) inset,0 0 10px rgba(0,0,0,.75)}.prism-previewer-color{background-image:linear-gradient(45deg,#bbb 25%,transparent 25%,transparent 75%,#bbb 75%,#bbb),linear-gradient(45deg,#bbb 25%,#eee 25%,#eee 75%,#bbb 75%,#bbb);background-size:10px 10px;background-position:0 0,5px 5px}.prism-previewer-color:before{background-color:inherit;background-clip:padding-box}.prism-previewer-easing{margin-top:-76px;margin-left:-30px;width:60px;height:60px;background:#333}.prism-previewer-easing.flipped{margin-bottom:-116px}.prism-previewer-easing svg{width:60px;height:60px}.prism-previewer-easing circle{fill:#2d3438;stroke:#fff}.prism-previewer-easing path{fill:none;stroke:#fff;stroke-linecap:round;stroke-width:4}.prism-previewer-easing line{stroke:#fff;stroke-opacity:.5;stroke-width:2}@-webkit-keyframes prism-previewer-time{0%{stroke-dasharray:0,500;stroke-dashoffset:0}50%{stroke-dasharray:100,500;stroke-dashoffset:0}100%{stroke-dasharray:0,500;stroke-dashoffset:-100}}@-o-keyframes prism-previewer-time{0%{stroke-dasharray:0,500;stroke-dashoffset:0}50%{stroke-dasharray:100,500;stroke-dashoffset:0}100%{stroke-dasharray:0,500;stroke-dashoffset:-100}}@-moz-keyframes prism-previewer-time{0%{stroke-dasharray:0,500;stroke-dashoffset:0}50%{stroke-dasharray:100,500;stroke-dashoffset:0}100%{stroke-dasharray:0,500;stroke-dashoffset:-100}}@keyframes prism-previewer-time{0%{stroke-dasharray:0,500;stroke-dashoffset:0}50%{stroke-dasharray:100,500;stroke-dashoffset:0}100%{stroke-dasharray:0,500;stroke-dashoffset:-100}}.prism-previewer-time:before{border-radius:50%;background:#fff}.prism-previewer-time:after{margin-top:4px}.prism-previewer-time svg{width:32px;height:32px;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.prism-previewer-time circle{fill:transparent;stroke:#2d3438;stroke-opacity:.9;stroke-width:32;stroke-dasharray:0,500;stroke-dashoffset:0;-webkit-animation:prism-previewer-time linear infinite 3s;-moz-animation:prism-previewer-time linear infinite 3s;-o-animation:prism-previewer-time linear infinite 3s;animation:prism-previewer-time linear infinite 3s} \ No newline at end of file diff --git a/plugins/previewers/prism-previewers.min.js b/plugins/previewers/prism-previewers.min.js index 2595fbdcff..2b28cd2570 100644 --- a/plugins/previewers/prism-previewers.min.js +++ b/plugins/previewers/prism-previewers.min.js @@ -1 +1 @@ -!function(){if(("undefined"==typeof self||self.Prism)&&self.document&&Function.prototype.bind){var e={gradient:{create:function(){var e={},s=function(e,s,i){var t="180deg";return/^(?:-?\d*\.?\d+(?:deg|rad)|to\b|top|right|bottom|left)/.test(i[0])&&(t=i.shift(),t.indexOf("to ")<0&&(t.indexOf("top")>=0?t=t.indexOf("left")>=0?"to bottom right":t.indexOf("right")>=0?"to bottom left":"to bottom":t.indexOf("bottom")>=0?t=t.indexOf("left")>=0?"to top right":t.indexOf("right")>=0?"to top left":"to top":t.indexOf("left")>=0?t="to right":t.indexOf("right")>=0?t="to left":e&&(t.indexOf("deg")>=0?t=90-parseFloat(t)+"deg":t.indexOf("rad")>=0&&(t=Math.PI/2-parseFloat(t)+"rad")))),s+"("+t+","+i.join(",")+")"},i=function(e,s,i){if(i[0].indexOf("at")<0){var t="center",a="ellipse",r="farthest-corner";if(/\bcenter|top|right|bottom|left\b|^\d+/.test(i[0])&&(t=i.shift().replace(/\s*-?\d+(?:rad|deg)\s*/,"")),/\bcircle|ellipse|closest|farthest|contain|cover\b/.test(i[0])){var n=i.shift().split(/\s+/);!n[0]||"circle"!==n[0]&&"ellipse"!==n[0]||(a=n.shift()),n[0]&&(r=n.shift()),"cover"===r?r="farthest-corner":"contain"===r&&(r="clothest-side")}return s+"("+a+" "+r+" at "+t+","+i.join(",")+")"}return s+"("+i.join(",")+")"},t=function(t){if(e[t])return e[t];var a=t.match(/^(\b|\B-[a-z]{1,10}-)((?:repeating-)?(?:linear|radial)-gradient)/),r=a&&a[1],n=a&&a[2],l=t.replace(/^(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\(|\)$/g,"").split(/\s*,\s*/);return e[t]=n.indexOf("linear")>=0?s(r,n,l):n.indexOf("radial")>=0?i(r,n,l):n+"("+l.join(",")+")"};return function(){new Prism.plugins.Previewer("gradient",function(e){return this.firstChild.style.backgroundImage="",this.firstChild.style.backgroundImage=t(e),!!this.firstChild.style.backgroundImage},"*",function(){this._elt.innerHTML="
        "})}}(),tokens:{gradient:{pattern:/(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\((?:(?:rgb|hsl)a?\(.+?\)|[^\)])+\)/gi,inside:{"function":/[\w-]+(?=\()/,punctuation:/[(),]/}}},languages:{css:!0,less:!0,sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},angle:{create:function(){new Prism.plugins.Previewer("angle",function(e){var s,i,t=parseFloat(e),a=e.match(/[a-z]+$/i);if(!t||!a)return!1;switch(a=a[0]){case"deg":s=360;break;case"grad":s=400;break;case"rad":s=2*Math.PI;break;case"turn":s=1}return i=100*t/s,i%=100,this[(0>t?"set":"remove")+"Attribute"]("data-negative",""),this.querySelector("circle").style.strokeDasharray=Math.abs(i)+",500",!0},"*",function(){this._elt.innerHTML=''})},tokens:{angle:/(?:\b|\B-|(?=\B\.))\d*\.?\d+(?:deg|g?rad|turn)\b/i},languages:{css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},color:{create:function(){new Prism.plugins.Previewer("color",function(e){return this.style.backgroundColor="",this.style.backgroundColor=e,!!this.style.backgroundColor})},tokens:{color:{pattern:/\B#(?:[0-9a-f]{3}){1,2}\b|\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B|\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGray|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGray|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGray|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gray|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGray|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGray|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGray|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,inside:{"function":/[\w-]+(?=\()/,punctuation:/[(),]/}}},languages:{css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},easing:{create:function(){new Prism.plugins.Previewer("easing",function(e){e={linear:"0,0,1,1",ease:".25,.1,.25,1","ease-in":".42,0,1,1","ease-out":"0,0,.58,1","ease-in-out":".42,0,.58,1"}[e]||e;var s=e.match(/-?\d*\.?\d+/g);if(4===s.length){s=s.map(function(e,s){return 100*(s%2?1-e:e)}),this.querySelector("path").setAttribute("d","M0,100 C"+s[0]+","+s[1]+", "+s[2]+","+s[3]+", 100,0");var i=this.querySelectorAll("line");return i[0].setAttribute("x2",s[0]),i[0].setAttribute("y2",s[1]),i[1].setAttribute("x2",s[2]),i[1].setAttribute("y2",s[3]),!0}return!1},"*",function(){this._elt.innerHTML=''})},tokens:{easing:{pattern:/\bcubic-bezier\((?:-?\d*\.?\d+,\s*){3}-?\d*\.?\d+\)\B|\b(?:linear|ease(?:-in)?(?:-out)?)(?=\s|[;}]|$)/i,inside:{"function":/[\w-]+(?=\()/,punctuation:/[(),]/}}},languages:{css:!0,less:!0,sass:[{lang:"sass",inside:"inside",before:"punctuation",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},time:{create:function(){new Prism.plugins.Previewer("time",function(e){var s=parseFloat(e),i=e.match(/[a-z]+$/i);return s&&i?(i=i[0],this.querySelector("circle").style.animationDuration=2*s+i,!0):!1},"*",function(){this._elt.innerHTML=''})},tokens:{time:/(?:\b|\B-|(?=\B\.))\d*\.?\d+m?s\b/i},languages:{css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}}},s=function(e){var s=0,i=0,t=e;if(t.parentNode){do s+=t.offsetLeft,i+=t.offsetTop;while((t=t.offsetParent)&&t.nodeType<9);t=e;do s-=t.scrollLeft,i-=t.scrollTop;while((t=t.parentNode)&&!/body/i.test(t.nodeName))}return{top:i,right:innerWidth-s-e.offsetWidth,bottom:innerHeight-i-e.offsetHeight,left:s}},i=/(?:^|\s)token(?=$|\s)/,t=/(?:^|\s)active(?=$|\s)/g,a=/(?:^|\s)flipped(?=$|\s)/g,r=function(e,s,i,t){this._elt=null,this._type=e,this._clsRegexp=RegExp("(?:^|\\s)"+e+"(?=$|\\s)"),this._token=null,this.updater=s,this._mouseout=this.mouseout.bind(this),this.initializer=t;var a=this;i||(i=["*"]),"Array"!==Prism.util.type(i)&&(i=[i]),i.forEach(function(e){"string"!=typeof e&&(e=e.lang),r.byLanguages[e]||(r.byLanguages[e]=[]),r.byLanguages[e].indexOf(a)<0&&r.byLanguages[e].push(a)}),r.byType[e]=this};r.prototype.init=function(){this._elt||(this._elt=document.createElement("div"),this._elt.className="prism-previewer prism-previewer-"+this._type,document.body.appendChild(this._elt),this.initializer&&this.initializer())},r.prototype.isDisabled=function(e){do if(e.hasAttribute&&e.hasAttribute("data-previewers")){var s=e.getAttribute("data-previewers");return-1===(s||"").split(/\s+/).indexOf(this._type)}while(e=e.parentNode);return!1},r.prototype.check=function(e){if(!i.test(e.className)||!this.isDisabled(e)){do if(i.test(e.className)&&this._clsRegexp.test(e.className))break;while(e=e.parentNode);e&&e!==this._token&&(this._token=e,this.show())}},r.prototype.mouseout=function(){this._token.removeEventListener("mouseout",this._mouseout,!1),this._token=null,this.hide()},r.prototype.show=function(){if(this._elt||this.init(),this._token)if(this.updater.call(this._elt,this._token.textContent)){this._token.addEventListener("mouseout",this._mouseout,!1);var e=s(this._token);this._elt.className+=" active",e.top-this._elt.offsetHeight>0?(this._elt.className=this._elt.className.replace(a,""),this._elt.style.top=e.top+"px",this._elt.style.bottom=""):(this._elt.className+=" flipped",this._elt.style.bottom=e.bottom+"px",this._elt.style.top=""),this._elt.style.left=e.left+Math.min(200,this._token.offsetWidth/2)+"px"}else this.hide()},r.prototype.hide=function(){this._elt.className=this._elt.className.replace(t,"")},r.byLanguages={},r.byType={},r.initEvents=function(e,s){var i=[];r.byLanguages[s]&&(i=i.concat(r.byLanguages[s])),r.byLanguages["*"]&&(i=i.concat(r.byLanguages["*"])),e.addEventListener("mouseover",function(e){var s=e.target;i.forEach(function(e){e.check(s)})},!1)},Prism.plugins.Previewer=r,Prism.hooks.add("before-highlight",function(s){for(var i in e){var t=e[i].languages;if(s.language&&t[s.language]&&!t[s.language].initialized){var a=t[s.language];"Array"!==Prism.util.type(a)&&(a=[a]),a.forEach(function(a){var r,n,l,o;a===!0?(r="important",n=s.language,a=s.language):(r=a.before||"important",n=a.inside||a.lang,l=a.root||Prism.languages,o=a.skip,a=s.language),!o&&Prism.languages[a]&&(Prism.languages.insertBefore(n,r,e[i].tokens,l),s.grammar=Prism.languages[a],t[s.language]={initialized:!0})})}}}),Prism.hooks.add("after-highlight",function(e){(r.byLanguages["*"]||r.byLanguages[e.language])&&r.initEvents(e.element,e.language)});for(var n in e)e[n].create()}}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&Function.prototype.bind){var n,s,l={gradient:{create:(n={},s=function(e){if(n[e])return n[e];var s=e.match(/^(\b|\B-[a-z]{1,10}-)((?:repeating-)?(?:linear|radial)-gradient)/),t=s&&s[1],i=s&&s[2],a=e.replace(/^(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\(|\)$/g,"").split(/\s*,\s*/);return 0<=i.indexOf("linear")?n[e]=function(e,s,t){var i="180deg";return/^(?:-?(?:\d+(?:\.\d+)?|\.\d+)(?:deg|rad)|to\b|top|right|bottom|left)/.test(t[0])&&(i=t.shift()).indexOf("to ")<0&&(0<=i.indexOf("top")?i=0<=i.indexOf("left")?"to bottom right":0<=i.indexOf("right")?"to bottom left":"to bottom":0<=i.indexOf("bottom")?i=0<=i.indexOf("left")?"to top right":0<=i.indexOf("right")?"to top left":"to top":0<=i.indexOf("left")?i="to right":0<=i.indexOf("right")?i="to left":e&&(0<=i.indexOf("deg")?i=90-parseFloat(i)+"deg":0<=i.indexOf("rad")&&(i=Math.PI/2-parseFloat(i)+"rad"))),s+"("+i+","+t.join(",")+")"}(t,i,a):0<=i.indexOf("radial")?n[e]=function(e,s,t){if(t[0].indexOf("at")<0){var i="center",a="ellipse",n="farthest-corner";if(/\b(?:bottom|center|left|right|top)\b|^\d+/.test(t[0])&&(i=t.shift().replace(/\s*-?\d+(?:deg|rad)\s*/,"")),/\b(?:circle|closest|contain|cover|ellipse|farthest)\b/.test(t[0])){var r=t.shift().split(/\s+/);!r[0]||"circle"!==r[0]&&"ellipse"!==r[0]||(a=r.shift()),r[0]&&(n=r.shift()),"cover"===n?n="farthest-corner":"contain"===n&&(n="clothest-side")}return s+"("+a+" "+n+" at "+i+","+t.join(",")+")"}return s+"("+t.join(",")+")"}(0,i,a):n[e]=i+"("+a.join(",")+")"},function(){new Prism.plugins.Previewer("gradient",function(e){return this.firstChild.style.backgroundImage="",this.firstChild.style.backgroundImage=s(e),!!this.firstChild.style.backgroundImage},"*",function(){this._elt.innerHTML="
        "})}),tokens:{gradient:{pattern:/(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\((?:(?:hsl|rgb)a?\(.+?\)|[^\)])+\)/gi,inside:{function:/[\w-]+(?=\()/,punctuation:/[(),]/}}},languages:{css:!0,less:!0,sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},angle:{create:function(){new Prism.plugins.Previewer("angle",function(e){var s,t,i=parseFloat(e),a=e.match(/[a-z]+$/i);if(!i||!a)return!1;switch(a=a[0]){case"deg":s=360;break;case"grad":s=400;break;case"rad":s=2*Math.PI;break;case"turn":s=1}return t=100*i/s,t%=100,this[(i<0?"set":"remove")+"Attribute"]("data-negative",""),this.querySelector("circle").style.strokeDasharray=Math.abs(t)+",500",!0},"*",function(){this._elt.innerHTML=''})},tokens:{angle:/(?:\b|\B-|(?=\B\.))(?:\d+(?:\.\d+)?|\.\d+)(?:deg|g?rad|turn)\b/i},languages:{css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"func",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},color:{create:function(){new Prism.plugins.Previewer("color",function(e){return this.style.backgroundColor="",this.style.backgroundColor=e,!!this.style.backgroundColor})},tokens:{color:[Prism.languages.css.hexcode].concat(Prism.languages.css.color)},languages:{css:!1,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",before:"punctuation",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!1,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},easing:{create:function(){new Prism.plugins.Previewer("easing",function(e){var s=(e={linear:"0,0,1,1",ease:".25,.1,.25,1","ease-in":".42,0,1,1","ease-out":"0,0,.58,1","ease-in-out":".42,0,.58,1"}[e]||e).match(/-?(?:\d+(?:\.\d+)?|\.\d+)/g);if(4!==s.length)return!1;s=s.map(function(e,s){return 100*(s%2?1-e:e)}),this.querySelector("path").setAttribute("d","M0,100 C"+s[0]+","+s[1]+", "+s[2]+","+s[3]+", 100,0");var t=this.querySelectorAll("line");return t[0].setAttribute("x2",s[0]),t[0].setAttribute("y2",s[1]),t[1].setAttribute("x2",s[2]),t[1].setAttribute("y2",s[3]),!0},"*",function(){this._elt.innerHTML=''})},tokens:{easing:{pattern:/\bcubic-bezier\((?:-?(?:\d+(?:\.\d+)?|\.\d+),\s*){3}-?(?:\d+(?:\.\d+)?|\.\d+)\)\B|\b(?:ease(?:-in)?(?:-out)?|linear)(?=\s|[;}]|$)/i,inside:{function:/[\w-]+(?=\()/,punctuation:/[(),]/}}},languages:{css:!0,less:!0,sass:[{lang:"sass",inside:"inside",before:"punctuation",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]},{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}},time:{create:function(){new Prism.plugins.Previewer("time",function(e){var s=parseFloat(e),t=e.match(/[a-z]+$/i);return!(!s||!t)&&(t=t[0],this.querySelector("circle").style.animationDuration=2*s+t,!0)},"*",function(){this._elt.innerHTML=''})},tokens:{time:/(?:\b|\B-|(?=\B\.))(?:\d+(?:\.\d+)?|\.\d+)m?s\b/i},languages:{css:!0,less:!0,markup:{lang:"markup",before:"punctuation",inside:"inside",root:Prism.languages.markup&&Prism.languages.markup.tag.inside["attr-value"]},sass:[{lang:"sass",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["property-line"]},{lang:"sass",before:"operator",inside:"inside",root:Prism.languages.sass&&Prism.languages.sass["variable-line"]}],scss:!0,stylus:[{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["property-declaration"].inside},{lang:"stylus",before:"hexcode",inside:"rest",root:Prism.languages.stylus&&Prism.languages.stylus["variable-declaration"].inside}]}}},t="token",i="active",a="flipped",r=function(e,s,t,i){this._elt=null,this._type=e,this._token=null,this.updater=s,this._mouseout=this.mouseout.bind(this),this.initializer=i;var a=this;t||(t=["*"]),Array.isArray(t)||(t=[t]),t.forEach(function(e){"string"!=typeof e&&(e=e.lang),r.byLanguages[e]||(r.byLanguages[e]=[]),r.byLanguages[e].indexOf(a)<0&&r.byLanguages[e].push(a)}),r.byType[e]=this};for(var e in r.prototype.init=function(){this._elt||(this._elt=document.createElement("div"),this._elt.className="prism-previewer prism-previewer-"+this._type,document.body.appendChild(this._elt),this.initializer&&this.initializer())},r.prototype.isDisabled=function(e){do{if(e.hasAttribute&&e.hasAttribute("data-previewers"))return-1===(e.getAttribute("data-previewers")||"").split(/\s+/).indexOf(this._type)}while(e=e.parentNode);return!1},r.prototype.check=function(e){if(!e.classList.contains(t)||!this.isDisabled(e)){do{if(e.classList&&e.classList.contains(t)&&e.classList.contains(this._type))break}while(e=e.parentNode);e&&e!==this._token&&(this._token=e,this.show())}},r.prototype.mouseout=function(){this._token.removeEventListener("mouseout",this._mouseout,!1),this._token=null,this.hide()},r.prototype.show=function(){if(this._elt||this.init(),this._token)if(this.updater.call(this._elt,this._token.textContent)){this._token.addEventListener("mouseout",this._mouseout,!1);var e=function(e){var s=e.getBoundingClientRect(),t=s.left,i=s.top,a=document.documentElement.getBoundingClientRect();return t-=a.left,{top:i-=a.top,right:innerWidth-t-s.width,bottom:innerHeight-i-s.height,left:t,width:s.width,height:s.height}}(this._token);this._elt.classList.add(i),0 - + Remove initial line feed ▲ Prism plugins - + - + - + -
        -
        - -

        Remove initial line feed

        -

        Removes the initial line feed in code blocks.

        -
        +

        How to use (DEPRECATED)

        @@ -46,14 +41,14 @@

        With the class added

        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.js b/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.js index f62a8bfef0..ffad4b9393 100644 --- a/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.js +++ b/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.js @@ -1,21 +1,21 @@ -(function() { +(function () { -if (typeof self === 'undefined' || !self.Prism || !self.document) { - return; -} + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } -Prism.hooks.add('before-sanity-check', function (env) { - if (env.code) { - var pre = env.element.parentNode; - var clsReg = /\s*\bkeep-initial-line-feed\b\s*/; - if ( - pre && pre.nodeName.toLowerCase() === 'pre' && - // Apply only if nor the
         or the  have the class
        -			(!clsReg.test(pre.className) && !clsReg.test(env.element.className))
        -		) {
        -			env.code = env.code.replace(/^(?:\r?\n|\r)/, '');
        +	Prism.hooks.add('before-sanity-check', function (env) {
        +		if (env.code) {
        +			var pre = env.element.parentNode;
        +			var clsReg = /(?:^|\s)keep-initial-line-feed(?:\s|$)/;
        +			if (
        +				pre && pre.nodeName.toLowerCase() === 'pre' &&
        +				// Apply only if nor the 
         or the  have the class
        +				(!clsReg.test(pre.className) && !clsReg.test(env.element.className))
        +			) {
        +				env.code = env.code.replace(/^(?:\r?\n|\r)/, '');
        +			}
         		}
        -	}
        -});
        +	});
         
        -}());
        \ No newline at end of file
        +}());
        diff --git a/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.min.js b/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.min.js
        index e0016a496b..f507edf165 100644
        --- a/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.min.js
        +++ b/plugins/remove-initial-line-feed/prism-remove-initial-line-feed.min.js
        @@ -1 +1 @@
        -!function(){"undefined"!=typeof self&&self.Prism&&self.document&&Prism.hooks.add("before-sanity-check",function(e){if(e.code){var s=e.element.parentNode,n=/\s*\bkeep-initial-line-feed\b\s*/;!s||"pre"!==s.nodeName.toLowerCase()||n.test(s.className)||n.test(e.element.className)||(e.code=e.code.replace(/^(?:\r?\n|\r)/,""))}})}();
        \ No newline at end of file
        +"undefined"!=typeof Prism&&"undefined"!=typeof document&&Prism.hooks.add("before-sanity-check",function(e){if(e.code){var n=e.element.parentNode,o=/(?:^|\s)keep-initial-line-feed(?:\s|$)/;!n||"pre"!==n.nodeName.toLowerCase()||o.test(n.className)||o.test(e.element.className)||(e.code=e.code.replace(/^(?:\r?\n|\r)/,""))}});
        \ No newline at end of file
        diff --git a/plugins/show-invisibles/index.html b/plugins/show-invisibles/index.html
        index 98c8719f88..664a1b94e6 100644
        --- a/plugins/show-invisibles/index.html
        +++ b/plugins/show-invisibles/index.html
        @@ -3,43 +3,38 @@
         
         
         
        -
        +
         Show Invisibles ▲ Prism plugins
         
        -
        +
         
         
        -
        +
         
         
        -
        +
         
         
         
        -
        -
        - -

        Show Invisibles

        -

        Show hidden characters such as tabs and line breaks.

        -
        +

        Examples

        - +
        
        -	
        +
         	
        
        -	
        +
         	
        
         
        -
        +
        - + - + diff --git a/plugins/show-invisibles/prism-show-invisibles.css b/plugins/show-invisibles/prism-show-invisibles.css index 9af783d502..6b39a32915 100644 --- a/plugins/show-invisibles/prism-show-invisibles.css +++ b/plugins/show-invisibles/prism-show-invisibles.css @@ -9,25 +9,26 @@ .token.cr:before, .token.lf:before, .token.space:before { - color: hsl(24, 20%, 85%); + color: #808080; + opacity: 0.6; position: absolute; } .token.tab:not(:empty):before { - content: '\21E5'; + content: '\21E5'; } .token.cr:before { - content: '\240D'; + content: '\240D'; } .token.crlf:before { - content: '\240D\240A'; + content: '\240D\240A'; } .token.lf:before { - content: '\240A'; + content: '\240A'; } .token.space:before { content: '\00B7'; -} \ No newline at end of file +} diff --git a/plugins/show-invisibles/prism-show-invisibles.js b/plugins/show-invisibles/prism-show-invisibles.js index f3d120a9e8..e1f97f9581 100644 --- a/plugins/show-invisibles/prism-show-invisibles.js +++ b/plugins/show-invisibles/prism-show-invisibles.js @@ -1,21 +1,83 @@ -(function(){ - -if ( - typeof self !== 'undefined' && !self.Prism || - typeof global !== 'undefined' && !global.Prism -) { - return; -} - -Prism.hooks.add('before-highlight', function(env) { - var tokens = env.grammar; - - if (!tokens) return; - - tokens.tab = /\t/g; - tokens.crlf = /\r\n/g; - tokens.lf = /\n/g; - tokens.cr = /\r/g; - tokens.space = / /g; -}); -})(); +(function () { + + if (typeof Prism === 'undefined') { + return; + } + + + var invisibles = { + 'tab': /\t/, + 'crlf': /\r\n/, + 'lf': /\n/, + 'cr': /\r/, + 'space': / / + }; + + + /** + * Handles the recursive calling of `addInvisibles` for one token. + * + * @param {Object|Array} tokens The grammar or array which contains the token. + * @param {string|number} name The name or index of the token in `tokens`. + */ + function handleToken(tokens, name) { + var value = tokens[name]; + + var type = Prism.util.type(value); + switch (type) { + case 'RegExp': + var inside = {}; + tokens[name] = { + pattern: value, + inside: inside + }; + addInvisibles(inside); + break; + + case 'Array': + for (var i = 0, l = value.length; i < l; i++) { + handleToken(value, i); + } + break; + + default: // 'Object' + // eslint-disable-next-line no-redeclare + var inside = value.inside || (value.inside = {}); + addInvisibles(inside); + break; + } + } + + /** + * Recursively adds patterns to match invisible characters to the given grammar (if not added already). + * + * @param {Object} grammar + */ + function addInvisibles(grammar) { + if (!grammar || grammar['tab']) { + return; + } + + // assign invisibles here to "mark" the grammar in case of self references + for (var name in invisibles) { + if (invisibles.hasOwnProperty(name)) { + grammar[name] = invisibles[name]; + } + } + + // eslint-disable-next-line no-redeclare + for (var name in grammar) { + if (grammar.hasOwnProperty(name) && !invisibles[name]) { + if (name === 'rest') { + addInvisibles(grammar['rest']); + } else { + handleToken(grammar, name); + } + } + } + } + + Prism.hooks.add('before-highlight', function (env) { + addInvisibles(env.grammar); + }); +}()); diff --git a/plugins/show-invisibles/prism-show-invisibles.min.css b/plugins/show-invisibles/prism-show-invisibles.min.css new file mode 100644 index 0000000000..0e2b048b90 --- /dev/null +++ b/plugins/show-invisibles/prism-show-invisibles.min.css @@ -0,0 +1 @@ +.token.cr,.token.lf,.token.space,.token.tab:not(:empty){position:relative}.token.cr:before,.token.lf:before,.token.space:before,.token.tab:not(:empty):before{color:grey;opacity:.6;position:absolute}.token.tab:not(:empty):before{content:'\21E5'}.token.cr:before{content:'\240D'}.token.crlf:before{content:'\240D\240A'}.token.lf:before{content:'\240A'}.token.space:before{content:'\00B7'} \ No newline at end of file diff --git a/plugins/show-invisibles/prism-show-invisibles.min.js b/plugins/show-invisibles/prism-show-invisibles.min.js index 9df7258c89..56231c4aa7 100644 --- a/plugins/show-invisibles/prism-show-invisibles.min.js +++ b/plugins/show-invisibles/prism-show-invisibles.min.js @@ -1 +1 @@ -!function(){"undefined"!=typeof self&&!self.Prism||"undefined"!=typeof global&&!global.Prism||Prism.hooks.add("before-highlight",function(e){var f=e.grammar;f&&(f.tab=/\t/g,f.crlf=/\r\n/g,f.lf=/\n/g,f.cr=/\r/g,f.space=/ /g)})}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism){var i={tab:/\t/,crlf:/\r\n/,lf:/\n/,cr:/\r/,space:/ /};Prism.hooks.add("before-highlight",function(r){s(r.grammar)})}function f(r,e){var i=r[e];switch(Prism.util.type(i)){case"RegExp":var a={};r[e]={pattern:i,inside:a},s(a);break;case"Array":for(var n=0,t=i.length;n - + Show Language ▲ Prism plugins - + - + - + -
        -
        - -

        Show Language

        -

        Display the highlighted language in code blocks (inline code does not show the label).

        -
        +

        Examples

        @@ -37,18 +32,21 @@

        HTML (Markup)

        SVG

        The data-language attribute can be used to display a specific label whether it has been defined as a language or not.

        -
        
        +	
        
        +
        +	

        Plain text

        +
        Just some text (aka. not code).
        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/show-language/prism-show-language.js b/plugins/show-language/prism-show-language.js index 41647a8c72..f5eac704dd 100644 --- a/plugins/show-language/prism-show-language.js +++ b/plugins/show-language/prism-show-language.js @@ -1,28 +1,299 @@ -(function(){ +(function () { -if (typeof self === 'undefined' || !self.Prism || !self.document) { - return; -} - -if (!Prism.plugins.toolbar) { - console.warn('Show Languages plugin loaded before Toolbar plugin.'); + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } - return; -} + if (!Prism.plugins.toolbar) { + console.warn('Show Languages plugin loaded before Toolbar plugin.'); -// The languages map is built automatically with gulp -var Languages = /*languages_placeholder[*/{"html":"HTML","xml":"XML","svg":"SVG","mathml":"MathML","css":"CSS","clike":"C-like","javascript":"JavaScript","abap":"ABAP","actionscript":"ActionScript","apacheconf":"Apache Configuration","apl":"APL","applescript":"AppleScript","arff":"ARFF","asciidoc":"AsciiDoc","asm6502":"6502 Assembly","aspnet":"ASP.NET (C#)","autohotkey":"AutoHotkey","autoit":"AutoIt","basic":"BASIC","csharp":"C#","cpp":"C++","coffeescript":"CoffeeScript","csp":"Content-Security-Policy","css-extras":"CSS Extras","django":"Django/Jinja2","erb":"ERB","fsharp":"F#","gedcom":"GEDCOM","glsl":"GLSL","graphql":"GraphQL","http":"HTTP","hpkp":"HTTP Public-Key-Pins","hsts":"HTTP Strict-Transport-Security","ichigojam":"IchigoJam","inform7":"Inform 7","json":"JSON","latex":"LaTeX","livescript":"LiveScript","lolcode":"LOLCODE","markup-templating":"Markup templating","matlab":"MATLAB","mel":"MEL","n4js":"N4JS","nasm":"NASM","nginx":"nginx","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","opencl":"OpenCL","parigp":"PARI/GP","php":"PHP","php-extras":"PHP Extras","plsql":"PL/SQL","powershell":"PowerShell","properties":".properties","protobuf":"Protocol Buffers","q":"Q (kdb+ database)","jsx":"React JSX","tsx":"React TSX","renpy":"Ren'py","rest":"reST (reStructuredText)","sas":"SAS","sass":"Sass (Sass)","scss":"Sass (Scss)","sql":"SQL","soy":"Soy (Closure Template)","typescript":"TypeScript","vbnet":"VB.Net","vhdl":"VHDL","vim":"vim","visual-basic":"Visual Basic","wasm":"WebAssembly","wiki":"Wiki markup","xojo":"Xojo (REALbasic)","yaml":"YAML"}/*]*/; -Prism.plugins.toolbar.registerButton('show-language', function(env) { - var pre = env.element.parentNode; - if (!pre || !/pre/i.test(pre.nodeName)) { return; } - var language = pre.getAttribute('data-language') || Languages[env.language] || (env.language.substring(0, 1).toUpperCase() + env.language.substring(1)); - var element = document.createElement('span'); - element.textContent = language; + /* eslint-disable */ + + // The languages map is built automatically with gulp + var Languages = /*languages_placeholder[*/{ + "none": "Plain text", + "plain": "Plain text", + "plaintext": "Plain text", + "text": "Plain text", + "txt": "Plain text", + "html": "HTML", + "xml": "XML", + "svg": "SVG", + "mathml": "MathML", + "ssml": "SSML", + "rss": "RSS", + "css": "CSS", + "clike": "C-like", + "js": "JavaScript", + "abap": "ABAP", + "abnf": "ABNF", + "al": "AL", + "antlr4": "ANTLR4", + "g4": "ANTLR4", + "apacheconf": "Apache Configuration", + "apl": "APL", + "aql": "AQL", + "ino": "Arduino", + "arff": "ARFF", + "asciidoc": "AsciiDoc", + "adoc": "AsciiDoc", + "aspnet": "ASP.NET (C#)", + "asm6502": "6502 Assembly", + "asmatmel": "Atmel AVR Assembly", + "autohotkey": "AutoHotkey", + "autoit": "AutoIt", + "avisynth": "AviSynth", + "avs": "AviSynth", + "avro-idl": "Avro IDL", + "avdl": "Avro IDL", + "basic": "BASIC", + "bbcode": "BBcode", + "bnf": "BNF", + "rbnf": "RBNF", + "bsl": "BSL (1C:Enterprise)", + "oscript": "OneScript", + "csharp": "C#", + "cs": "C#", + "dotnet": "C#", + "cpp": "C++", + "cfscript": "CFScript", + "cfc": "CFScript", + "cil": "CIL", + "cmake": "CMake", + "cobol": "COBOL", + "coffee": "CoffeeScript", + "conc": "Concurnas", + "csp": "Content-Security-Policy", + "css-extras": "CSS Extras", + "csv": "CSV", + "dataweave": "DataWeave", + "dax": "DAX", + "django": "Django/Jinja2", + "jinja2": "Django/Jinja2", + "dns-zone-file": "DNS zone file", + "dns-zone": "DNS zone file", + "dockerfile": "Docker", + "dot": "DOT (Graphviz)", + "gv": "DOT (Graphviz)", + "ebnf": "EBNF", + "editorconfig": "EditorConfig", + "ejs": "EJS", + "etlua": "Embedded Lua templating", + "erb": "ERB", + "excel-formula": "Excel Formula", + "xlsx": "Excel Formula", + "xls": "Excel Formula", + "fsharp": "F#", + "firestore-security-rules": "Firestore security rules", + "ftl": "FreeMarker Template Language", + "gml": "GameMaker Language", + "gamemakerlanguage": "GameMaker Language", + "gap": "GAP (CAS)", + "gcode": "G-code", + "gdscript": "GDScript", + "gedcom": "GEDCOM", + "glsl": "GLSL", + "gn": "GN", + "gni": "GN", + "go-module": "Go module", + "go-mod": "Go module", + "graphql": "GraphQL", + "hbs": "Handlebars", + "hs": "Haskell", + "hcl": "HCL", + "hlsl": "HLSL", + "http": "HTTP", + "hpkp": "HTTP Public-Key-Pins", + "hsts": "HTTP Strict-Transport-Security", + "ichigojam": "IchigoJam", + "icu-message-format": "ICU Message Format", + "idr": "Idris", + "ignore": ".ignore", + "gitignore": ".gitignore", + "hgignore": ".hgignore", + "npmignore": ".npmignore", + "inform7": "Inform 7", + "javadoc": "JavaDoc", + "javadoclike": "JavaDoc-like", + "javastacktrace": "Java stack trace", + "jq": "JQ", + "jsdoc": "JSDoc", + "js-extras": "JS Extras", + "json": "JSON", + "webmanifest": "Web App Manifest", + "json5": "JSON5", + "jsonp": "JSONP", + "jsstacktrace": "JS stack trace", + "js-templates": "JS Templates", + "keepalived": "Keepalived Configure", + "kts": "Kotlin Script", + "kt": "Kotlin", + "kumir": "KuMir (КуМир)", + "kum": "KuMir (КуМир)", + "latex": "LaTeX", + "tex": "TeX", + "context": "ConTeXt", + "lilypond": "LilyPond", + "ly": "LilyPond", + "emacs": "Lisp", + "elisp": "Lisp", + "emacs-lisp": "Lisp", + "llvm": "LLVM IR", + "log": "Log file", + "lolcode": "LOLCODE", + "magma": "Magma (CAS)", + "md": "Markdown", + "markup-templating": "Markup templating", + "matlab": "MATLAB", + "maxscript": "MAXScript", + "mel": "MEL", + "mongodb": "MongoDB", + "moon": "MoonScript", + "n1ql": "N1QL", + "n4js": "N4JS", + "n4jsd": "N4JS", + "nand2tetris-hdl": "Nand To Tetris HDL", + "naniscript": "Naninovel Script", + "nani": "Naninovel Script", + "nasm": "NASM", + "neon": "NEON", + "nginx": "nginx", + "nsis": "NSIS", + "objectivec": "Objective-C", + "objc": "Objective-C", + "ocaml": "OCaml", + "opencl": "OpenCL", + "openqasm": "OpenQasm", + "qasm": "OpenQasm", + "parigp": "PARI/GP", + "objectpascal": "Object Pascal", + "psl": "PATROL Scripting Language", + "pcaxis": "PC-Axis", + "px": "PC-Axis", + "peoplecode": "PeopleCode", + "pcode": "PeopleCode", + "php": "PHP", + "phpdoc": "PHPDoc", + "php-extras": "PHP Extras", + "plsql": "PL/SQL", + "powerquery": "PowerQuery", + "pq": "PowerQuery", + "mscript": "PowerQuery", + "powershell": "PowerShell", + "promql": "PromQL", + "properties": ".properties", + "protobuf": "Protocol Buffers", + "purebasic": "PureBasic", + "pbfasm": "PureBasic", + "purs": "PureScript", + "py": "Python", + "qsharp": "Q#", + "qs": "Q#", + "q": "Q (kdb+ database)", + "qml": "QML", + "rkt": "Racket", + "cshtml": "Razor C#", + "razor": "Razor C#", + "jsx": "React JSX", + "tsx": "React TSX", + "renpy": "Ren'py", + "rpy": "Ren'py", + "rest": "reST (reStructuredText)", + "robotframework": "Robot Framework", + "robot": "Robot Framework", + "rb": "Ruby", + "sas": "SAS", + "sass": "Sass (Sass)", + "scss": "Sass (Scss)", + "shell-session": "Shell session", + "sh-session": "Shell session", + "shellsession": "Shell session", + "sml": "SML", + "smlnj": "SML/NJ", + "solidity": "Solidity (Ethereum)", + "sol": "Solidity (Ethereum)", + "solution-file": "Solution file", + "sln": "Solution file", + "soy": "Soy (Closure Template)", + "sparql": "SPARQL", + "rq": "SPARQL", + "splunk-spl": "Splunk SPL", + "sqf": "SQF: Status Quo Function (Arma 3)", + "sql": "SQL", + "iecst": "Structured Text (IEC 61131-3)", + "systemd": "Systemd configuration file", + "t4-templating": "T4 templating", + "t4-cs": "T4 Text Templates (C#)", + "t4": "T4 Text Templates (C#)", + "t4-vb": "T4 Text Templates (VB)", + "tap": "TAP", + "tt2": "Template Toolkit 2", + "toml": "TOML", + "trickle": "trickle", + "troy": "troy", + "trig": "TriG", + "ts": "TypeScript", + "tsconfig": "TSConfig", + "uscript": "UnrealScript", + "uc": "UnrealScript", + "uorazor": "UO Razor Script", + "uri": "URI", + "url": "URL", + "vbnet": "VB.Net", + "vhdl": "VHDL", + "vim": "vim", + "visual-basic": "Visual Basic", + "vba": "VBA", + "vb": "Visual Basic", + "wasm": "WebAssembly", + "web-idl": "Web IDL", + "webidl": "Web IDL", + "wiki": "Wiki markup", + "wolfram": "Wolfram language", + "nb": "Mathematica Notebook", + "wl": "Wolfram language", + "xeoracube": "XeoraCube", + "xml-doc": "XML doc (.net)", + "xojo": "Xojo (REALbasic)", + "xquery": "XQuery", + "yaml": "YAML", + "yml": "YAML", + "yang": "YANG" + }/*]*/; + + /* eslint-enable */ + + Prism.plugins.toolbar.registerButton('show-language', function (env) { + var pre = env.element.parentNode; + if (!pre || !/pre/i.test(pre.nodeName)) { + return; + } + + /** + * Tries to guess the name of a language given its id. + * + * @param {string} id The language id. + * @returns {string} + */ + function guessTitle(id) { + if (!id) { + return id; + } + return (id.substring(0, 1).toUpperCase() + id.substring(1)).replace(/s(?=cript)/, 'S'); + } + + var language = pre.getAttribute('data-language') || Languages[env.language] || guessTitle(env.language); + + if (!language) { + return; + } + var element = document.createElement('span'); + element.textContent = language; - return element; -}); + return element; + }); -})(); +}()); diff --git a/plugins/show-language/prism-show-language.min.js b/plugins/show-language/prism-show-language.min.js index a6f3ce737a..355479c388 100644 --- a/plugins/show-language/prism-show-language.min.js +++ b/plugins/show-language/prism-show-language.min.js @@ -1 +1 @@ -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){if(!Prism.plugins.toolbar)return console.warn("Show Languages plugin loaded before Toolbar plugin."),void 0;var e={html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",css:"CSS",clike:"C-like",javascript:"JavaScript",abap:"ABAP",actionscript:"ActionScript",apacheconf:"Apache Configuration",apl:"APL",applescript:"AppleScript",arff:"ARFF",asciidoc:"AsciiDoc",asm6502:"6502 Assembly",aspnet:"ASP.NET (C#)",autohotkey:"AutoHotkey",autoit:"AutoIt",basic:"BASIC",csharp:"C#",cpp:"C++",coffeescript:"CoffeeScript",csp:"Content-Security-Policy","css-extras":"CSS Extras",django:"Django/Jinja2",erb:"ERB",fsharp:"F#",gedcom:"GEDCOM",glsl:"GLSL",graphql:"GraphQL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam",inform7:"Inform 7",json:"JSON",latex:"LaTeX",livescript:"LiveScript",lolcode:"LOLCODE","markup-templating":"Markup templating",matlab:"MATLAB",mel:"MEL",n4js:"N4JS",nasm:"NASM",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",parigp:"PARI/GP",php:"PHP","php-extras":"PHP Extras",plsql:"PL/SQL",powershell:"PowerShell",properties:".properties",protobuf:"Protocol Buffers",q:"Q (kdb+ database)",jsx:"React JSX",tsx:"React TSX",renpy:"Ren'py",rest:"reST (reStructuredText)",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)",sql:"SQL",soy:"Soy (Closure Template)",typescript:"TypeScript",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim","visual-basic":"Visual Basic",wasm:"WebAssembly",wiki:"Wiki markup",xojo:"Xojo (REALbasic)",yaml:"YAML"};Prism.plugins.toolbar.registerButton("show-language",function(t){var a=t.element.parentNode;if(a&&/pre/i.test(a.nodeName)){var s=a.getAttribute("data-language")||e[t.language]||t.language.substring(0,1).toUpperCase()+t.language.substring(1),i=document.createElement("span");return i.textContent=s,i}})}}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document)if(Prism.plugins.toolbar){var i={none:"Plain text",plain:"Plain text",plaintext:"Plain text",text:"Plain text",txt:"Plain text",html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",rss:"RSS",css:"CSS",clike:"C-like",js:"JavaScript",abap:"ABAP",abnf:"ABNF",al:"AL",antlr4:"ANTLR4",g4:"ANTLR4",apacheconf:"Apache Configuration",apl:"APL",aql:"AQL",ino:"Arduino",arff:"ARFF",asciidoc:"AsciiDoc",adoc:"AsciiDoc",aspnet:"ASP.NET (C#)",asm6502:"6502 Assembly",asmatmel:"Atmel AVR Assembly",autohotkey:"AutoHotkey",autoit:"AutoIt",avisynth:"AviSynth",avs:"AviSynth","avro-idl":"Avro IDL",avdl:"Avro IDL",basic:"BASIC",bbcode:"BBcode",bnf:"BNF",rbnf:"RBNF",bsl:"BSL (1C:Enterprise)",oscript:"OneScript",csharp:"C#",cs:"C#",dotnet:"C#",cpp:"C++",cfscript:"CFScript",cfc:"CFScript",cil:"CIL",cmake:"CMake",cobol:"COBOL",coffee:"CoffeeScript",conc:"Concurnas",csp:"Content-Security-Policy","css-extras":"CSS Extras",csv:"CSV",dataweave:"DataWeave",dax:"DAX",django:"Django/Jinja2",jinja2:"Django/Jinja2","dns-zone-file":"DNS zone file","dns-zone":"DNS zone file",dockerfile:"Docker",dot:"DOT (Graphviz)",gv:"DOT (Graphviz)",ebnf:"EBNF",editorconfig:"EditorConfig",ejs:"EJS",etlua:"Embedded Lua templating",erb:"ERB","excel-formula":"Excel Formula",xlsx:"Excel Formula",xls:"Excel Formula",fsharp:"F#","firestore-security-rules":"Firestore security rules",ftl:"FreeMarker Template Language",gml:"GameMaker Language",gamemakerlanguage:"GameMaker Language",gap:"GAP (CAS)",gcode:"G-code",gdscript:"GDScript",gedcom:"GEDCOM",glsl:"GLSL",gn:"GN",gni:"GN","go-module":"Go module","go-mod":"Go module",graphql:"GraphQL",hbs:"Handlebars",hs:"Haskell",hcl:"HCL",hlsl:"HLSL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam","icu-message-format":"ICU Message Format",idr:"Idris",ignore:".ignore",gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore",inform7:"Inform 7",javadoc:"JavaDoc",javadoclike:"JavaDoc-like",javastacktrace:"Java stack trace",jq:"JQ",jsdoc:"JSDoc","js-extras":"JS Extras",json:"JSON",webmanifest:"Web App Manifest",json5:"JSON5",jsonp:"JSONP",jsstacktrace:"JS stack trace","js-templates":"JS Templates",keepalived:"Keepalived Configure",kts:"Kotlin Script",kt:"Kotlin",kumir:"KuMir (КуМир)",kum:"KuMir (КуМир)",latex:"LaTeX",tex:"TeX",context:"ConTeXt",lilypond:"LilyPond",ly:"LilyPond",emacs:"Lisp",elisp:"Lisp","emacs-lisp":"Lisp",llvm:"LLVM IR",log:"Log file",lolcode:"LOLCODE",magma:"Magma (CAS)",md:"Markdown","markup-templating":"Markup templating",matlab:"MATLAB",maxscript:"MAXScript",mel:"MEL",mongodb:"MongoDB",moon:"MoonScript",n1ql:"N1QL",n4js:"N4JS",n4jsd:"N4JS","nand2tetris-hdl":"Nand To Tetris HDL",naniscript:"Naninovel Script",nani:"Naninovel Script",nasm:"NASM",neon:"NEON",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",objc:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",openqasm:"OpenQasm",qasm:"OpenQasm",parigp:"PARI/GP",objectpascal:"Object Pascal",psl:"PATROL Scripting Language",pcaxis:"PC-Axis",px:"PC-Axis",peoplecode:"PeopleCode",pcode:"PeopleCode",php:"PHP",phpdoc:"PHPDoc","php-extras":"PHP Extras",plsql:"PL/SQL",powerquery:"PowerQuery",pq:"PowerQuery",mscript:"PowerQuery",powershell:"PowerShell",promql:"PromQL",properties:".properties",protobuf:"Protocol Buffers",purebasic:"PureBasic",pbfasm:"PureBasic",purs:"PureScript",py:"Python",qsharp:"Q#",qs:"Q#",q:"Q (kdb+ database)",qml:"QML",rkt:"Racket",cshtml:"Razor C#",razor:"Razor C#",jsx:"React JSX",tsx:"React TSX",renpy:"Ren'py",rpy:"Ren'py",rest:"reST (reStructuredText)",robotframework:"Robot Framework",robot:"Robot Framework",rb:"Ruby",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)","shell-session":"Shell session","sh-session":"Shell session",shellsession:"Shell session",sml:"SML",smlnj:"SML/NJ",solidity:"Solidity (Ethereum)",sol:"Solidity (Ethereum)","solution-file":"Solution file",sln:"Solution file",soy:"Soy (Closure Template)",sparql:"SPARQL",rq:"SPARQL","splunk-spl":"Splunk SPL",sqf:"SQF: Status Quo Function (Arma 3)",sql:"SQL",iecst:"Structured Text (IEC 61131-3)",systemd:"Systemd configuration file","t4-templating":"T4 templating","t4-cs":"T4 Text Templates (C#)",t4:"T4 Text Templates (C#)","t4-vb":"T4 Text Templates (VB)",tap:"TAP",tt2:"Template Toolkit 2",toml:"TOML",trickle:"trickle",troy:"troy",trig:"TriG",ts:"TypeScript",tsconfig:"TSConfig",uscript:"UnrealScript",uc:"UnrealScript",uorazor:"UO Razor Script",uri:"URI",url:"URL",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim","visual-basic":"Visual Basic",vba:"VBA",vb:"Visual Basic",wasm:"WebAssembly","web-idl":"Web IDL",webidl:"Web IDL",wiki:"Wiki markup",wolfram:"Wolfram language",nb:"Mathematica Notebook",wl:"Wolfram language",xeoracube:"XeoraCube","xml-doc":"XML doc (.net)",xojo:"Xojo (REALbasic)",xquery:"XQuery",yaml:"YAML",yml:"YAML",yang:"YANG"};Prism.plugins.toolbar.registerButton("show-language",function(e){var a=e.element.parentNode;if(a&&/pre/i.test(a.nodeName)){var t,o=a.getAttribute("data-language")||i[e.language]||((t=e.language)?(t.substring(0,1).toUpperCase()+t.substring(1)).replace(/s(?=cript)/,"S"):t);if(o){var s=document.createElement("span");return s.textContent=o,s}}})}else console.warn("Show Languages plugin loaded before Toolbar plugin.")}(); \ No newline at end of file diff --git a/plugins/toolbar/index.html b/plugins/toolbar/index.html index 64d8383098..6c5b88c152 100644 --- a/plugins/toolbar/index.html +++ b/plugins/toolbar/index.html @@ -3,25 +3,20 @@ - + Toolbar ▲ Prism plugins - + - + - + -
        -
        - -

        Toolbar

        -

        Attach a toolbar for plugins to easily register buttons on the top of a code block.

        -
        +

        How to use

        @@ -40,11 +35,13 @@

        How to use

        <template id="my-label-button"><button onclick="console.log('This is an inline-handler');">My button</button></template>
        +

        Registering buttons

        +

        For more flexibility, the Toolbar exposes a JavaScript function that can be used to register new buttons or labels to the Toolbar, Prism.plugins.toolbar.registerButton.

        The function accepts a key for the button and an object with a text property string and an optional - onClick function or url string. The onClick function will be called when the button is clicked, while the + onClick function or a url string. The onClick function will be called when the button is clicked, while the url property will be set to the anchor tag's href.

        Prism.plugins.toolbar.registerButton('hello-world', {
        @@ -59,7 +56,7 @@ 

        How to use

        If you need more control, you can provide a function to registerButton that returns either a span, a, or button element.

        -
        Prism.plugins.toolbar.registerButton('select-code', function() {
        +	
        Prism.plugins.toolbar.registerButton('select-code', function(env) {
         	var button = document.createElement('button');
         	button.innerHTML = 'Select Code';
         
        @@ -83,19 +80,27 @@ 

        How to use

        The above function creates the Select Code button you see, and when you click it, the code gets highlighted.

        +

        Ordering buttons

        +

        By default, the buttons will be added to the code snippet in the order they were registered. If more control over - the order is needed, an HTML attribute can be added to the body tag with a comma-separated string indicating the - order.

        + the order is needed, the data-toolbar-order attribute can be used. Given a comma-separated list of button names, it will ensure that these buttons will be displayed in the given order.
        + Buttons not listed will not be displayed. This means that buttons can be disabled using this technique.

        + +

        Example: The "Hello World!" button will appear before the "Select Code" button and the custom label button will not be displayed.

        + +
        <pre data-toolbar-order="hello-world,select-code" data-label="Hello World!"><code></code></pre>
        + +

        The data-toolbar-order attribute is inherited, so you can define the button order for the whole document by adding the attribute to the body of the page.

        <body data-toolbar-order="select-code,hello-world,label">
        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/toolbar/prism-toolbar.css b/plugins/toolbar/prism-toolbar.css index 2b234e19f0..59676aea4c 100644 --- a/plugins/toolbar/prism-toolbar.css +++ b/plugins/toolbar/prism-toolbar.css @@ -4,6 +4,7 @@ div.code-toolbar { div.code-toolbar > .toolbar { position: absolute; + z-index: 10; top: .3em; right: .2em; transition: opacity 0.3s ease-in-out; @@ -14,15 +15,21 @@ div.code-toolbar:hover > .toolbar { opacity: 1; } -div.code-toolbar > .toolbar .toolbar-item { +/* Separate line b/c rules are thrown out if selector is invalid. + IE11 and old Edge versions don't support :focus-within. */ +div.code-toolbar:focus-within > .toolbar { + opacity: 1; +} + +div.code-toolbar > .toolbar > .toolbar-item { display: inline-block; } -div.code-toolbar > .toolbar a { +div.code-toolbar > .toolbar > .toolbar-item > a { cursor: pointer; } -div.code-toolbar > .toolbar button { +div.code-toolbar > .toolbar > .toolbar-item > button { background: none; border: 0; color: inherit; @@ -35,9 +42,9 @@ div.code-toolbar > .toolbar button { -ms-user-select: none; } -div.code-toolbar > .toolbar a, -div.code-toolbar > .toolbar button, -div.code-toolbar > .toolbar span { +div.code-toolbar > .toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar > .toolbar-item > span { color: #bbb; font-size: .8em; padding: 0 .5em; @@ -47,12 +54,12 @@ div.code-toolbar > .toolbar span { border-radius: .5em; } -div.code-toolbar > .toolbar a:hover, -div.code-toolbar > .toolbar a:focus, -div.code-toolbar > .toolbar button:hover, -div.code-toolbar > .toolbar button:focus, -div.code-toolbar > .toolbar span:hover, -div.code-toolbar > .toolbar span:focus { +div.code-toolbar > .toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar > .toolbar-item > span:focus { color: inherit; text-decoration: none; } diff --git a/plugins/toolbar/prism-toolbar.js b/plugins/toolbar/prism-toolbar.js index 93294514b1..f59b751d72 100644 --- a/plugins/toolbar/prism-toolbar.js +++ b/plugins/toolbar/prism-toolbar.js @@ -1,19 +1,28 @@ -(function(){ - if (typeof self === 'undefined' || !self.Prism || !self.document) { +(function () { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { return; } var callbacks = []; var map = {}; - var noop = function() {}; + var noop = function () {}; Prism.plugins.toolbar = {}; + /** + * @typedef ButtonOptions + * @property {string} text The text displayed. + * @property {string} [url] The URL of the link which will be created. + * @property {Function} [onClick] The event listener for the `click` event of the created button. + * @property {string} [className] The class attribute to include with element. + */ + /** * Register a button callback with the toolbar. * * @param {string} key - * @param {Object|Function} opts + * @param {ButtonOptions|Function} opts */ var registerButton = Prism.plugins.toolbar.registerButton = function (key, opts) { var callback; @@ -37,15 +46,45 @@ element = document.createElement('span'); } + if (opts.className) { + element.classList.add(opts.className); + } + element.textContent = opts.text; return element; }; } + if (key in map) { + console.warn('There is a button with the key "' + key + '" registered already.'); + return; + } + callbacks.push(map[key] = callback); }; + /** + * Returns the callback order of the given element. + * + * @param {HTMLElement} element + * @returns {string[] | undefined} + */ + function getOrder(element) { + while (element) { + var order = element.getAttribute('data-toolbar-order'); + if (order != null) { + order = order.trim(); + if (order.length) { + return order.split(/\s*,\s*/g); + } else { + return []; + } + } + element = element.parentElement; + } + } + /** * Post-highlight Prism hook callback. * @@ -64,8 +103,8 @@ } // Create wrapper for
         to prevent scrolling toolbar with content
        -		var wrapper = document.createElement("div");
        -		wrapper.classList.add("code-toolbar");
        +		var wrapper = document.createElement('div');
        +		wrapper.classList.add('code-toolbar');
         		pre.parentNode.insertBefore(wrapper, pre);
         		wrapper.appendChild(pre);
         
        @@ -73,13 +112,16 @@
         		var toolbar = document.createElement('div');
         		toolbar.classList.add('toolbar');
         
        -		if (document.body.hasAttribute('data-toolbar-order')) {
        -			callbacks = document.body.getAttribute('data-toolbar-order').split(',').map(function(key) {
        +		// order callbacks
        +		var elementCallbacks = callbacks;
        +		var order = getOrder(env.element);
        +		if (order) {
        +			elementCallbacks = order.map(function (key) {
         				return map[key] || noop;
         			});
         		}
         
        -		callbacks.forEach(function(callback) {
        +		elementCallbacks.forEach(function (callback) {
         			var element = callback(env);
         
         			if (!element) {
        @@ -97,7 +139,7 @@
         		wrapper.appendChild(toolbar);
         	};
         
        -	registerButton('label', function(env) {
        +	registerButton('label', function (env) {
         		var pre = env.element.parentNode;
         		if (!pre || !/pre/i.test(pre.nodeName)) {
         			return;
        @@ -107,12 +149,12 @@
         			return;
         		}
         
        -		var element, template;
        +		var element; var template;
         		var text = pre.getAttribute('data-label');
         		try {
         			// Any normal text will blow up this selector.
         			template = document.querySelector('template#' + text);
        -		} catch (e) {}
        +		} catch (e) { /* noop */ }
         
         		if (template) {
         			element = template.content;
        @@ -134,4 +176,4 @@
         	 * Register the toolbar with Prism.
         	 */
         	Prism.hooks.add('complete', hook);
        -})();
        +}());
        diff --git a/plugins/toolbar/prism-toolbar.min.css b/plugins/toolbar/prism-toolbar.min.css
        new file mode 100644
        index 0000000000..d4298ec8dc
        --- /dev/null
        +++ b/plugins/toolbar/prism-toolbar.min.css
        @@ -0,0 +1 @@
        +div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity .3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none}
        \ No newline at end of file
        diff --git a/plugins/toolbar/prism-toolbar.min.js b/plugins/toolbar/prism-toolbar.min.js
        index 17cee96226..c2bc102848 100644
        --- a/plugins/toolbar/prism-toolbar.min.js
        +++ b/plugins/toolbar/prism-toolbar.min.js
        @@ -1 +1 @@
        -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var t=[],e={},n=function(){};Prism.plugins.toolbar={};var a=Prism.plugins.toolbar.registerButton=function(n,a){var o;o="function"==typeof a?a:function(t){var e;return"function"==typeof a.onClick?(e=document.createElement("button"),e.type="button",e.addEventListener("click",function(){a.onClick.call(this,t)})):"string"==typeof a.url?(e=document.createElement("a"),e.href=a.url):e=document.createElement("span"),e.textContent=a.text,e},t.push(e[n]=o)},o=Prism.plugins.toolbar.hook=function(a){var o=a.element.parentNode;if(o&&/pre/i.test(o.nodeName)&&!o.parentNode.classList.contains("code-toolbar")){var r=document.createElement("div");r.classList.add("code-toolbar"),o.parentNode.insertBefore(r,o),r.appendChild(o);var i=document.createElement("div");i.classList.add("toolbar"),document.body.hasAttribute("data-toolbar-order")&&(t=document.body.getAttribute("data-toolbar-order").split(",").map(function(t){return e[t]||n})),t.forEach(function(t){var e=t(a);if(e){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(e),i.appendChild(n)}}),r.appendChild(i)}};a("label",function(t){var e=t.element.parentNode;if(e&&/pre/i.test(e.nodeName)&&e.hasAttribute("data-label")){var n,a,o=e.getAttribute("data-label");try{a=document.querySelector("template#"+o)}catch(r){}return a?n=a.content:(e.hasAttribute("data-url")?(n=document.createElement("a"),n.href=e.getAttribute("data-url")):n=document.createElement("span"),n.textContent=o),n}}),Prism.hooks.add("complete",o)}}();
        \ No newline at end of file
        +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var i=[],l={},d=function(){};Prism.plugins.toolbar={};var e=Prism.plugins.toolbar.registerButton=function(e,n){var t;t="function"==typeof n?n:function(e){var t;return"function"==typeof n.onClick?((t=document.createElement("button")).type="button",t.addEventListener("click",function(){n.onClick.call(this,e)})):"string"==typeof n.url?(t=document.createElement("a")).href=n.url:t=document.createElement("span"),n.className&&t.classList.add(n.className),t.textContent=n.text,t},e in l?console.warn('There is a button with the key "'+e+'" registered already.'):i.push(l[e]=t)},t=Prism.plugins.toolbar.hook=function(a){var e=a.element.parentNode;if(e&&/pre/i.test(e.nodeName)&&!e.parentNode.classList.contains("code-toolbar")){var t=document.createElement("div");t.classList.add("code-toolbar"),e.parentNode.insertBefore(t,e),t.appendChild(e);var r=document.createElement("div");r.classList.add("toolbar");var n=i,o=function(e){for(;e;){var t=e.getAttribute("data-toolbar-order");if(null!=t)return(t=t.trim()).length?t.split(/\s*,\s*/g):[];e=e.parentElement}}(a.element);o&&(n=o.map(function(e){return l[e]||d})),n.forEach(function(e){var t=e(a);if(t){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(t),r.appendChild(n)}}),t.appendChild(r)}};e("label",function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-label")){var n,a,r=t.getAttribute("data-label");try{a=document.querySelector("template#"+r)}catch(e){}return a?n=a.content:(t.hasAttribute("data-url")?(n=document.createElement("a")).href=t.getAttribute("data-url"):n=document.createElement("span"),n.textContent=r),n}}),Prism.hooks.add("complete",t)}}();
        \ No newline at end of file
        diff --git a/plugins/treeview/icons/archive.svg b/plugins/treeview/icons/archive.svg
        new file mode 100644
        index 0000000000..b5ba2c5a1c
        --- /dev/null
        +++ b/plugins/treeview/icons/archive.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/audio.svg b/plugins/treeview/icons/audio.svg
        new file mode 100644
        index 0000000000..8e7ad6e8dd
        --- /dev/null
        +++ b/plugins/treeview/icons/audio.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/code.svg b/plugins/treeview/icons/code.svg
        new file mode 100644
        index 0000000000..5fd403c130
        --- /dev/null
        +++ b/plugins/treeview/icons/code.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/excel.svg b/plugins/treeview/icons/excel.svg
        new file mode 100644
        index 0000000000..4247a5c317
        --- /dev/null
        +++ b/plugins/treeview/icons/excel.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/file.svg b/plugins/treeview/icons/file.svg
        new file mode 100644
        index 0000000000..f9e8d6fb9a
        --- /dev/null
        +++ b/plugins/treeview/icons/file.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/folder.svg b/plugins/treeview/icons/folder.svg
        new file mode 100644
        index 0000000000..75e1b6c2a9
        --- /dev/null
        +++ b/plugins/treeview/icons/folder.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/image.svg b/plugins/treeview/icons/image.svg
        new file mode 100644
        index 0000000000..23bcb72d9e
        --- /dev/null
        +++ b/plugins/treeview/icons/image.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/pdf.svg b/plugins/treeview/icons/pdf.svg
        new file mode 100644
        index 0000000000..10b0dc732a
        --- /dev/null
        +++ b/plugins/treeview/icons/pdf.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/powerpoint.svg b/plugins/treeview/icons/powerpoint.svg
        new file mode 100644
        index 0000000000..f6f4dfe32c
        --- /dev/null
        +++ b/plugins/treeview/icons/powerpoint.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/text.svg b/plugins/treeview/icons/text.svg
        new file mode 100644
        index 0000000000..30291a4713
        --- /dev/null
        +++ b/plugins/treeview/icons/text.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/video.svg b/plugins/treeview/icons/video.svg
        new file mode 100644
        index 0000000000..f2895deb9e
        --- /dev/null
        +++ b/plugins/treeview/icons/video.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/icons/word.svg b/plugins/treeview/icons/word.svg
        new file mode 100644
        index 0000000000..1a7b0832e5
        --- /dev/null
        +++ b/plugins/treeview/icons/word.svg
        @@ -0,0 +1,6 @@
        +
        +
        +	
        +
        diff --git a/plugins/treeview/index.html b/plugins/treeview/index.html
        new file mode 100644
        index 0000000000..8fc7f579fd
        --- /dev/null
        +++ b/plugins/treeview/index.html
        @@ -0,0 +1,83 @@
        +
        +
        +
        +
        +	
        +	
        +	Treeview ▲ Prism plugins
        +	
        +	
        +	
        +	
        +	
        +
        +	
        +	
        +
        +
        +
        +
        + +
        +

        How to use

        +

        You may use tree -F to get a compatible text structure.

        + +
        root_folder/
        +|-- a first folder/
        +|   |-- holidays.mov
        +|   |-- javascript-file.js
        +|   `-- some_picture.jpg
        +|-- documents/
        +|   |-- spreadsheet.xls
        +|   |-- manual.pdf
        +|   |-- document.docx
        +|   `-- presentation.ppt
        +|       `-- test
        +|-- empty_folder/
        +|-- going deeper/
        +|   |-- going deeper/
        +|   |   `-- going deeper/
        +|   |        `-- going deeper/
        +|   |            `-- .secret_file
        +|   |-- style.css
        +|   `-- index.html
        +|-- music and movies/
        +|   |-- great-song.mp3
        +|   |-- S01E02.new.episode.avi
        +|   |-- S01E02.new.episode.nfo
        +|   `-- track 1.cda
        +|-- .gitignore
        +|-- .htaccess
        +|-- .npmignore
        +|-- archive 1.zip
        +|-- archive 2.tar.gz
        +|-- logo.svg
        +`-- README.md
        + +

        You can also use the following box-drawing characters to represent the tree:

        + +
        root_folder/
        +├── a first folder/
        +|   ├── holidays.mov
        +|   ├── javascript-file.js
        +|   └── some_picture.jpg
        +├── documents/
        +|   ├── spreadsheet.xls
        +|   ├── manual.pdf
        +|   ├── document.docx
        +|   └── presentation.ppt
        +└── etc.
        +
        + +
        + +
        + + + + + + + + + diff --git a/plugins/treeview/prism-treeview.css b/plugins/treeview/prism-treeview.css new file mode 100644 index 0000000000..99ee658cb0 --- /dev/null +++ b/plugins/treeview/prism-treeview.css @@ -0,0 +1,168 @@ +.token.treeview-part .entry-line { + position: relative; + text-indent: -99em; + display: inline-block; + vertical-align: top; + width: 1.2em; +} +.token.treeview-part .entry-line:before, +.token.treeview-part .line-h:after { + content: ""; + position: absolute; + top: 0; + left: 50%; + width: 50%; + height: 100%; +} +.token.treeview-part .line-h:before, +.token.treeview-part .line-v:before { + border-left: 1px solid #ccc; +} +.token.treeview-part .line-v-last:before { + height: 50%; + border-left: 1px solid #ccc; + border-bottom: 1px solid #ccc; +} +.token.treeview-part .line-h:after { + height: 50%; + border-bottom: 1px solid #ccc; +} +.token.treeview-part .entry-name { + position: relative; + display: inline-block; + vertical-align: top; +} +.token.treeview-part .entry-name.dotfile { + opacity: 0.5; +} + +/* @GENERATED-FONT */ +@font-face { + font-family: "PrismTreeview"; + /** + * This font is generated from the .svg files in the `icons` folder. See the `treeviewIconFont` function in + * `gulpfile.js/index.js` for more information. + * + * Use the following escape sequences to refer to a specific icon: + * + * - \ea01 file + * - \ea02 folder + * - \ea03 image + * - \ea04 audio + * - \ea05 video + * - \ea06 text + * - \ea07 code + * - \ea08 archive + * - \ea09 pdf + * - \ea0a excel + * - \ea0b powerpoint + * - \ea0c word + */ + src: url("data:application/font-woff;base64,d09GRgABAAAAAAgYAAsAAAAAEGAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADsAAABUIIslek9TLzIAAAFEAAAAPwAAAFY1UkH9Y21hcAAAAYQAAAB/AAACCtvO7yxnbHlmAAACBAAAA+MAAAlACm1VqmhlYWQAAAXoAAAAKgAAADZfxj5jaGhlYQAABhQAAAAYAAAAJAFbAMFobXR4AAAGLAAAAA4AAAA0CGQAAGxvY2EAAAY8AAAAHAAAABwM9A9CbWF4cAAABlgAAAAfAAAAIAEgAHZuYW1lAAAGeAAAATcAAAJSfUrk+HBvc3QAAAewAAAAZgAAAIka0DSfeJxjYGRgYOBiMGCwY2BycfMJYeDLSSzJY5BiYGGAAJA8MpsxJzM9kYEDxgPKsYBpDiBmg4gCACY7BUgAeJxjYGRYyjiBgZWBgaGQoRZISkLpUAYOBj0GBiYGVmYGrCAgzTWFweEV4ysehs1ArgDDFgZGIA3CDAB2tQjAAHic7ZHLEcMwCESfLCz/VEoKSEE5parURxMOC4c0Ec283WGFdABgBXrwCAzam4bOK9KWeefM3Hhmjyn3ed+hTRq1pS7Ra/HjYGPniHcXMy4G/zNTP7/KW5HTXArkvdBW3ArN19dCG/NRIN8K5HuB/CiQn4U26VeBfBbML9NEH78AeJyVVc1u20YQ3pn905JcSgr/YsuSDTEg3cR1bFEkYyS1HQcQ2jQF2hot6vYSoECKnnPLA/SWUy9NTr31Bfp+6azsNI0SGiolzu7ODnfn+2Z2lnHG3rxhr9nfLGKbLGesncAYYnUHpsVnMG/uwyzNdFIVd6HI6twp8+R3LpT4TSglLoTHwwJgG2/dFvKrl9yI507/p5CCq4LTxB/PlPjkFaMHnWB/0S9je7RTPS+utnGtom1T2q5pk/e3H0M1S18rsXAL7wgpxQuhAmteGGvNjmcfGXuwnFNOPCXxeOGmnjrBLWNyBeNtVq2Hs03yus1aPS3mzSyNVSfu588iW1Q93x/4fjcHn+5EkS2tMxr4xIRa8ese+4L9uKZnxEqs8+ldyN9atU02a5t5uQ8hZGms1QTKpaKYqnipiNNOAIeIADC0JNEOYY+jtSgFoOchiAjRGFACpUTRje8bwIYWGCDEgENY8MEu9bnCYCdAxftoNg0KiSpUtPaHcanYwzXRu6T4r40b5npal3V7UHWCPJW9niyl1vIHgoujEXZjudBkeWkOeMQBRmbEPhKzij1i52t6/TadL+3q7H0U1eq4E8cG4gIIwQLx8VX7ToPXgPrehVc5QXHR7gMSmwjKfaYAP4KvZV+yn9bE18y2IY37LvtyrSg3i7ZK++B603ndlg/gBJpZRsfpBI6hyiaQ6FjlnThz8lAC3LgBIMnXDOAXxBQ4SIgiEhx2AcGCAwAhwjXRpCQms42bwAUt75BvAwgONzdgOfWEwzk4Ylzj4mz+5YEzzXzWX9aNlk7ot65y5QnBHsNlm6zDTu7sspRqG4V+fgJ1lVBZ07Nm7s5nemo3Lf3PO7iwtnroQ5/YDGwPRUip6fV6L+27p+wCHwSvPs85UnHqId8NAn5IBsKdv95KrL9m31Gsf2a/rluDslk1y1J9GE+LUmmVT/OyOHaFKGnapt2H5XeJTmKd6qYNoVVZOy+pWzr7rMip3ndG/4mQSoUcMbAqG/YNIAdXhkAqTVruXhocSKN0iS4Rwj7vSS4fcF/La07BfeQSuRAcFeW+9igjwPhhYPpGCBCBHhxiKMyFMFT7ziRH7RtfIWdiha+TdW+Rqs7bLHdN2ZJIKl0um0x3op9saYr0REeRdj09pl43pMzz4tjztrY8L4o8bzT+oLY27PR/eFtXs/YY5vtwB5Iqad14eYN0ujveMaGWqkdU3TKbQSC5Uvxaf4fA7SAQ3r2tEfIhd4duld91bwMisjqBw22orthNcroXl7KqO1329HBgAexgoCfGAwiDPoBnriki3lmNojrzvD0tjo6E3vPYP6E2BMIAeJxjYGRgYADiY8t3FsTz23xl4GbYzIAB/v9nWM6wBcjgYGAC8QH+QQhZAAB4nGNgZGBg2MzAACeXMzAyoAJeADPyAh14nGNgAILNpGEA0fgIZQAAAAAAAAA2AHIAvgE+AZgCCAKMAv4DlgPsBEYEoHicY2BkYGDgZchi4GQAASYg5gJCBob/YD4DABTSAZcAeJx9kU1uwjAQhV/4qwpqhdSqi67cTTeVEmBXDgBbhBD7AHYISuLUMSD2PUdP0HNwjp6i676k3qQS9Ujjb968mYUNoI8zPJTHw02Vy9PAFatfbpLuHbfIT47b6MF33KH+6riLF0wc93CHN27wWtdUHvHuuIFbfDhuUv903CKfHbfxgC/HHerfjrtYen3HPTx7ambiIl0YKQ+xPM5ltE9CU9NqxVKaItaZGPqDmj6VmTShlRuxOoniEI2sVUIZnYqJzqxMEi1yo3dybf2ttfk4CJTT/bVOMYNBjAIpFiTJOLCWOGLOHGGPBCE7l32XO0tmw04MjQwCQ7774B//lDmrZkJY3hvOrHBiLuiJMKJqoVgrejQ3CP5Yubt0JwxNJa96Oypr6j621VSOMQKG+uP36eKmHylcb0MAeJxtwdEOgjAMBdBeWEFR/Mdl7bTJtMsygc/nwVfPoYF+QP+tGDAigDFhxgVXLLjhjhUPCtmKTtmLaGN7x6dy/Io5bybqoevRQ3LRObb0sk3HKpn1SFqW6ru26vbpYfcmRCccJhqsAAA=") + format("woff"); +} + +.token.treeview-part .entry-name:before { + content: "\ea01"; + font-family: "PrismTreeview"; + font-size: inherit; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + width: 2.5ex; + display: inline-block; +} + +.token.treeview-part .entry-name.dir:before { + content: "\ea02"; +} +.token.treeview-part .entry-name.ext-bmp:before, +.token.treeview-part .entry-name.ext-eps:before, +.token.treeview-part .entry-name.ext-gif:before, +.token.treeview-part .entry-name.ext-jpe:before, +.token.treeview-part .entry-name.ext-jpg:before, +.token.treeview-part .entry-name.ext-jpeg:before, +.token.treeview-part .entry-name.ext-png:before, +.token.treeview-part .entry-name.ext-svg:before, +.token.treeview-part .entry-name.ext-tiff:before { + content: "\ea03"; +} +.token.treeview-part .entry-name.ext-cfg:before, +.token.treeview-part .entry-name.ext-conf:before, +.token.treeview-part .entry-name.ext-config:before, +.token.treeview-part .entry-name.ext-csv:before, +.token.treeview-part .entry-name.ext-ini:before, +.token.treeview-part .entry-name.ext-log:before, +.token.treeview-part .entry-name.ext-md:before, +.token.treeview-part .entry-name.ext-nfo:before, +.token.treeview-part .entry-name.ext-txt:before { + content: "\ea06"; +} +.token.treeview-part .entry-name.ext-asp:before, +.token.treeview-part .entry-name.ext-aspx:before, +.token.treeview-part .entry-name.ext-c:before, +.token.treeview-part .entry-name.ext-cc:before, +.token.treeview-part .entry-name.ext-cpp:before, +.token.treeview-part .entry-name.ext-cs:before, +.token.treeview-part .entry-name.ext-css:before, +.token.treeview-part .entry-name.ext-h:before, +.token.treeview-part .entry-name.ext-hh:before, +.token.treeview-part .entry-name.ext-htm:before, +.token.treeview-part .entry-name.ext-html:before, +.token.treeview-part .entry-name.ext-jav:before, +.token.treeview-part .entry-name.ext-java:before, +.token.treeview-part .entry-name.ext-js:before, +.token.treeview-part .entry-name.ext-php:before, +.token.treeview-part .entry-name.ext-rb:before, +.token.treeview-part .entry-name.ext-xml:before { + content: "\ea07"; +} +.token.treeview-part .entry-name.ext-7z:before, +.token.treeview-part .entry-name.ext-bz:before, +.token.treeview-part .entry-name.ext-bz2:before, +.token.treeview-part .entry-name.ext-gz:before, +.token.treeview-part .entry-name.ext-rar:before, +.token.treeview-part .entry-name.ext-tar:before, +.token.treeview-part .entry-name.ext-tgz:before, +.token.treeview-part .entry-name.ext-zip:before { + content: "\ea08"; +} +.token.treeview-part .entry-name.ext-aac:before, +.token.treeview-part .entry-name.ext-au:before, +.token.treeview-part .entry-name.ext-cda:before, +.token.treeview-part .entry-name.ext-flac:before, +.token.treeview-part .entry-name.ext-mp3:before, +.token.treeview-part .entry-name.ext-oga:before, +.token.treeview-part .entry-name.ext-ogg:before, +.token.treeview-part .entry-name.ext-wav:before, +.token.treeview-part .entry-name.ext-wma:before { + content: "\ea04"; +} +.token.treeview-part .entry-name.ext-avi:before, +.token.treeview-part .entry-name.ext-flv:before, +.token.treeview-part .entry-name.ext-mkv:before, +.token.treeview-part .entry-name.ext-mov:before, +.token.treeview-part .entry-name.ext-mp4:before, +.token.treeview-part .entry-name.ext-mpeg:before, +.token.treeview-part .entry-name.ext-mpg:before, +.token.treeview-part .entry-name.ext-ogv:before, +.token.treeview-part .entry-name.ext-webm:before { + content: "\ea05"; +} +.token.treeview-part .entry-name.ext-pdf:before { + content: "\ea09"; +} +.token.treeview-part .entry-name.ext-xls:before, +.token.treeview-part .entry-name.ext-xlsx:before { + content: "\ea0a"; +} +.token.treeview-part .entry-name.ext-doc:before, +.token.treeview-part .entry-name.ext-docm:before, +.token.treeview-part .entry-name.ext-docx:before { + content: "\ea0c"; +} +.token.treeview-part .entry-name.ext-pps:before, +.token.treeview-part .entry-name.ext-ppt:before, +.token.treeview-part .entry-name.ext-pptx:before { + content: "\ea0b"; +} diff --git a/plugins/treeview/prism-treeview.js b/plugins/treeview/prism-treeview.js new file mode 100644 index 0000000000..945668320a --- /dev/null +++ b/plugins/treeview/prism-treeview.js @@ -0,0 +1,70 @@ +(function () { + + if (typeof Prism === 'undefined') { + return; + } + + Prism.languages.treeview = { + 'treeview-part': { + pattern: /^.+/m, + inside: { + 'entry-line': [ + { + pattern: /\|-- |├── /, + alias: 'line-h' + }, + { + pattern: /\| {3}|│ {3}/, + alias: 'line-v' + }, + { + pattern: /`-- |└── /, + alias: 'line-v-last' + }, + { + pattern: / {4}/, + alias: 'line-v-gap' + } + ], + 'entry-name': { + pattern: /.*\S.*/, + inside: { + // symlink + 'operator': / -> /, + } + } + } + } + }; + + Prism.hooks.add('wrap', function (env) { + if (env.language === 'treeview' && env.type === 'entry-name') { + var classes = env.classes; + + var folderPattern = /(^|[^\\])\/\s*$/; + if (folderPattern.test(env.content)) { + // folder + + // remove trailing / + env.content = env.content.replace(folderPattern, '$1'); + classes.push('dir'); + } else { + // file + + // remove trailing file marker + env.content = env.content.replace(/(^|[^\\])[=*|]\s*$/, '$1'); + + var parts = env.content.toLowerCase().replace(/\s+/g, '').split('.'); + while (parts.length > 1) { + parts.shift(); + // Ex. 'foo.min.js' would become 'foo.min.js' + classes.push('ext-' + parts.join('-')); + } + } + + if (env.content[0] === '.') { + classes.push('dotfile'); + } + } + }); +}()); diff --git a/plugins/treeview/prism-treeview.min.css b/plugins/treeview/prism-treeview.min.css new file mode 100644 index 0000000000..9856725d67 --- /dev/null +++ b/plugins/treeview/prism-treeview.min.css @@ -0,0 +1 @@ +.token.treeview-part .entry-line{position:relative;text-indent:-99em;display:inline-block;vertical-align:top;width:1.2em}.token.treeview-part .entry-line:before,.token.treeview-part .line-h:after{content:"";position:absolute;top:0;left:50%;width:50%;height:100%}.token.treeview-part .line-h:before,.token.treeview-part .line-v:before{border-left:1px solid #ccc}.token.treeview-part .line-v-last:before{height:50%;border-left:1px solid #ccc;border-bottom:1px solid #ccc}.token.treeview-part .line-h:after{height:50%;border-bottom:1px solid #ccc}.token.treeview-part .entry-name{position:relative;display:inline-block;vertical-align:top}.token.treeview-part .entry-name.dotfile{opacity:.5}@font-face{font-family:PrismTreeview;src:url(data:application/font-woff;base64,d09GRgABAAAAAAgYAAsAAAAAEGAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADsAAABUIIslek9TLzIAAAFEAAAAPwAAAFY1UkH9Y21hcAAAAYQAAAB/AAACCtvO7yxnbHlmAAACBAAAA+MAAAlACm1VqmhlYWQAAAXoAAAAKgAAADZfxj5jaGhlYQAABhQAAAAYAAAAJAFbAMFobXR4AAAGLAAAAA4AAAA0CGQAAGxvY2EAAAY8AAAAHAAAABwM9A9CbWF4cAAABlgAAAAfAAAAIAEgAHZuYW1lAAAGeAAAATcAAAJSfUrk+HBvc3QAAAewAAAAZgAAAIka0DSfeJxjYGRgYOBiMGCwY2BycfMJYeDLSSzJY5BiYGGAAJA8MpsxJzM9kYEDxgPKsYBpDiBmg4gCACY7BUgAeJxjYGRYyjiBgZWBgaGQoRZISkLpUAYOBj0GBiYGVmYGrCAgzTWFweEV4ysehs1ArgDDFgZGIA3CDAB2tQjAAHic7ZHLEcMwCESfLCz/VEoKSEE5parURxMOC4c0Ec283WGFdABgBXrwCAzam4bOK9KWeefM3Hhmjyn3ed+hTRq1pS7Ra/HjYGPniHcXMy4G/zNTP7/KW5HTXArkvdBW3ArN19dCG/NRIN8K5HuB/CiQn4U26VeBfBbML9NEH78AeJyVVc1u20YQ3pn905JcSgr/YsuSDTEg3cR1bFEkYyS1HQcQ2jQF2hot6vYSoECKnnPLA/SWUy9NTr31Bfp+6azsNI0SGiolzu7ODnfn+2Z2lnHG3rxhr9nfLGKbLGesncAYYnUHpsVnMG/uwyzNdFIVd6HI6twp8+R3LpT4TSglLoTHwwJgG2/dFvKrl9yI507/p5CCq4LTxB/PlPjkFaMHnWB/0S9je7RTPS+utnGtom1T2q5pk/e3H0M1S18rsXAL7wgpxQuhAmteGGvNjmcfGXuwnFNOPCXxeOGmnjrBLWNyBeNtVq2Hs03yus1aPS3mzSyNVSfu588iW1Q93x/4fjcHn+5EkS2tMxr4xIRa8ese+4L9uKZnxEqs8+ldyN9atU02a5t5uQ8hZGms1QTKpaKYqnipiNNOAIeIADC0JNEOYY+jtSgFoOchiAjRGFACpUTRje8bwIYWGCDEgENY8MEu9bnCYCdAxftoNg0KiSpUtPaHcanYwzXRu6T4r40b5npal3V7UHWCPJW9niyl1vIHgoujEXZjudBkeWkOeMQBRmbEPhKzij1i52t6/TadL+3q7H0U1eq4E8cG4gIIwQLx8VX7ToPXgPrehVc5QXHR7gMSmwjKfaYAP4KvZV+yn9bE18y2IY37LvtyrSg3i7ZK++B603ndlg/gBJpZRsfpBI6hyiaQ6FjlnThz8lAC3LgBIMnXDOAXxBQ4SIgiEhx2AcGCAwAhwjXRpCQms42bwAUt75BvAwgONzdgOfWEwzk4Ylzj4mz+5YEzzXzWX9aNlk7ot65y5QnBHsNlm6zDTu7sspRqG4V+fgJ1lVBZ07Nm7s5nemo3Lf3PO7iwtnroQ5/YDGwPRUip6fV6L+27p+wCHwSvPs85UnHqId8NAn5IBsKdv95KrL9m31Gsf2a/rluDslk1y1J9GE+LUmmVT/OyOHaFKGnapt2H5XeJTmKd6qYNoVVZOy+pWzr7rMip3ndG/4mQSoUcMbAqG/YNIAdXhkAqTVruXhocSKN0iS4Rwj7vSS4fcF/La07BfeQSuRAcFeW+9igjwPhhYPpGCBCBHhxiKMyFMFT7ziRH7RtfIWdiha+TdW+Rqs7bLHdN2ZJIKl0um0x3op9saYr0REeRdj09pl43pMzz4tjztrY8L4o8bzT+oLY27PR/eFtXs/YY5vtwB5Iqad14eYN0ujveMaGWqkdU3TKbQSC5Uvxaf4fA7SAQ3r2tEfIhd4duld91bwMisjqBw22orthNcroXl7KqO1329HBgAexgoCfGAwiDPoBnriki3lmNojrzvD0tjo6E3vPYP6E2BMIAeJxjYGRgYADiY8t3FsTz23xl4GbYzIAB/v9nWM6wBcjgYGAC8QH+QQhZAAB4nGNgZGBg2MzAACeXMzAyoAJeADPyAh14nGNgAILNpGEA0fgIZQAAAAAAAAA2AHIAvgE+AZgCCAKMAv4DlgPsBEYEoHicY2BkYGDgZchi4GQAASYg5gJCBob/YD4DABTSAZcAeJx9kU1uwjAQhV/4qwpqhdSqi67cTTeVEmBXDgBbhBD7AHYISuLUMSD2PUdP0HNwjp6i676k3qQS9Ujjb968mYUNoI8zPJTHw02Vy9PAFatfbpLuHbfIT47b6MF33KH+6riLF0wc93CHN27wWtdUHvHuuIFbfDhuUv903CKfHbfxgC/HHerfjrtYen3HPTx7ambiIl0YKQ+xPM5ltE9CU9NqxVKaItaZGPqDmj6VmTShlRuxOoniEI2sVUIZnYqJzqxMEi1yo3dybf2ttfk4CJTT/bVOMYNBjAIpFiTJOLCWOGLOHGGPBCE7l32XO0tmw04MjQwCQ7774B//lDmrZkJY3hvOrHBiLuiJMKJqoVgrejQ3CP5Yubt0JwxNJa96Oypr6j621VSOMQKG+uP36eKmHylcb0MAeJxtwdEOgjAMBdBeWEFR/Mdl7bTJtMsygc/nwVfPoYF+QP+tGDAigDFhxgVXLLjhjhUPCtmKTtmLaGN7x6dy/Io5bybqoevRQ3LRObb0sk3HKpn1SFqW6ru26vbpYfcmRCccJhqsAAA=) format("woff")}.token.treeview-part .entry-name:before{content:"\ea01";font-family:PrismTreeview;font-size:inherit;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:2.5ex;display:inline-block}.token.treeview-part .entry-name.dir:before{content:"\ea02"}.token.treeview-part .entry-name.ext-bmp:before,.token.treeview-part .entry-name.ext-eps:before,.token.treeview-part .entry-name.ext-gif:before,.token.treeview-part .entry-name.ext-jpe:before,.token.treeview-part .entry-name.ext-jpeg:before,.token.treeview-part .entry-name.ext-jpg:before,.token.treeview-part .entry-name.ext-png:before,.token.treeview-part .entry-name.ext-svg:before,.token.treeview-part .entry-name.ext-tiff:before{content:"\ea03"}.token.treeview-part .entry-name.ext-cfg:before,.token.treeview-part .entry-name.ext-conf:before,.token.treeview-part .entry-name.ext-config:before,.token.treeview-part .entry-name.ext-csv:before,.token.treeview-part .entry-name.ext-ini:before,.token.treeview-part .entry-name.ext-log:before,.token.treeview-part .entry-name.ext-md:before,.token.treeview-part .entry-name.ext-nfo:before,.token.treeview-part .entry-name.ext-txt:before{content:"\ea06"}.token.treeview-part .entry-name.ext-asp:before,.token.treeview-part .entry-name.ext-aspx:before,.token.treeview-part .entry-name.ext-c:before,.token.treeview-part .entry-name.ext-cc:before,.token.treeview-part .entry-name.ext-cpp:before,.token.treeview-part .entry-name.ext-cs:before,.token.treeview-part .entry-name.ext-css:before,.token.treeview-part .entry-name.ext-h:before,.token.treeview-part .entry-name.ext-hh:before,.token.treeview-part .entry-name.ext-htm:before,.token.treeview-part .entry-name.ext-html:before,.token.treeview-part .entry-name.ext-jav:before,.token.treeview-part .entry-name.ext-java:before,.token.treeview-part .entry-name.ext-js:before,.token.treeview-part .entry-name.ext-php:before,.token.treeview-part .entry-name.ext-rb:before,.token.treeview-part .entry-name.ext-xml:before{content:"\ea07"}.token.treeview-part .entry-name.ext-7z:before,.token.treeview-part .entry-name.ext-bz2:before,.token.treeview-part .entry-name.ext-bz:before,.token.treeview-part .entry-name.ext-gz:before,.token.treeview-part .entry-name.ext-rar:before,.token.treeview-part .entry-name.ext-tar:before,.token.treeview-part .entry-name.ext-tgz:before,.token.treeview-part .entry-name.ext-zip:before{content:"\ea08"}.token.treeview-part .entry-name.ext-aac:before,.token.treeview-part .entry-name.ext-au:before,.token.treeview-part .entry-name.ext-cda:before,.token.treeview-part .entry-name.ext-flac:before,.token.treeview-part .entry-name.ext-mp3:before,.token.treeview-part .entry-name.ext-oga:before,.token.treeview-part .entry-name.ext-ogg:before,.token.treeview-part .entry-name.ext-wav:before,.token.treeview-part .entry-name.ext-wma:before{content:"\ea04"}.token.treeview-part .entry-name.ext-avi:before,.token.treeview-part .entry-name.ext-flv:before,.token.treeview-part .entry-name.ext-mkv:before,.token.treeview-part .entry-name.ext-mov:before,.token.treeview-part .entry-name.ext-mp4:before,.token.treeview-part .entry-name.ext-mpeg:before,.token.treeview-part .entry-name.ext-mpg:before,.token.treeview-part .entry-name.ext-ogv:before,.token.treeview-part .entry-name.ext-webm:before{content:"\ea05"}.token.treeview-part .entry-name.ext-pdf:before{content:"\ea09"}.token.treeview-part .entry-name.ext-xls:before,.token.treeview-part .entry-name.ext-xlsx:before{content:"\ea0a"}.token.treeview-part .entry-name.ext-doc:before,.token.treeview-part .entry-name.ext-docm:before,.token.treeview-part .entry-name.ext-docx:before{content:"\ea0c"}.token.treeview-part .entry-name.ext-pps:before,.token.treeview-part .entry-name.ext-ppt:before,.token.treeview-part .entry-name.ext-pptx:before{content:"\ea0b"} \ No newline at end of file diff --git a/plugins/treeview/prism-treeview.min.js b/plugins/treeview/prism-treeview.min.js new file mode 100644 index 0000000000..7c59a60f75 --- /dev/null +++ b/plugins/treeview/prism-treeview.min.js @@ -0,0 +1 @@ +"undefined"!=typeof Prism&&(Prism.languages.treeview={"treeview-part":{pattern:/^.+/m,inside:{"entry-line":[{pattern:/\|-- |├── /,alias:"line-h"},{pattern:/\| {3}|│ {3}/,alias:"line-v"},{pattern:/`-- |└── /,alias:"line-v-last"},{pattern:/ {4}/,alias:"line-v-gap"}],"entry-name":{pattern:/.*\S.*/,inside:{operator:/ -> /}}}}},Prism.hooks.add("wrap",function(e){if("treeview"===e.language&&"entry-name"===e.type){var t=e.classes,n=/(^|[^\\])\/\s*$/;if(n.test(e.content))e.content=e.content.replace(n,"$1"),t.push("dir");else{e.content=e.content.replace(/(^|[^\\])[=*|]\s*$/,"$1");for(var a=e.content.toLowerCase().replace(/\s+/g,"").split(".");1 - + Unescaped markup ▲ Prism plugins - + - + - + -
        -
        - -

        Unescaped markup

        -

        Write markup without having to escape anything.

        -
        +

        How to use

        This plugin provides several methods of achieving the same thing:

          -
        • Instead of using <pre><code> elements, use <script type="text/plain"> -
          <script type="text/plain" class="language-markup">
          +		
        • + Instead of using <pre><code> elements, use <script type="text/plain">: + +
          <script type="text/plain" class="language-markup">
           <p>Example</p>
           </script>
        • -
        • Use a HTML-comment to escape your code -
          <pre class="language-markup"><code><!--
          +		
        • + Use an HTML-comment to escape your code: + +
          <pre class="language-markup"><code><!--
           <p>Example</p>
          ---></code></pre>
        • +--></code></pre>
          + + This will only work if the code element contains exactly one comment and nothing else (not even spaces). + E.g. <code> <!-- some text --></code> and <code>text<!-- more text --></code> will not work. +
        @@ -51,18 +54,18 @@

        Examples

        - + Keep markup ▲ Prism plugins - + - @@ -113,18 +116,18 @@

        FAQ

        - + Keep markup ▲ Prism plugins - + - +
        -
        +

        Unescaped markup

        Write markup without having to escape anything.

        @@ -157,13 +160,13 @@

        FAQ

        Also inline code is not as frequently copy-pasted, which was the major source of annoyance that got me to write this plugin.

        -
        +
        - + - + -->
        @@ -183,13 +186,13 @@

        FAQ

        Also inline code is not as frequently copy-pasted, which was the major source of annoyance that got me to write this plugin.

        -
        +
        - + - + diff --git a/plugins/unescaped-markup/prism-unescaped-markup.js b/plugins/unescaped-markup/prism-unescaped-markup.js index 8684ebacff..03dc4b15e1 100644 --- a/plugins/unescaped-markup/prism-unescaped-markup.js +++ b/plugins/unescaped-markup/prism-unescaped-markup.js @@ -1,44 +1,62 @@ (function () { - if (typeof self === 'undefined' || !self.Prism || !self.document || !Prism.languages.markup) { + if (typeof Prism === 'undefined' || typeof document === 'undefined') { return; } + // https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill + if (!Element.prototype.matches) { + Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; + } + + Prism.plugins.UnescapedMarkup = true; Prism.hooks.add('before-highlightall', function (env) { - env.selector += ", [class*='lang-'] script[type='text/plain'], [class*='language-'] script[type='text/plain']" + - ", script[type='text/plain'][class*='lang-'], script[type='text/plain'][class*='language-']"; + env.selector += ', [class*="lang-"] script[type="text/plain"]' + + ', [class*="language-"] script[type="text/plain"]' + + ', script[type="text/plain"][class*="lang-"]' + + ', script[type="text/plain"][class*="language-"]'; }); Prism.hooks.add('before-sanity-check', function (env) { - if ((env.element.matches || env.element.msMatchesSelector).call(env.element, "script[type='text/plain']")) { - var code = document.createElement("code"); - var pre = document.createElement("pre"); - - pre.className = code.className = env.element.className; - - if (env.element.dataset) { - Object.keys(env.element.dataset).forEach(function (key) { - if (Object.prototype.hasOwnProperty.call(env.element.dataset, key)) { - pre.dataset[key] = env.element.dataset[key]; - } - }); - } + /** @type {HTMLElement} */ + var element = env.element; + + if (element.matches('script[type="text/plain"]')) { + // found a "),t.textContent=e.code,n.appendChild(t),e.element.parentNode.replaceChild(n,e.element),e.element=t,void 0}var n=e.element.parentNode;!e.code&&n&&"pre"==n.nodeName.toLowerCase()&&e.element.childNodes.length&&"#comment"==e.element.childNodes[0].nodeName&&(e.element.textContent=e.code=e.element.childNodes[0].textContent)}))}(); \ No newline at end of file +"undefined"!=typeof Prism&&"undefined"!=typeof document&&(Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector),Prism.plugins.UnescapedMarkup=!0,Prism.hooks.add("before-highlightall",function(e){e.selector+=', [class*="lang-"] script[type="text/plain"], [class*="language-"] script[type="text/plain"], script[type="text/plain"][class*="lang-"], script[type="text/plain"][class*="language-"]'}),Prism.hooks.add("before-sanity-check",function(e){var t=e.element;if(t.matches('script[type="text/plain"]')){var a=document.createElement("code"),c=document.createElement("pre");c.className=a.className=t.className;var n=t.dataset;return Object.keys(n||{}).forEach(function(e){Object.prototype.hasOwnProperty.call(n,e)&&(c.dataset[e]=n[e])}),a.textContent=e.code=e.code.replace(/<\/script(?:>|>)/gi,"<\/script>"),c.appendChild(a),t.parentNode.replaceChild(c,t),void(e.element=a)}if(!e.code){var o=t.childNodes;1===o.length&&"#comment"==o[0].nodeName&&(t.textContent=e.code=o[0].textContent)}})); \ No newline at end of file diff --git a/plugins/wpd/index.html b/plugins/wpd/index.html index 3714a7b244..0cb0b3565c 100644 --- a/plugins/wpd/index.html +++ b/plugins/wpd/index.html @@ -3,33 +3,28 @@ - + WebPlatform Docs ▲ Prism plugins - + - + - + -
        -
        - -

        WebPlatform Docs

        -

        Makes tokens link to WebPlatform.org documentation. The links open in a new tab.

        -
        +

        How to use

        - +

        No setup required, just include the plugin in your download and you’re good to go!

        - +

        Tokens that currently link to documentation:

        - +
        • HTML, MathML and SVG tags
        • HTML, MathML and SVG non-namespaced attributes
        • @@ -38,31 +33,31 @@

          How to use

        • (Non-prefixed) CSS pseudo-classes
        • (Non-prefixed) CSS pseudo-elements (starting with ::)
        - +

        Beta: This plugin is still in beta. Please help make it better: Test it and report any false positives etc!

        Examples

        - +

        CSS

        -
        
        +	
        
         	
        
        -	
        +
         	

        HTML

        
        -	
        +
         	

        SVG

        -
        
        +	
        
         
        -
        +
        - + - + - \ No newline at end of file + diff --git a/plugins/wpd/prism-wpd.js b/plugins/wpd/prism-wpd.js index dc147d4f65..6872638e46 100644 --- a/plugins/wpd/prism-wpd.js +++ b/plugins/wpd/prism-wpd.js @@ -1,169 +1,154 @@ -(function(){ - -if ( - typeof self !== 'undefined' && !self.Prism || - typeof global !== 'undefined' && !global.Prism -) { - return; -} - -if (Prism.languages.css) { - // check whether the selector is an advanced pattern before extending it - if (Prism.languages.css.selector.pattern) - { - Prism.languages.css.selector.inside['pseudo-class'] = /:[\w-]+/; - Prism.languages.css.selector.inside['pseudo-element'] = /::[\w-]+/; +(function () { + + if (typeof Prism === 'undefined') { + return; } - else - { - Prism.languages.css.selector = { - pattern: Prism.languages.css.selector, - inside: { - 'pseudo-class': /:[\w-]+/, - 'pseudo-element': /::[\w-]+/ - } - }; + + if (Prism.languages.css) { + // check whether the selector is an advanced pattern before extending it + if (Prism.languages.css.selector.pattern) { + Prism.languages.css.selector.inside['pseudo-class'] = /:[\w-]+/; + Prism.languages.css.selector.inside['pseudo-element'] = /::[\w-]+/; + } else { + Prism.languages.css.selector = { + pattern: Prism.languages.css.selector, + inside: { + 'pseudo-class': /:[\w-]+/, + 'pseudo-element': /::[\w-]+/ + } + }; + } } -} - -if (Prism.languages.markup) { - Prism.languages.markup.tag.inside.tag.inside['tag-id'] = /[\w-]+/; - - var Tags = { - HTML: { - 'a': 1, 'abbr': 1, 'acronym': 1, 'b': 1, 'basefont': 1, 'bdo': 1, 'big': 1, 'blink': 1, 'cite': 1, 'code': 1, 'dfn': 1, 'em': 1, 'kbd': 1, 'i': 1, - 'rp': 1, 'rt': 1, 'ruby': 1, 's': 1, 'samp': 1, 'small': 1, 'spacer': 1, 'strike': 1, 'strong': 1, 'sub': 1, 'sup': 1, 'time': 1, 'tt': 1, 'u': 1, - 'var': 1, 'wbr': 1, 'noframes': 1, 'summary': 1, 'command': 1, 'dt': 1, 'dd': 1, 'figure': 1, 'figcaption': 1, 'center': 1, 'section': 1, 'nav': 1, - 'article': 1, 'aside': 1, 'hgroup': 1, 'header': 1, 'footer': 1, 'address': 1, 'noscript': 1, 'isIndex': 1, 'main': 1, 'mark': 1, 'marquee': 1, - 'meter': 1, 'menu': 1 - }, - SVG: { - 'animateColor': 1, 'animateMotion': 1, 'animateTransform': 1, 'glyph': 1, 'feBlend': 1, 'feColorMatrix': 1, 'feComponentTransfer': 1, - 'feFuncR': 1, 'feFuncG': 1, 'feFuncB': 1, 'feFuncA': 1, 'feComposite': 1, 'feConvolveMatrix': 1, 'feDiffuseLighting': 1, 'feDisplacementMap': 1, - 'feFlood': 1, 'feGaussianBlur': 1, 'feImage': 1, 'feMerge': 1, 'feMergeNode': 1, 'feMorphology': 1, 'feOffset': 1, 'feSpecularLighting': 1, - 'feTile': 1, 'feTurbulence': 1, 'feDistantLight': 1, 'fePointLight': 1, 'feSpotLight': 1, 'linearGradient': 1, 'radialGradient': 1, 'altGlyph': 1, - 'textPath': 1, 'tref': 1, 'altglyph': 1, 'textpath': 1, 'altglyphdef': 1, 'altglyphitem': 1, 'clipPath': 1, 'color-profile': 1, 'cursor': 1, - 'font-face': 1, 'font-face-format': 1, 'font-face-name': 1, 'font-face-src': 1, 'font-face-uri': 1, 'foreignObject': 1, 'glyphRef': 1, - 'hkern': 1, 'vkern': 1 - }, - MathML: {} + + if (Prism.languages.markup) { + Prism.languages.markup.tag.inside.tag.inside['tag-id'] = /[\w-]+/; + + var Tags = { + HTML: { + 'a': 1, 'abbr': 1, 'acronym': 1, 'b': 1, 'basefont': 1, 'bdo': 1, 'big': 1, 'blink': 1, 'cite': 1, 'code': 1, 'dfn': 1, 'em': 1, 'kbd': 1, 'i': 1, + 'rp': 1, 'rt': 1, 'ruby': 1, 's': 1, 'samp': 1, 'small': 1, 'spacer': 1, 'strike': 1, 'strong': 1, 'sub': 1, 'sup': 1, 'time': 1, 'tt': 1, 'u': 1, + 'var': 1, 'wbr': 1, 'noframes': 1, 'summary': 1, 'command': 1, 'dt': 1, 'dd': 1, 'figure': 1, 'figcaption': 1, 'center': 1, 'section': 1, 'nav': 1, + 'article': 1, 'aside': 1, 'hgroup': 1, 'header': 1, 'footer': 1, 'address': 1, 'noscript': 1, 'isIndex': 1, 'main': 1, 'mark': 1, 'marquee': 1, + 'meter': 1, 'menu': 1 + }, + SVG: { + 'animateColor': 1, 'animateMotion': 1, 'animateTransform': 1, 'glyph': 1, 'feBlend': 1, 'feColorMatrix': 1, 'feComponentTransfer': 1, + 'feFuncR': 1, 'feFuncG': 1, 'feFuncB': 1, 'feFuncA': 1, 'feComposite': 1, 'feConvolveMatrix': 1, 'feDiffuseLighting': 1, 'feDisplacementMap': 1, + 'feFlood': 1, 'feGaussianBlur': 1, 'feImage': 1, 'feMerge': 1, 'feMergeNode': 1, 'feMorphology': 1, 'feOffset': 1, 'feSpecularLighting': 1, + 'feTile': 1, 'feTurbulence': 1, 'feDistantLight': 1, 'fePointLight': 1, 'feSpotLight': 1, 'linearGradient': 1, 'radialGradient': 1, 'altGlyph': 1, + 'textPath': 1, 'tref': 1, 'altglyph': 1, 'textpath': 1, 'altglyphdef': 1, 'altglyphitem': 1, 'clipPath': 1, 'color-profile': 1, 'cursor': 1, + 'font-face': 1, 'font-face-format': 1, 'font-face-name': 1, 'font-face-src': 1, 'font-face-uri': 1, 'foreignObject': 1, 'glyphRef': 1, + 'hkern': 1, 'vkern': 1 + }, + MathML: {} + }; } -} -var language; + var language; -Prism.hooks.add('wrap', function(env) { - if ((env.type == 'tag-id' - || (env.type == 'property' && env.content.indexOf('-') != 0) - || (env.type == 'rule'&& env.content.indexOf('@-') != 0) - || (env.type == 'pseudo-class'&& env.content.indexOf(':-') != 0) - || (env.type == 'pseudo-element'&& env.content.indexOf('::-') != 0) - || (env.type == 'attr-name' && env.content.indexOf('data-') != 0) + Prism.hooks.add('wrap', function (env) { + if ((env.type == 'tag-id' + || (env.type == 'property' && env.content.indexOf('-') != 0) + || (env.type == 'rule' && env.content.indexOf('@-') != 0) + || (env.type == 'pseudo-class' && env.content.indexOf(':-') != 0) + || (env.type == 'pseudo-element' && env.content.indexOf('::-') != 0) + || (env.type == 'attr-name' && env.content.indexOf('data-') != 0) ) && env.content.indexOf('<') === -1 - ) { - if (env.language == 'css' - || env.language == 'scss' - || env.language == 'markup' ) { - var href = 'https://webplatform.github.io/docs/'; - var content = env.content; + if (env.language == 'css' + || env.language == 'scss' + || env.language == 'markup' + ) { + var href = 'https://webplatform.github.io/docs/'; + var content = env.content; - if (env.language == 'css' || env.language == 'scss') { - href += 'css/'; + if (env.language == 'css' || env.language == 'scss') { + href += 'css/'; - if (env.type == 'property') { - href += 'properties/'; - } - else if (env.type == 'rule') { - href += 'atrules/'; - content = content.substring(1); - } - else if (env.type == 'pseudo-class') { - href += 'selectors/pseudo-classes/'; - content = content.substring(1); - } - else if (env.type == 'pseudo-element') { - href += 'selectors/pseudo-elements/'; - content = content.substring(2); - } - } - else if (env.language == 'markup') { - if (env.type == 'tag-id') { - // Check language - language = getLanguage(env.content) || language; - - if (language) { - href += language + '/elements/'; - } - else { - return; // Abort - } - } - else if (env.type == 'attr-name') { - if (language) { - href += language + '/attributes/'; + if (env.type == 'property') { + href += 'properties/'; + } else if (env.type == 'rule') { + href += 'atrules/'; + content = content.substring(1); + } else if (env.type == 'pseudo-class') { + href += 'selectors/pseudo-classes/'; + content = content.substring(1); + } else if (env.type == 'pseudo-element') { + href += 'selectors/pseudo-elements/'; + content = content.substring(2); } - else { - return; // Abort + } else if (env.language == 'markup') { + if (env.type == 'tag-id') { + // Check language + language = getLanguage(env.content) || language; + + if (language) { + href += language + '/elements/'; + } else { + return; // Abort + } + } else if (env.type == 'attr-name') { + if (language) { + href += language + '/attributes/'; + } else { + return; // Abort + } } } - } - href += content; - env.tag = 'a'; - env.attributes.href = href; - env.attributes.target = '_blank'; + href += content; + env.tag = 'a'; + env.attributes.href = href; + env.attributes.target = '_blank'; + } } - } -}); + }); -function getLanguage(tag) { - var tagL = tag.toLowerCase(); - - if (Tags.HTML[tagL]) { - return 'html'; - } - else if (Tags.SVG[tag]) { - return 'svg'; - } - else if (Tags.MathML[tag]) { - return 'mathml'; - } - - // Not in dictionary, perform check - if (Tags.HTML[tagL] !== 0 && typeof document !== 'undefined') { - var htmlInterface = (document.createElement(tag).toString().match(/\[object HTML(.+)Element\]/) || [])[1]; - - if (htmlInterface && htmlInterface != 'Unknown') { - Tags.HTML[tagL] = 1; + function getLanguage(tag) { + var tagL = tag.toLowerCase(); + + if (Tags.HTML[tagL]) { return 'html'; - } - } - - Tags.HTML[tagL] = 0; - - if (Tags.SVG[tag] !== 0 && typeof document !== 'undefined') { - var svgInterface = (document.createElementNS('http://www.w3.org/2000/svg', tag).toString().match(/\[object SVG(.+)Element\]/) || [])[1]; - - if (svgInterface && svgInterface != 'Unknown') { - Tags.SVG[tag] = 1; + } else if (Tags.SVG[tag]) { return 'svg'; - } - } - - Tags.SVG[tag] = 0; - - // Lame way to detect MathML, but browsers don’t expose interface names there :( - if (Tags.MathML[tag] !== 0) { - if (tag.indexOf('m') === 0) { - Tags.MathML[tag] = 1; + } else if (Tags.MathML[tag]) { return 'mathml'; } + + // Not in dictionary, perform check + if (Tags.HTML[tagL] !== 0 && typeof document !== 'undefined') { + var htmlInterface = (document.createElement(tag).toString().match(/\[object HTML(.+)Element\]/) || [])[1]; + + if (htmlInterface && htmlInterface != 'Unknown') { + Tags.HTML[tagL] = 1; + return 'html'; + } + } + + Tags.HTML[tagL] = 0; + + if (Tags.SVG[tag] !== 0 && typeof document !== 'undefined') { + var svgInterface = (document.createElementNS('http://www.w3.org/2000/svg', tag).toString().match(/\[object SVG(.+)Element\]/) || [])[1]; + + if (svgInterface && svgInterface != 'Unknown') { + Tags.SVG[tag] = 1; + return 'svg'; + } + } + + Tags.SVG[tag] = 0; + + // Lame way to detect MathML, but browsers don’t expose interface names there :( + if (Tags.MathML[tag] !== 0) { + if (tag.indexOf('m') === 0) { + Tags.MathML[tag] = 1; + return 'mathml'; + } + } + + Tags.MathML[tag] = 0; + + return null; } - - Tags.MathML[tag] = 0; - - return null; -} -})(); \ No newline at end of file +}()); diff --git a/plugins/wpd/prism-wpd.min.css b/plugins/wpd/prism-wpd.min.css new file mode 100644 index 0000000000..43b0cf6112 --- /dev/null +++ b/plugins/wpd/prism-wpd.min.css @@ -0,0 +1 @@ +code[class*=language-] a[href],pre[class*=language-] a[href]{cursor:help;text-decoration:none}code[class*=language-] a[href]:hover,pre[class*=language-] a[href]:hover{cursor:help;text-decoration:underline} \ No newline at end of file diff --git a/plugins/wpd/prism-wpd.min.js b/plugins/wpd/prism-wpd.min.js index 86bad36272..4d2f395544 100644 --- a/plugins/wpd/prism-wpd.min.js +++ b/plugins/wpd/prism-wpd.min.js @@ -1 +1 @@ -!function(){function e(e){var n=e.toLowerCase();if(t.HTML[n])return"html";if(t.SVG[e])return"svg";if(t.MathML[e])return"mathml";if(0!==t.HTML[n]&&"undefined"!=typeof document){var a=(document.createElement(e).toString().match(/\[object HTML(.+)Element\]/)||[])[1];if(a&&"Unknown"!=a)return t.HTML[n]=1,"html"}if(t.HTML[n]=0,0!==t.SVG[e]&&"undefined"!=typeof document){var s=(document.createElementNS("http://www.w3.org/2000/svg",e).toString().match(/\[object SVG(.+)Element\]/)||[])[1];if(s&&"Unknown"!=s)return t.SVG[e]=1,"svg"}return t.SVG[e]=0,0!==t.MathML[e]&&0===e.indexOf("m")?(t.MathML[e]=1,"mathml"):(t.MathML[e]=0,null)}if(("undefined"==typeof self||self.Prism)&&("undefined"==typeof global||global.Prism)){if(Prism.languages.css&&(Prism.languages.css.selector.pattern?(Prism.languages.css.selector.inside["pseudo-class"]=/:[\w-]+/,Prism.languages.css.selector.inside["pseudo-element"]=/::[\w-]+/):Prism.languages.css.selector={pattern:Prism.languages.css.selector,inside:{"pseudo-class":/:[\w-]+/,"pseudo-element":/::[\w-]+/}}),Prism.languages.markup){Prism.languages.markup.tag.inside.tag.inside["tag-id"]=/[\w-]+/;var t={HTML:{a:1,abbr:1,acronym:1,b:1,basefont:1,bdo:1,big:1,blink:1,cite:1,code:1,dfn:1,em:1,kbd:1,i:1,rp:1,rt:1,ruby:1,s:1,samp:1,small:1,spacer:1,strike:1,strong:1,sub:1,sup:1,time:1,tt:1,u:1,"var":1,wbr:1,noframes:1,summary:1,command:1,dt:1,dd:1,figure:1,figcaption:1,center:1,section:1,nav:1,article:1,aside:1,hgroup:1,header:1,footer:1,address:1,noscript:1,isIndex:1,main:1,mark:1,marquee:1,meter:1,menu:1},SVG:{animateColor:1,animateMotion:1,animateTransform:1,glyph:1,feBlend:1,feColorMatrix:1,feComponentTransfer:1,feFuncR:1,feFuncG:1,feFuncB:1,feFuncA:1,feComposite:1,feConvolveMatrix:1,feDiffuseLighting:1,feDisplacementMap:1,feFlood:1,feGaussianBlur:1,feImage:1,feMerge:1,feMergeNode:1,feMorphology:1,feOffset:1,feSpecularLighting:1,feTile:1,feTurbulence:1,feDistantLight:1,fePointLight:1,feSpotLight:1,linearGradient:1,radialGradient:1,altGlyph:1,textPath:1,tref:1,altglyph:1,textpath:1,altglyphdef:1,altglyphitem:1,clipPath:1,"color-profile":1,cursor:1,"font-face":1,"font-face-format":1,"font-face-name":1,"font-face-src":1,"font-face-uri":1,foreignObject:1,glyphRef:1,hkern:1,vkern:1},MathML:{}}}var n;Prism.hooks.add("wrap",function(t){if(("tag-id"==t.type||"property"==t.type&&0!=t.content.indexOf("-")||"rule"==t.type&&0!=t.content.indexOf("@-")||"pseudo-class"==t.type&&0!=t.content.indexOf(":-")||"pseudo-element"==t.type&&0!=t.content.indexOf("::-")||"attr-name"==t.type&&0!=t.content.indexOf("data-"))&&-1===t.content.indexOf("<")&&("css"==t.language||"scss"==t.language||"markup"==t.language)){var a="https://webplatform.github.io/docs/",s=t.content;if("css"==t.language||"scss"==t.language)a+="css/","property"==t.type?a+="properties/":"rule"==t.type?(a+="atrules/",s=s.substring(1)):"pseudo-class"==t.type?(a+="selectors/pseudo-classes/",s=s.substring(1)):"pseudo-element"==t.type&&(a+="selectors/pseudo-elements/",s=s.substring(2));else if("markup"==t.language)if("tag-id"==t.type){if(n=e(t.content)||n,!n)return;a+=n+"/elements/"}else if("attr-name"==t.type){if(!n)return;a+=n+"/attributes/"}a+=s,t.tag="a",t.attributes.href=a,t.attributes.target="_blank"}})}}(); \ No newline at end of file +!function(){if("undefined"!=typeof Prism){if(Prism.languages.css&&(Prism.languages.css.selector.pattern?(Prism.languages.css.selector.inside["pseudo-class"]=/:[\w-]+/,Prism.languages.css.selector.inside["pseudo-element"]=/::[\w-]+/):Prism.languages.css.selector={pattern:Prism.languages.css.selector,inside:{"pseudo-class":/:[\w-]+/,"pseudo-element":/::[\w-]+/}}),Prism.languages.markup){Prism.languages.markup.tag.inside.tag.inside["tag-id"]=/[\w-]+/;var s={HTML:{a:1,abbr:1,acronym:1,b:1,basefont:1,bdo:1,big:1,blink:1,cite:1,code:1,dfn:1,em:1,kbd:1,i:1,rp:1,rt:1,ruby:1,s:1,samp:1,small:1,spacer:1,strike:1,strong:1,sub:1,sup:1,time:1,tt:1,u:1,var:1,wbr:1,noframes:1,summary:1,command:1,dt:1,dd:1,figure:1,figcaption:1,center:1,section:1,nav:1,article:1,aside:1,hgroup:1,header:1,footer:1,address:1,noscript:1,isIndex:1,main:1,mark:1,marquee:1,meter:1,menu:1},SVG:{animateColor:1,animateMotion:1,animateTransform:1,glyph:1,feBlend:1,feColorMatrix:1,feComponentTransfer:1,feFuncR:1,feFuncG:1,feFuncB:1,feFuncA:1,feComposite:1,feConvolveMatrix:1,feDiffuseLighting:1,feDisplacementMap:1,feFlood:1,feGaussianBlur:1,feImage:1,feMerge:1,feMergeNode:1,feMorphology:1,feOffset:1,feSpecularLighting:1,feTile:1,feTurbulence:1,feDistantLight:1,fePointLight:1,feSpotLight:1,linearGradient:1,radialGradient:1,altGlyph:1,textPath:1,tref:1,altglyph:1,textpath:1,altglyphdef:1,altglyphitem:1,clipPath:1,"color-profile":1,cursor:1,"font-face":1,"font-face-format":1,"font-face-name":1,"font-face-src":1,"font-face-uri":1,foreignObject:1,glyphRef:1,hkern:1,vkern:1},MathML:{}}}var a;Prism.hooks.add("wrap",function(e){if(("tag-id"==e.type||"property"==e.type&&0!=e.content.indexOf("-")||"rule"==e.type&&0!=e.content.indexOf("@-")||"pseudo-class"==e.type&&0!=e.content.indexOf(":-")||"pseudo-element"==e.type&&0!=e.content.indexOf("::-")||"attr-name"==e.type&&0!=e.content.indexOf("data-"))&&-1===e.content.indexOf("<")&&("css"==e.language||"scss"==e.language||"markup"==e.language)){var t="https://webplatform.github.io/docs/",n=e.content;if("css"==e.language||"scss"==e.language)t+="css/","property"==e.type?t+="properties/":"rule"==e.type?(t+="atrules/",n=n.substring(1)):"pseudo-class"==e.type?(t+="selectors/pseudo-classes/",n=n.substring(1)):"pseudo-element"==e.type&&(t+="selectors/pseudo-elements/",n=n.substring(2));else if("markup"==e.language)if("tag-id"==e.type){if(!(a=function(e){var t=e.toLowerCase();{if(s.HTML[t])return"html";if(s.SVG[e])return"svg";if(s.MathML[e])return"mathml"}if(0!==s.HTML[t]&&"undefined"!=typeof document){var n=(document.createElement(e).toString().match(/\[object HTML(.+)Element\]/)||[])[1];if(n&&"Unknown"!=n)return s.HTML[t]=1,"html"}if((s.HTML[t]=0)!==s.SVG[e]&&"undefined"!=typeof document){var a=(document.createElementNS("http://www.w3.org/2000/svg",e).toString().match(/\[object SVG(.+)Element\]/)||[])[1];if(a&&"Unknown"!=a)return s.SVG[e]=1,"svg"}if((s.SVG[e]=0)!==s.MathML[e]&&0===e.indexOf("m"))return s.MathML[e]=1,"mathml";return s.MathML[e]=0,null}(e.content)||a))return;t+=a+"/elements/"}else if("attr-name"==e.type){if(!a)return;t+=a+"/attributes/"}t+=n,e.tag="a",e.attributes.href=t,e.attributes.target="_blank"}})}}(); \ No newline at end of file diff --git a/prism.js b/prism.js index 6cbfbb4d98..04e9a28e61 100644 --- a/prism.js +++ b/prism.js @@ -3,328 +3,963 @@ Begin prism-core.js ********************************************** */ +/// + var _self = (typeof window !== 'undefined') ? window // if in browser : ( (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) - ? self // if in worker - : {} // if in node js + ? self // if in worker + : {} // if in node js ); /** * Prism: Lightweight, robust, elegant syntax highlighting - * MIT license http://www.opensource.org/licenses/mit-license.php/ - * @author Lea Verou http://lea.verou.me + * + * @license MIT + * @author Lea Verou + * @namespace + * @public */ +var Prism = (function (_self) { -var Prism = (function(){ - -// Private helper vars -var lang = /\blang(?:uage)?-([\w-]+)\b/i; -var uniqueId = 0; - -var _ = _self.Prism = { - manual: _self.Prism && _self.Prism.manual, - disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler, - util: { - encode: function (tokens) { - if (tokens instanceof Token) { - return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias); - } else if (_.util.type(tokens) === 'Array') { - return tokens.map(_.util.encode); - } else { - return tokens.replace(/&/g, '&').replace(/ to load Prism's script + * ``` + * + * @default false + * @type {boolean} + * @memberof Prism + * @public + */ + manual: _self.Prism && _self.Prism.manual, + /** + * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses + * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your + * own worker, you don't want it to do this. + * + * By setting this value to `true`, Prism will not add its own listeners to the worker. + * + * You obviously have to change this value before Prism executes. To do this, you can add an + * empty Prism object into the global scope before loading the Prism script like this: + * + * ```js + * window.Prism = window.Prism || {}; + * Prism.disableWorkerMessageHandler = true; + * // Load Prism's script + * ``` + * + * @default false + * @type {boolean} + * @memberof Prism + * @public + */ + disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler, - switch (type) { - case 'Object': - if (visited[_.util.objId(o)]) { - return visited[_.util.objId(o)]; - } - var clone = {}; - visited[_.util.objId(o)] = clone; + /** + * A namespace for utility methods. + * + * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may + * change or disappear at any time. + * + * @namespace + * @memberof Prism + */ + util: { + encode: function encode(tokens) { + if (tokens instanceof Token) { + return new Token(tokens.type, encode(tokens.content), tokens.alias); + } else if (Array.isArray(tokens)) { + return tokens.map(encode); + } else { + return tokens.replace(/&/g, '&').replace(/} [visited] + * @returns {T} + * @template T + */ + clone: function deepClone(o, visited) { + visited = visited || {}; + + var clone; var id; + switch (_.util.type(o)) { + case 'Object': + id = _.util.objId(o); + if (visited[id]) { + return visited[id]; + } + clone = /** @type {Record} */ ({}); + visited[id] = clone; + + for (var key in o) { + if (o.hasOwnProperty(key)) { + clone[key] = deepClone(o[key], visited); + } } - } - return clone; + return /** @type {any} */ (clone); - case 'Array': - if (visited[_.util.objId(o)]) { - return visited[_.util.objId(o)]; - } - var clone = []; - visited[_.util.objId(o)] = clone; + case 'Array': + id = _.util.objId(o); + if (visited[id]) { + return visited[id]; + } + clone = []; + visited[id] = clone; - o.forEach(function (v, i) { - clone[i] = _.util.clone(v, visited); - }); + (/** @type {Array} */(/** @type {any} */(o))).forEach(function (v, i) { + clone[i] = deepClone(v, visited); + }); - return clone; - } + return /** @type {any} */ (clone); - return o; - } - }, + default: + return o; + } + }, - languages: { - extend: function (id, redef) { - var lang = _.util.clone(_.languages[id]); + /** + * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class. + * + * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned. + * + * @param {Element} element + * @returns {string} + */ + getLanguage: function (element) { + while (element) { + var m = lang.exec(element.className); + if (m) { + return m[1].toLowerCase(); + } + element = element.parentElement; + } + return 'none'; + }, - for (var key in redef) { - lang[key] = redef[key]; - } + /** + * Sets the Prism `language-xxxx` class of the given element. + * + * @param {Element} element + * @param {string} language + * @returns {void} + */ + setLanguage: function (element, language) { + // remove all `language-xxxx` classes + // (this might leave behind a leading space) + element.className = element.className.replace(RegExp(lang, 'gi'), ''); + + // add the new `language-xxxx` class + // (using `classList` will automatically clean up spaces for us) + element.classList.add('language-' + language); + }, + + /** + * Returns the script element that is currently executing. + * + * This does __not__ work for line script element. + * + * @returns {HTMLScriptElement | null} + */ + currentScript: function () { + if (typeof document === 'undefined') { + return null; + } + if ('currentScript' in document && 1 < 2 /* hack to trip TS' flow analysis */) { + return /** @type {any} */ (document.currentScript); + } - return lang; + // IE11 workaround + // we'll get the src of the current script by parsing IE11's error stack trace + // this will not work for inline scripts + + try { + throw new Error(); + } catch (err) { + // Get file src url from stack. Specifically works with the format of stack traces in IE. + // A stack will look like this: + // + // Error + // at _.util.currentScript (http://localhost/components/prism-core.js:119:5) + // at Global code (http://localhost/components/prism-core.js:606:1) + + var src = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(err.stack) || [])[1]; + if (src) { + var scripts = document.getElementsByTagName('script'); + for (var i in scripts) { + if (scripts[i].src == src) { + return scripts[i]; + } + } + } + return null; + } + }, + + /** + * Returns whether a given class is active for `element`. + * + * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated + * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the + * given class is just the given class with a `no-` prefix. + * + * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is + * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its + * ancestors have the given class or the negated version of it, then the default activation will be returned. + * + * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated + * version of it, the class is considered active. + * + * @param {Element} element + * @param {string} className + * @param {boolean} [defaultActivation=false] + * @returns {boolean} + */ + isActive: function (element, className, defaultActivation) { + var no = 'no-' + className; + + while (element) { + var classList = element.classList; + if (classList.contains(className)) { + return true; + } + if (classList.contains(no)) { + return false; + } + element = element.parentElement; + } + return !!defaultActivation; + } }, /** - * Insert a token before another token in a language literal - * As this needs to recreate the object (we cannot actually insert before keys in object literals), - * we cannot just provide an object, we need anobject and a key. - * @param inside The key (or language id) of the parent - * @param before The key to insert before. If not provided, the function appends instead. - * @param insert Object with the key/value pairs to insert - * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted. + * This namespace contains all currently loaded languages and the some helper functions to create and modify languages. + * + * @namespace + * @memberof Prism + * @public */ - insertBefore: function (inside, before, insert, root) { - root = root || _.languages; - var grammar = root[inside]; + languages: { + /** + * The grammar for plain, unformatted text. + */ + plain: plainTextGrammar, + plaintext: plainTextGrammar, + text: plainTextGrammar, + txt: plainTextGrammar, + + /** + * Creates a deep copy of the language with the given id and appends the given tokens. + * + * If a token in `redef` also appears in the copied language, then the existing token in the copied language + * will be overwritten at its original position. + * + * ## Best practices + * + * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language) + * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to + * understand the language definition because, normally, the order of tokens matters in Prism grammars. + * + * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens. + * Furthermore, all non-overwriting tokens should be placed after the overwriting ones. + * + * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`. + * @param {Grammar} redef The new tokens to append. + * @returns {Grammar} The new language created. + * @public + * @example + * Prism.languages['css-with-colors'] = Prism.languages.extend('css', { + * // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token + * // at its original position + * 'comment': { ... }, + * // CSS doesn't have a 'color' token, so this token will be appended + * 'color': /\b(?:red|green|blue)\b/ + * }); + */ + extend: function (id, redef) { + var lang = _.util.clone(_.languages[id]); + + for (var key in redef) { + lang[key] = redef[key]; + } - if (arguments.length == 2) { - insert = arguments[1]; + return lang; + }, + + /** + * Inserts tokens _before_ another token in a language definition or any other grammar. + * + * ## Usage + * + * This helper method makes it easy to modify existing languages. For example, the CSS language definition + * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded + * in HTML through ` - + - +
        -
        +

        Test drive

        Take Prism for a spin!

        @@ -75,25 +149,97 @@

        Test drive

        Result:

        +
        + + +

        Language:

        -
        +
        - - + + + + - - + + diff --git a/tests/aliases-test.js b/tests/aliases-test.js new file mode 100644 index 0000000000..892cb5005a --- /dev/null +++ b/tests/aliases-test.js @@ -0,0 +1,72 @@ +'use strict'; + +const { assert } = require('chai'); +const PrismLoader = require('./helper/prism-loader'); +const { languages } = require('./../components.json'); + + +function toArray(value) { + if (Array.isArray(value)) { + return value; + } else if (value === undefined) { + return []; + } + return [value]; +} + +// the keys of Prism.languages without any loaded languages (basically just a few functions) +const ignoreKeys = Object.keys(PrismLoader.createEmptyPrism().languages); + + +for (const lang in languages) { + if (lang === 'meta') { + continue; + } + + describe(`Testing language aliases of '${lang}'`, function () { + + if (languages[lang].aliasTitles) { + it('- should have all alias titles registered as alias', function () { + let aliases = new Set(toArray(languages[lang].alias)); + + Object.keys(languages[lang].aliasTitles).forEach(id => { + if (!aliases.has(id)) { + const titleJson = JSON.stringify(languages[lang].aliasTitles[id]); + assert.fail(`The alias '${id}' with the title ${titleJson} is not registered as an alias.`); + } + }); + }); + } + + it('- should known all aliases', function () { + + let loadedLanguages = new Set(Object.keys(PrismLoader.createInstance(lang).languages)); + + // check that all aliases are defined + toArray(languages[lang].alias).forEach(alias => { + assert.isTrue(loadedLanguages.has(alias), `The registered alias '${alias}' is not present.`); + }); + + + // remove ignore keys + ignoreKeys.forEach(x => loadedLanguages.delete(x)); + + // remove language, aliases, and requirements + function remove(lang) { + loadedLanguages.delete(lang); + toArray(languages[lang].alias).forEach(alias => loadedLanguages.delete(alias)); + + // remove recursively + toArray(languages[lang].require).forEach(id => remove(id)); + } + remove(lang); + + + // there should be nothing left + if (loadedLanguages.size > 0) { + const unregisteredAliases = `(${loadedLanguages.size}) ${JSON.stringify([...loadedLanguages])}`; + assert.fail(`There are unregistered aliases: ${unregisteredAliases}`); + } + }); + }); +} diff --git a/tests/core/greedy.js b/tests/core/greedy.js new file mode 100644 index 0000000000..8d2b81b80e --- /dev/null +++ b/tests/core/greedy.js @@ -0,0 +1,122 @@ +'use strict'; + +const { assert } = require('chai'); +const PrismLoader = require('../helper/prism-loader'); +const TestCase = require('../helper/test-case'); +const TokenStreamTransformer = require('../helper/token-stream-transformer'); + + +function testTokens({ grammar, code, expected }) { + const Prism = PrismLoader.createEmptyPrism(); + Prism.languages.test = grammar; + + const simpleTokens = TokenStreamTransformer.simplify(TestCase.tokenize(Prism, code, 'test')); + + assert.deepStrictEqual(simpleTokens, expected); +} + +describe('Greedy matching', function () { + + it('should correctly handle tokens with the same name', function () { + testTokens({ + grammar: { + 'comment': [ + /\/\/.*/, + { + pattern: /\/\*[\s\S]*?(?:\*\/|$)/, + greedy: true + } + ] + }, + code: '// /*\n/* comment */', + expected: [ + ['comment', '// /*'], + ['comment', '/* comment */'] + ] + }); + }); + + it('should support patterns with top-level alternatives that do not contain the lookbehind group', function () { + testTokens({ + grammar: { + 'a': /'[^']*'/, + 'b': { + // This pattern has 2 top-level alternatives: foo and (^|[^\\])"[^"]*" + pattern: /foo|(^|[^\\])"[^"]*"/, + lookbehind: true, + greedy: true + } + }, + code: 'foo "bar" \'baz\'', + expected: [ + ['b', 'foo'], + ['b', '"bar"'], + ['a', "'baz'"] + ] + }); + }); + + it('should correctly rematch tokens', function () { + testTokens({ + grammar: { + 'a': { + pattern: /'[^'\r\n]*'/, + }, + 'b': { + pattern: /"[^"\r\n]*"/, + greedy: true, + }, + 'c': { + pattern: /<[^>\r\n]*>/, + greedy: true, + } + }, + code: `<'> '' ''\n<"> "" ""`, + expected: [ + ['c', "<'>"], + " '", + ['a', "' '"], + "'\n", + + ['c', '<">'], + ['b', '""'], + ['b', '""'], + ] + }); + }); + + it('should always match tokens against the whole text', function () { + // this is to test for a bug where greedy tokens where matched like non-greedy ones if the token stream ended on + // a string + testTokens({ + grammar: { + 'a': /a/, + 'b': { + pattern: /^b/, + greedy: true + } + }, + code: 'bab', + expected: [ + ['b', 'b'], + ['a', 'a'], + 'b' + ] + }); + }); + + it('issue3052', function () { + // If a greedy pattern creates an empty token at the end of the string, then this token should be discarded + testTokens({ + grammar: { + 'oh-no': { + pattern: /$/, + greedy: true + } + }, + code: 'foo', + expected: ['foo'] + }); + }); + +}); diff --git a/tests/coverage.js b/tests/coverage.js new file mode 100644 index 0000000000..cd7175789f --- /dev/null +++ b/tests/coverage.js @@ -0,0 +1,260 @@ +'use strict'; + +const TestDiscovery = require('./helper/test-discovery'); +const TestCase = require('./helper/test-case'); +const PrismLoader = require('./helper/prism-loader'); +const { BFS, BFSPathToPrismTokenPath } = require('./helper/util'); +const { assert } = require('chai'); +const components = require('../components.json'); +const ALL_LANGUAGES = [...Object.keys(components.languages).filter(k => k !== 'meta')]; + + +describe('Pattern test coverage', function () { + /** + * @type {Map} + * @typedef PatternData + * @property {RegExp} pattern + * @property {string} language + * @property {Set} from + * @property {RegExpExecArray[]} matches + */ + const patterns = new Map(); + + /** + * @param {string | string[]} languages + * @returns {import("./helper/prism-loader").Prism} + */ + function createInstance(languages) { + const Prism = PrismLoader.createInstance(languages); + + BFS(Prism.languages, (path, object) => { + const { key, value } = path[path.length - 1]; + const tokenPath = BFSPathToPrismTokenPath(path); + + if (Object.prototype.toString.call(value) == '[object RegExp]') { + const regex = makeGlobal(value); + object[key] = regex; + + const patternKey = String(regex); + let data = patterns.get(patternKey); + if (!data) { + data = { + pattern: regex, + language: path[1].key, + from: new Set([tokenPath]), + matches: [] + }; + patterns.set(patternKey, data); + } else { + data.from.add(tokenPath); + } + + regex.exec = string => { + let match = RegExp.prototype.exec.call(regex, string); + if (match) { + data.matches.push(match); + } + return match; + }; + } + }); + + return Prism; + } + + describe('Register all patterns', function () { + it('all', function () { + this.slow(10 * 1000); + // This will cause ALL regexes of Prism to be registered in the patterns map. + // (Languages that don't have any tests can't be caught otherwise.) + createInstance(ALL_LANGUAGES); + }); + }); + + describe('Run all language tests', function () { + // define tests for all tests in all languages in the test suite + for (const [languageIdentifier, files] of TestDiscovery.loadAllTests()) { + it(languageIdentifier, function () { + this.timeout(10 * 1000); + + for (const filePath of files) { + try { + TestCase.run({ + languageIdentifier, + filePath, + updateMode: 'none', + createInstance + }); + } catch (error) { + // we don't case about whether the test succeeds, + // we just want to gather usage data + } + } + }); + } + }); + + describe('Coverage', function () { + for (const language of ALL_LANGUAGES) { + describe(language, function () { + it(`- should cover all patterns`, function () { + const untested = getAllOf(language).filter(d => d.matches.length === 0); + if (untested.length === 0) { + return; + } + + const problems = untested.map(data => { + return formatProblem(data, [ + 'This pattern is completely untested. Add test files that match this pattern.' + ]); + }); + + assert.fail([ + `${problems.length} pattern(s) are untested:\n` + + 'You can learn more about writing tests at https://prismjs.com/test-suite.html#writing-tests', + ...problems + ].join('\n\n')); + }); + + it(`- should exhaustively cover all keywords in keyword lists`, function () { + const problems = []; + + for (const data of getAllOf(language)) { + if (data.matches.length === 0) { + // don't report the same pattern twice + continue; + } + + const keywords = getKeywordList(data.pattern); + if (!keywords) { + continue; + } + const keywordCount = keywords.size; + + data.matches.forEach(([m]) => { + if (data.pattern.ignoreCase) { + m = m.toUpperCase(); + } + keywords.delete(m); + }); + + if (keywords.size > 0) { + problems.push(formatProblem(data, [ + `Add test files to test all keywords. The following keywords (${keywords.size}/${keywordCount}) are untested:`, + ...[...keywords].map(k => ` ${k}`) + ])); + } + } + + if (problems.length === 0) { + return; + } + + assert.fail([ + `${problems.length} keyword list(s) are not exhaustively tested:\n` + + 'You can learn more about writing tests at https://prismjs.com/test-suite.html#writing-tests', + ...problems + ].join('\n\n')); + }); + }); + } + }); + + /** + * @param {string} language + * @returns {PatternData[]} + */ + function getAllOf(language) { + return [...patterns.values()].filter(d => d.language === language); + } + + /** + * @param {string} string + * @param {number} maxLength + * @returns {string} + */ + function short(string, maxLength) { + if (string.length > maxLength) { + return string.slice(0, maxLength - 1) + '…'; + } else { + return string; + } + } + + /** + * If the given pattern string describes a keyword list, all keyword will be returned. Otherwise, `null` will be + * returned. + * + * @param {RegExp} pattern + * @returns {Set | null} + */ + function getKeywordList(pattern) { + // Right now, only keyword lists of the form /\b(?:foo|bar)\b/ are supported. + // In the future, we might want to convert these regexes to NFAs and iterate all words to cover more complex + // keyword lists and even operator and punctuation lists. + + let source = pattern.source.replace(/^\\b|\\b$/g, ''); + if (source.startsWith('(?:') && source.endsWith(')')) { + source = source.slice('(?:'.length, source.length - ')'.length); + } + + if (/^\w+(?:\|\w+)*$/.test(source)) { + if (pattern.ignoreCase) { + source = source.toUpperCase(); + } + return new Set(source.split(/\|/g)); + } else { + return null; + } + } + + /** + * @param {Iterable} occurrences + * @returns {{ origin: string; otherOccurrences: string[] }} + */ + function splitOccurrences(occurrences) { + const all = [...occurrences]; + return { + origin: all[0], + otherOccurrences: all.slice(1), + }; + } + + /** + * @param {PatternData} data + * @param {string[]} messageLines + * @returns {string} + */ + function formatProblem(data, messageLines) { + const { origin, otherOccurrences } = splitOccurrences(data.from); + + const lines = [ + `${origin}:`, + short(String(data.pattern), 100), + '', + ...messageLines, + ]; + + if (otherOccurrences.length) { + lines.push( + '', + 'Other occurrences of this pattern:', + ...otherOccurrences.map(o => `- ${o}`) + ); + } + + return lines.join('\n '); + } +}); + +/** + * @param {RegExp} regex + * @returns {RegExp} + */ +function makeGlobal(regex) { + if (regex.global) { + return regex; + } else { + return RegExp(regex.source, regex.flags + 'g'); + } +} diff --git a/tests/dependencies-test.js b/tests/dependencies-test.js new file mode 100644 index 0000000000..ebacf5bf7f --- /dev/null +++ b/tests/dependencies-test.js @@ -0,0 +1,428 @@ +const { assert } = require('chai'); +const getLoader = require('../dependencies'); +const components = require('../components.json'); + + +describe('Dependency logic', function () { + + /** @type {import("../dependencies").Components} */ + const components = { + languages: { + 'a': { + alias: 'a2' + }, + 'b': { + alias: 'b2' + }, + 'c': { + require: 'a', + optional: ['b', 'e'] + }, + 'd': { + require: ['c', 'b'], + alias: 'xyz' + }, + }, + pluginsOrSomething: { + 'e': { + modify: 'a' + }, + } + }; + + /** + * Returns the ids of `getLoader`. + * + * @param {string[]} load + * @param {string[]} [loaded] + * @returns {string[]} + */ + function getIds(load, loaded) { + return getLoader(components, load, loaded).getIds(); + } + + describe('Returned ids', function () { + + it('- should load requirements', function () { + assert.sameMembers(getIds(['d']), ['a', 'b', 'c', 'd']); + }); + + it('- should not load already loaded requirements if not necessary', function () { + assert.sameMembers(getIds(['d'], ['a', 'b']), ['c', 'd']); + }); + + it('- should load already loaded requirements if requested', function () { + assert.sameMembers(getIds(['a', 'd'], ['a', 'b']), ['a', 'c', 'd']); + }); + + it('- should reload modified components', function () { + assert.sameMembers(getIds(['e'], ['a', 'b', 'c', 'd']), ['a', 'c', 'd', 'e']); + }); + + it('- should work with empty load', function () { + assert.sameMembers(getIds([], ['a', 'b', 'c', 'd']), []); + }); + + it('- should return unknown ids as is', function () { + assert.sameMembers(getIds(['c', 'foo'], ['bar']), ['foo', 'c', 'a']); + }); + + it('- should throw on unknown dependencies', function () { + assert.throws(() => { + /** @type {import("../dependencies").Components} */ + const circular = { + languages: { + a: { + require: 'c' + }, + b: 'B' + } + }; + getLoader(circular, ['a']).getIds(); + }); + }); + + }); + + describe('Load order', function () { + + // Note: The order of a and b isn't defined, so don't add any test with both of them being loaded here + + it('- should load components in the correct order (require)', function () { + assert.deepStrictEqual(getIds(['c']), ['a', 'c']); + }); + + it('- should load components in the correct order (modify)', function () { + assert.deepStrictEqual(getIds(['e', 'a']), ['a', 'e']); + }); + + it('- should load components in the correct order (optional)', function () { + assert.deepStrictEqual(getIds(['c', 'b'], ['a']), ['b', 'c']); + }); + + it('- should load components in the correct order (require + optional)', function () { + assert.deepStrictEqual(getIds(['d'], ['a']), ['b', 'c', 'd']); + }); + + it('- should load components in the correct order (require + modify + optional)', function () { + assert.deepStrictEqual(getIds(['d', 'e'], ['b']), ['a', 'e', 'c', 'd']); + }); + + }); + + describe('Aliases', function () { + + it('- should resolve aliases in the list of components to load', function () { + assert.sameMembers(getIds(['xyz']), ['a', 'b', 'c', 'd']); + }); + + it('- should resolve aliases in the list of loaded components', function () { + assert.sameMembers(getIds(['d'], ['a', 'a2', 'b2']), ['c', 'd']); + }); + + it('- should throw on duplicate aliases', function () { + assert.throws(() => { + /** @type {import("../dependencies").Components} */ + const circular = { + languages: { + a: { + alias: 'c' + }, + b: { + alias: 'c' + } + } + }; + getLoader(circular, ['a', 'foo' /* force the lazy alias resolver */]).getIds(); + }); + }); + + it('- should throw on aliases which are components', function () { + assert.throws(() => { + /** @type {import("../dependencies").Components} */ + const circular = { + languages: { + a: { + alias: 'b' + }, + b: 'B' + } + }; + getLoader(circular, ['a', 'foo' /* force the lazy alias resolver */]).getIds(); + }); + }); + + }); + + describe('Circular dependencies', function () { + + it('- should throw on circular dependencies', function () { + assert.throws(() => { + /** @type {import("../dependencies").Components} */ + const circular = { + languages: { + a: { + require: 'b' + }, + b: { + optional: 'a' + } + } + }; + getLoader(circular, ['a']).getIds(); + }); + }); + + }); + + describe('Async loading', function () { + + it('- should load components in the correct order', async function () { + + /** @type {import("../dependencies").Components} */ + const localComponents = { + languages: { + 'a': {}, + 'b': { + require: 'a' + }, + 'c': { + require: 'b' + } + } + }; + + /** @type {string[]} */ + const actualLoadOrder = []; + /** @type {string[]} */ + const actualResolveOrder = []; + + /** + * + * @param {string} id + * @returns {Promise} + */ + function loadComp(id) { + actualLoadOrder.push(id); + + // the idea is that the components which have to be loaded first, take the longest, so if all were to + // start getting loaded at the same time, their order would be the reverse of the expected order. + let delay; + if (id === 'a') { + delay = 30; + } else if (id === 'b') { + delay = 20; + } else if (id === 'c') { + delay = 10; + } + + return new Promise((resolve) => { + setTimeout(() => { + actualResolveOrder.push(id); + resolve(); + }, delay); + }); + } + + const loader = getLoader(localComponents, ['c']); + + await loader.load(id => loadComp(id), { + series: async (before, after) => { + await before; + await after(); + }, + parallel: async (values) => { + await Promise.all(values); + } + }); + + assert.deepStrictEqual(actualLoadOrder, ['a', 'b', 'c'], 'actualLoadOrder:'); + assert.deepStrictEqual(actualResolveOrder, ['a', 'b', 'c'], 'actualResolveOrder:'); + }); + + }); + +}); + +describe('components.json', function () { + + /** + * @param {T | T[] | undefined | null} value + * @returns {T[]} + * @template T + */ + function toArray(value) { + if (Array.isArray(value)) { + return value; + } else if (value == undefined) { + return []; + } else { + return [value]; + } + } + + /** + * @param {(entry: import("../dependencies").ComponentEntry, id: string, entries: Object) => void} consumeFn + */ + function forEachEntry(consumeFn) { + /** @type {Object} */ + const entries = {}; + + for (const category in components) { + for (const id in components[category]) { + const entry = components[category][id]; + if (id !== 'meta' && entry && typeof entry === 'object') { + entries[id] = entry; + } + } + } + + for (const id in entries) { + consumeFn(entries[id], id, entries); + } + } + + const entryProperties = [ + 'title', + 'description', + 'alias', + 'aliasTitles', + 'owner', + + 'require', + 'optional', + 'modify', + + 'noCSS', + 'option' + ]; + + it('- should be valid', function () { + try { + const allIds = []; + for (const category in components) { + Object.keys(components[category]).forEach(id => allIds.push(id)); + } + // and an alias, so we force the lazy alias resolver to check all aliases + allIds.push('js'); + + getLoader(components, allIds).getIds(); + } catch (error) { + assert.fail(error.toString()); + } + }); + + it('- should not have redundant optional dependencies', function () { + forEachEntry((entry, id) => { + const optional = new Set(toArray(entry.optional)); + + for (const modifyId of toArray(entry.modify)) { + if (optional.has(modifyId)) { + assert.fail(`The component "${id}" has declared "${modifyId}" as both optional and modify.`); + } + } + for (const requireId of toArray(entry.require)) { + if (optional.has(requireId)) { + assert.fail(`The component "${id}" has declared "${requireId}" as both optional and require.`); + } + } + }); + }); + + it('- should have a sorted language list', function () { + const ignore = new Set(['meta', 'markup', 'css', 'clike', 'javascript']); + /** @type {{ id: string, title: string }[]} */ + const languages = Object.keys(components.languages).filter(key => !ignore.has(key)).map(key => { + return { + id: key, + title: components.languages[key].title + }; + }); + + /** + * Transforms the given title into an intermediate representation to allowed for sensible comparisons + * between titles. + * + * @param {string} title + */ + function transformTitle(title) { + return title.replace(/\W+/g, '').replace(/^\d+/, '').toLowerCase(); + } + + const sorted = [...languages].sort((a, b) => { + const comp = transformTitle(a.title).localeCompare(transformTitle(b.title)); + if (comp !== 0) { + return comp; + } + // a and b have the same intermediate form (e.g. "C" => "C", "C++" => "C", "C#" => "C"). + return a.title.toLowerCase().localeCompare(b.title.toLowerCase()); + }); + + assert.sameOrderedMembers(languages, sorted); + }); + + it('- should not have single-element or empty arrays', function () { + /** @type {keyof import("../dependencies").ComponentEntry} */ + const properties = ['alias', 'optional', 'require', 'modify']; + + forEachEntry((entry, id) => { + for (const prop of properties) { + const value = entry[prop]; + if (Array.isArray(value)) { + if (value.length === 0) { + assert.fail( + `The component "${id}" defines an empty array for "${prop}".` + + ` Please remove the "${prop}" property.` + ); + } else if (value.length === 1) { + assert.fail( + `The component "${id}" defines a single-empty array for "${prop}".` + + ` Please replace the array with its element.` + + `\n\t${JSON.stringify(prop)}: ${JSON.stringify(value[0])}` + ); + } + } + } + }); + }); + + it('- should only have alias titles for valid aliases', function () { + forEachEntry((entry, id) => { + const title = entry.title; + const alias = toArray(entry.alias); + const aliasTitles = entry.aliasTitles; + + for (const key in aliasTitles) { + if (alias.indexOf(key) === -1) { + assert.fail( + `Component "${id}":` + + ` The alias ${JSON.stringify(key)} in "aliasTitles" is not defined in "alias".` + ); + } + if (aliasTitles[key] === title) { + assert.fail( + `Component "${id}":` + + ` The alias title for ${JSON.stringify(key)} is the same as the normal title.` + + ` Remove the alias title or choose a different alias title.` + ); + } + } + }); + }); + + it('- should not have unknown properties', function () { + const knownProperties = new Set(entryProperties); + + forEachEntry((entry, id) => { + for (const prop in entry) { + if (!knownProperties.has(prop)) { + assert.fail( + `Component "${id}":` + + ` The property ${JSON.stringify(prop)} is not supported by Prism.` + ); + } + } + }); + }); + +}); diff --git a/tests/examples-test.js b/tests/examples-test.js new file mode 100644 index 0000000000..870bbf9e96 --- /dev/null +++ b/tests/examples-test.js @@ -0,0 +1,185 @@ +const fs = require('fs'); +const { assert } = require('chai'); +const { Parser } = require('htmlparser2'); +// use the JSON file because this file is less susceptible to merge conflicts +const { languages } = require('../components.json'); + + +describe('Examples', function () { + + const exampleFiles = new Set(fs.readdirSync(__dirname + '/../examples')); + const ignore = new Set([ + // these are libraries and not languages + 'markup-templating', + 't4-templating', + // this does alter some languages but it's mainly a library + 'javadoclike' + ]); + const validFiles = new Set(); + + /** @type {string[]} */ + const missing = []; + for (const lang in languages) { + if (lang === 'meta') { + continue; + } + + const file = `prism-${lang}.html`; + if (!exampleFiles.has(file)) { + if (!ignore.has(lang)) { + missing.push(lang); + } + } else { + validFiles.add(file); + } + } + + const superfluous = [...exampleFiles].filter(f => !validFiles.has(f)); + + + it('- should be available for every language', function () { + assert.isEmpty(missing, 'Following languages do not have an example file in ./examples/\n' + + missing.join('\n')); + }); + + it('- should only be available for registered languages', function () { + assert.isEmpty(superfluous, 'Following files are not associated with any language\n' + + superfluous.map(f => `./examples/${f}`).join('\n')); + }); + + describe('Validate HTML templates', function () { + for (const file of validFiles) { + it('- ./examples/' + file, async function () { + const content = fs.readFileSync(__dirname + '/../examples/' + file, 'utf-8'); + await validateHTML(content); + }); + } + }); + +}); + + +/** + * Validates the given HTML string of an example file. + * + * @param {string} html + */ +async function validateHTML(html) { + const root = await parseHTML(html); + + /** + * @param {TagNode} node + */ + function checkCodeElements(node) { + if (node.tagName === 'code') { + assert.equal(node.children.length, 1, + 'A element is only allowed to contain text, no tags. ' + + 'Did you perhaps not escape all "<" characters?'); + + const child = node.children[0]; + if (child.type !== 'text') { + // throw to help TypeScript's flow analysis + throw assert.equal(child.type, 'text', 'The child of a element must be text only.'); + } + + const text = child.rawText; + + assert.notMatch(text, / { + if (n.type === 'tag') { + checkCodeElements(n); + } + }); + } + } + + for (const node of root.children) { + if (node.type === 'text') { + assert.isEmpty(node.rawText.trim(), 'All non-whitespace text has to be in

        tags.'); + } else { + // only known tags + assert.match(node.tagName, /^(?:h2|h3|ol|p|pre|ul)$/, 'Only some tags are allowed as top level tags.'); + + //

         elements must have only one child, a  element
        +			if (node.tagName === 'pre') {
        +				assert.equal(node.children.length, 1,
        +					'
         element must have one and only one child node, a  element.'
        +					+ ' This also means that spaces and line breaks around the  element are not allowed.');
        +
        +				const child = node.children[0];
        +				if (child.type !== 'tag') {
        +					// throw to help TypeScript's flow analysis
        +					throw assert.equal(child.type, 'tag', 'The child of a 
         element must be a  element.');
        +				}
        +				assert.equal(child.tagName, 'code', 'The child of a 
         element must be a  element.');
        +			}
        +
        +			checkCodeElements(node);
        +		}
        +	}
        +}
        +
        +/**
        + * Parses the given HTML fragment and returns a simple tree of the fragment.
        + *
        + * @param {string} html
        + * @returns {Promise}
        + *
        + * @typedef TagNode
        + * @property {"tag"} type
        + * @property {string | null} tagName
        + * @property {Object} attributes
        + * @property {(TagNode | TextNode)[]} children
        + *
        + * @typedef TextNode
        + * @property {"text"} type
        + * @property {string} rawText
        + */
        +function parseHTML(html) {
        +	return new Promise((resolve, reject) => {
        +		/** @type {TagNode} */
        +		const tree = {
        +			type: 'tag',
        +			tagName: null,
        +			attributes: {},
        +			children: []
        +		};
        +		/** @type {TagNode[]} */
        +		let stack = [tree];
        +
        +		const p = new Parser({
        +			onerror(err) {
        +				reject(err);
        +			},
        +			onend() {
        +				resolve(tree);
        +			},
        +
        +			ontext(data) {
        +				stack[stack.length - 1].children.push({
        +					type: 'text',
        +					rawText: data
        +				});
        +			},
        +
        +			onopentag(name, attrs) {
        +				/** @type {TagNode} */
        +				const newElement = {
        +					type: 'tag',
        +					tagName: name,
        +					attributes: attrs,
        +					children: []
        +				};
        +				stack[stack.length - 1].children.push(newElement);
        +				stack.push(newElement);
        +			},
        +			onclosetag() {
        +				stack.pop();
        +			}
        +
        +		}, { lowerCaseTags: false });
        +		p.end(html);
        +	});
        +}
        diff --git a/tests/helper/checks.js b/tests/helper/checks.js
        new file mode 100644
        index 0000000000..d1dba603c3
        --- /dev/null
        +++ b/tests/helper/checks.js
        @@ -0,0 +1,215 @@
        +'use strict';
        +
        +function testFunction(name, object, tester) {
        +	const func = object[name];
        +
        +	object[name] = function () {
        +		tester.apply(this, arguments);
        +		return func.apply(this, arguments);
        +	};
        +}
        +
        +/**
        + * @param {readonly T[]} a1
        + * @param {readonly T[]} a2
        + * @returns {boolean}
        + * @template T
        + */
        +function arrayEqual(a1, a2) {
        +	if (a1.length !== a2.length) {
        +		return false;
        +	}
        +	for (let i = 0, l = a1.length; i < l; i++) {
        +		if (a1[i] !== a2[i]) {
        +			return false;
        +		}
        +	}
        +	return true;
        +}
        +
        +/**
        + * Returns a slice of the first array that doesn't contain the leading and trailing elements the both arrays have in
        + * common.
        + *
        + * Examples:
        + *
        + *     trimCommon([1,2,3,4], [1,3,2,4]) => [2,3]
        + *     trimCommon([1,2,3,4], [1,2,3,4]) => []
        + *     trimCommon([1,2,0,0,3,4], [1,2,3,4]) => [0,0]
        + *     trimCommon([1,2,3,4], [1,2,0,0,3,4]) => []
        + *
        + * @param {readonly T[]} a1
        + * @param {readonly T[]} a2
        + * @returns {T[]}
        + * @template T
        + */
        +function trimCommon(a1, a2) {
        +	let commonBefore = 0;
        +	for (let i = 0; i < a1.length; i++) {
        +		if (a1[i] === a2[i]) {
        +			commonBefore++;
        +		} else {
        +			break;
        +		}
        +	}
        +	a1 = a1.slice(commonBefore);
        +	let commonAfter = 0;
        +	for (let i = 0; i < a1.length; i++) {
        +		if (a1[a1.length - 1 - i] === a2[a2.length - 1 - i]) {
        +			commonAfter++;
        +		} else {
        +			break;
        +		}
        +	}
        +	return a1.slice(0, a1.length - commonAfter);
        +}
        +
        +/**
        + * @param {string[]} a
        + */
        +function joinEnglishList(a) {
        +	if (a.length === 0) {
        +		return '(no elements)';
        +	} else if (a.length === 1) {
        +		return a[0];
        +	} else if (a.length === 2) {
        +		return `${a[0]} and ${a[1]}`;
        +	} else {
        +		return a.slice(0, a.length - 1).join(', ') + ', and ' + a[a.length - 1];
        +	}
        +}
        +
        +
        +module.exports = (Prism) => {
        +
        +	// The test for Prism.languages.extend has to be able to tell whether an object is a clone, so we mark it with a
        +	// special property
        +	const oldClone = Prism.util.clone;
        +	Prism.util.clone = obj => {
        +		const clone = oldClone(obj);
        +		if (clone && typeof clone === 'object') {
        +			Object.defineProperty(clone, '__cloned', { value: true });
        +		}
        +		return clone;
        +	};
        +
        +
        +	function extendTest(id, redef) {
        +		let redefStr;
        +		if (Prism.util.type(redef) === 'Object') {
        +			redefStr = '{\n';
        +			for (const key in redef) {
        +				const element = redef[key];
        +				let elementStr;
        +				if (Array.isArray(element)) {
        +					elementStr = `[ ... ${element.length} element(s) ]`;
        +				} else if (Prism.util.type(element) === 'RegExp') {
        +					elementStr = 'RegExp';
        +				} else if (Prism.util.type(element) === 'Object') {
        +					elementStr = '{ ... }';
        +				} else {
        +					elementStr = String(element);
        +				}
        +				redefStr += `\t'${key}': ${elementStr},\n`;
        +			}
        +			redefStr += '}';
        +		} else {
        +			redefStr = String(redef);
        +		}
        +		const details = `\n\nActual method call (nonconforming):` +
        +			`\n\n\tPrism.languages.extend('${id}', ${redefStr.replace(/\n/g, '\n\t')});` +
        +			'\n\nFor more information see: https://prismjs.com/docs/Prism.languages.html#.extend';
        +
        +		// type checks
        +		if (typeof id !== 'string') {
        +			throw new TypeError(`The id argument has to be a 'string'.` + details);
        +		}
        +		if (typeof redef !== 'object') {
        +			throw new TypeError(`The redef argument has to be an 'object'.` + details);
        +		}
        +
        +		// language has to be loaded
        +		if (!(id in Prism.languages)) {
        +			throw new Error(`Cannot extend '${id}' because it is not defined in Prism.languages.`);
        +		}
        +
        +		// rest property check
        +		if ('rest' in redef) {
        +			throw new Error(`The redef object is not allowed to contain a "rest" property.` + details);
        +		}
        +
        +		// redef cannot be a direct reference to a language
        +		let isReference = false;
        +		Prism.languages.DFS(Prism.languages, (key, value) => {
        +			if (value === redef) {
        +				isReference = true;
        +			}
        +		});
        +		if (isReference) {
        +			throw new Error(`The redef object cannot be a reference to an existing language.` +
        +				` Use Prism.util.clone(object) to create a deep clone.` + details);
        +		}
        +
        +		// check the order of properties in redef
        +		if (!redef.__cloned) {
        +			const languageKeys = Object.keys(Prism.languages[id]);
        +			const redefKeys = Object.keys(redef);
        +			const overwriteKeys = redefKeys.filter(k => languageKeys.indexOf(k) !== -1);
        +			const appendKeys = redefKeys.filter(k => languageKeys.indexOf(k) === -1);
        +			if (!arrayEqual(redefKeys, [...overwriteKeys, ...appendKeys])) {
        +				const lastOverwrite = overwriteKeys[overwriteKeys.length - 1];
        +				const lastOverwriteIndex = redefKeys.indexOf(lastOverwrite);
        +				const offenders = appendKeys.filter(k => redefKeys.indexOf(k) < lastOverwriteIndex);
        +				const offendersList = joinEnglishList(offenders.map(k => `'${k}'`));
        +
        +				throw new Error(
        +					`All tokens in the redef object that do not overwrite tokens of the extended language have to be placed after the last token that does overwrite an existing token.` +
        +					` Move the token(s) ${offendersList} after the '${lastOverwrite}' token.` + details);
        +			}
        +
        +			const sortedOverwriteKeys = [...overwriteKeys].sort((a, b) => {
        +				return languageKeys.indexOf(a) - languageKeys.indexOf(b);
        +			});
        +			if (!arrayEqual(overwriteKeys, sortedOverwriteKeys)) {
        +				const trimmedUnsorted = trimCommon(overwriteKeys, sortedOverwriteKeys).map(k => `'${k}'`).join(', ');
        +				const trimmedSorted = trimCommon(sortedOverwriteKeys, overwriteKeys).map(k => `'${k}'`).join(', ');
        +				throw new Error(
        +					'The tokens in the redef object that overwrite existing tokens of the extended language should be in the order of the existing tokens. ' +
        +					`The tokens ${trimmedUnsorted} should be in the order ${trimmedSorted}.` + details);
        +			}
        +		}
        +	}
        +
        +	function insertBeforeTest(inside, before, insert, root) {
        +		const details = `\ninsertBefore("${inside}", "${before}", ${insert}, ${root})`;
        +
        +		// type checks
        +		if (typeof inside !== 'string') {
        +			throw new TypeError(`The inside argument has to be a 'string'.` + details);
        +		}
        +		if (typeof before !== 'string') {
        +			throw new TypeError(`The before argument has to be a 'string'.` + details);
        +		}
        +		if (typeof insert !== 'object') {
        +			throw new TypeError(`The insert argument has to be an 'object'.` + details);
        +		}
        +		if (root && typeof root !== 'object') {
        +			throw new TypeError(`The root argument has to be an 'object' if defined.` + details);
        +		}
        +
        +
        +		root = root || Prism.languages;
        +		let grammar = root[inside];
        +
        +		if (typeof grammar !== 'object') {
        +			throw new Error(`The grammar "${inside}" has to be an 'object' not '${typeof grammar}'.`);
        +		}
        +		if (!(before in grammar)) {
        +			throw new Error(`"${before}" has to be a key of the grammar "${inside}".`);
        +		}
        +	}
        +
        +	testFunction('extend', Prism.languages, extendTest);
        +	testFunction('insertBefore', Prism.languages, insertBeforeTest);
        +
        +};
        diff --git a/tests/helper/prism-dom-util.js b/tests/helper/prism-dom-util.js
        new file mode 100644
        index 0000000000..86de3645fe
        --- /dev/null
        +++ b/tests/helper/prism-dom-util.js
        @@ -0,0 +1,58 @@
        +const { assert } = require('chai');
        +const PrismLoader = require('./prism-loader');
        +
        +/**
        + * @typedef {import("./prism-loader").PrismDOM} PrismDOM
        + * @typedef {import("./prism-loader").PrismWindow} PrismWindow
        + */
        +
        +module.exports = {
        +	/**
        +	 * @param {PrismWindow} window
        +	 */
        +	createUtil(window) {
        +		const { Prism, document } = window;
        +
        +		const util = {
        +			assert: {
        +				highlight({ language = 'none', code, expected }) {
        +					assert.strictEqual(Prism.highlight(code, Prism.languages[language], language), expected);
        +				},
        +				highlightElement({ language = 'none', code, expected }) {
        +					const element = document.createElement('CODE');
        +					element.classList.add('language-' + language);
        +					element.textContent = code;
        +
        +					Prism.highlightElement(element);
        +
        +					assert.strictEqual(element.innerHTML, expected);
        +				}
        +			},
        +		};
        +
        +		return util;
        +	},
        +
        +	/**
        +	 * Creates a Prism DOM instance that will be automatically cleaned up after the given test suite finished.
        +	 *
        +	 * @param {ReturnType} suite
        +	 * @param {Partial>} options
        +	 */
        +	createScopedPrismDom(suite, options = {}) {
        +		const dom = PrismLoader.createPrismDOM();
        +
        +		suite.afterAll(function () {
        +			dom.window.close();
        +		});
        +
        +		if (options.languages) {
        +			dom.loadLanguages(options.languages);
        +		}
        +		if (options.plugins) {
        +			dom.loadPlugins(options.plugins);
        +		}
        +
        +		return dom;
        +	}
        +};
        diff --git a/tests/helper/prism-loader.js b/tests/helper/prism-loader.js
        index 3257485a5f..1a9ef4dd98 100644
        --- a/tests/helper/prism-loader.js
        +++ b/tests/helper/prism-loader.js
        @@ -1,10 +1,40 @@
        -"use strict";
        -
        -var fs = require("fs");
        -var vm = require("vm");
        -var components = require("../../components");
        -var languagesCatalog = components.languages;
        -
        +'use strict';
        +const fs = require('fs');
        +const { JSDOM } = require('jsdom');
        +const components = require('../../components.json');
        +const getLoader = require('../../dependencies');
        +const coreChecks = require('./checks');
        +const { languages: languagesCatalog, plugins: pluginsCatalog } = components;
        +
        +
        +/**
        + * @typedef {import('../../components/prism-core')} Prism
        + */
        +
        +/**
        + * @typedef PrismLoaderContext
        + * @property {Prism} Prism The Prism instance.
        + * @property {Set} loaded A set of loaded components.
        + */
        +
        +/**
        + * @typedef {import("jsdom").DOMWindow & { Prism: Prism }} PrismWindow
        + *
        + * @typedef PrismDOM
        + * @property {JSDOM} dom
        + * @property {PrismWindow} window
        + * @property {Document} document
        + * @property {Prism} Prism
        + * @property {(languages: string | string[]) => void} loadLanguages
        + * @property {(plugins: string | string[]) => void} loadPlugins
        + */
        +
        +/** @type {Map} */
        +const fileSourceCache = new Map();
        +/** @type {() => any} */
        +let coreSupplierFunction = null;
        +/** @type {Map void>} */
        +const languageCache = new Map();
         
         module.exports = {
         
        @@ -12,11 +42,11 @@ module.exports = {
         	 * Creates a new Prism instance with the given language loaded
         	 *
         	 * @param {string|string[]} languages
        -	 * @returns {Prism}
        +	 * @returns {import('../../components/prism-core')}
         	 */
        -	createInstance: function (languages) {
        -		var context = {
        -			loadedLanguages: [],
        +	createInstance(languages) {
        +		let context = {
        +			loaded: new Set(),
         			Prism: this.createEmptyPrism()
         		};
         
        @@ -26,55 +56,79 @@ module.exports = {
         	},
         
         	/**
        -	 * Loads the given languages and appends the config to the given Prism object
        +	 * Creates a new JavaScript DOM instance with Prism being loaded.
         	 *
        -	 * @private
        -	 * @param {string|string[]} languages
        -	 * @param {{loadedLanguages: string[], Prism: Prism}} context
        -	 * @returns {{loadedLanguages: string[], Prism: Prism}}
        +	 * @returns {PrismDOM}
         	 */
        -	loadLanguages: function (languages, context) {
        -		if (typeof languages === 'string') {
        -			languages = [languages];
        -		}
        -
        -		var self = this;
        -
        -		languages.forEach(function (language) {
        -			context = self.loadLanguage(language, context);
        +	createPrismDOM() {
        +		const dom = new JSDOM(``, {
        +			runScripts: 'outside-only'
         		});
        +		const window = dom.window;
        +
        +		window.self = window; // set self for plugins
        +		window.eval(this.loadComponentSource('core'));
        +
        +		/** The set of loaded languages and plugins */
        +		const loaded = new Set();
        +
        +		/**
        +		 * Loads the given languages or plugins.
        +		 *
        +		 * @param {string | string[]} languagesOrPlugins
        +		 */
        +		const load = (languagesOrPlugins) => {
        +			getLoader(components, toArray(languagesOrPlugins), [...loaded]).load(id => {
        +				let source;
        +				if (languagesCatalog[id]) {
        +					source = this.loadComponentSource(id);
        +				} else if (pluginsCatalog[id]) {
        +					source = this.loadPluginSource(id);
        +				} else {
        +					throw new Error(`Language or plugin '${id}' not found.`);
        +				}
        +
        +				window.eval(source);
        +				loaded.add(id);
        +			});
        +		};
         
        -		return context;
        +		return {
        +			dom,
        +			window: /** @type {PrismWindow} */ (window),
        +			document: window.document,
        +			Prism: window.Prism,
        +			loadLanguages: load,
        +			loadPlugins: load,
        +		};
         	},
         
         	/**
        -	 * Loads the given language (including recursively loading the dependencies) and
        -	 * appends the config to the given Prism object
        +	 * Loads the given languages and appends the config to the given Prism object.
         	 *
         	 * @private
        -	 * @param {string} language
        -	 * @param {{loadedLanguages: string[], Prism: Prism}} context
        -	 * @returns {{loadedLanguages: string[], Prism: Prism}}
        +	 * @param {string|string[]} languages
        +	 * @param {PrismLoaderContext} context
        +	 * @returns {PrismLoaderContext}
         	 */
        -	loadLanguage: function (language, context) {
        -		if (!languagesCatalog[language]) {
        -			throw new Error("Language '" + language + "' not found.");
        -		}
        -
        -		// the given language was already loaded
        -		if (-1 < context.loadedLanguages.indexOf(language)) {
        -			return context;
        -		}
        -
        -		// if the language has a dependency -> load it first
        -		if (languagesCatalog[language].require) {
        -			context = this.loadLanguages(languagesCatalog[language].require, context);
        -		}
        -
        -		// load the language itself
        -		var languageSource = this.loadFileSource(language);
        -		context.Prism = this.runFileWithContext(languageSource, {Prism: context.Prism}).Prism;
        -		context.loadedLanguages.push(language);
        +	loadLanguages(languages, context) {
        +		getLoader(components, toArray(languages), [...context.loaded]).load(id => {
        +			if (!languagesCatalog[id]) {
        +				throw new Error(`Language '${id}' not found.`);
        +			}
        +
        +			// get the function which adds the language from cache
        +			let languageFunction = languageCache.get(id);
        +			if (languageFunction === undefined) {
        +				// make a function from the code which take "Prism" as an argument, so the language grammar
        +				// references the function argument
        +				const func = new Function('Prism', this.loadComponentSource(id));
        +				languageCache.set(id, languageFunction = (Prism) => func(Prism));
        +			}
        +			languageFunction(context.Prism);
        +
        +			context.loaded.add(id);
        +		});
         
         		return context;
         	},
        @@ -86,46 +140,72 @@ module.exports = {
         	 * @private
         	 * @returns {Prism}
         	 */
        -	createEmptyPrism: function () {
        -		var coreSource = this.loadFileSource("core");
        -		var context = this.runFileWithContext(coreSource);
        -		return context.Prism;
        +	createEmptyPrism() {
        +		if (!coreSupplierFunction) {
        +			const source = this.loadComponentSource('core');
        +			// Core exports itself in 2 ways:
        +			//  1) it uses `module.exports = Prism` which what we'll use
        +			//  2) it uses `global.Prism = Prism` which we want to sabotage to prevent leaking
        +			const func = new Function('module', 'global', source);
        +			coreSupplierFunction = () => {
        +				const module = {
        +					// that's all we care about
        +					exports: {}
        +				};
        +				func(module, {});
        +				return module.exports;
        +			};
        +		}
        +		const Prism = coreSupplierFunction();
        +		coreChecks(Prism);
        +		return Prism;
         	},
         
        -
         	/**
        -	 * Cached file sources, to prevent massive HDD work
        +	 * Loads the given component's file source as string
         	 *
         	 * @private
        -	 * @type {Object.}
        +	 * @param {string} name
        +	 * @returns {string}
         	 */
        -	fileSourceCache: {},
        -
        +	loadComponentSource(name) {
        +		return this.loadFileSource(__dirname + '/../../components/prism-' + name + '.js');
        +	},
         
         	/**
        -	 * Loads the given file source as string
        +	 * Loads the given plugin's file source as string
         	 *
         	 * @private
         	 * @param {string} name
         	 * @returns {string}
         	 */
        -	loadFileSource: function (name) {
        -		return this.fileSourceCache[name] = this.fileSourceCache[name] || fs.readFileSync(__dirname + "/../../components/prism-" + name + ".js", "utf8");
        +	loadPluginSource(name) {
        +		return this.loadFileSource(`${__dirname}/../../plugins/${name}/prism-${name}.js`);
         	},
         
        -
         	/**
        -	 * Runs a VM for a given file source with the given context
        +	 * Loads the given file source as string
         	 *
         	 * @private
        -	 * @param {string} fileSource
        -	 * @param {*} [context]
        -	 *
        -	 * @returns {*}
        +	 * @param {string} src
        +	 * @returns {string}
         	 */
        -	runFileWithContext: function (fileSource, context) {
        -		context = context || {};
        -		vm.runInNewContext(fileSource, context);
        -		return context;
        +	loadFileSource(src) {
        +		let content = fileSourceCache.get(src);
        +		if (content === undefined) {
        +			fileSourceCache.set(src, content = fs.readFileSync(src, 'utf8'));
        +		}
        +		return content;
         	}
         };
        +
        +/**
        + * Wraps the given value in an array if it's not an array already.
        + *
        + * @param {T[] | T} value
        + * @returns {T[]}
        + * @template T
        + */
        +function toArray(value) {
        +	return Array.isArray(value) ? value : [value];
        +}
        diff --git a/tests/helper/test-case.js b/tests/helper/test-case.js
        index cbf51a953b..d69e2c3d98 100644
        --- a/tests/helper/test-case.js
        +++ b/tests/helper/test-case.js
        @@ -1,40 +1,331 @@
        -"use strict";
        +'use strict';
         
        -var fs = require("fs");
        -var assert = require("chai").assert;
        -var PrismLoader = require("./prism-loader");
        -var TokenStreamTransformer = require("./token-stream-transformer");
        +const fs = require('fs');
        +const path = require('path');
        +const { assert } = require('chai');
        +const Prettier = require('prettier');
        +const PrismLoader = require('./prism-loader');
        +const TokenStreamTransformer = require('./token-stream-transformer');
         
         /**
        - * Handles parsing of a test case file.
        - *
        + * @typedef {import("./token-stream-transformer").TokenStream} TokenStream
        + * @typedef {import("../../components/prism-core.js")} Prism
        + */
        +
        +/**
        + * @param {string[]} languages
        + * @returns {Prism}
        + */
        +const defaultCreateInstance = (languages) => PrismLoader.createInstance(languages);
        +
        +/**
        + * Handles parsing and printing of a test case file.
          *
        - * A test case file consists of at least two parts, separated by a line of dashes.
        + * A test case file consists of at most three parts, separated by a line of at least 10 dashes.
          * This separation line must start at the beginning of the line and consist of at least three dashes.
          *
        - * The test case file can either consist of two parts:
        - *
        - *     {source code}
        - *     ----
        - *     {expected token stream}
        - *
        - *
        - * or of three parts:
        - *
        - *     {source code}
        - *     ----
        - *     {expected token stream}
        - *     ----
        - *     {text comment explaining the test case}
        + *     {code: the source code of the test case}
        + *     ----------
        + *     {expected: the expected value of the test case}
        + *     ----------
        + *     {description: explaining the test case}
          *
        - * If the file contains more than three parts, the remaining parts are just ignored.
        - * If the file however does not contain at least two parts (so no expected token stream),
        - * the test case will later be marked as failed.
        + * All parts are optional.
          *
        - *
        - * @type {{runTestCase: Function, transformCompiledTokenStream: Function, parseTestCaseFile: Function}}
        + * If the file contains more than three parts, the remaining parts are part of the description.
          */
        +class TestCaseFile {
        +	/**
        +	 * @param {string} code
        +	 * @param {string | undefined} [expected]
        +	 * @param {string | undefined} [description]
        +	 */
        +	constructor(code, expected, description) {
        +		this.code = code;
        +		this.expected = expected || '';
        +		this.description = description || '';
        +
        +		/**
        +		 * The end of line sequence used when printed.
        +		 *
        +		 * @type {"\n" | "\r\n"}
        +		 */
        +		this.eol = '\n';
        +
        +		/**
        +		 * The number of the first line of `code`.
        +		 *
        +		 * @type {number}
        +		 */
        +		this.codeLineStart = NaN;
        +		/**
        +		 * The number of the first line of `expected`.
        +		 *
        +		 * @type {number}
        +		 */
        +		this.expectedLineStart = NaN;
        +		/**
        +		 * The number of the first line of `description`.
        +		 *
        +		 * @type {number}
        +		 */
        +		this.descriptionLineStart = NaN;
        +	}
        +
        +	/**
        +	 * Returns the file content of the given test file.
        +	 *
        +	 * @returns {string}
        +	 */
        +	print() {
        +		const code = this.code.trim();
        +		const expected = (this.expected || '').trim();
        +		const description = (this.description || '').trim();
        +
        +		const parts = [code];
        +		if (description) {
        +			parts.push(expected, description);
        +		} else if (expected) {
        +			parts.push(expected);
        +		}
        +
        +		// join all parts together and normalize line ends to LF
        +		const content = parts
        +			.join('\n\n----------------------------------------------------\n\n')
        +			.replace(/\r\n?|\n/g, this.eol);
        +
        +		return content + this.eol;
        +	}
        +
        +	/**
        +	 * Writes the given test case file to disk.
        +	 *
        +	 * @param {string} filePath
        +	 */
        +	writeToFile(filePath) {
        +		fs.writeFileSync(filePath, this.print(), 'utf-8');
        +	}
        +
        +	/**
        +	 * Parses the given file contents into a test file.
        +	 *
        +	 * The line ends of the code, expected value, and description are all normalized to CRLF.
        +	 *
        +	 * @param {string} content
        +	 * @returns {TestCaseFile}
        +	 */
        +	static parse(content) {
        +		const eol = (/\r\n|\n/.exec(content) || ['\n'])[0];
        +
        +		// normalize line ends to CRLF
        +		content = content.replace(/\r\n?|\n/g, '\r\n');
        +
        +		const parts = content.split(/^-{10,}[ \t]*$/m, 3);
        +		const code = parts[0] || '';
        +		const expected = parts[1] || '';
        +		const description = parts[2] || '';
        +
        +		const file = new TestCaseFile(code.trim(), expected.trim(), description.trim());
        +		file.eol = /** @type {"\r\n" | "\n"} */ (eol);
        +
        +		const codeStartSpaces = /^\s*/.exec(code)[0];
        +		const expectedStartSpaces = /^\s*/.exec(expected)[0];
        +		const descriptionStartSpaces = /^\s*/.exec(description)[0];
        +
        +		const codeLineCount = code.split(/\r\n/).length;
        +		const expectedLineCount = expected.split(/\r\n/).length;
        +
        +		file.codeLineStart = codeStartSpaces.split(/\r\n/).length;
        +		file.expectedLineStart = codeLineCount + expectedStartSpaces.split(/\r\n/).length;
        +		file.descriptionLineStart = codeLineCount + expectedLineCount + descriptionStartSpaces.split(/\r\n/).length;
        +
        +		return file;
        +	}
        +
        +	/**
        +	 * Reads the given test case file from disk.
        +	 *
        +	 * @param {string} filePath
        +	 * @returns {TestCaseFile}
        +	 */
        +	static readFromFile(filePath) {
        +		return TestCaseFile.parse(fs.readFileSync(filePath, 'utf8'));
        +	}
        +}
        +
        +/**
        + * @template T
        + * @typedef Runner
        + * @property {(Prism: Prism, code: string, language: string) => T} run
        + * @property {(actual: T) => string} print
        + * @property {(actual: T, expected: string) => boolean} isEqual
        + * @property {(actual: T, expected: string, message: (firstDifference: number) => string) => void} assertEqual
        + */
        +
        +/**
        + * @implements {Runner}
        + */
        +class TokenizeJSONRunner {
        +	/**
        +	 * @param {Prism} Prism
        +	 * @param {string} code
        +	 * @param {string} language
        +	 * @returns {TokenStream}
        +	 */
        +	run(Prism, code, language) {
        +		return tokenize(Prism, code, language);
        +	}
        +	/**
        +	 * @param {TokenStream} actual
        +	 * @returns {string}
        +	 */
        +	print(actual) {
        +		return TokenStreamTransformer.prettyprint(actual, '\t');
        +	}
        +	/**
        +	 * @param {TokenStream} actual
        +	 * @param {string} expected
        +	 * @returns {boolean}
        +	 */
        +	isEqual(actual, expected) {
        +		const simplifiedActual = TokenStreamTransformer.simplify(actual);
        +		let simplifiedExpected;
        +		try {
        +			simplifiedExpected = JSON.parse(expected);
        +		} catch (error) {
        +			return false;
        +		}
        +
        +		return JSON.stringify(simplifiedActual) === JSON.stringify(simplifiedExpected);
        +	}
        +	/**
        +	 * @param {TokenStream} actual
        +	 * @param {string} expected
        +	 * @param {(firstDifference: number) => string} message
        +	 * @returns {void}
        +	 */
        +	assertEqual(actual, expected, message) {
        +		const simplifiedActual = TokenStreamTransformer.simplify(actual);
        +		const simplifiedExpected = JSON.parse(expected);
        +
        +		const actualString = JSON.stringify(simplifiedActual);
        +		const expectedString = JSON.stringify(simplifiedExpected);
        +
        +		const difference = firstDiff(expectedString, actualString);
        +		if (difference === undefined) {
        +			// both are equal
        +			return;
        +		}
        +
        +		// The index of the first difference between the expected token stream and the actual token stream.
        +		// The index is in the raw expected token stream JSON of the test case.
        +		const diffIndex = translateIndexIgnoreSpaces(expected, expectedString, difference);
        +
        +		assert.deepEqual(simplifiedActual, simplifiedExpected, message(diffIndex));
        +	}
        +}
        +
        +/**
        + * @implements {Runner}
        + */
        +class HighlightHTMLRunner {
        +	/**
        +	 * @param {Prism} Prism
        +	 * @param {string} code
        +	 * @param {string} language
        +	 * @returns {string}
        +	 */
        +	run(Prism, code, language) {
        +		const env = {
        +			element: {},
        +			language,
        +			grammar: Prism.languages[language],
        +			code,
        +		};
        +
        +		Prism.hooks.run('before-highlight', env);
        +		env.highlightedCode = Prism.highlight(env.code, env.grammar, env.language);
        +		Prism.hooks.run('before-insert', env);
        +		env.element.innerHTML = env.highlightedCode;
        +		Prism.hooks.run('after-highlight', env);
        +		Prism.hooks.run('complete', env);
        +
        +		return env.highlightedCode;
        +	}
        +	/**
        +	 * @param {string} actual
        +	 * @returns {string}
        +	 */
        +	print(actual) {
        +		return Prettier.format(actual, {
        +			printWidth: 100,
        +			tabWidth: 4,
        +			useTabs: true,
        +			htmlWhitespaceSensitivity: 'ignore',
        +			filepath: 'fake.html',
        +		});
        +	}
        +	/**
        +	 * @param {string} actual
        +	 * @param {string} expected
        +	 * @returns {boolean}
        +	 */
        +	isEqual(actual, expected) {
        +		return this.normalize(actual) === this.normalize(expected);
        +	}
        +	/**
        +	 * @param {string} actual
        +	 * @param {string} expected
        +	 * @param {(firstDifference: number) => string} message
        +	 * @returns {void}
        +	 */
        +	assertEqual(actual, expected, message) {
        +		// We don't calculate the index of the first difference because it's difficult.
        +		assert.deepEqual(this.normalize(actual), this.normalize(expected), message(0));
        +	}
        +
        +	/**
        +	 * Normalizes the given HTML by removing all leading spaces and trailing spaces. Line breaks will also be normalized
        +	 * to enable good diffing.
        +	 *
        +	 * @param {string} html
        +	 * @returns {string}
        +	 */
        +	normalize(html) {
        +		return html
        +			.replace(//g, '>\n')
        +			.replace(/[ \t]*[\r\n]\s*/g, '\n')
        +			.trim();
        +	}
        +}
        +
        +
         module.exports = {
        +	TestCaseFile,
        +
        +	/**
        +	 * Runs the given test file and asserts the result.
        +	 *
        +	 * This function will determine what kind of test files the given file is and call the appropriate method to run the
        +	 * test.
        +	 *
        +	 * @param {RunOptions} options
        +	 * @returns {void}
        +	 *
        +	 * @typedef RunOptions
        +	 * @property {string} languageIdentifier
        +	 * @property {string} filePath
        +	 * @property {"none" | "insert" | "update"} updateMode
        +	 * @property {(languages: string[]) => Prism} [createInstance]
        +	 */
        +	run(options) {
        +		if (path.extname(options.filePath) === '.test') {
        +			this.runTestCase(options.languageIdentifier, options.filePath, options.updateMode, options.createInstance);
        +		} else {
        +			this.runTestsWithHooks(options.languageIdentifier, require(options.filePath), options.createInstance);
        +		}
        +	},
         
         	/**
         	 * Runs the given test case file and asserts the result
        @@ -50,43 +341,85 @@ module.exports = {
         	 *
         	 * @param {string} languageIdentifier
         	 * @param {string} filePath
        +	 * @param {"none" | "insert" | "update"} updateMode
        +	 * @param {(languages: string[]) => Prism} [createInstance]
         	 */
        -	runTestCase: function (languageIdentifier, filePath) {
        -		var testCase = this.parseTestCaseFile(filePath);
        -		var usedLanguages = this.parseLanguageNames(languageIdentifier);
        -
        -		if (null === testCase) {
        -			throw new Error("Test case file has invalid format (or the provided token stream is invalid JSON), please read the docs.");
        +	runTestCase(languageIdentifier, filePath, updateMode, createInstance = defaultCreateInstance) {
        +		let runner;
        +		if (/\.html\.test$/i.test(filePath)) {
        +			runner = new HighlightHTMLRunner();
        +		} else {
        +			runner = new TokenizeJSONRunner();
         		}
        +		this.runTestCaseWithRunner(languageIdentifier, filePath, updateMode, runner, createInstance);
        +	},
        +
        +	/**
        +	 * @param {string} languageIdentifier
        +	 * @param {string} filePath
        +	 * @param {"none" | "insert" | "update"} updateMode
        +	 * @param {Runner} runner
        +	 * @param {(languages: string[]) => Prism} createInstance
        +	 * @template T
        +	 */
        +	runTestCaseWithRunner(languageIdentifier, filePath, updateMode, runner, createInstance) {
        +		const testCase = TestCaseFile.readFromFile(filePath);
        +		const usedLanguages = this.parseLanguageNames(languageIdentifier);
        +
        +		const Prism = createInstance(usedLanguages.languages);
         
        -		var Prism = PrismLoader.createInstance(usedLanguages.languages);
         		// the first language is the main language to highlight
        -		var mainLanguageGrammar = Prism.languages[usedLanguages.mainLanguage];
        -		var env = {
        -			code: testCase.testSource,
        -			grammar: mainLanguageGrammar,
        -			language: usedLanguages.mainLanguage
        -		};
        -		Prism.hooks.run('before-tokenize', env);
        -		env.tokens = Prism.tokenize(env.code, env.grammar);
        -		Prism.hooks.run('after-tokenize', env);
        -		var compiledTokenStream = env.tokens;
        +		const actualValue = runner.run(Prism, testCase.code, usedLanguages.mainLanguage);
        +
        +		function updateFile() {
        +			// change the file
        +			testCase.expected = runner.print(actualValue);
        +			testCase.writeToFile(filePath);
        +		}
         
        -		var simplifiedTokenStream = TokenStreamTransformer.simplify(compiledTokenStream);
        +		if (!testCase.expected) {
        +			// the test case doesn't have an expected value
         
        -		var tzd = JSON.stringify( simplifiedTokenStream ); var exp = JSON.stringify( testCase.expectedTokenStream );
        -		var i = 0; var j = 0; var diff = "";
        -		while ( j < tzd.length ){ if (exp[i] != tzd[j] || i == exp.length) diff += tzd[j]; else i++; j++; }
        +			if (updateMode === 'none') {
        +				throw new Error('This test case doesn\'t have an expected token stream.'
        +					+ ' Either add the JSON of a token stream or run \`npm run test:languages -- --insert\`'
        +					+ ' to automatically add the current token stream.');
        +			}
        +
        +			updateFile();
        +		} else {
        +			// there is an expected value
        +
        +			if (runner.isEqual(actualValue, testCase.expected)) {
        +				// no difference
        +				return;
        +			}
        +
        +			if (updateMode === 'update') {
        +				updateFile();
        +				return;
        +			}
         
        -		// var message = "\nToken Stream: \n" + JSON.stringify( simplifiedTokenStream, null, " " ) + 
        -		var message = "\nToken Stream: \n" + tzd + 
        -			"\n-----------------------------------------\n" +
        -			"Expected Token Stream: \n" + exp +
        -			"\n-----------------------------------------\n" + diff;
        +			runner.assertEqual(actualValue, testCase.expected, diffIndex => {
        +				const expectedLines = testCase.expected.substr(0, diffIndex).split(/\r\n?|\n/g);
        +				const columnNumber = expectedLines.pop().length + 1;
        +				const lineNumber = testCase.expectedLineStart + expectedLines.length;
         
        -		var result = assert.deepEqual(simplifiedTokenStream, testCase.expectedTokenStream, testCase.comment + message);
        +				return testCase.description +
        +					`\nThe expected token stream differs from the actual token stream.` +
        +					` Either change the ${usedLanguages.mainLanguage} language or update the expected token stream.` +
        +					` Run \`npm run test:languages -- --update\` to update all missing or incorrect expected token streams.` +
        +					`\n\n\nActual Token Stream:` +
        +					`\n-----------------------------------------\n` +
        +					runner.print(actualValue) +
        +					`\n-----------------------------------------\n` +
        +					`File: ${filePath}:${lineNumber}:${columnNumber}\n\n`;
        +			});
        +		}
         	},
         
        +	tokenize,
        +
         
         	/**
         	 * Parses the language names and finds the main language.
        @@ -98,20 +431,20 @@ module.exports = {
         	 *
         	 * @returns {{languages: string[], mainLanguage: string}}
         	 */
        -	parseLanguageNames: function (languageIdentifier) {
        -		var languages = languageIdentifier.split("+");
        -		var mainLanguage = null;
        +	parseLanguageNames(languageIdentifier) {
        +		let languages = languageIdentifier.split('+');
        +		let mainLanguage = null;
         
         		languages = languages.map(
         			function (language) {
        -				var pos = language.indexOf("!");
        +				const pos = language.indexOf('!');
         
         				if (-1 < pos) {
         					if (mainLanguage) {
        -						throw "There are multiple main languages defined.";
        +						throw 'There are multiple main languages defined.';
         					}
         
        -					mainLanguage = language.replace("!", "");
        +					mainLanguage = language.replace('!', '');
         					return mainLanguage;
         				}
         
        @@ -120,7 +453,7 @@ module.exports = {
         		);
         
         		if (!mainLanguage) {
        -			mainLanguage = languages[languages.length-1];
        +			mainLanguage = languages[languages.length - 1];
         		}
         
         		return {
        @@ -128,69 +461,81 @@ module.exports = {
         			mainLanguage: mainLanguage
         		};
         	},
        +};
         
        +/**
        + * Returns the token stream of the given code highlighted with `language`.
        + *
        + * The `before-tokenize` and `after-tokenize` hooks will also be executed.
        + *
        + * @param {import('../../components/prism-core')} Prism The Prism instance which will tokenize `code`.
        + * @param {string} code The code to tokenize.
        + * @param {string} language The language id.
        + * @returns {TokenStream}
        + */
        +function tokenize(Prism, code, language) {
        +	const env = {
        +		code,
        +		grammar: Prism.languages[language],
        +		language
        +	};
         
        -	/**
        -	 * Parses the test case from the given test case file
        -	 *
        -	 * @private
        -	 * @param {string} filePath
        -	 * @returns {{testSource: string, expectedTokenStream: Array.>, comment:string?}|null}
        -	 */
        -	parseTestCaseFile: function (filePath) {
        -		var testCaseSource = fs.readFileSync(filePath, "utf8");
        -		var testCaseParts = testCaseSource.split(/^-{10,}\w*$/m);
        +	Prism.hooks.run('before-tokenize', env);
        +	env.tokens = Prism.tokenize(env.code, env.grammar);
        +	Prism.hooks.run('after-tokenize', env);
         
        -		try {
        -			var testCase = {
        -				testSource: testCaseParts[0].trim(),
        -				expectedTokenStream: JSON.parse(testCaseParts[1]),
        -				comment: null
        -			};
        -
        -			// if there are three parts, the third one is the comment
        -			// explaining the test case
        -			if (testCaseParts[2]) {
        -				testCase.comment = testCaseParts[2].trim();
        -			}
        +	return env.tokens;
        +}
         
        -			return testCase;
        -		}
        -		catch (e) {
        -			// the JSON can't be parsed (e.g. it could be empty)
        -			return null;
        +/**
        + * Returns the index at which the given expected string differs from the given actual string.
        + *
        + * This will returns `undefined` if the strings are equal.
        + *
        + * @param {string} expected
        + * @param {string} actual
        + * @returns {number | undefined}
        + */
        +function firstDiff(expected, actual) {
        +	let i = 0;
        +	let j = 0;
        +	while (i < expected.length && j < actual.length) {
        +		if (expected[i] !== actual[j]) {
        +			return i;
         		}
        -	},
        +		i++; j++;
        +	}
         
        -	/**
        -	 * Runs the given pieces of codes and asserts their result.
        -	 *
        -	 * Code is provided as the key and expected result as the value.
        -	 *
        -	 * @param {string} languageIdentifier
        -	 * @param {object} codes
        -	 */
        -	runTestsWithHooks: function (languageIdentifier, codes) {
        -		var usedLanguages = this.parseLanguageNames(languageIdentifier);
        -		var Prism = PrismLoader.createInstance(usedLanguages.languages);
        -		// the first language is the main language to highlight
        +	if (i == expected.length && j == actual.length) {
        +		return undefined;
        +	}
        +	return i;
        +}
         
        -		for (var code in codes) {
        -			if (codes.hasOwnProperty(code)) {
        -				var env = {
        -					element: {},
        -					language: usedLanguages.mainLanguage,
        -					grammar: Prism.languages[usedLanguages.mainLanguage],
        -					code: code
        -				};
        -				Prism.hooks.run('before-highlight', env);
        -				env.highlightedCode = Prism.highlight(env.code, env.grammar, env.language);
        -				Prism.hooks.run('before-insert', env);
        -				env.element.innerHTML = env.highlightedCode;
        -				Prism.hooks.run('after-highlight', env);
        -				Prism.hooks.run('complete', env);
        -				assert.equal(env.highlightedCode, codes[code]);
        -			}
        +/**
        + * Translates an index within a string (`withoutSpaces`) to the index of another string (`spacey`) where the only
        + * difference between the two strings is that the other string can have any number of additional white spaces at any
        + * position.
        + *
        + * In out use case, the `withoutSpaces` string is an unformatted JSON string and the `spacey` string is a formatted JSON
        + * string.
        + *
        + * @param {string} spacey
        + * @param {string} withoutSpaces
        + * @param {number} withoutSpaceIndex
        + * @returns {number | undefined}
        + */
        +function translateIndexIgnoreSpaces(spacey, withoutSpaces, withoutSpaceIndex) {
        +	let i = 0;
        +	let j = 0;
        +	while (i < spacey.length && j < withoutSpaces.length) {
        +		while (spacey[i] !== withoutSpaces[j]) {
        +			i++;
         		}
        +		if (j === withoutSpaceIndex) {
        +			return i;
        +		}
        +		i++; j++;
         	}
        -};
        +	return undefined;
        +}
        diff --git a/tests/helper/test-discovery.js b/tests/helper/test-discovery.js
        index b2aade1ad5..3e374a393c 100644
        --- a/tests/helper/test-discovery.js
        +++ b/tests/helper/test-discovery.js
        @@ -1,48 +1,39 @@
        -"use strict";
        +'use strict';
         
        -var fs = require("fs");
        -var path = require("path");
        +const fs = require('fs');
        +const path = require('path');
         
        +const LANGUAGES_DIR = path.join(__dirname, '..', 'languages');
         
         module.exports = {
         
         	/**
         	 * Loads the list of all available tests
         	 *
        -	 * @param {string} rootDir
        -	 * @returns {Object.}
        +	 * @param {string} [rootDir]
        +	 * @returns {Map}
         	 */
        -	loadAllTests: function (rootDir) {
        -		var testSuite = {};
        -		var self = this;
        +	loadAllTests(rootDir) {
        +		rootDir = rootDir || LANGUAGES_DIR;
         
        -		this.getAllDirectories(rootDir).forEach(
        -			function (language) {
        -				testSuite[language] = self.getAllFiles(path.join(rootDir, language));
        -			}
        -		);
        -
        -		return testSuite;
        +		return new Map(this.getAllDirectories(rootDir).map(language => {
        +			return [language, this.getAllFiles(path.join(rootDir, language))];
        +		}));
         	},
         
         	/**
         	 * Loads the list of available tests that match the given languages
         	 *
        -	 * @param {string} rootDir
         	 * @param {string|string[]} languages
        -	 * @returns {Object.}
        +	 * @param {string} [rootDir]
        +	 * @returns {Map}
         	 */
        -	loadSomeTests: function (rootDir, languages) {
        -		var testSuite = {};
        -		var self = this;
        -
        -		this.getSomeDirectories(rootDir, languages).forEach(
        -			function (language) {
        -				testSuite[language] = self.getAllFiles(path.join(rootDir, language));
        -			}
        -		);
        +	loadSomeTests(languages, rootDir) {
        +		rootDir = rootDir || LANGUAGES_DIR;
         
        -		return testSuite;
        +		return new Map(this.getSomeDirectories(rootDir, languages).map(language => {
        +			return [language, this.getAllFiles(path.join(rootDir, language))];
        +		}));
         	},
         
         
        @@ -51,14 +42,12 @@ module.exports = {
         	 * in the given src directory
         	 *
         	 * @param {string} src
        -	 * @returns {Array.}
        +	 * @returns {string[]}
         	 */
        -	getAllDirectories: function (src) {
        -		return fs.readdirSync(src).filter(
        -			function (file) {
        -				return fs.statSync(path.join(src, file)).isDirectory();
        -			}
        -		);
        +	getAllDirectories(src) {
        +		return fs.readdirSync(src).filter(file => {
        +			return fs.statSync(path.join(src, file)).isDirectory();
        +		});
         	},
         
         	/**
        @@ -67,30 +56,26 @@ module.exports = {
         	 *
         	 * @param {string} src
         	 * @param {string|string[]} languages
        -	 * @returns {Array.}
        +	 * @returns {string[]}
         	 */
        -	getSomeDirectories: function (src, languages) {
        -		var self = this;
        -		return fs.readdirSync(src).filter(
        -			function (file) {
        -				return fs.statSync(path.join(src, file)).isDirectory() && self.directoryMatches(file, languages);
        -			}
        -		);
        +	getSomeDirectories(src, languages) {
        +		return fs.readdirSync(src).filter(file => {
        +			return fs.statSync(path.join(src, file)).isDirectory() && this.directoryMatches(file, languages);
        +		});
         	},
         
         	/**
         	 * Returns whether a directory matches one of the given languages.
        +	 *
         	 * @param {string} directory
         	 * @param {string|string[]} languages
         	 */
        -	directoryMatches: function (directory, languages) {
        +	directoryMatches(directory, languages) {
         		if (!Array.isArray(languages)) {
         			languages = [languages];
         		}
        -		var dirLanguages = directory.split(/!?\+!?/);
        -		return dirLanguages.some(function (lang) {
        -			return languages.indexOf(lang) >= 0;
        -		});
        +		const dirLanguages = directory.split(/!?\+!?/);
        +		return dirLanguages.some(lang => languages.indexOf(lang) >= 0);
         	},
         
         
        @@ -99,17 +84,16 @@ module.exports = {
         	 *
         	 * @private
         	 * @param {string} src
        -	 * @returns {Array.}
        +	 * @returns {string[]}
         	 */
        -	getAllFiles: function (src) {
        -		return fs.readdirSync(src).filter(
        -			function (fileName) {
        -				return fs.statSync(path.join(src, fileName)).isFile();
        -			}
        -		).map(
        -			function (fileName) {
        +	getAllFiles(src) {
        +		return fs.readdirSync(src)
        +			.filter(fileName => {
        +				return path.extname(fileName) === '.test'
        +					&& fs.statSync(path.join(src, fileName)).isFile();
        +			})
        +			.map(fileName => {
         				return path.join(src, fileName);
        -			}
        -		);
        +			});
         	}
         };
        diff --git a/tests/helper/token-stream-transformer.js b/tests/helper/token-stream-transformer.js
        index deb831c45b..8a92a548b7 100644
        --- a/tests/helper/token-stream-transformer.js
        +++ b/tests/helper/token-stream-transformer.js
        @@ -1,7 +1,21 @@
        -"use strict";
        +'use strict';
         
         
        +/**
        + * @typedef TokenStreamItem
        + * @property {string} type
        + * @property {string | Array} content
        + *
        + * @typedef {Array} TokenStream
        + *
        + * @typedef {Array} SimplifiedTokenStream
        + *
        + * @typedef {Array} PrettyTokenStream
        + * @typedef {string | LineBreakItem | GlueItem | [string, string | Array]} PrettyTokenStreamItem
        + */
        +
         module.exports = {
        +
         	/**
         	 * Simplifies the token stream to ease the matching with the expected token stream.
         	 *
        @@ -9,24 +23,465 @@ module.exports = {
         	 * * In arrays each value is transformed individually
         	 * * Values that are empty (empty arrays or strings only containing whitespace)
         	 *
        -	 *
        -	 * @param {Array} tokenStream
        -	 * @returns {Array.}
        +	 * @param {TokenStream} tokenStream
        +	 * @returns {SimplifiedTokenStream}
         	 */
        -	simplify: function (tokenStream) {
        -		if (Array.isArray(tokenStream)) {
        -			return tokenStream
        -				.map(this.simplify.bind(this))
        -				.filter(function (value) {
        -					return !(Array.isArray(value) && !value.length) && !(typeof value === "string" && !value.trim().length);
        +	simplify: function simplify(tokenStream) {
        +		return tokenStream
        +			.map(innerSimple)
        +			.filter(value => !(typeof value === 'string' && isBlank(value)));
        +
        +		/**
        +		 * @param {string | TokenStreamItem} value
        +		 * @returns {string | [string, string | Array]}
        +		 */
        +		function innerSimple(value) {
        +			if (typeof value === 'object') {
        +				if (Array.isArray(value.content)) {
        +					return [value.type, simplify(value.content)];
        +				} else {
        +					return [value.type, value.content];
         				}
        -			);
        +			} else {
        +				return value;
        +			}
         		}
        -		else if (typeof tokenStream === "object") {
        -			return [tokenStream.type, this.simplify(tokenStream.content)];
        +	},
        +
        +	/**
        +	 * @param {TokenStream} tokenStream
        +	 * @param {string} [indentation]
        +	 * @returns {string}
        +	 */
        +	prettyprint(tokenStream, indentation) {
        +		return printPrettyTokenStream(toPrettyTokenStream(tokenStream), undefined, indentation);
        +	}
        +};
        +
        +/**
        + * This item indicates that one or multiple line breaks are present between the preceding and following items in the
        + * source token stream.
        + *
        + * Only if an item is enabled will it appear in the pretty-printed token stream.
        + */
        +class LineBreakItem {
        +	/** @param {number} sourceCount */
        +	constructor(sourceCount) {
        +		this.sourceCount = sourceCount;
        +		this.enabled = false;
        +	}
        +}
        +/**
        + * This item indicates the the preceding and following items are to be printed on the same line in the pretty-printed
        + * token stream.
        + */
        +class GlueItem { }
        +
        +/**
        + * @param {TokenStream} tokenStream
        + * @param {number} [level]
        + * @returns {PrettyTokenStream}
        + */
        +function toPrettyTokenStream(tokenStream, level = 0) {
        +	/** @type {PrettyTokenStream} */
        +	const prettyStream = [];
        +	for (const token of tokenStream) {
        +		if (typeof token === 'string') {
        +			if (isBlank(token)) {
        +				// blank string
        +				const lineBreaks = countLineBreaks(token);
        +				if (lineBreaks > 0) {
        +					prettyStream.push(new LineBreakItem(lineBreaks));
        +				}
        +			} else {
        +				// might start with line breaks
        +				const startLineBreaks = countLineBreaks(/^\s*/.exec(token)[0]);
        +				if (startLineBreaks > 0) {
        +					prettyStream.push(new LineBreakItem(startLineBreaks));
        +				}
        +
        +				prettyStream.push(token);
        +
        +				const endLineBreaks = countLineBreaks(/\s*$/.exec(token)[0]);
        +				if (endLineBreaks > 0) {
        +					prettyStream.push(new LineBreakItem(endLineBreaks));
        +				}
        +			}
        +		} else {
        +			prettyStream.push(innerSimple(token));
         		}
        -		else {
        -			return tokenStream;
        +	}
        +	/**
        +	 * @param {TokenStreamItem} value
        +	 * @returns {[string, string | Array]}
        +	 */
        +	function innerSimple(value) {
        +		if (Array.isArray(value.content)) {
        +			return [value.type, toPrettyTokenStream(value.content, level + 1)];
        +		} else {
        +			return [value.type, value.content];
         		}
         	}
        -};
        +
        +	prettyFormat(prettyStream, (level + 1) * 4);
        +	return prettyStream;
        +}
        +
        +/**
        + * @param {PrettyTokenStream} prettyStream
        + * @param {number} indentationWidth
        + * @returns {void}
        + */
        +function prettyFormat(prettyStream, indentationWidth) {
        +	// The maximum number of (glued) tokens per line
        +	const MAX_TOKEN_PER_LINE = 5;
        +	// The maximum number of characters per line
        +	// (this is based on an estimation. The actual output might be longer.)
        +	const MAX_PRINT_WIDTH = 80 - indentationWidth;
        +
        +	prettyTrimLineBreaks(prettyStream);
        +	// enable all line breaks with >=2 breaks in the source token stream
        +	prettyEnableLineBreaks(prettyStream, br => br.sourceCount >= 2);
        +
        +	const ranges = prettySplit(prettyStream, br => br instanceof LineBreakItem && br.enabled);
        +	for (const group of ranges) {
        +		if (prettySomeLineBreak(group, true, br => br.enabled)) {
        +			// Since we just split by enabled line break, only nested line breaks can be enabled. This usually
        +			// indicates complex token streams, so let's just enable all line breaks and call it a day.
        +			prettyEnableLineBreaks(group, () => true);
        +		} else {
        +			// try to optimize for the pattern /{1,MAX_TOKEN_PER_LINE}(\n{1,MAX_TOKEN_PER_LINE})*/
        +			const lines = prettySplit(group, i => i instanceof LineBreakItem);
        +
        +			/**
        +			 * Returns whether lines can generally be glued together (no line breaks within lines and don't glue with
        +			 * nested tokens).
        +			 */
        +			function glueable() {
        +				return lines.every(g => {
        +					if (g.length > 1) {
        +						if (prettyContainsNonTriviallyNested(g)) {
        +							// the token with nested tokens might be glued together with other tokens and we can't allow
        +							// that to happen
        +							return false;
        +						} else {
        +							return true;
        +						}
        +					} else {
        +						// we can safely ignore all tokens that are on their own line
        +						return true;
        +					}
        +				});
        +			}
        +			function tokensPerLine() {
        +				return lines.map(g => prettyCountTokens(g, true));
        +			}
        +			/**
        +			 * Returns an estimate for the output length each line will have
        +			 */
        +			function widthPerLine() {
        +				return lines.map(g => {
        +					if (g.length > 1) {
        +						return g
        +							.map(item => {
        +								if (isToken(item)) {
        +									if (typeof item === 'string') {
        +										return ', '.length + JSON.stringify(item).length;
        +									} else {
        +										return ', '.length + JSON.stringify(item).length + ' '.length;
        +									}
        +								} else {
        +									return 0;
        +								}
        +							})
        +							.reduce((a, b) => a + b, 0) - ', '.length;
        +					} else {
        +						// we don't really care about the print width of a single-token line
        +						return 1;
        +					}
        +				});
        +			}
        +
        +			const glueTokens = glueable()
        +				// at most this many tokens per line
        +				&& Math.max(...tokensPerLine()) <= MAX_TOKEN_PER_LINE
        +				// the output of each line can be at most this many characters long
        +				&& Math.max(...widthPerLine()) <= MAX_PRINT_WIDTH
        +				// We need to have at least 2 lines in this group OR this group isn't the only group in the stream.
        +				// This will prevent all tokens of a really short token stream to be glued together.
        +				&& (lines.length > 1 || ranges.length > 1);
        +
        +			if (glueTokens) {
        +				prettyGlueTogetherAll(prettyStream, group);
        +			} else {
        +				const flatTokenCount = prettyCountTokens(group, false);
        +				const deepTokenCount = prettyCountTokens(group, true);
        +				if (
        +					// prevent a one-token-per-line situation
        +					flatTokenCount > lines.length &&
        +					// require at least 2 tokens per line on average
        +					deepTokenCount >= lines.length * 2
        +				) {
        +					prettyEnableLineBreaks(group, () => true);
        +				}
        +			}
        +		}
        +	}
        +}
        +
        +/**
        + * @param {PrettyTokenStream} prettyStream
        + * @param {number} [indentationLevel]
        + * @param {string} [indentationChar]
        + * @returns {string}
        + */
        +function printPrettyTokenStream(prettyStream, indentationLevel = 1, indentationChar = '    ') {
        +	// can't use tabs because the console will convert one tab to four spaces
        +	const indentation = new Array(indentationLevel + 1).join(indentationChar);
        +
        +	let out = '';
        +	out += '[\n';
        +
        +	let glued = false;
        +	prettyStream.forEach((item, i) => {
        +		if (item instanceof LineBreakItem) {
        +			if (item.enabled) {
        +				out += '\n';
        +			}
        +		} else if (item instanceof GlueItem) {
        +			out = out.trimEnd();
        +			if (out[out.length - 1] === ',') {
        +				out += ' ';
        +			}
        +			glued = true;
        +		} else {
        +			if (glued) {
        +				glued = false;
        +			} else {
        +				out += indentation;
        +			}
        +
        +			if (typeof item === 'string') {
        +				out += JSON.stringify(item);
        +			} else {
        +				const name = item[0];
        +				const content = item[1];
        +
        +				out += '[' + JSON.stringify(name) + ', ';
        +
        +				if (typeof content === 'string') {
        +					// simple string literal
        +					out += JSON.stringify(content);
        +				} else if (content.length === 1 && typeof content[0] === 'string') {
        +					// token stream that only contains a single string literal
        +					out += JSON.stringify(content);
        +				} else {
        +					// token stream
        +					out += printPrettyTokenStream(content, indentationLevel + 1, indentationChar);
        +				}
        +
        +				out += ']';
        +			}
        +
        +			const lineEnd = (i === prettyStream.length - 1) ? '\n' : ',\n';
        +			out += lineEnd;
        +		}
        +	});
        +	out += indentation.substr(indentationChar.length) + ']';
        +	return out;
        +}
        +
        +/**
        + * Returns whether the given string is empty or contains only whitespace characters.
        + *
        + * @param {string} str
        + * @returns {boolean}
        + */
        +function isBlank(str) {
        +	return /^\s*$/.test(str);
        +}
        +
        +/**
        + * @param {string} str
        + * @returns {number}
        + */
        +function countLineBreaks(str) {
        +	return str.split(/\r\n?|\n/).length - 1;
        +}
        +
        +/**
        + * Trim all line breaks at the start and at the end of the pretty stream.
        + *
        + * @param {PrettyTokenStream} prettyStream
        + * @returns {void}
        + */
        +function prettyTrimLineBreaks(prettyStream) {
        +	let value;
        +	while ((value = prettyStream[0])) {
        +		if (value instanceof LineBreakItem) {
        +			prettyStream.shift();
        +		} else {
        +			break;
        +		}
        +	}
        +	while ((value = prettyStream[prettyStream.length - 1])) {
        +		if (value instanceof LineBreakItem) {
        +			prettyStream.pop();
        +		} else {
        +			break;
        +		}
        +	}
        +}
        +
        +/**
        + * Enables all line breaks in the pretty token stream (but not in nested token stream) that contain at least some
        + * number of line breaks in the source token stream.
        + *
        + * @param {PrettyTokenStream} prettyStream
        + * @param {(item: LineBreakItem) => boolean} cond
        + */
        +function prettyEnableLineBreaks(prettyStream, cond) {
        +	prettyStream.forEach(token => {
        +		if (token instanceof LineBreakItem && cond(token)) {
        +			token.enabled = true;
        +		}
        +	});
        +}
        +
        +/**
        + * Splits the given pretty stream on all items for which `cond` return `true`. The items for which `cond` returns
        + * `true` will not be part of any of the created streams. No empty streams will be returned.
        + *
        + * @param {PrettyTokenStream} prettyStream
        + * @param {(item: PrettyTokenStreamItem) => boolean} cond
        + * @returns {PrettyTokenStream[]}
        + */
        +function prettySplit(prettyStream, cond) {
        +	/** @type {PrettyTokenStream[]} */
        +	const result = [];
        +	/** @type {PrettyTokenStream} */
        +	let current = [];
        +	for (const item of prettyStream) {
        +		if (cond(item)) {
        +			if (current.length > 0) {
        +				result.push(current);
        +				current = [];
        +			}
        +		} else {
        +			current.push(item);
        +		}
        +	}
        +	if (current.length > 0) {
        +		result.push(current);
        +		current = [];
        +	}
        +	return result;
        +}
        +
        +/**
        + * @param {PrettyTokenStream} prettyStream
        + * @param {boolean} recursive
        + * @param {(item: LineBreakItem) => boolean} cond
        + * @returns {boolean}
        + */
        +function prettySomeLineBreak(prettyStream, recursive, cond) {
        +	for (const item of prettyStream) {
        +		if (item instanceof LineBreakItem && cond(item)) {
        +			return true;
        +		} else if (recursive && isNested(item) && prettySomeLineBreak(item[1], true, cond)) {
        +			return true;
        +		}
        +	}
        +	return false;
        +}
        +/**
        + * @param {PrettyTokenStream} prettyStream
        + * @returns {boolean}
        + */
        +function prettyContainsNonTriviallyNested(prettyStream) {
        +	for (const item of prettyStream) {
        +		if (isNested(item) && !isTriviallyNested(item)) {
        +			return true;
        +		}
        +	}
        +	return false;
        +}
        +/**
        + * @param {PrettyTokenStream} prettyStream
        + * @param {boolean} recursive
        + * @returns {number}
        + */
        +function prettyCountTokens(prettyStream, recursive) {
        +	let count = 0;
        +	for (const item of prettyStream) {
        +		if (isToken(item)) {
        +			count++;
        +			if (recursive && isNested(item) && !isTriviallyNested(item)) {
        +				count += prettyCountTokens(item[1], true);
        +			}
        +		}
        +	}
        +	return count;
        +}
        +
        +/**
        + * Adds glue between the given tokens in the given stream.
        + *
        + * @param {PrettyTokenStream} prettyStream
        + * @param {string | [string, string | any[]]} prev
        + * @param {string | [string, string | any[]]} next
        + */
        +function prettyGlueTogether(prettyStream, prev, next) {
        +	// strings may appear more than once in the stream, so we have to search for tokens.
        +	if (typeof prev !== 'string') {
        +		let index = prettyStream.indexOf(prev);
        +		if (index === -1 || prettyStream[index + 1] !== next) {
        +			throw new Error('Cannot glue: At least one of the tokens is not part of the given token stream.');
        +		}
        +		prettyStream.splice(index + 1, 0, new GlueItem());
        +	} else {
        +		let index = prettyStream.indexOf(next);
        +		if (index === -1 || prettyStream[index - 1] !== prev) {
        +			throw new Error('Cannot glue: At least one of the tokens is not part of the given token stream.');
        +		}
        +		prettyStream.splice(index, 0, new GlueItem());
        +	}
        +}
        +/**
        + * Glues together all token in the given slice of the given token stream.
        + *
        + * @param {PrettyTokenStream} prettyStream
        + * @param {PrettyTokenStream} slice
        + */
        +function prettyGlueTogetherAll(prettyStream, slice) {
        +	for (let i = 1, l = slice.length; i < l; i++) {
        +		const prev = slice[i - 1];
        +		const next = slice[i];
        +		if (isToken(prev) && isToken(next)) {
        +			prettyGlueTogether(prettyStream, prev, next);
        +		}
        +	}
        +}
        +
        +/**
        + * @param {PrettyTokenStreamItem} item
        + * @returns {item is (string | [string, string | any[]])}
        + */
        +function isToken(item) {
        +	return typeof item === 'string' || Array.isArray(item);
        +}
        +
        +/**
        + * @param {PrettyTokenStreamItem} item
        + * @returns {item is [string, any[]]}
        + */
        +function isNested(item) {
        +	return Array.isArray(item) && Array.isArray(item[1]);
        +}
        +/**
        + * @param {PrettyTokenStreamItem} item
        + * @returns {item is [string, [string]]}
        + */
        +function isTriviallyNested(item) {
        +	return isNested(item) && item[1].length === 1 && typeof item[1][0] === 'string';
        +}
        diff --git a/tests/helper/util.js b/tests/helper/util.js
        new file mode 100644
        index 0000000000..e4c72879fc
        --- /dev/null
        +++ b/tests/helper/util.js
        @@ -0,0 +1,101 @@
        +const { RegExpParser } = require('regexpp');
        +
        +
        +/**
        + * @typedef {import("regexpp/ast").Pattern} Pattern
        + * @typedef {import("regexpp/ast").Flags} Flags
        + * @typedef {{ pattern: Pattern, flags: Flags }} LiteralAST
        + */
        +
        +
        +const parser = new RegExpParser();
        +/** @type {Map} */
        +const astCache = new Map();
        +
        +
        +module.exports = {
        +
        +	/**
        +	 * Performs a breadth-first search on the given start element.
        +	 *
        +	 * @param {any} start
        +	 * @param {(path: { key: string, value: any }[], obj: Record) => void} callback
        +	 */
        +	BFS(start, callback) {
        +		const visited = new Set();
        +		/** @type {{ key: string, value: any }[][]} */
        +		let toVisit = [
        +			[{ key: null, value: start }]
        +		];
        +
        +		while (toVisit.length > 0) {
        +			/** @type {{ key: string, value: any }[][]} */
        +			const newToVisit = [];
        +
        +			for (const path of toVisit) {
        +				const obj = path[path.length - 1].value;
        +				if (!visited.has(obj)) {
        +					visited.add(obj);
        +
        +					for (const key in obj) {
        +						const value = obj[key];
        +
        +						path.push({ key, value });
        +						callback(path, obj);
        +
        +						if (Array.isArray(value) || Object.prototype.toString.call(value) == '[object Object]') {
        +							newToVisit.push([...path]);
        +						}
        +
        +						path.pop();
        +					}
        +				}
        +			}
        +
        +			toVisit = newToVisit;
        +		}
        +	},
        +
        +	/**
        +	 * Given the `BFS` path given to `BFS` callbacks, this will return the Prism language token path of the current
        +	 * value (e.g. `Prism.languages.xml.tag.pattern`).
        +	 *
        +	 * @param {readonly{ key: string, value: any }[]} path
        +	 * @param {string} [root]
        +	 * @returns {string}
        +	 */
        +	BFSPathToPrismTokenPath(path, root = 'Prism.languages') {
        +		let tokenPath = root;
        +		for (const { key } of path) {
        +			if (!key) {
        +				// do nothing
        +			} else if (/^\d+$/.test(key)) {
        +				tokenPath += `[${key}]`;
        +			} else if (/^[a-z]\w*$/i.test(key)) {
        +				tokenPath += `.${key}`;
        +			} else {
        +				tokenPath += `[${JSON.stringify(key)}]`;
        +			}
        +		}
        +		return tokenPath;
        +	},
        +
        +	/**
        +	 * Returns the AST of a given pattern.
        +	 *
        +	 * @param {RegExp} regex
        +	 * @returns {LiteralAST}
        +	 */
        +	parseRegex(regex) {
        +		const key = regex.toString();
        +		let literal = astCache.get(key);
        +		if (literal === undefined) {
        +			const flags = parser.parseFlags(regex.flags, undefined);
        +			const pattern = parser.parsePattern(regex.source, undefined, undefined, flags.unicode);
        +			literal = { pattern, flags };
        +			astCache.set(key, literal);
        +		}
        +		return literal;
        +	}
        +
        +};
        diff --git a/tests/identifier-test.js b/tests/identifier-test.js
        new file mode 100644
        index 0000000000..3d9ef0ec79
        --- /dev/null
        +++ b/tests/identifier-test.js
        @@ -0,0 +1,232 @@
        +'use strict';
        +
        +const { assert } = require('chai');
        +const PrismLoader = require('./helper/prism-loader');
        +const { languages } = require('../components.json');
        +const TokenStreamTransformer = require('./helper/token-stream-transformer');
        +
        +
        +// This is where you can exclude a language from the identifier test.
        +//
        +// To exclude a language to the `testOptions` variable and add your language and the identifier types it should
        +// excluded from. All languages opt-in for all identifier types by default, so you have to explicitly disable each type
        +// you want to disable by setting it to `false`.
        +// Also add a small comment explaining why the language was excluded.
        +//
        +// The actual identifiers for all identifier types are defined in the `identifiers` variable.
        +
        +/**
        + * @type {Partial>}
        + *
        + * @typedef IdentifierTestOptions
        + * @property {boolean} [word=true]
        + * @property {boolean} [number=true]
        + * @property {boolean} [template=true]
        + */
        +const testOptions = {
        +	// all of these have a special syntax for tokens of the form __something__
        +	'asciidoc': {
        +		template: false
        +	},
        +	'markdown': {
        +		template: false
        +	},
        +	'textile': {
        +		template: false
        +	},
        +
        +	'false': {
        +		word: false,
        +		template: false
        +	},
        +	// Hoon uses _ in its keywords
        +	'hoon': {
        +		word: false,
        +		template: false
        +	},
        +
        +	// LilyPond doesn't tokenize based on words
        +	'lilypond': {
        +		word: false,
        +		number: false,
        +		template: false,
        +	},
        +
        +	// Nevod uses underscore symbol as operator and allows hyphen to be part of identifier
        +	'nevod': {
        +		word: false,
        +		template: false,
        +	},
        +};
        +
        +/** @type {Record} */
        +const identifiers = {
        +	word: [
        +		'abc',
        +		'word',
        +		'foo1',
        +		'foo123',
        +		'foo123bar',
        +		'foo_123',
        +		'foo_123_bar',
        +	],
        +	number: [
        +		'0',
        +		'1',
        +		'9',
        +		'123',
        +		'123456789',
        +	],
        +	template: [
        +		'__PHP0__',
        +		'__LANG0__',
        +		'__LANG123__',
        +		'___PLACEHOLDER_0___',
        +		'___PLACEHOLDER_123___',
        +	],
        +};
        +
        +
        +// Below is the implementation of the test.
        +// If you only came here to exclude a language, you won't find anything below.
        +
        +
        +/** @type {Record} */
        +const aliasMap = {};
        +for (const name in languages) {
        +	const element = languages[name];
        +	if (element.alias) {
        +		if (Array.isArray(element.alias)) {
        +			element.alias.forEach(a => {
        +				aliasMap[a] = name;
        +			});
        +		} else {
        +			aliasMap[element.alias] = name;
        +		}
        +	}
        +}
        +
        +for (const lang in languages) {
        +	if (lang === 'meta') {
        +		continue;
        +	}
        +
        +	describe(`Test '${lang}'`, function () {
        +		const Prism = PrismLoader.createInstance(lang);
        +		testLiterals(Prism, lang);
        +	});
        +
        +	function toArray(value) {
        +		if (Array.isArray(value)) {
        +			return value;
        +		} else if (value != null) {
        +			return [value];
        +		} else {
        +			return [];
        +		}
        +	}
        +
        +	let optional = toArray(languages[lang].optional);
        +	let modify = toArray(languages[lang].modify);
        +
        +	if (optional.length > 0 || modify.length > 0) {
        +		let name = `Test '${lang}'`;
        +		if (optional.length > 0) {
        +			name += ` + optional dependencies '${optional.join("', '")}'`;
        +		}
        +		if (modify.length > 0) {
        +			name += ` + modify dependencies '${modify.join("', '")}'`;
        +		}
        +
        +		describe(name, function () {
        +			const Prism = PrismLoader.createInstance([...optional, ...modify, lang]);
        +			testLiterals(Prism, lang);
        +		});
        +	}
        +}
        +
        +/**
        + * @param {string} lang
        + * @returns {IdentifierTestOptions}
        + */
        +function getOptions(lang) {
        +	return testOptions[aliasMap[lang] || lang] || {};
        +}
        +
        +/**
        + * @param {string | Token | (string | Token)[]} token
        + * @returns {boolean}
        + *
        + * @typedef Token
        + * @property {string} type
        + * @property {string | Token | (string | Token)[]} content
        + */
        +function isNotBroken(token) {
        +	if (typeof token === 'string') {
        +		return true;
        +	} else if (Array.isArray(token)) {
        +		return token.length === 1 && isNotBroken(token[0]);
        +	} else {
        +		return isNotBroken(token.content);
        +	}
        +}
        +
        +/**
        + * Tests all patterns in the given Prism instance.
        + *
        + * @param {any} Prism
        + * @param {string} lang
        + */
        +function testLiterals(Prism, lang) {
        +
        +	/**
        +	 * @param {string[]} identifierElements
        +	 * @param {keyof IdentifierTestOptions} identifierType
        +	 */
        +	function matchNotBroken(identifierElements, identifierType) {
        +		for (const name in Prism.languages) {
        +			const grammar = Prism.languages[name];
        +			if (typeof grammar !== 'object') {
        +				continue;
        +			}
        +
        +			const options = getOptions(name);
        +			if (options[identifierType] === false) {
        +				continue;
        +			}
        +
        +			for (const ident of identifierElements) {
        +				const tokens = Prism.tokenize(ident, grammar);
        +
        +				if (!isNotBroken(tokens)) {
        +					assert.fail(
        +						`${name}: Failed to tokenize the ${identifierType} '${ident}' as one or no token.\n` +
        +						'Actual token stream:\n\n' +
        +						TokenStreamTransformer.prettyprint(tokens) +
        +						'\n\n' +
        +						'How to fix this:\n' +
        +						'If your language failed any of the identifier tests then some patterns in your language can break identifiers. ' +
        +						'An identifier is broken if it is split into two different token (e.g. the identifier \'foo123\' (this could be a variable name) but \'123\' is tokenized as a number). ' +
        +						'This is usually a bug and means that some patterns need more boundary checking.\n' +
        +						'This test defines an identifier as /[A-Za-z_][A-Za-z_0-9]*/ so you can use \\b boundary assertions.\n\n' +
        +						'If the syntactic concept of an identifier is not applicable to your language, you can exclude your language from this test (or parts of it). ' +
        +						'Open \'' + __filename + '\' and follow the instructions to exclude a language. ' +
        +						'(This is usually not what you should do. Only very few language do not have the concept of identifiers.)'
        +					);
        +				}
        +			}
        +		}
        +	}
        +
        +
        +	const options = getOptions(lang);
        +	for (const key in identifiers) {
        +		const identifierType = /** @type {keyof IdentifierTestOptions} */ (key);
        +		const element = identifiers[identifierType];
        +		if (options[identifierType] !== false) {
        +			it(`- should not break ${identifierType} identifiers`, function () {
        +				matchNotBroken(element, identifierType);
        +			});
        +		}
        +	}
        +}
        diff --git a/tests/languages/ini/selector_feature.test b/tests/languages/abnf/comment_feature.test
        similarity index 51%
        rename from tests/languages/ini/selector_feature.test
        rename to tests/languages/abnf/comment_feature.test
        index 3158a665da..1107b4ceaf 100644
        --- a/tests/languages/ini/selector_feature.test
        +++ b/tests/languages/abnf/comment_feature.test
        @@ -1,13 +1,13 @@
        -[owner]
        -[foobar]
        -
        -----------------------------------------------------
        -
        -[
        -	["selector", "[owner]"],
        -	["selector", "[foobar]"]
        -]
        -
        -----------------------------------------------------
        -
        -Checks for section titles.
        \ No newline at end of file
        +;
        +; comment
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", ";"],
        +	["comment", "; comment"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        diff --git a/tests/languages/abnf/core-rule_feature.test b/tests/languages/abnf/core-rule_feature.test
        new file mode 100644
        index 0000000000..6b692e5ed5
        --- /dev/null
        +++ b/tests/languages/abnf/core-rule_feature.test
        @@ -0,0 +1,53 @@
        +ALPHA
        +BIT
        +CHAR
        +CR
        +CRLF
        +CTL
        +DIGIT
        +DQUOTE
        +HEXDIG
        +HTAB
        +LF
        +LWSP
        +OCTET
        +SP
        +VCHAR
        +WSP
        +
        +bit
        +biT
        +
        +
        +----------------------------------------------------
        +
        +[
        +	["core-rule", ["ALPHA"]],
        +	["core-rule", ["BIT"]],
        +	["core-rule", ["CHAR"]],
        +	["core-rule", ["CR"]],
        +	["core-rule", ["CRLF"]],
        +	["core-rule", ["CTL"]],
        +	["core-rule", ["DIGIT"]],
        +	["core-rule", ["DQUOTE"]],
        +	["core-rule", ["HEXDIG"]],
        +	["core-rule", ["HTAB"]],
        +	["core-rule", ["LF"]],
        +	["core-rule", ["LWSP"]],
        +	["core-rule", ["OCTET"]],
        +	["core-rule", ["SP"]],
        +	["core-rule", ["VCHAR"]],
        +	["core-rule", ["WSP"]],
        +
        +	["core-rule", ["bit"]],
        +	["core-rule", ["biT"]],
        +	["core-rule", [
        +		["punctuation", "<"],
        +		"bIt",
        +		["punctuation", ">"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for core rules.
        diff --git a/tests/languages/abnf/definition_feature.test b/tests/languages/abnf/definition_feature.test
        new file mode 100644
        index 0000000000..92166ce353
        --- /dev/null
        +++ b/tests/languages/abnf/definition_feature.test
        @@ -0,0 +1,22 @@
        +foo-bar   =  %x20
        + =/ foo-bar
        +
        +----------------------------------------------------
        +
        +[
        +	["definition", ["foo-bar"]],
        +	["operator", "="],
        +	["terminal", "%x20"],
        +
        +	["definition", [
        +		["punctuation", "<"],
        +		"foo-foo",
        +		["punctuation", ">"]
        +	]],
        +	["operator", "=/"],
        +	["rule", ["foo-bar"]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for definitions.
        diff --git a/tests/languages/abnf/operator_feature.test b/tests/languages/abnf/operator_feature.test
        new file mode 100644
        index 0000000000..c5c5e4158f
        --- /dev/null
        +++ b/tests/languages/abnf/operator_feature.test
        @@ -0,0 +1,13 @@
        += =/ /
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "="],
        +	["operator", "=/"],
        +	["operator", "/"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/abnf/punctuation_feature.test b/tests/languages/abnf/punctuation_feature.test
        new file mode 100644
        index 0000000000..f1581e32dc
        --- /dev/null
        +++ b/tests/languages/abnf/punctuation_feature.test
        @@ -0,0 +1,15 @@
        +()
        +[]
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for punctuation.
        diff --git a/tests/languages/abnf/range_feature.test b/tests/languages/abnf/range_feature.test
        new file mode 100644
        index 0000000000..b56bc1c9e3
        --- /dev/null
        +++ b/tests/languages/abnf/range_feature.test
        @@ -0,0 +1,17 @@
        +%b0-11111
        +%d0-31
        +%x0-1F
        +%x0-1f
        +
        +----------------------------------------------------
        +
        +[
        +	["range", "%b0-11111"],
        +	["range", "%d0-31"],
        +	["range", "%x0-1F"],
        +	["range", "%x0-1f"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for ranges.
        diff --git a/tests/languages/abnf/repetition_feature.test b/tests/languages/abnf/repetition_feature.test
        new file mode 100644
        index 0000000000..3f56e6d201
        --- /dev/null
        +++ b/tests/languages/abnf/repetition_feature.test
        @@ -0,0 +1,19 @@
        +*foo
        +2foo
        +*2foo
        +2*foo
        +2*3foo
        +
        +----------------------------------------------------
        +
        +[
        +	["repetition", "*"], ["rule", ["foo"]],
        +	["repetition", "2"], ["rule", ["foo"]],
        +	["repetition", "*2"], ["rule", ["foo"]],
        +	["repetition", "2*"], ["rule", ["foo"]],
        +	["repetition", "2*3"], ["rule", ["foo"]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for repetitions.
        diff --git a/tests/languages/abnf/rule_feature.test b/tests/languages/abnf/rule_feature.test
        new file mode 100644
        index 0000000000..9b75d334e7
        --- /dev/null
        +++ b/tests/languages/abnf/rule_feature.test
        @@ -0,0 +1,19 @@
        +foo
        +foo-Bar
        +
        +
        +----------------------------------------------------
        +
        +[
        +	["rule", ["foo"]],
        +	["rule", ["foo-Bar"]],
        +	["rule", [
        +		["punctuation", "<"],
        +		"foo-bar",
        +		["punctuation", ">"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for rules.
        diff --git a/tests/languages/abnf/string_feature.test b/tests/languages/abnf/string_feature.test
        new file mode 100644
        index 0000000000..213de24d82
        --- /dev/null
        +++ b/tests/languages/abnf/string_feature.test
        @@ -0,0 +1,29 @@
        +""
        +"a"
        +"abc"
        +";"
        +
        +%s"abc"
        +%i"abc"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", ["\"\""]],
        +	["string", ["\"a\""]],
        +	["string", ["\"abc\""]],
        +	["string", ["\";\""]],
        +
        +	["string", [
        +		["punctuation", "%s"],
        +		"\"abc\""
        +	]],
        +	["string", [
        +		["punctuation", "%i"],
        +		"\"abc\""
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/abnf/terminal_feature.test b/tests/languages/abnf/terminal_feature.test
        new file mode 100644
        index 0000000000..8b55c01400
        --- /dev/null
        +++ b/tests/languages/abnf/terminal_feature.test
        @@ -0,0 +1,19 @@
        +%b1000001
        +%d65
        +%x41
        +%d65.66.67
        +%x41.42.43
        +
        +----------------------------------------------------
        +
        +[
        +	["terminal", "%b1000001"],
        +	["terminal", "%d65"],
        +	["terminal", "%x41"],
        +	["terminal", "%d65.66.67"],
        +	["terminal", "%x41.42.43"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/ada/punctuation_feature.test b/tests/languages/ada/punctuation_feature.test
        new file mode 100644
        index 0000000000..46bf069344
        --- /dev/null
        +++ b/tests/languages/ada/punctuation_feature.test
        @@ -0,0 +1,14 @@
        +. ..
        +, ; ( ) :
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "."],
        +	["punctuation", ".."],
        +	["punctuation", ","],
        +	["punctuation", ";"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ":"]
        +]
        diff --git a/tests/languages/agda/comment_feature.test b/tests/languages/agda/comment_feature.test
        new file mode 100644
        index 0000000000..de122ad76c
        --- /dev/null
        +++ b/tests/languages/agda/comment_feature.test
        @@ -0,0 +1,18 @@
        +{-
        +	This is a
        +	multiline comment
        +-}
        +-- This is a singleline comment
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "{-\r\n\tThis is a\r\n\tmultiline comment\r\n-}"],
        +	["comment", "-- This is a singleline comment"]
        +]
        +
        +----------------------------------------------------
        +
        +In agda there are two kinds of comments:
        +	- Multiline comments wrapped by {- -}
        +	- Singleline comments leading by --
        diff --git a/tests/languages/agda/data_feature.test b/tests/languages/agda/data_feature.test
        new file mode 100644
        index 0000000000..777d70c2cf
        --- /dev/null
        +++ b/tests/languages/agda/data_feature.test
        @@ -0,0 +1,36 @@
        +data _≐_ {ℓ} {A : Set ℓ} (x : A) : A → Prop ℓ where
        +	refl : x ≐ x
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "data"],
        +	["class-name", "_≐_"],
        +	["punctuation", "{"],
        +	"ℓ",
        +	["punctuation", "}"],
        +	["punctuation", "{"],
        +	["function", "A "],
        +	["operator", ":"],
        +	["keyword", "Set"],
        +	" ℓ",
        +	["punctuation", "}"],
        +	["punctuation", "("],
        +	["function", "x "],
        +	["operator", ":"],
        +	" A",
        +	["punctuation", ")"],
        +	["operator", ":"],
        +	" A ",
        +	["operator", "→"],
        +	" Prop ℓ ",
        +	["keyword", "where"],
        +	["function", "refl "],
        +	["operator", ":"],
        +	" x ≐ x"
        +]
        +
        +----------------------------------------------------
        +
        +The `data` keyword in Agda is used to declare a type (of course it can be dependent)
        +in a fashion like Haskell's GADTs.
        diff --git a/tests/languages/agda/function_feature.test b/tests/languages/agda/function_feature.test
        new file mode 100644
        index 0000000000..a90e6d9473
        --- /dev/null
        +++ b/tests/languages/agda/function_feature.test
        @@ -0,0 +1,57 @@
        +merge : {A : Set} (_<_ : A → A → Bool) → List A → List A → List A
        +merge xs [] = xs
        +merge [] ys = ys
        +merge xs@(x ∷ xs₁) ys@(y ∷ ys₁) =
        +	if x < y then x ∷ merge xs₁ ys
        +					 else y ∷ merge xs ys₁
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "merge "],
        +	["operator", ":"],
        +	["punctuation", "{"],
        +	["function", "A "],
        +	["operator", ":"],
        +	["keyword", "Set"],
        +	["punctuation", "}"],
        +	["punctuation", "("],
        +	["function", "_<_ "],
        +	["operator", ":"],
        +	" A ",
        +	["operator", "→"],
        +	" A ",
        +	["operator", "→"],
        +	" Bool",
        +	["punctuation", ")"],
        +	["operator", "→"],
        +	" List A ",
        +	["operator", "→"],
        +	" List A ",
        +	["operator", "→"],
        +	" List A\r\nmerge xs [] ",
        +	["operator", "="],
        +	" xs\r\nmerge [] ys ",
        +	["operator", "="],
        +	" ys\r\nmerge xs",
        +	["punctuation", "@"],
        +	["punctuation", "("],
        +	"x ∷ xs₁",
        +	["punctuation", ")"],
        +	" ys",
        +	["punctuation", "@"],
        +	["punctuation", "("],
        +	"y ∷ ys₁",
        +	["punctuation", ")"],
        +	["operator", "="],
        +
        +	"\r\n\tif x < y then x ∷ merge xs₁ ys\r\n\t\t\t\t\t else y ∷ merge xs ys₁"
        +]
        +
        +----------------------------------------------------
        +
        +Functions in Agda are PURE and TOTAL.
        +Different from Haskell, they can be *dependent* and they can receive implicit arguments.
        +Functions can be infix, or even mixfix, and they become operators.
        +So it is generally not possible to highlight all the "operators" as they are functions.
        +(Also, types are functions too, so it is generally impossible to highlight types.)
        diff --git a/tests/languages/agda/module_feature.test b/tests/languages/agda/module_feature.test
        new file mode 100644
        index 0000000000..f745538842
        --- /dev/null
        +++ b/tests/languages/agda/module_feature.test
        @@ -0,0 +1,52 @@
        +module Test.test where
        +import Relation.Binary.PropositionalEquality as Eq
        +open Eq hiding (_≡_; refl)
        +open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _∎) renaming (begin_ to start_)
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "module"],
        +	" Test",
        +	["punctuation", "."],
        +	"test ",
        +	["keyword", "where"],
        +
        +	["keyword", "import"],
        +	" Relation",
        +	["punctuation", "."],
        +	"Binary",
        +	["punctuation", "."],
        +	"PropositionalEquality as Eq\r\n",
        +
        +	["keyword", "open"],
        +	" Eq ",
        +	["keyword", "hiding"],
        +	["punctuation", "("],
        +	"_≡_",
        +	["punctuation", ";"],
        +	" refl",
        +	["punctuation", ")"],
        +
        +	["keyword", "open"],
        +	" Eq",
        +	["punctuation", "."],
        +	"≡-Reasoning ",
        +	["keyword", "using"],
        +	["punctuation", "("],
        +	"begin_",
        +	["punctuation", ";"],
        +	" _≡⟨⟩_",
        +	["punctuation", ";"],
        +	" _∎",
        +	["punctuation", ")"],
        +	["keyword", "renaming"],
        +	["punctuation", "("],
        +	"begin_ to start_",
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Agda's module system is one based on namespaces and corresponding to file structure.
        +It supports namespace importing, open importing, partial hiding/using and renaming.
        diff --git a/tests/languages/agda/record_feature.test b/tests/languages/agda/record_feature.test
        new file mode 100644
        index 0000000000..4910599c67
        --- /dev/null
        +++ b/tests/languages/agda/record_feature.test
        @@ -0,0 +1,41 @@
        +record Fin (n : Nat) : Set where
        +	constructor _[_]
        +	field
        +		⟦_⟧   : Nat
        +		proof : suc ⟦_⟧ ≤ n
        +open Fin
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "record"],
        +	["class-name", "Fin"],
        +	["punctuation", "("],
        +	["function", "n "],
        +	["operator", ":"],
        +	" Nat",
        +	["punctuation", ")"],
        +	["operator", ":"],
        +	["keyword", "Set"],
        +	["keyword", "where"],
        +
        +	["keyword", "constructor"],
        +	" _[_]\r\n\t",
        +
        +	["keyword", "field"],
        +
        +	["function", "⟦_⟧   "],
        +	["operator", ":"],
        +	" Nat\r\n\t\t",
        +
        +	["function", "proof "],
        +	["operator", ":"],
        +	" suc ⟦_⟧ ≤ n\r\n",
        +
        +	["keyword", "open"],
        +	" Fin"
        +]
        +
        +----------------------------------------------------
        +
        +Agda's record is like objects, but different in many aspects and much more powerful.
        diff --git a/tests/languages/al/boolean_feature.test b/tests/languages/al/boolean_feature.test
        new file mode 100644
        index 0000000000..a225c7b053
        --- /dev/null
        +++ b/tests/languages/al/boolean_feature.test
        @@ -0,0 +1,17 @@
        +false
        +true
        +FALSE
        +TRUE
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "false"],
        +	["boolean", "true"],
        +	["boolean", "FALSE"],
        +	["boolean", "TRUE"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for booleans.
        diff --git a/tests/languages/al/class-name_feature.test b/tests/languages/al/class-name_feature.test
        new file mode 100644
        index 0000000000..8987988b2b
        --- /dev/null
        +++ b/tests/languages/al/class-name_feature.test
        @@ -0,0 +1,211 @@
        +automation
        +biginteger
        +bigtext
        +blob
        +boolean
        +byte
        +char
        +clienttype
        +code
        +completiontriggererrorlevel
        +connectiontype
        +database
        +dataclassification
        +datascope
        +date
        +dateformula
        +datetime
        +decimal
        +defaultlayout
        +dialog
        +dictionary
        +dotnetassembly
        +dotnettypedeclaration
        +duration
        +errorinfo
        +errortype
        +executioncontext
        +executionmode
        +fieldclass
        +fieldref
        +fieldtype
        +file
        +filterpagebuilder
        +guid
        +httpclient
        +httpcontent
        +httpheaders
        +httprequestmessage
        +httpresponsemessage
        +instream
        +integer
        +joker
        +jsonarray
        +jsonobject
        +jsontoken
        +jsonvalue
        +keyref
        +list
        +moduledependencyinfo
        +moduleinfo
        +none
        +notification
        +notificationscope
        +objecttype
        +option
        +outstream
        +pageresult
        +record
        +recordid
        +recordref
        +reportformat
        +securityfilter
        +sessionsettings
        +tableconnectiontype
        +tablefilter
        +testaction
        +testfield
        +testfilterfield
        +testpage
        +testpermissions
        +testrequestpage
        +text
        +textbuilder
        +textconst
        +textencoding
        +time
        +transactionmodel
        +transactiontype
        +variant
        +verbosity
        +version
        +view
        +views
        +webserviceactioncontext
        +webserviceactionresultcode
        +xmlattribute
        +xmlattributecollection
        +xmlcdata
        +xmlcomment
        +xmldeclaration
        +xmldocument
        +xmldocumenttype
        +xmlelement
        +xmlnamespacemanager
        +xmlnametable
        +xmlnode
        +xmlnodelist
        +xmlprocessinginstruction
        +xmlreadoptions
        +xmltext
        +xmlwriteoptions
        +
        +----------------------------------------------------
        +
        +[
        +	["class-name", "automation"],
        +	["class-name", "biginteger"],
        +	["class-name", "bigtext"],
        +	["class-name", "blob"],
        +	["class-name", "boolean"],
        +	["class-name", "byte"],
        +	["class-name", "char"],
        +	["class-name", "clienttype"],
        +	["class-name", "code"],
        +	["class-name", "completiontriggererrorlevel"],
        +	["class-name", "connectiontype"],
        +	["class-name", "database"],
        +	["class-name", "dataclassification"],
        +	["class-name", "datascope"],
        +	["class-name", "date"],
        +	["class-name", "dateformula"],
        +	["class-name", "datetime"],
        +	["class-name", "decimal"],
        +	["class-name", "defaultlayout"],
        +	["class-name", "dialog"],
        +	["class-name", "dictionary"],
        +	["class-name", "dotnetassembly"],
        +	["class-name", "dotnettypedeclaration"],
        +	["class-name", "duration"],
        +	["class-name", "errorinfo"],
        +	["class-name", "errortype"],
        +	["class-name", "executioncontext"],
        +	["class-name", "executionmode"],
        +	["class-name", "fieldclass"],
        +	["class-name", "fieldref"],
        +	["class-name", "fieldtype"],
        +	["class-name", "file"],
        +	["class-name", "filterpagebuilder"],
        +	["class-name", "guid"],
        +	["class-name", "httpclient"],
        +	["class-name", "httpcontent"],
        +	["class-name", "httpheaders"],
        +	["class-name", "httprequestmessage"],
        +	["class-name", "httpresponsemessage"],
        +	["class-name", "instream"],
        +	["class-name", "integer"],
        +	["class-name", "joker"],
        +	["class-name", "jsonarray"],
        +	["class-name", "jsonobject"],
        +	["class-name", "jsontoken"],
        +	["class-name", "jsonvalue"],
        +	["class-name", "keyref"],
        +	["class-name", "list"],
        +	["class-name", "moduledependencyinfo"],
        +	["class-name", "moduleinfo"],
        +	["class-name", "none"],
        +	["class-name", "notification"],
        +	["class-name", "notificationscope"],
        +	["class-name", "objecttype"],
        +	["class-name", "option"],
        +	["class-name", "outstream"],
        +	["class-name", "pageresult"],
        +	["class-name", "record"],
        +	["class-name", "recordid"],
        +	["class-name", "recordref"],
        +	["class-name", "reportformat"],
        +	["class-name", "securityfilter"],
        +	["class-name", "sessionsettings"],
        +	["class-name", "tableconnectiontype"],
        +	["class-name", "tablefilter"],
        +	["class-name", "testaction"],
        +	["class-name", "testfield"],
        +	["class-name", "testfilterfield"],
        +	["class-name", "testpage"],
        +	["class-name", "testpermissions"],
        +	["class-name", "testrequestpage"],
        +	["class-name", "text"],
        +	["class-name", "textbuilder"],
        +	["class-name", "textconst"],
        +	["class-name", "textencoding"],
        +	["class-name", "time"],
        +	["class-name", "transactionmodel"],
        +	["class-name", "transactiontype"],
        +	["class-name", "variant"],
        +	["class-name", "verbosity"],
        +	["class-name", "version"],
        +	["class-name", "view"],
        +	["class-name", "views"],
        +	["class-name", "webserviceactioncontext"],
        +	["class-name", "webserviceactionresultcode"],
        +	["class-name", "xmlattribute"],
        +	["class-name", "xmlattributecollection"],
        +	["class-name", "xmlcdata"],
        +	["class-name", "xmlcomment"],
        +	["class-name", "xmldeclaration"],
        +	["class-name", "xmldocument"],
        +	["class-name", "xmldocumenttype"],
        +	["class-name", "xmlelement"],
        +	["class-name", "xmlnamespacemanager"],
        +	["class-name", "xmlnametable"],
        +	["class-name", "xmlnode"],
        +	["class-name", "xmlnodelist"],
        +	["class-name", "xmlprocessinginstruction"],
        +	["class-name", "xmlreadoptions"],
        +	["class-name", "xmltext"],
        +	["class-name", "xmlwriteoptions"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for class names.
        diff --git a/tests/languages/al/comment_feature.test b/tests/languages/al/comment_feature.test
        new file mode 100644
        index 0000000000..77f0c737a3
        --- /dev/null
        +++ b/tests/languages/al/comment_feature.test
        @@ -0,0 +1,17 @@
        +// comment
        +/**/
        +/*
        + comment
        +*/
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// comment"],
        +	["comment", "/**/"],
        +	["comment", "/*\r\n comment\r\n*/"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        diff --git a/tests/languages/al/function_feature.test b/tests/languages/al/function_feature.test
        new file mode 100644
        index 0000000000..5f106ac077
        --- /dev/null
        +++ b/tests/languages/al/function_feature.test
        @@ -0,0 +1,92 @@
        +procedure CallJavaScript(i : integer; s: text; d : decimal; c : char);
        +local procedure AssignGlobalToLocal(var addin : ControlAddIn TestAddIn)
        +trigger Callback(i : integer; s: text; d : decimal; c : char)
        +trigger OnAction();
        +event Callback(i : integer; s: text; d : decimal; c : char);
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "procedure"],
        +	["function", "CallJavaScript"],
        +	["punctuation", "("],
        +	"i ",
        +	["punctuation", ":"],
        +	["class-name", "integer"],
        +	["punctuation", ";"],
        +	" s",
        +	["punctuation", ":"],
        +	["class-name", "text"],
        +	["punctuation", ";"],
        +	" d ",
        +	["punctuation", ":"],
        +	["class-name", "decimal"],
        +	["punctuation", ";"],
        +	" c ",
        +	["punctuation", ":"],
        +	["class-name", "char"],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "local"],
        +	["keyword", "procedure"],
        +	["function", "AssignGlobalToLocal"],
        +	["punctuation", "("],
        +	["keyword", "var"],
        +	" addin ",
        +	["punctuation", ":"],
        +	["keyword", "ControlAddIn"],
        +	" TestAddIn",
        +	["punctuation", ")"],
        +
        +	["keyword", "trigger"],
        +	["function", "Callback"],
        +	["punctuation", "("],
        +	"i ",
        +	["punctuation", ":"],
        +	["class-name", "integer"],
        +	["punctuation", ";"],
        +	" s",
        +	["punctuation", ":"],
        +	["class-name", "text"],
        +	["punctuation", ";"],
        +	" d ",
        +	["punctuation", ":"],
        +	["class-name", "decimal"],
        +	["punctuation", ";"],
        +	" c ",
        +	["punctuation", ":"],
        +	["class-name", "char"],
        +	["punctuation", ")"],
        +
        +	["keyword", "trigger"],
        +	["function", "OnAction"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "event"],
        +	["function", "Callback"],
        +	["punctuation", "("],
        +	"i ",
        +	["punctuation", ":"],
        +	["class-name", "integer"],
        +	["punctuation", ";"],
        +	" s",
        +	["punctuation", ":"],
        +	["class-name", "text"],
        +	["punctuation", ";"],
        +	" d ",
        +	["punctuation", ":"],
        +	["class-name", "decimal"],
        +	["punctuation", ";"],
        +	" c ",
        +	["punctuation", ":"],
        +	["class-name", "char"],
        +	["punctuation", ")"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for functions.
        diff --git a/tests/languages/al/keyword_feature.test b/tests/languages/al/keyword_feature.test
        new file mode 100644
        index 0000000000..2734cb20a3
        --- /dev/null
        +++ b/tests/languages/al/keyword_feature.test
        @@ -0,0 +1,210 @@
        +array
        +asserterror
        +begin
        +break
        +case
        +do
        +downto
        +else
        +end
        +event
        +exit
        +for
        +foreach
        +function
        +if
        +implements
        +in
        +indataset
        +interface
        +internal
        +local
        +of
        +procedure
        +program
        +protected
        +repeat
        +runonclient
        +securityfiltering
        +suppressdispose
        +temporary
        +then
        +to
        +trigger
        +until
        +var
        +while
        +with
        +withevents
        +
        +action
        +actions
        +addafter
        +addbefore
        +addfirst
        +addlast
        +area
        +assembly
        +chartpart
        +codeunit
        +column
        +controladdin
        +cuegroup
        +customizes
        +dataitem
        +dataset
        +dotnet
        +elements
        +enum
        +enumextension
        +extends
        +field
        +fieldattribute
        +fieldelement
        +fieldgroup
        +fieldgroups
        +fields
        +filter
        +fixed
        +grid
        +group
        +key
        +keys
        +label
        +labels
        +layout
        +modify
        +moveafter
        +movebefore
        +movefirst
        +movelast
        +page
        +pagecustomization
        +pageextension
        +part
        +profile
        +query
        +repeater
        +report
        +requestpage
        +schema
        +separator
        +systempart
        +table
        +tableelement
        +tableextension
        +textattribute
        +textelement
        +type
        +usercontrol
        +value
        +xmlport
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "array"],
        +	["keyword", "asserterror"],
        +	["keyword", "begin"],
        +	["keyword", "break"],
        +	["keyword", "case"],
        +	["keyword", "do"],
        +	["keyword", "downto"],
        +	["keyword", "else"],
        +	["keyword", "end"],
        +	["keyword", "event"],
        +	["keyword", "exit"],
        +	["keyword", "for"],
        +	["keyword", "foreach"],
        +	["keyword", "function"],
        +	["keyword", "if"],
        +	["keyword", "implements"],
        +	["keyword", "in"],
        +	["keyword", "indataset"],
        +	["keyword", "interface"],
        +	["keyword", "internal"],
        +	["keyword", "local"],
        +	["keyword", "of"],
        +	["keyword", "procedure"],
        +	["keyword", "program"],
        +	["keyword", "protected"],
        +	["keyword", "repeat"],
        +	["keyword", "runonclient"],
        +	["keyword", "securityfiltering"],
        +	["keyword", "suppressdispose"],
        +	["keyword", "temporary"],
        +	["keyword", "then"],
        +	["keyword", "to"],
        +	["keyword", "trigger"],
        +	["keyword", "until"],
        +	["keyword", "var"],
        +	["keyword", "while"],
        +	["keyword", "with"],
        +	["keyword", "withevents"],
        +	["keyword", "action"],
        +	["keyword", "actions"],
        +	["keyword", "addafter"],
        +	["keyword", "addbefore"],
        +	["keyword", "addfirst"],
        +	["keyword", "addlast"],
        +	["keyword", "area"],
        +	["keyword", "assembly"],
        +	["keyword", "chartpart"],
        +	["keyword", "codeunit"],
        +	["keyword", "column"],
        +	["keyword", "controladdin"],
        +	["keyword", "cuegroup"],
        +	["keyword", "customizes"],
        +	["keyword", "dataitem"],
        +	["keyword", "dataset"],
        +	["keyword", "dotnet"],
        +	["keyword", "elements"],
        +	["keyword", "enum"],
        +	["keyword", "enumextension"],
        +	["keyword", "extends"],
        +	["keyword", "field"],
        +	["keyword", "fieldattribute"],
        +	["keyword", "fieldelement"],
        +	["keyword", "fieldgroup"],
        +	["keyword", "fieldgroups"],
        +	["keyword", "fields"],
        +	["keyword", "filter"],
        +	["keyword", "fixed"],
        +	["keyword", "grid"],
        +	["keyword", "group"],
        +	["keyword", "key"],
        +	["keyword", "keys"],
        +	["keyword", "label"],
        +	["keyword", "labels"],
        +	["keyword", "layout"],
        +	["keyword", "modify"],
        +	["keyword", "moveafter"],
        +	["keyword", "movebefore"],
        +	["keyword", "movefirst"],
        +	["keyword", "movelast"],
        +	["keyword", "page"],
        +	["keyword", "pagecustomization"],
        +	["keyword", "pageextension"],
        +	["keyword", "part"],
        +	["keyword", "profile"],
        +	["keyword", "query"],
        +	["keyword", "repeater"],
        +	["keyword", "report"],
        +	["keyword", "requestpage"],
        +	["keyword", "schema"],
        +	["keyword", "separator"],
        +	["keyword", "systempart"],
        +	["keyword", "table"],
        +	["keyword", "tableelement"],
        +	["keyword", "tableextension"],
        +	["keyword", "textattribute"],
        +	["keyword", "textelement"],
        +	["keyword", "type"],
        +	["keyword", "usercontrol"],
        +	["keyword", "value"],
        +	["keyword", "xmlport"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for keywords and other literals which behave like keywords.
        diff --git a/tests/languages/al/operator_feature.test b/tests/languages/al/operator_feature.test
        new file mode 100644
        index 0000000000..2ec9708ed6
        --- /dev/null
        +++ b/tests/languages/al/operator_feature.test
        @@ -0,0 +1,57 @@
        ++ - * /
        ++= -= *= /=
        +
        +< <= > >= <> =
        +
        +:=
        +::
        +
        +100..100
        +
        +AND DIV MOD NOT OR XOR
        +and div mod not or xor
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +
        +	["operator", "+="],
        +	["operator", "-="],
        +	["operator", "*="],
        +	["operator", "/="],
        +
        +	["operator", "<"],
        +	["operator", "<="],
        +	["operator", ">"],
        +	["operator", ">="],
        +	["operator", "<>"],
        +	["operator", "="],
        +
        +	["operator", ":="],
        +	["operator", "::"],
        +
        +	["number", "100"],
        +	["operator", ".."],
        +	["number", "100"],
        +
        +	["operator", "AND"],
        +	["operator", "DIV"],
        +	["operator", "MOD"],
        +	["operator", "NOT"],
        +	["operator", "OR"],
        +	["operator", "XOR"],
        +	["operator", "and"],
        +	["operator", "div"],
        +	["operator", "mod"],
        +	["operator", "not"],
        +	["operator", "or"],
        +	["operator", "xor"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/al/string_feature.test b/tests/languages/al/string_feature.test
        new file mode 100644
        index 0000000000..e6e5babbca
        --- /dev/null
        +++ b/tests/languages/al/string_feature.test
        @@ -0,0 +1,20 @@
        +''
        +""
        +'foo'
        +"bar"
        +
        +'C:\text.txt'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "''"],
        +	["string", "\"\""],
        +	["string", "'foo'"],
        +	["string", "\"bar\""],
        +	["string", "'C:\\text.txt'"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/al/variable_feature.test b/tests/languages/al/variable_feature.test
        new file mode 100644
        index 0000000000..5a09ed0079
        --- /dev/null
        +++ b/tests/languages/al/variable_feature.test
        @@ -0,0 +1,21 @@
        +CurrFieldNo
        +CurrPage
        +CurrReport
        +RequestOptionsPage
        +Rec
        +xRec
        +
        +----------------------------------------------------
        +
        +[
        +	["variable", "CurrFieldNo"],
        +	["variable", "CurrPage"],
        +	["variable", "CurrReport"],
        +	["variable", "RequestOptionsPage"],
        +	["variable", "Rec"],
        +	["variable", "xRec"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for variables.
        diff --git a/tests/languages/antlr4/action_feature.test b/tests/languages/antlr4/action_feature.test
        new file mode 100644
        index 0000000000..4288ebb6d5
        --- /dev/null
        +++ b/tests/languages/antlr4/action_feature.test
        @@ -0,0 +1,52 @@
        +options { superClass = LexerAdaptor; }
        +
        +@lexer::header {
        +  import { Token } from 'antlr4ts/Token';
        +  import { CommonToken } from 'antlr4ts/CommonToken';
        +  import { Python3Parser } from './Python3Parser';
        +}
        +
        +END : 'end' {System.out.println("found an end");} ;
        +
        +@header {
        +from LexerAdaptor import LexerAdaptor
        +}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "options"],
        +	["action", [
        +		["punctuation", "{"],
        +		["content", " superClass = LexerAdaptor; "],
        +		["punctuation", "}"]
        +	]],
        +
        +	["annotation", "@lexer::header"],
        +	["action", [
        +		["punctuation", "{"],
        +		["content", "\r\n  import { Token } from 'antlr4ts/Token';\r\n  import { CommonToken } from 'antlr4ts/CommonToken';\r\n  import { Python3Parser } from './Python3Parser';\r\n"],
        +		["punctuation", "}"]
        +	]],
        +
        +	["definition", "END"],
        +	["punctuation", ":"],
        +	["string", "'end'"],
        +	["action", [
        +		["punctuation", "{"],
        +		["content", "System.out.println(\"found an end\");"],
        +		["punctuation", "}"]
        +	]],
        +	["punctuation", ";"],
        +
        +	["annotation", "@header"],
        +	["action", [
        +		["punctuation", "{"],
        +		["content", "\r\nfrom LexerAdaptor import LexerAdaptor\r\n"],
        +		["punctuation", "}"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for actions.
        diff --git a/tests/languages/antlr4/annotation_feature.test b/tests/languages/antlr4/annotation_feature.test
        new file mode 100644
        index 0000000000..803ddbb11e
        --- /dev/null
        +++ b/tests/languages/antlr4/annotation_feature.test
        @@ -0,0 +1,21 @@
        +@header {}
        +@lexer::header {}
        +
        +----------------------------------------------------
        +
        +[
        +	["annotation", "@header"],
        +	["action", [
        +		["punctuation", "{"],
        +		["punctuation", "}"]
        +	]],
        +	["annotation", "@lexer::header"],
        +	["action", [
        +		["punctuation", "{"],
        +		["punctuation", "}"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for annotations.
        diff --git a/tests/languages/antlr4/character-class_feature.test b/tests/languages/antlr4/character-class_feature.test
        new file mode 100644
        index 0000000000..d610fe2e6f
        --- /dev/null
        +++ b/tests/languages/antlr4/character-class_feature.test
        @@ -0,0 +1,51 @@
        +[abc]
        +[\r\n\\\]]
        +[a-z]
        +[+-] [-+]
        +[\uFFFF\u{10FFFF}\p{Block=Latin_1_Supplement}]
        +
        +----------------------------------------------------
        +
        +[
        +	["character-class", [
        +		["punctuation", "["],
        +		"abc",
        +		["punctuation", "]"]
        +	]],
        +	["character-class", [
        +		["punctuation", "["],
        +		["escape", "\\r"],
        +		["escape", "\\n"],
        +		["escape", "\\\\"],
        +		["escape", "\\]"],
        +		["punctuation", "]"]
        +	]],
        +	["character-class", [
        +		["punctuation", "["],
        +		"a",
        +		["range", "-"],
        +		"z",
        +		["punctuation", "]"]
        +	]],
        +	["character-class", [
        +		["punctuation", "["],
        +		"+-",
        +		["punctuation", "]"]
        +	]],
        +	["character-class", [
        +		["punctuation", "["],
        +		"-+",
        +		["punctuation", "]"]
        +	]],
        +	["character-class", [
        +		["punctuation", "["],
        +		["escape", "\\uFFFF"],
        +		["escape", "\\u{10FFFF}"],
        +		["escape", "\\p{Block=Latin_1_Supplement}"],
        +		["punctuation", "]"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for character classes.
        diff --git a/tests/languages/antlr4/command_feature.test b/tests/languages/antlr4/command_feature.test
        new file mode 100644
        index 0000000000..a0a9e7a5b3
        --- /dev/null
        +++ b/tests/languages/antlr4/command_feature.test
        @@ -0,0 +1,213 @@
        +WS : [ \t]+ -> skip ;
        +
        +OPEN        : '<' -> pushMode(INSIDE) ;
        +XMLDeclOpen : ' pushMode(INSIDE) ;
        +SPECIAL_OPEN: ' more, pushMode(PROC_INSTR) ;
        +
        +mode INSIDE;
        +CLOSE        : '>' -> popMode ;
        +SPECIAL_CLOSE: '?>' -> popMode ;
        +SLASH_CLOSE  : '/>' -> popMode ;
        +
        +LQUOTE : '"' -> more, mode(STR) ;
        +WS : [ \t]+ -> skip ;
        +mode STR;
        +STRING : '"' -> mode(DEFAULT_MODE) ;
        +TEXT : . -> more ;
        +
        +DOUBLE : '"' .*? '"'   -> type(STRING) ;
        +SINGLE : '\'' .*? '\'' -> type(STRING) ;
        +WS     : [ \t]+    -> skip ;
        +
        +WS : [ \t]+ -> channel(HIDDEN) ;
        +
        +----------------------------------------------------
        +
        +[
        +	["definition", "WS"],
        +	["punctuation", ":"],
        +	["character-class", [
        +		["punctuation", "["],
        +		["escape", "\\t"],
        +		["punctuation", "]"]
        +	]],
        +	["operator", "+"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "skip"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "OPEN"],
        +	["punctuation", ":"],
        +	["string", "'<'"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "pushMode"],
        +		["punctuation", "("],
        +		"INSIDE",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "XMLDeclOpen"],
        +	["punctuation", ":"],
        +	["string", "'"],
        +	["command", [
        +		["function", "pushMode"],
        +		["punctuation", "("],
        +		"INSIDE",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "SPECIAL_OPEN"],
        +	["punctuation", ":"],
        +	["string", "'"],
        +	["command", [
        +		["function", "more"],
        +		["punctuation", ","],
        +		["function", "pushMode"],
        +		["punctuation", "("],
        +		"PROC_INSTR",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"],
        +	["keyword", "mode"],
        +	["constant", "INSIDE"],
        +	["punctuation", ";"],
        +	["definition", "CLOSE"],
        +	["punctuation", ":"],
        +	["string", "'>'"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "popMode"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "SPECIAL_CLOSE"],
        +	["punctuation", ":"],
        +	["string", "'?>'"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "popMode"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "SLASH_CLOSE"],
        +	["punctuation", ":"],
        +	["string", "'/>'"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "popMode"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "LQUOTE"],
        +	["punctuation", ":"],
        +	["string", "'\"'"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "more"],
        +		["punctuation", ","],
        +		["function", "mode"],
        +		["punctuation", "("],
        +		"STR",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "WS"],
        +	["punctuation", ":"],
        +	["character-class", [
        +		["punctuation", "["],
        +		["escape", "\\t"],
        +		["punctuation", "]"]
        +	]],
        +	["operator", "+"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "skip"]
        +	]],
        +	["punctuation", ";"],
        +	["keyword", "mode"],
        +	["constant", "STR"],
        +	["punctuation", ";"],
        +	["definition", "STRING"],
        +	["punctuation", ":"],
        +	["string", "'\"'"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "mode"],
        +		["punctuation", "("],
        +		"DEFAULT_MODE",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "TEXT"],
        +	["punctuation", ":"],
        +	" . ",
        +	["operator", "->"],
        +	["command", [
        +		["function", "more"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "DOUBLE"],
        +	["punctuation", ":"],
        +	["string", "'\"'"],
        +	" .",
        +	["operator", "*?"],
        +	["string", "'\"'"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "type"],
        +		["punctuation", "("],
        +		"STRING",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "SINGLE"],
        +	["punctuation", ":"],
        +	["string", "'\\''"],
        +	" .",
        +	["operator", "*?"],
        +	["string", "'\\''"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "type"],
        +		["punctuation", "("],
        +		"STRING",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "WS"],
        +	["punctuation", ":"],
        +	["character-class", [
        +		["punctuation", "["],
        +		["escape", "\\t"],
        +		["punctuation", "]"]
        +	]],
        +	["operator", "+"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "skip"]
        +	]],
        +	["punctuation", ";"],
        +	["definition", "WS"],
        +	["punctuation", ":"],
        +	["character-class", [
        +		["punctuation", "["],
        +		["escape", "\\t"],
        +		["punctuation", "]"]
        +	]],
        +	["operator", "+"],
        +	["operator", "->"],
        +	["command", [
        +		["function", "channel"],
        +		["punctuation", "("],
        +		"HIDDEN",
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for commands.
        diff --git a/tests/languages/hpkp/unsafe_maxage_feature.test b/tests/languages/antlr4/comment_feature.test
        similarity index 50%
        rename from tests/languages/hpkp/unsafe_maxage_feature.test
        rename to tests/languages/antlr4/comment_feature.test
        index 4f1ff96158..2b794ba47c 100644
        --- a/tests/languages/hpkp/unsafe_maxage_feature.test
        +++ b/tests/languages/antlr4/comment_feature.test
        @@ -1,12 +1,15 @@
        -max-age=123
        -
        -----------------------------------------------------
        -
        -[
        -	["directive", "max-age="],
        -	["unsafe", "123"]
        -]
        -
        -----------------------------------------------------
        -
        -Checks for HPKP with an "unsafe" max-age.
        +// comment
        +/*
        + comment
        +*/
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// comment"],
        +	["comment", "/*\r\n comment\r\n*/"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        diff --git a/tests/languages/antlr4/definition_feature.test b/tests/languages/antlr4/definition_feature.test
        new file mode 100644
        index 0000000000..85f620b053
        --- /dev/null
        +++ b/tests/languages/antlr4/definition_feature.test
        @@ -0,0 +1,25 @@
        +foo : FOO ;
        +FOO : BAR ;
        +fragment BAR : 'bar' ;
        +
        +----------------------------------------------------
        +
        +[
        +	["definition", "foo"],
        +	["punctuation", ":"],
        +	["constant", "FOO"],
        +	["punctuation", ";"],
        +	["definition", "FOO"],
        +	["punctuation", ":"],
        +	["constant", "BAR"],
        +	["punctuation", ";"],
        +	["keyword", "fragment"],
        +	["definition", "BAR"],
        +	["punctuation", ":"],
        +	["string", "'bar'"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for token and rule definitions.
        diff --git a/tests/languages/antlr4/keyword_feature.test b/tests/languages/antlr4/keyword_feature.test
        new file mode 100644
        index 0000000000..acd4318aaa
        --- /dev/null
        +++ b/tests/languages/antlr4/keyword_feature.test
        @@ -0,0 +1,37 @@
        +catch
        +channels
        +finally
        +fragment
        +grammar
        +import
        +lexer
        +locals
        +mode
        +options
        +parser
        +returns
        +throws
        +tokens
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "catch"],
        +	["keyword", "channels"],
        +	["keyword", "finally"],
        +	["keyword", "fragment"],
        +	["keyword", "grammar"],
        +	["keyword", "import"],
        +	["keyword", "lexer"],
        +	["keyword", "locals"],
        +	["keyword", "mode"],
        +	["keyword", "options"],
        +	["keyword", "parser"],
        +	["keyword", "returns"],
        +	["keyword", "throws"],
        +	["keyword", "tokens"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for keywords.
        diff --git a/tests/languages/antlr4/label_feature.test b/tests/languages/antlr4/label_feature.test
        new file mode 100644
        index 0000000000..74c4191c01
        --- /dev/null
        +++ b/tests/languages/antlr4/label_feature.test
        @@ -0,0 +1,43 @@
        +stat: 'return' e ';' # Return
        +	| 'break' ';' # Break
        +	;
        +e   : e '*' e # Mult
        +	| e '+' e # Add
        +	| INT # Int
        +	;
        +
        +----------------------------------------------------
        +
        +[
        +	["definition", "stat"],
        +	["punctuation", ":"],
        +	["string", "'return'"],
        +	" e ",
        +	["string", "';'"],
        +	["label", "# Return"],
        +	["operator", "|"],
        +	["string", "'break'"],
        +	["string", "';'"],
        +	["label", "# Break"],
        +	["punctuation", ";"],
        +
        +	["definition", "e"],
        +	["punctuation", ":"],
        +	" e ",
        +	["string", "'*'"],
        +	" e ",
        +	["label", "# Mult"],
        +	["operator", "|"],
        +	" e ",
        +	["string", "'+'"],
        +	" e ",
        +	["label", "# Add"],
        +	["operator", "|"],
        +	["constant", "INT"],
        +	["label", "# Int"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for labels.
        diff --git a/tests/languages/antlr4/operator_feature.test b/tests/languages/antlr4/operator_feature.test
        new file mode 100644
        index 0000000000..8416023b5a
        --- /dev/null
        +++ b/tests/languages/antlr4/operator_feature.test
        @@ -0,0 +1,24 @@
        +* + ?
        +*? +? ??
        +
        +| ~ ..
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "*"],
        +	["operator", "+"],
        +	["operator", "?"],
        +
        +	["operator", "*?"],
        +	["operator", "+?"],
        +	["operator", "??"],
        +
        +	["operator", "|"],
        +	["operator", "~"],
        +	["operator", ".."]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/antlr4/string_feature.test b/tests/languages/antlr4/string_feature.test
        new file mode 100644
        index 0000000000..15174ca291
        --- /dev/null
        +++ b/tests/languages/antlr4/string_feature.test
        @@ -0,0 +1,17 @@
        +'foo'
        +'a'
        +'\''
        +'\r\n'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "'foo'"],
        +	["string", "'a'"],
        +	["string", "'\\''"],
        +	["string", "'\\r\\n'"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/apacheconf/directive-flags_feature.test b/tests/languages/apacheconf/directive-flags_feature.test
        index 0bb206ecba..69ae37eed4 100644
        --- a/tests/languages/apacheconf/directive-flags_feature.test
        +++ b/tests/languages/apacheconf/directive-flags_feature.test
        @@ -1,13 +1,15 @@
         [OR]
         [L,QSA]
        +[L,R=301,NC]
         
         ----------------------------------------------------
         
         [
         	["directive-flags", "[OR]"],
        -	["directive-flags", "[L,QSA]"]
        +	["directive-flags", "[L,QSA]"],
        +	["directive-flags", "[L,R=301,NC]"]
         ]
         
         ----------------------------------------------------
         
        -Checks for directive flags.
        \ No newline at end of file
        +Checks for directive flags.
        diff --git a/tests/languages/apacheconf/directive-inline_feature.test b/tests/languages/apacheconf/directive-inline_feature.test
        index 6b4df43b26..fe8fc186ee 100644
        --- a/tests/languages/apacheconf/directive-inline_feature.test
        +++ b/tests/languages/apacheconf/directive-inline_feature.test
        @@ -524,6 +524,7 @@ SSLRequireSSL
         SSLSessionCache
         SSLSessionCacheTimeout
         SSLSessionTicketKeyFile
        +SSLSessionTickets
         SSLSRPUnknownUserSeed
         SSLSRPVerifierFile
         SSLStaplingCache
        @@ -1105,6 +1106,7 @@ xml2StartParse
         	["directive-inline", "SSLSessionCache"],
         	["directive-inline", "SSLSessionCacheTimeout"],
         	["directive-inline", "SSLSessionTicketKeyFile"],
        +	["directive-inline", "SSLSessionTickets"],
         	["directive-inline", "SSLSRPUnknownUserSeed"],
         	["directive-inline", "SSLSRPVerifierFile"],
         	["directive-inline", "SSLStaplingCache"],
        @@ -1160,4 +1162,4 @@ xml2StartParse
         
         ----------------------------------------------------
         
        -Checks for all inline directives.
        \ No newline at end of file
        +Checks for all inline directives.
        diff --git a/tests/languages/apex/annotation_feature.test b/tests/languages/apex/annotation_feature.test
        new file mode 100644
        index 0000000000..24a84e8a75
        --- /dev/null
        +++ b/tests/languages/apex/annotation_feature.test
        @@ -0,0 +1,16 @@
        +@Future
        +@IsTest
        +@isTest(SeeAllData=true)
        +
        +----------------------------------------------------
        +
        +[
        +	["annotation", "@Future"],
        +	["annotation", "@IsTest"],
        +	["annotation", "@isTest"],
        +	["punctuation", "("],
        +	"SeeAllData",
        +	["operator", "="],
        +	["boolean", "true"],
        +	["punctuation", ")"]
        +]
        diff --git a/tests/languages/apex/boolean_feature.test b/tests/languages/apex/boolean_feature.test
        new file mode 100644
        index 0000000000..62b158804d
        --- /dev/null
        +++ b/tests/languages/apex/boolean_feature.test
        @@ -0,0 +1,9 @@
        +true
        +false
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "true"],
        +	["boolean", "false"]
        +]
        diff --git a/tests/languages/apex/class-name_feature.test b/tests/languages/apex/class-name_feature.test
        new file mode 100644
        index 0000000000..8074dc60fd
        --- /dev/null
        +++ b/tests/languages/apex/class-name_feature.test
        @@ -0,0 +1,334 @@
        +Integer i;
        +Integer i = (Integer)obj;
        +Integer[] myInts = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        +Object obj = new MyApexClass();
        +list itemList;
        +List>> my_list_2 = new List>>();
        +Map updateMap = new Map();
        +set AllItems = new set();
        +
        +public Season getSouthernHemisphereSeason(season northernHemisphereSeason) {}
        +
        +for(Shipping_Invoice__C sc : AllShippingInvoices){}
        +public static Integer calculate() {}
        +
        +if (sobject instanceof Account) {
        +	Account a = (Account) sobject;
        +}
        +
        +public class myOuterClass {}
        +public enum MyEnumClass { X, Y }
        +public class YellowMarker extends Marker {}
        +interface MySecondInterface extends MyInterface {}
        +public virtual class InnerClass implements MySecondInterface {}
        +
        +
        +class Foo {
        +	List accs {get; set;}
        +	Integer i {get; set;}
        +}
        +
        +
        +public with sharing class sharingClass {}
        +public without sharing class noSharing {}
        +public inherited sharing class InheritedSharingClass{}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "Integer"],
        +	" i",
        +	["punctuation", ";"],
        +	["keyword", "Integer"],
        +	" i ",
        +	["operator", "="],
        +	["punctuation", "("],
        +	["keyword", "Integer"],
        +	["punctuation", ")"],
        +	"obj",
        +	["punctuation", ";"],
        +	["class-name", [
        +		["keyword", "Integer"],
        +		["punctuation", "["],
        +		["punctuation", "]"]
        +	]],
        +	" myInts ",
        +	["operator", "="],
        +	["keyword", "new"],
        +	["class-name", [
        +		["keyword", "Integer"],
        +		["punctuation", "["],
        +		["punctuation", "]"]
        +	]],
        +	["punctuation", "{"],
        +	["number", "1"],
        +	["punctuation", ","],
        +	["number", "2"],
        +	["punctuation", ","],
        +	["number", "3"],
        +	["punctuation", ","],
        +	["number", "4"],
        +	["punctuation", ","],
        +	["number", "5"],
        +	["punctuation", ","],
        +	["number", "6"],
        +	["punctuation", ","],
        +	["number", "7"],
        +	["punctuation", ","],
        +	["number", "8"],
        +	["punctuation", ","],
        +	["number", "9"],
        +	["punctuation", ","],
        +	["number", "10"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +	["keyword", "Object"],
        +	" obj ",
        +	["operator", "="],
        +	["keyword", "new"],
        +	["class-name", [
        +		"MyApexClass"
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["class-name", [
        +		["keyword", "list"],
        +		["punctuation", "<"],
        +		"Item__c",
        +		["punctuation", ">"]
        +	]],
        +	" itemList",
        +	["punctuation", ";"],
        +	["class-name", [
        +		["keyword", "List"],
        +		["punctuation", "<"],
        +		["keyword", "List"],
        +		["punctuation", "<"],
        +		["keyword", "Set"],
        +		["punctuation", "<"],
        +		["keyword", "Integer"],
        +		["punctuation", ">"],
        +		["punctuation", ">"],
        +		["punctuation", ">"]
        +	]],
        +	" my_list_2 ",
        +	["operator", "="],
        +	["keyword", "new"],
        +	["class-name", [
        +		["keyword", "List"],
        +		["punctuation", "<"],
        +		["keyword", "List"],
        +		["punctuation", "<"],
        +		["keyword", "Set"],
        +		["punctuation", "<"],
        +		["keyword", "Integer"],
        +		["punctuation", ">"],
        +		["punctuation", ">"],
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["class-name", [
        +		["keyword", "Map"],
        +		["punctuation", "<"],
        +		"ID",
        +		["punctuation", ","],
        +		" Shipping_Invoice__C",
        +		["punctuation", ">"]
        +	]],
        +	" updateMap ",
        +	["operator", "="],
        +	["keyword", "new"],
        +	["class-name", [
        +		["keyword", "Map"],
        +		["punctuation", "<"],
        +		"ID",
        +		["punctuation", ","],
        +		" Shipping_Invoice__C",
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["class-name", [
        +		["keyword", "set"],
        +		["punctuation", "<"],
        +		"Id",
        +		["punctuation", ">"]
        +	]],
        +	" AllItems ",
        +	["operator", "="],
        +	["keyword", "new"],
        +	["class-name", [
        +		["keyword", "set"],
        +		["punctuation", "<"],
        +		"id",
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "public"],
        +	["class-name", [
        +		"Season"
        +	]],
        +	["function", "getSouthernHemisphereSeason"],
        +	["punctuation", "("],
        +	["class-name", [
        +		"season"
        +	]],
        +	" northernHemisphereSeason",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "for"],
        +	["punctuation", "("],
        +	["class-name", [
        +		"Shipping_Invoice__C"
        +	]],
        +	" sc ",
        +	["operator", ":"],
        +	" AllShippingInvoices",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["keyword", "public"],
        +	["keyword", "static"],
        +	["keyword", "Integer"],
        +	["function", "calculate"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	["keyword", "sobject"],
        +	["keyword", "instanceof"],
        +	["class-name", [
        +		"Account"
        +	]],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["class-name", [
        +		"Account"
        +	]],
        +	" a ",
        +	["operator", "="],
        +	["punctuation", "("],
        +	["class-name", [
        +		"Account"
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "sobject"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +
        +	["keyword", "public"],
        +	["keyword", "class"],
        +	["class-name", [
        +		"myOuterClass"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["keyword", "public"],
        +	["keyword", "enum"],
        +	["class-name", [
        +		"MyEnumClass"
        +	]],
        +	["punctuation", "{"],
        +	" X",
        +	["punctuation", ","],
        +	" Y ",
        +	["punctuation", "}"],
        +	["keyword", "public"],
        +	["keyword", "class"],
        +	["class-name", [
        +		"YellowMarker"
        +	]],
        +	["keyword", "extends"],
        +	["class-name", [
        +		"Marker"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["keyword", "interface"],
        +	["class-name", [
        +		"MySecondInterface"
        +	]],
        +	["keyword", "extends"],
        +	["class-name", [
        +		"MyInterface"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["keyword", "public"],
        +	["keyword", "virtual"],
        +	["keyword", "class"],
        +	["class-name", [
        +		"InnerClass"
        +	]],
        +	["keyword", "implements"],
        +	["class-name", [
        +		"MySecondInterface"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "class"],
        +	["class-name", [
        +		"Foo"
        +	]],
        +	["punctuation", "{"],
        +	["class-name", [
        +		["keyword", "List"],
        +		["punctuation", "<"],
        +		"Account",
        +		["punctuation", ">"]
        +	]],
        +	" accs ",
        +	["punctuation", "{"],
        +	["keyword", "get"],
        +	["punctuation", ";"],
        +	["keyword", "set"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +	["keyword", "Integer"],
        +	" i ",
        +	["punctuation", "{"],
        +	["keyword", "get"],
        +	["punctuation", ";"],
        +	["keyword", "set"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +	["punctuation", "}"],
        +
        +	["keyword", "public"],
        +	["keyword", "with sharing"],
        +	["keyword", "class"],
        +	["class-name", [
        +		"sharingClass"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["keyword", "public"],
        +	["keyword", "without sharing"],
        +	["keyword", "class"],
        +	["class-name", [
        +		"noSharing"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["keyword", "public"],
        +	["keyword", "inherited sharing"],
        +	["keyword", "class"],
        +	["class-name", [
        +		"InheritedSharingClass"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/apex/comment_feature.test b/tests/languages/apex/comment_feature.test
        new file mode 100644
        index 0000000000..37590c35d1
        --- /dev/null
        +++ b/tests/languages/apex/comment_feature.test
        @@ -0,0 +1,11 @@
        +// comment
        +/*
        +comment
        +*/
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// comment"],
        +	["comment", "/*\r\ncomment\r\n*/"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/apex/number_feature.test b/tests/languages/apex/number_feature.test
        new file mode 100644
        index 0000000000..e2be1e3fd2
        --- /dev/null
        +++ b/tests/languages/apex/number_feature.test
        @@ -0,0 +1,15 @@
        +0
        +123
        +.123
        +21.3
        +123L
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "0"],
        +	["number", "123"],
        +	["number", ".123"],
        +	["number", "21.3"],
        +	["number", "123L"]
        +]
        diff --git a/tests/languages/apex/operator_feature.test b/tests/languages/apex/operator_feature.test
        new file mode 100644
        index 0000000000..e7e8464c32
        --- /dev/null
        +++ b/tests/languages/apex/operator_feature.test
        @@ -0,0 +1,64 @@
        +=
        +
        ++= *= -= /=
        +|= &= <<= >>= >>>=
        +
        +? :
        +
        +&& ||
        +== === < > <= >= != !==
        +
        ++ - * / !
        +++ --
        +& |
        +^ ^=
        +<< >> >>>
        +
        +?.
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "="],
        +
        +	["operator", "+="],
        +	["operator", "*="],
        +	["operator", "-="],
        +	["operator", "/="],
        +	["operator", "|="],
        +	["operator", "&="],
        +	["operator", "<<="],
        +	["operator", ">>="],
        +	["operator", ">>>="],
        +
        +	["operator", "?"],
        +	["operator", ":"],
        +
        +	["operator", "&&"],
        +	["operator", "||"],
        +	["operator", "=="],
        +	["operator", "==="],
        +	["operator", "<"],
        +	["operator", ">"],
        +	["operator", "<="],
        +	["operator", ">="],
        +	["operator", "!="],
        +	["operator", "!=="],
        +
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "!"],
        +	["operator", "++"],
        +	["operator", "--"],
        +	["operator", "&"],
        +	["operator", "|"],
        +	["operator", "^"],
        +	["operator", "^="],
        +	["operator", "<<"],
        +	["operator", ">>"],
        +	["operator", ">>>"],
        +
        +	["operator", "?."]
        +]
        diff --git a/tests/languages/apex/punctuation_feature.test b/tests/languages/apex/punctuation_feature.test
        new file mode 100644
        index 0000000000..7be7561bec
        --- /dev/null
        +++ b/tests/languages/apex/punctuation_feature.test
        @@ -0,0 +1,16 @@
        +( ) [ ] { }
        +. , ;
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", "."],
        +	["punctuation", ","],
        +	["punctuation", ";"]
        +]
        diff --git a/tests/languages/apex/sql_feature.test b/tests/languages/apex/sql_feature.test
        new file mode 100644
        index 0000000000..2ade8e615d
        --- /dev/null
        +++ b/tests/languages/apex/sql_feature.test
        @@ -0,0 +1,48 @@
        +b = [SELECT Price__c FROM Book__c WHERE Id =:b.Id];
        +return [SELECT Name FROM Contact];
        +
        +// don't capture array indexing
        +a[0].Name = 'Acme';
        +
        +----------------------------------------------------
        +
        +[
        +	"b ",
        +	["operator", "="],
        +	["sql", [
        +		["punctuation", "["],
        +		["keyword", "SELECT"],
        +		" Price__c ",
        +		["keyword", "FROM"],
        +		" Book__c ",
        +		["keyword", "WHERE"],
        +		" Id ",
        +		["operator", "="],
        +		":b",
        +		["punctuation", "."],
        +		"Id",
        +		["punctuation", "]"]
        +	]],
        +	["punctuation", ";"],
        +	["keyword", "return"],
        +	["sql", [
        +		["punctuation", "["],
        +		["keyword", "SELECT"],
        +		" Name ",
        +		["keyword", "FROM"],
        +		" Contact",
        +		["punctuation", "]"]
        +	]],
        +	["punctuation", ";"],
        +
        +	["comment", "// don't capture array indexing"],
        +	"\r\na",
        +	["punctuation", "["],
        +	["number", "0"],
        +	["punctuation", "]"],
        +	["punctuation", "."],
        +	"Name ",
        +	["operator", "="],
        +	["string", "'Acme'"],
        +	["punctuation", ";"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/apex/string_feature.test b/tests/languages/apex/string_feature.test
        new file mode 100644
        index 0000000000..5d6f204ad5
        --- /dev/null
        +++ b/tests/languages/apex/string_feature.test
        @@ -0,0 +1,13 @@
        +''
        +'  '
        +'\''
        +'foo\nbar'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "''"],
        +	["string", "'  '"],
        +	["string", "'\\''"],
        +	["string", "'foo\\nbar'"]
        +]
        diff --git a/tests/languages/apex/trigger_feature.test b/tests/languages/apex/trigger_feature.test
        new file mode 100644
        index 0000000000..c59d1f0162
        --- /dev/null
        +++ b/tests/languages/apex/trigger_feature.test
        @@ -0,0 +1,39 @@
        +trigger HelloWorldTrigger on Book__c (before insert) {}
        +
        +trigger T1 on Account (before delete, after delete, after undelete) {}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "trigger"],
        +	["trigger", "HelloWorldTrigger"],
        +	["keyword", "on"],
        +	["class-name", [
        +		"Book__c"
        +	]],
        +	["punctuation", "("],
        +	["keyword", "before"],
        +	["keyword", "insert"],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "trigger"],
        +	["trigger", "T1"],
        +	["keyword", "on"],
        +	["class-name", [
        +		"Account"
        +	]],
        +	["punctuation", "("],
        +	["keyword", "before"],
        +	["keyword", "delete"],
        +	["punctuation", ","],
        +	["keyword", "after"],
        +	["keyword", "delete"],
        +	["punctuation", ","],
        +	["keyword", "after"],
        +	["keyword", "undelete"],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
        +]
        diff --git a/tests/languages/apl/dyadic-operator_feature.test b/tests/languages/apl/dyadic-operator_feature.test
        index bd141edef6..cec61b4f55 100644
        --- a/tests/languages/apl/dyadic-operator_feature.test
        +++ b/tests/languages/apl/dyadic-operator_feature.test
        @@ -1,15 +1,15 @@
         . ⍣ ⍠
         ⍤ ∘ ⌸
        -@ ⌺
        +@ ⌺ ⍥
         
         ----------------------------------------------------
         
         [
         	["dyadic-operator", "."], ["dyadic-operator", "⍣"], ["dyadic-operator", "⍠"],
         	["dyadic-operator", "⍤"], ["dyadic-operator", "∘"], ["dyadic-operator", "⌸"],
        -	["dyadic-operator", "@"], ["dyadic-operator", "⌺"]
        +	["dyadic-operator", "@"], ["dyadic-operator", "⌺"], ["dyadic-operator", "⍥"]
         ]
         
         ----------------------------------------------------
         
        -Checks for dyadic operators.
        \ No newline at end of file
        +Checks for dyadic operators.
        diff --git a/tests/languages/applescript/class-name_feature.test b/tests/languages/applescript/class-name_feature.test
        new file mode 100644
        index 0000000000..db348ead10
        --- /dev/null
        +++ b/tests/languages/applescript/class-name_feature.test
        @@ -0,0 +1,90 @@
        +alias application boolean class constant
        +date file integer list number
        +POSIX file
        +real record reference
        +RGB color
        +script text centimetres centimeters feet
        +inches kilometres kilometers metres meters
        +miles yards
        +square feet square kilometres square kilometers square metres
        +square meters square miles square yards
        +cubic centimetres cubic centimeters cubic feet cubic inches
        +cubic metres cubic meters cubic yards
        +gallons litres liters quarts grams
        +kilograms ounces pounds
        +degrees Celsius degrees Fahrenheit degrees Kelvin
        +
        +----------------------------------------------------
        +
        +[
        +	["class-name", "alias"],
        +	["class-name", "application"],
        +	["class-name", "boolean"],
        +	["class-name", "class"],
        +	["class-name", "constant"],
        +
        +	["class-name", "date"],
        +	["class-name", "file"],
        +	["class-name", "integer"],
        +	["class-name", "list"],
        +	["class-name", "number"],
        +
        +	["class-name", "POSIX file"],
        +
        +	["class-name", "real"],
        +	["class-name", "record"],
        +	["class-name", "reference"],
        +
        +	["class-name", "RGB color"],
        +
        +	["class-name", "script"],
        +	["class-name", "text"],
        +	["class-name", "centimetres"],
        +	["class-name", "centimeters"],
        +	["class-name", "feet"],
        +
        +	["class-name", "inches"],
        +	["class-name", "kilometres"],
        +	["class-name", "kilometers"],
        +	["class-name", "metres"],
        +	["class-name", "meters"],
        +
        +	["class-name", "miles"],
        +	["class-name", "yards"],
        +
        +	["class-name", "square feet"],
        +	["class-name", "square kilometres"],
        +	["class-name", "square kilometers"],
        +	["class-name", "square metres"],
        +
        +	["class-name", "square meters"],
        +	["class-name", "square miles"],
        +	["class-name", "square yards"],
        +
        +	["class-name", "cubic centimetres"],
        +	["class-name", "cubic centimeters"],
        +	["class-name", "cubic feet"],
        +	["class-name", "cubic inches"],
        +
        +	["class-name", "cubic metres"],
        +	["class-name", "cubic meters"],
        +	["class-name", "cubic yards"],
        +
        +	["class-name", "gallons"],
        +	["class-name", "litres"],
        +	["class-name", "liters"],
        +	["class-name", "quarts"],
        +	["class-name", "grams"],
        +
        +	["class-name", "kilograms"],
        +	["class-name", "ounces"],
        +	["class-name", "pounds"],
        +
        +	["class-name", "degrees Celsius"],
        +	["class-name", "degrees Fahrenheit"],
        +	["class-name", "degrees Kelvin"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all classes.
        diff --git a/tests/languages/applescript/class_feature.test b/tests/languages/applescript/class_feature.test
        deleted file mode 100644
        index 547906deab..0000000000
        --- a/tests/languages/applescript/class_feature.test
        +++ /dev/null
        @@ -1,39 +0,0 @@
        -alias application boolean class constant
        -date file integer list number
        -POSIX file
        -real record reference
        -RGB color
        -script text centimetres centimeters feet
        -inches kilometres kilometers metres meters
        -miles yards
        -square feet square kilometres square kilometers square metres
        -square meters square miles square yards
        -cubic centimetres cubic centimeters cubic feet cubic inches
        -cubic metres cubic meters cubic yards
        -gallons litres liters quarts grams
        -kilograms ounces pounds
        -degrees Celsius degrees Fahrenheit degrees Kelvin
        -
        -----------------------------------------------------
        -
        -[
        -	["class", "alias"], ["class", "application"], ["class", "boolean"], ["class", "class"], ["class", "constant"],
        -	["class", "date"], ["class", "file"], ["class", "integer"], ["class", "list"], ["class", "number"],
        -	["class", "POSIX file"],
        -	["class", "real"], ["class", "record"], ["class", "reference"],
        -	["class", "RGB color"],
        -	["class", "script"], ["class", "text"], ["class", "centimetres"], ["class", "centimeters"], ["class", "feet"],
        -	["class", "inches"], ["class", "kilometres"], ["class", "kilometers"], ["class", "metres"], ["class", "meters"],
        -	["class", "miles"], ["class", "yards"],
        -	["class", "square feet"], ["class", "square kilometres"], ["class", "square kilometers"], ["class", "square metres"],
        -	["class", "square meters"], ["class", "square miles"], ["class", "square yards"],
        -	["class", "cubic centimetres"], ["class", "cubic centimeters"], ["class", "cubic feet"], ["class", "cubic inches"],
        -	["class", "cubic metres"], ["class", "cubic meters"], ["class", "cubic yards"],
        -	["class", "gallons"], ["class", "litres"], ["class", "liters"], ["class", "quarts"], ["class", "grams"],
        -	["class", "kilograms"], ["class", "ounces"], ["class", "pounds"],
        -	["class", "degrees Celsius"], ["class", "degrees Fahrenheit"], ["class", "degrees Kelvin"]
        -]
        -
        -----------------------------------------------------
        -
        -Checks for all classes.
        \ No newline at end of file
        diff --git a/tests/languages/applescript/punctuation_feature.test b/tests/languages/applescript/punctuation_feature.test
        new file mode 100644
        index 0000000000..183ea153e7
        --- /dev/null
        +++ b/tests/languages/applescript/punctuation_feature.test
        @@ -0,0 +1,18 @@
        +{ } ( ) : ,
        +¬ « » 《 》
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ":"],
        +	["punctuation", ","],
        +	["punctuation", "¬"],
        +	["punctuation", "«"],
        +	["punctuation", "»"],
        +	["punctuation", "《"],
        +	["punctuation", "》"]
        +]
        diff --git a/tests/languages/aql/boolean_feature.test b/tests/languages/aql/boolean_feature.test
        new file mode 100644
        index 0000000000..6d5c41a781
        --- /dev/null
        +++ b/tests/languages/aql/boolean_feature.test
        @@ -0,0 +1,13 @@
        +true
        +false
        +TRUE
        +FALSE
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "true"],
        +	["boolean", "false"],
        +	["boolean", "TRUE"],
        +	["boolean", "FALSE"]
        +]
        diff --git a/tests/languages/aql/comment_feature.test b/tests/languages/aql/comment_feature.test
        new file mode 100644
        index 0000000000..ea3f62ae31
        --- /dev/null
        +++ b/tests/languages/aql/comment_feature.test
        @@ -0,0 +1,16 @@
        +// single line
        +/*
        + multi
        + line
        + */
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// single line"],
        +	["comment", "/*\r\n multi\r\n line\r\n */"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        diff --git a/tests/languages/aql/identifier_feature.test b/tests/languages/aql/identifier_feature.test
        new file mode 100644
        index 0000000000..664358bbef
        --- /dev/null
        +++ b/tests/languages/aql/identifier_feature.test
        @@ -0,0 +1,9 @@
        +´filter´
        +`sort`
        +
        +----------------------------------------------------
        +
        +[
        +	["identifier", "´filter´"],
        +	["identifier", "`sort`"]
        +]
        diff --git a/tests/languages/aql/keyword_feature.test b/tests/languages/aql/keyword_feature.test
        new file mode 100644
        index 0000000000..d095cb4ae9
        --- /dev/null
        +++ b/tests/languages/aql/keyword_feature.test
        @@ -0,0 +1,111 @@
        +WITH COUNT INTO
        +COUNT
        +
        +AGGREGATE
        +ALL
        +AND
        +ANY
        +ASC
        +COLLECT
        +DESC
        +DISTINCT
        +FILTER
        +FOR
        +GRAPH
        +IN
        +INBOUND
        +INSERT
        +INTO
        +K_PATHS
        +K_SHORTEST_PATHS
        +LET
        +LIKE
        +LIMIT
        +NONE
        +NOT
        +NULL
        +OR
        +OUTBOUND
        +REMOVE
        +REPLACE
        +RETURN
        +SHORTEST_PATH
        +SORT
        +UPDATE
        +UPSERT
        +WINDOW
        +WITH
        +
        +KEEP
        +PRUNE
        +SEARCH
        +TO
        +
        +CURRENT
        +NEW
        +OLD
        +
        +OPTIONS {}
        +OPTIONS
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "WITH"],
        +	["keyword", "COUNT"],
        +	["keyword", "INTO"],
        +	"\r\nCOUNT\r\n\r\n",
        +
        +	["keyword", "AGGREGATE"],
        +	["keyword", "ALL"],
        +	["keyword", "AND"],
        +	["keyword", "ANY"],
        +	["keyword", "ASC"],
        +	["keyword", "COLLECT"],
        +	["keyword", "DESC"],
        +	["keyword", "DISTINCT"],
        +	["keyword", "FILTER"],
        +	["keyword", "FOR"],
        +	["keyword", "GRAPH"],
        +	["keyword", "IN"],
        +	["keyword", "INBOUND"],
        +	["keyword", "INSERT"],
        +	["keyword", "INTO"],
        +	["keyword", "K_PATHS"],
        +	["keyword", "K_SHORTEST_PATHS"],
        +	["keyword", "LET"],
        +	["keyword", "LIKE"],
        +	["keyword", "LIMIT"],
        +	["keyword", "NONE"],
        +	["keyword", "NOT"],
        +	["keyword", "NULL"],
        +	["keyword", "OR"],
        +	["keyword", "OUTBOUND"],
        +	["keyword", "REMOVE"],
        +	["keyword", "REPLACE"],
        +	["keyword", "RETURN"],
        +	["keyword", "SHORTEST_PATH"],
        +	["keyword", "SORT"],
        +	["keyword", "UPDATE"],
        +	["keyword", "UPSERT"],
        +	["keyword", "WINDOW"],
        +	["keyword", "WITH"],
        +
        +	["keyword", "KEEP"],
        +	["keyword", "PRUNE"],
        +	["keyword", "SEARCH"],
        +	["keyword", "TO"],
        +
        +	["keyword", "CURRENT"],
        +	["keyword", "NEW"],
        +	["keyword", "OLD"],
        +
        +	["keyword", "OPTIONS"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	"\r\nOPTIONS"
        +]
        +
        +----------------------------------------------------
        +
        +Checks for keywords.
        diff --git a/tests/languages/aql/number_feature.test b/tests/languages/aql/number_feature.test
        new file mode 100644
        index 0000000000..4fd7800bf8
        --- /dev/null
        +++ b/tests/languages/aql/number_feature.test
        @@ -0,0 +1,29 @@
        +1
        +42
        +1.23
        +99.99
        +0.5
        +.5
        +4.87e103
        +4.87E103
        +0b10101110
        +0xabcdef02
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "1"],
        +	["number", "42"],
        +	["number", "1.23"],
        +	["number", "99.99"],
        +	["number", "0.5"],
        +	["number", ".5"],
        +	["number", "4.87e103"],
        +	["number", "4.87E103"],
        +	["number", "0b10101110"],
        +	["number", "0xabcdef02"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for numbers.
        diff --git a/tests/languages/aql/operator_feature.test b/tests/languages/aql/operator_feature.test
        new file mode 100644
        index 0000000000..9b0d1313b3
        --- /dev/null
        +++ b/tests/languages/aql/operator_feature.test
        @@ -0,0 +1,55 @@
        ++ - * / %
        +> >= <= < == != =
        +!~ =~
        +
        +! && ||
        +
        +[**] [***] [****]
        +
        +..
        +1..100
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "%"],
        +
        +	["operator", ">"],
        +	["operator", ">="],
        +	["operator", "<="],
        +	["operator", "<"],
        +	["operator", "=="],
        +	["operator", "!="],
        +	["operator", "="],
        +
        +	["operator", "!~"],
        +	["operator", "=~"],
        +
        +	["operator", "!"],
        +	["operator", "&&"],
        +	["operator", "||"],
        +
        +	["punctuation", "["],
        +	["operator", "**"],
        +	["punctuation", "]"],
        +	["punctuation", "["],
        +	["operator", "***"],
        +	["punctuation", "]"],
        +	["punctuation", "["],
        +	["operator", "****"],
        +	["punctuation", "]"],
        +
        +	["range", ".."],
        +
        +	["number", "1"],
        +	["range", ".."],
        +	["number", "100"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/aql/property_feature.test b/tests/languages/aql/property_feature.test
        new file mode 100644
        index 0000000000..9783aa3d24
        --- /dev/null
        +++ b/tests/languages/aql/property_feature.test
        @@ -0,0 +1,134 @@
        +{ foo: … }
        +{ 'foo': … }
        +{ "foo": … }
        +{ `foo`: … }
        +{ ´foo´: … }
        +
        +// not a property
        +LET opType = IS_NULL(OLD) ? "insert" : "update"
        +
        +LET foo = { CURRENT: 1, keep: 2, NEW: 3, OLD: 4, options: 5, prune: 6, search: 7, to: 8 }
        +LET bar = foo[CURRENT] + foo.NEW + foo["OLD"] + foo[keep] + foo.options + foo["prune"] + foo.search + foo[to]
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "{"],
        +	["property", "foo"],
        +	["punctuation", ":"],
        +	" … ",
        +	["punctuation", "}"],
        +	["punctuation", "{"],
        +	["property", "'foo'"],
        +	["punctuation", ":"],
        +	" … ",
        +	["punctuation", "}"],
        +	["punctuation", "{"],
        +	["property", "\"foo\""],
        +	["punctuation", ":"],
        +	" … ",
        +	["punctuation", "}"],
        +	["punctuation", "{"],
        +	["property", "`foo`"],
        +	["punctuation", ":"],
        +	" … ",
        +	["punctuation", "}"],
        +	["punctuation", "{"],
        +	["property", "´foo´"],
        +	["punctuation", ":"],
        +	" … ",
        +	["punctuation", "}"],
        +
        +	["comment", "// not a property"],
        +	["keyword", "LET"],
        +	" opType ",
        +	["operator", "="],
        +	["function", "IS_NULL"],
        +	["punctuation", "("],
        +	["keyword", "OLD"],
        +	["punctuation", ")"],
        +	["punctuation", "?"],
        +	["string", "\"insert\""],
        +	["punctuation", ":"],
        +	["string", "\"update\""],
        +
        +	["keyword", "LET"],
        +	" foo ",
        +	["operator", "="],
        +	["punctuation", "{"],
        +	["property", "CURRENT"],
        +	["punctuation", ":"],
        +	["number", "1"],
        +	["punctuation", ","],
        +	["property", "keep"],
        +	["punctuation", ":"],
        +	["number", "2"],
        +	["punctuation", ","],
        +	["property", "NEW"],
        +	["punctuation", ":"],
        +	["number", "3"],
        +	["punctuation", ","],
        +	["property", "OLD"],
        +	["punctuation", ":"],
        +	["number", "4"],
        +	["punctuation", ","],
        +	["property", "options"],
        +	["punctuation", ":"],
        +	["number", "5"],
        +	["punctuation", ","],
        +	["property", "prune"],
        +	["punctuation", ":"],
        +	["number", "6"],
        +	["punctuation", ","],
        +	["property", "search"],
        +	["punctuation", ":"],
        +	["number", "7"],
        +	["punctuation", ","],
        +	["property", "to"],
        +	["punctuation", ":"],
        +	["number", "8"],
        +	["punctuation", "}"],
        +	["keyword", "LET"],
        +	" bar ",
        +	["operator", "="],
        +	" foo",
        +	["punctuation", "["],
        +	"CURRENT",
        +	["punctuation", "]"],
        +	["operator", "+"],
        +	" foo",
        +	["punctuation", "."],
        +	"NEW ",
        +	["operator", "+"],
        +	" foo",
        +	["punctuation", "["],
        +	["string", "\"OLD\""],
        +	["punctuation", "]"],
        +	["operator", "+"],
        +	" foo",
        +	["punctuation", "["],
        +	"keep",
        +	["punctuation", "]"],
        +	["operator", "+"],
        +	" foo",
        +	["punctuation", "."],
        +	"options ",
        +	["operator", "+"],
        +	" foo",
        +	["punctuation", "["],
        +	["string", "\"prune\""],
        +	["punctuation", "]"],
        +	["operator", "+"],
        +	" foo",
        +	["punctuation", "."],
        +	"search ",
        +	["operator", "+"],
        +	" foo",
        +	["punctuation", "["],
        +	"to",
        +	["punctuation", "]"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for properties. (beware of ternary operators)
        diff --git a/tests/languages/aql/string_feature.test b/tests/languages/aql/string_feature.test
        new file mode 100644
        index 0000000000..21db276995
        --- /dev/null
        +++ b/tests/languages/aql/string_feature.test
        @@ -0,0 +1,31 @@
        +"yikes!"
        +"don't know"
        +"this is a \"quoted\" word"
        +"this is a longer string."
        +"the path separator on Windows is \\"
        +
        +'yikes!'
        +'don\'t know'
        +'this is a "quoted" word'
        +'this is a longer string.'
        +'the path separator on Windows is \\'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"yikes!\""],
        +	["string", "\"don't know\""],
        +	["string", "\"this is a \\\"quoted\\\" word\""],
        +	["string", "\"this is a longer string.\""],
        +	["string", "\"the path separator on Windows is \\\\\""],
        +
        +	["string", "'yikes!'"],
        +	["string", "'don\\'t know'"],
        +	["string", "'this is a \"quoted\" word'"],
        +	["string", "'this is a longer string.'"],
        +	["string", "'the path separator on Windows is \\\\'"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/aql/variable_feature.test b/tests/languages/aql/variable_feature.test
        new file mode 100644
        index 0000000000..be9ced52d0
        --- /dev/null
        +++ b/tests/languages/aql/variable_feature.test
        @@ -0,0 +1,28 @@
        +FILTER u.id == @id && u.name == @name
        +FOR u IN @@collection
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "FILTER"],
        +	" u",
        +	["punctuation", "."],
        +	"id ",
        +	["operator", "=="],
        +	["variable", "@id"],
        +	["operator", "&&"],
        +	" u",
        +	["punctuation", "."],
        +	"name ",
        +	["operator", "=="],
        +	["variable", "@name"],
        +
        +	["keyword", "FOR"],
        +	" u ",
        +	["keyword", "IN"],
        +	["variable", "@@collection"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for variable binds.
        diff --git a/tests/languages/arduino/builtin_feature.test b/tests/languages/arduino/builtin_feature.test
        new file mode 100644
        index 0000000000..29bf7785b7
        --- /dev/null
        +++ b/tests/languages/arduino/builtin_feature.test
        @@ -0,0 +1,667 @@
        +KeyboardController
        +MouseController
        +SoftwareSerial
        +EthernetServer
        +EthernetClient
        +LiquidCrystal
        +LiquidCrystal_I2C
        +RobotControl
        +GSMVoiceCall
        +EthernetUDP
        +EsploraTFT
        +HttpClient
        +RobotMotor
        +WiFiClient
        +GSMScanner
        +FileSystem
        +Scheduler
        +GSMServer
        +YunClient
        +YunServer
        +IPAddress
        +GSMClient
        +GSMModem
        +Keyboard
        +Ethernet
        +Console
        +GSMBand
        +Esplora
        +Stepper
        +Process
        +WiFiUDP
        +GSM_SMS
        +Mailbox
        +USBHost
        +Firmata
        +PImage
        +Client
        +Server
        +GSMPIN
        +FileIO
        +Bridge
        +Serial
        +EEPROM
        +Stream
        +Mouse
        +Audio
        +Servo
        +File
        +Task
        +GPRS
        +WiFi
        +Wire
        +TFT
        +GSM
        +SPI
        +SD
        +runShellCommandAsynchronously
        +analogWriteResolution
        +retrieveCallingNumber
        +printFirmwareVersion
        +analogReadResolution
        +sendDigitalPortPair
        +noListenOnLocalhost
        +readJoystickButton
        +setFirmwareVersion
        +readJoystickSwitch
        +scrollDisplayRight
        +getVoiceCallStatus
        +scrollDisplayLeft
        +writeMicroseconds
        +delayMicroseconds
        +beginTransmission
        +getSignalStrength
        +runAsynchronously
        +getAsynchronously
        +listenOnLocalhost
        +getCurrentCarrier
        +readAccelerometer
        +messageAvailable
        +sendDigitalPorts
        +lineFollowConfig
        +countryNameWrite
        +runShellCommand
        +readStringUntil
        +rewindDirectory
        +readTemperature
        +setClockDivider
        +readLightSensor
        +endTransmission
        +analogReference
        +detachInterrupt
        +countryNameRead
        +attachInterrupt
        +encryptionType
        +readBytesUntil
        +robotNameWrite
        +readMicrophone
        +robotNameRead
        +cityNameWrite
        +userNameWrite
        +readJoystickY
        +readJoystickX
        +mouseReleased
        +openNextFile
        +scanNetworks
        +noInterrupts
        +digitalWrite
        +beginSpeaker
        +mousePressed
        +isActionDone
        +mouseDragged
        +displayLogos
        +noAutoscroll
        +addParameter
        +remoteNumber
        +getModifiers
        +keyboardRead
        +userNameRead
        +waitContinue
        +processInput
        +parseCommand
        +printVersion
        +readNetworks
        +writeMessage
        +blinkVersion
        +cityNameRead
        +readMessage
        +setDataMode
        +parsePacket
        +isListening
        +setBitOrder
        +beginPacket
        +isDirectory
        +motorsWrite
        +drawCompass
        +digitalRead
        +clearScreen
        +serialEvent
        +rightToLeft
        +setTextSize
        +leftToRight
        +requestFrom
        +keyReleased
        +compassRead
        +analogWrite
        +interrupts
        +WiFiServer
        +disconnect
        +playMelody
        +parseFloat
        +autoscroll
        +getPINUsed
        +setPINUsed
        +setTimeout
        +sendAnalog
        +readSlider
        +analogRead
        +beginWrite
        +createChar
        +motorsStop
        +keyPressed
        +tempoWrite
        +readButton
        +subnetMask
        +debugPrint
        +macAddress
        +writeGreen
        +randomSeed
        +attachGPRS
        +readString
        +sendString
        +remotePort
        +releaseAll
        +mouseMoved
        +background
        +getXChange
        +getYChange
        +answerCall
        +getResult
        +voiceCall
        +endPacket
        +constrain
        +getSocket
        +writeJSON
        +getButton
        +available
        +connected
        +findUntil
        +readBytes
        +exitValue
        +readGreen
        +writeBlue
        +startLoop
        +isPressed
        +sendSysex
        +pauseMode
        +gatewayIP
        +setCursor
        +getOemKey
        +tuneWrite
        +noDisplay
        +loadImage
        +switchPIN
        +onRequest
        +onReceive
        +changePIN
        +playFile
        +noBuffer
        +parseInt
        +overflow
        +checkPIN
        +knobRead
        +beginTFT
        +bitClear
        +updateIR
        +bitWrite
        +position
        +writeRGB
        +highByte
        +writeRed
        +setSpeed
        +readBlue
        +noStroke
        +remoteIP
        +transfer
        +shutdown
        +hangCall
        +beginSMS
        +endWrite
        +attached
        +maintain
        +noCursor
        +checkReg
        +checkPUK
        +shiftOut
        +isValid
        +shiftIn
        +pulseIn
        +connect
        +println
        +localIP
        +pinMode
        +getIMEI
        +display
        +noBlink
        +process
        +getBand
        +running
        +beginSD
        +drawBMP
        +lowByte
        +setBand
        +release
        +bitRead
        +prepare
        +pointTo
        +readRed
        +setMode
        +noFill
        +remove
        +listen
        +stroke
        +detach
        +attach
        +noTone
        +exists
        +buffer
        +height
        +bitSet
        +circle
        +config
        +cursor
        +random
        +IRread
        +setDNS
        +endSMS
        +getKey
        +micros
        +millis
        +begin
        +print
        +write
        +ready
        +flush
        +width
        +isPIN
        +blink
        +clear
        +press
        +mkdir
        +rmdir
        +close
        +point
        +yield
        +image
        +BSSID
        +click
        +delay
        +read
        +text
        +move
        +peek
        +beep
        +rect
        +line
        +open
        +seek
        +fill
        +size
        +turn
        +stop
        +home
        +find
        +step
        +tone
        +sqrt
        +RSSI
        +SSID
        +end
        +bit
        +tan
        +cos
        +sin
        +pow
        +map
        +abs
        +max
        +min
        +get
        +run
        +put
        +
        +----------------------------------------------------
        +
        +[
        +	["builtin", "KeyboardController"],
        +	["builtin", "MouseController"],
        +	["builtin", "SoftwareSerial"],
        +	["builtin", "EthernetServer"],
        +	["builtin", "EthernetClient"],
        +	["builtin", "LiquidCrystal"],
        +	["builtin", "LiquidCrystal_I2C"],
        +	["builtin", "RobotControl"],
        +	["builtin", "GSMVoiceCall"],
        +	["builtin", "EthernetUDP"],
        +	["builtin", "EsploraTFT"],
        +	["builtin", "HttpClient"],
        +	["builtin", "RobotMotor"],
        +	["builtin", "WiFiClient"],
        +	["builtin", "GSMScanner"],
        +	["builtin", "FileSystem"],
        +	["builtin", "Scheduler"],
        +	["builtin", "GSMServer"],
        +	["builtin", "YunClient"],
        +	["builtin", "YunServer"],
        +	["builtin", "IPAddress"],
        +	["builtin", "GSMClient"],
        +	["builtin", "GSMModem"],
        +	["builtin", "Keyboard"],
        +	["builtin", "Ethernet"],
        +	["builtin", "Console"],
        +	["builtin", "GSMBand"],
        +	["builtin", "Esplora"],
        +	["builtin", "Stepper"],
        +	["builtin", "Process"],
        +	["builtin", "WiFiUDP"],
        +	["builtin", "GSM_SMS"],
        +	["builtin", "Mailbox"],
        +	["builtin", "USBHost"],
        +	["builtin", "Firmata"],
        +	["builtin", "PImage"],
        +	["builtin", "Client"],
        +	["builtin", "Server"],
        +	["builtin", "GSMPIN"],
        +	["builtin", "FileIO"],
        +	["builtin", "Bridge"],
        +	["builtin", "Serial"],
        +	["builtin", "EEPROM"],
        +	["builtin", "Stream"],
        +	["builtin", "Mouse"],
        +	["builtin", "Audio"],
        +	["builtin", "Servo"],
        +	["builtin", "File"],
        +	["builtin", "Task"],
        +	["builtin", "GPRS"],
        +	["builtin", "WiFi"],
        +	["builtin", "Wire"],
        +	["builtin", "TFT"],
        +	["builtin", "GSM"],
        +	["builtin", "SPI"],
        +	["builtin", "SD"],
        +	["builtin", "runShellCommandAsynchronously"],
        +	["builtin", "analogWriteResolution"],
        +	["builtin", "retrieveCallingNumber"],
        +	["builtin", "printFirmwareVersion"],
        +	["builtin", "analogReadResolution"],
        +	["builtin", "sendDigitalPortPair"],
        +	["builtin", "noListenOnLocalhost"],
        +	["builtin", "readJoystickButton"],
        +	["builtin", "setFirmwareVersion"],
        +	["builtin", "readJoystickSwitch"],
        +	["builtin", "scrollDisplayRight"],
        +	["builtin", "getVoiceCallStatus"],
        +	["builtin", "scrollDisplayLeft"],
        +	["builtin", "writeMicroseconds"],
        +	["builtin", "delayMicroseconds"],
        +	["builtin", "beginTransmission"],
        +	["builtin", "getSignalStrength"],
        +	["builtin", "runAsynchronously"],
        +	["builtin", "getAsynchronously"],
        +	["builtin", "listenOnLocalhost"],
        +	["builtin", "getCurrentCarrier"],
        +	["builtin", "readAccelerometer"],
        +	["builtin", "messageAvailable"],
        +	["builtin", "sendDigitalPorts"],
        +	["builtin", "lineFollowConfig"],
        +	["builtin", "countryNameWrite"],
        +	["builtin", "runShellCommand"],
        +	["builtin", "readStringUntil"],
        +	["builtin", "rewindDirectory"],
        +	["builtin", "readTemperature"],
        +	["builtin", "setClockDivider"],
        +	["builtin", "readLightSensor"],
        +	["builtin", "endTransmission"],
        +	["builtin", "analogReference"],
        +	["builtin", "detachInterrupt"],
        +	["builtin", "countryNameRead"],
        +	["builtin", "attachInterrupt"],
        +	["builtin", "encryptionType"],
        +	["builtin", "readBytesUntil"],
        +	["builtin", "robotNameWrite"],
        +	["builtin", "readMicrophone"],
        +	["builtin", "robotNameRead"],
        +	["builtin", "cityNameWrite"],
        +	["builtin", "userNameWrite"],
        +	["builtin", "readJoystickY"],
        +	["builtin", "readJoystickX"],
        +	["builtin", "mouseReleased"],
        +	["builtin", "openNextFile"],
        +	["builtin", "scanNetworks"],
        +	["builtin", "noInterrupts"],
        +	["builtin", "digitalWrite"],
        +	["builtin", "beginSpeaker"],
        +	["builtin", "mousePressed"],
        +	["builtin", "isActionDone"],
        +	["builtin", "mouseDragged"],
        +	["builtin", "displayLogos"],
        +	["builtin", "noAutoscroll"],
        +	["builtin", "addParameter"],
        +	["builtin", "remoteNumber"],
        +	["builtin", "getModifiers"],
        +	["builtin", "keyboardRead"],
        +	["builtin", "userNameRead"],
        +	["builtin", "waitContinue"],
        +	["builtin", "processInput"],
        +	["builtin", "parseCommand"],
        +	["builtin", "printVersion"],
        +	["builtin", "readNetworks"],
        +	["builtin", "writeMessage"],
        +	["builtin", "blinkVersion"],
        +	["builtin", "cityNameRead"],
        +	["builtin", "readMessage"],
        +	["builtin", "setDataMode"],
        +	["builtin", "parsePacket"],
        +	["builtin", "isListening"],
        +	["builtin", "setBitOrder"],
        +	["builtin", "beginPacket"],
        +	["builtin", "isDirectory"],
        +	["builtin", "motorsWrite"],
        +	["builtin", "drawCompass"],
        +	["builtin", "digitalRead"],
        +	["builtin", "clearScreen"],
        +	["builtin", "serialEvent"],
        +	["builtin", "rightToLeft"],
        +	["builtin", "setTextSize"],
        +	["builtin", "leftToRight"],
        +	["builtin", "requestFrom"],
        +	["builtin", "keyReleased"],
        +	["builtin", "compassRead"],
        +	["builtin", "analogWrite"],
        +	["builtin", "interrupts"],
        +	["builtin", "WiFiServer"],
        +	["builtin", "disconnect"],
        +	["builtin", "playMelody"],
        +	["builtin", "parseFloat"],
        +	["builtin", "autoscroll"],
        +	["builtin", "getPINUsed"],
        +	["builtin", "setPINUsed"],
        +	["builtin", "setTimeout"],
        +	["builtin", "sendAnalog"],
        +	["builtin", "readSlider"],
        +	["builtin", "analogRead"],
        +	["builtin", "beginWrite"],
        +	["builtin", "createChar"],
        +	["builtin", "motorsStop"],
        +	["builtin", "keyPressed"],
        +	["builtin", "tempoWrite"],
        +	["builtin", "readButton"],
        +	["builtin", "subnetMask"],
        +	["builtin", "debugPrint"],
        +	["builtin", "macAddress"],
        +	["builtin", "writeGreen"],
        +	["builtin", "randomSeed"],
        +	["builtin", "attachGPRS"],
        +	["builtin", "readString"],
        +	["builtin", "sendString"],
        +	["builtin", "remotePort"],
        +	["builtin", "releaseAll"],
        +	["builtin", "mouseMoved"],
        +	["builtin", "background"],
        +	["builtin", "getXChange"],
        +	["builtin", "getYChange"],
        +	["builtin", "answerCall"],
        +	["builtin", "getResult"],
        +	["builtin", "voiceCall"],
        +	["builtin", "endPacket"],
        +	["builtin", "constrain"],
        +	["builtin", "getSocket"],
        +	["builtin", "writeJSON"],
        +	["builtin", "getButton"],
        +	["builtin", "available"],
        +	["builtin", "connected"],
        +	["builtin", "findUntil"],
        +	["builtin", "readBytes"],
        +	["builtin", "exitValue"],
        +	["builtin", "readGreen"],
        +	["builtin", "writeBlue"],
        +	["builtin", "startLoop"],
        +	["builtin", "isPressed"],
        +	["builtin", "sendSysex"],
        +	["builtin", "pauseMode"],
        +	["builtin", "gatewayIP"],
        +	["builtin", "setCursor"],
        +	["builtin", "getOemKey"],
        +	["builtin", "tuneWrite"],
        +	["builtin", "noDisplay"],
        +	["builtin", "loadImage"],
        +	["builtin", "switchPIN"],
        +	["builtin", "onRequest"],
        +	["builtin", "onReceive"],
        +	["builtin", "changePIN"],
        +	["builtin", "playFile"],
        +	["builtin", "noBuffer"],
        +	["builtin", "parseInt"],
        +	["builtin", "overflow"],
        +	["builtin", "checkPIN"],
        +	["builtin", "knobRead"],
        +	["builtin", "beginTFT"],
        +	["builtin", "bitClear"],
        +	["builtin", "updateIR"],
        +	["builtin", "bitWrite"],
        +	["builtin", "position"],
        +	["builtin", "writeRGB"],
        +	["builtin", "highByte"],
        +	["builtin", "writeRed"],
        +	["builtin", "setSpeed"],
        +	["builtin", "readBlue"],
        +	["builtin", "noStroke"],
        +	["builtin", "remoteIP"],
        +	["builtin", "transfer"],
        +	["builtin", "shutdown"],
        +	["builtin", "hangCall"],
        +	["builtin", "beginSMS"],
        +	["builtin", "endWrite"],
        +	["builtin", "attached"],
        +	["builtin", "maintain"],
        +	["builtin", "noCursor"],
        +	["builtin", "checkReg"],
        +	["builtin", "checkPUK"],
        +	["builtin", "shiftOut"],
        +	["builtin", "isValid"],
        +	["builtin", "shiftIn"],
        +	["builtin", "pulseIn"],
        +	["builtin", "connect"],
        +	["builtin", "println"],
        +	["builtin", "localIP"],
        +	["builtin", "pinMode"],
        +	["builtin", "getIMEI"],
        +	["builtin", "display"],
        +	["builtin", "noBlink"],
        +	["builtin", "process"],
        +	["builtin", "getBand"],
        +	["builtin", "running"],
        +	["builtin", "beginSD"],
        +	["builtin", "drawBMP"],
        +	["builtin", "lowByte"],
        +	["builtin", "setBand"],
        +	["builtin", "release"],
        +	["builtin", "bitRead"],
        +	["builtin", "prepare"],
        +	["builtin", "pointTo"],
        +	["builtin", "readRed"],
        +	["builtin", "setMode"],
        +	["builtin", "noFill"],
        +	["builtin", "remove"],
        +	["builtin", "listen"],
        +	["builtin", "stroke"],
        +	["builtin", "detach"],
        +	["builtin", "attach"],
        +	["builtin", "noTone"],
        +	["builtin", "exists"],
        +	["builtin", "buffer"],
        +	["builtin", "height"],
        +	["builtin", "bitSet"],
        +	["builtin", "circle"],
        +	["builtin", "config"],
        +	["builtin", "cursor"],
        +	["builtin", "random"],
        +	["builtin", "IRread"],
        +	["builtin", "setDNS"],
        +	["builtin", "endSMS"],
        +	["builtin", "getKey"],
        +	["builtin", "micros"],
        +	["builtin", "millis"],
        +	["builtin", "begin"],
        +	["builtin", "print"],
        +	["builtin", "write"],
        +	["builtin", "ready"],
        +	["builtin", "flush"],
        +	["builtin", "width"],
        +	["builtin", "isPIN"],
        +	["builtin", "blink"],
        +	["builtin", "clear"],
        +	["builtin", "press"],
        +	["builtin", "mkdir"],
        +	["builtin", "rmdir"],
        +	["builtin", "close"],
        +	["builtin", "point"],
        +	["builtin", "yield"],
        +	["builtin", "image"],
        +	["builtin", "BSSID"],
        +	["builtin", "click"],
        +	["builtin", "delay"],
        +	["builtin", "read"],
        +	["builtin", "text"],
        +	["builtin", "move"],
        +	["builtin", "peek"],
        +	["builtin", "beep"],
        +	["builtin", "rect"],
        +	["builtin", "line"],
        +	["builtin", "open"],
        +	["builtin", "seek"],
        +	["builtin", "fill"],
        +	["builtin", "size"],
        +	["builtin", "turn"],
        +	["builtin", "stop"],
        +	["builtin", "home"],
        +	["builtin", "find"],
        +	["builtin", "step"],
        +	["builtin", "tone"],
        +	["builtin", "sqrt"],
        +	["builtin", "RSSI"],
        +	["builtin", "SSID"],
        +	["builtin", "end"],
        +	["builtin", "bit"],
        +	["builtin", "tan"],
        +	["builtin", "cos"],
        +	["builtin", "sin"],
        +	["builtin", "pow"],
        +	["builtin", "map"],
        +	["builtin", "abs"],
        +	["builtin", "max"],
        +	["builtin", "min"],
        +	["builtin", "get"],
        +	["builtin", "run"],
        +	["builtin", "put"]
        +]
        diff --git a/tests/languages/arduino/constant_feature.test b/tests/languages/arduino/constant_feature.test
        new file mode 100644
        index 0000000000..ea33346ac5
        --- /dev/null
        +++ b/tests/languages/arduino/constant_feature.test
        @@ -0,0 +1,43 @@
        +DIGITAL_MESSAGE
        +FIRMATA_STRING
        +ANALOG_MESSAGE
        +REPORT_DIGITAL
        +REPORT_ANALOG
        +INPUT_PULLUP
        +SET_PIN_MODE
        +INTERNAL2V56
        +SYSTEM_RESET
        +LED_BUILTIN
        +INTERNAL1V1
        +SYSEX_START
        +INTERNAL
        +EXTERNAL
        +DEFAULT
        +OUTPUT
        +INPUT
        +HIGH
        +LOW
        +
        +----------------------------------------------------
        +
        +[
        +	["constant", "DIGITAL_MESSAGE"],
        +	["constant", "FIRMATA_STRING"],
        +	["constant", "ANALOG_MESSAGE"],
        +	["constant", "REPORT_DIGITAL"],
        +	["constant", "REPORT_ANALOG"],
        +	["constant", "INPUT_PULLUP"],
        +	["constant", "SET_PIN_MODE"],
        +	["constant", "INTERNAL2V56"],
        +	["constant", "SYSTEM_RESET"],
        +	["constant", "LED_BUILTIN"],
        +	["constant", "INTERNAL1V1"],
        +	["constant", "SYSEX_START"],
        +	["constant", "INTERNAL"],
        +	["constant", "EXTERNAL"],
        +	["constant", "DEFAULT"],
        +	["constant", "OUTPUT"],
        +	["constant", "INPUT"],
        +	["constant", "HIGH"],
        +	["constant", "LOW"]
        +]
        diff --git a/tests/languages/arduino/keyword_feature.test b/tests/languages/arduino/keyword_feature.test
        new file mode 100644
        index 0000000000..7b44538984
        --- /dev/null
        +++ b/tests/languages/arduino/keyword_feature.test
        @@ -0,0 +1,75 @@
        +setup
        +if
        +else
        +while
        +do
        +for
        +return
        +in
        +instanceof
        +default
        +function
        +loop
        +goto
        +switch
        +case
        +new
        +try
        +throw
        +catch
        +finally
        +null
        +break
        +continue
        +boolean
        +bool
        +void
        +byte
        +word
        +string
        +String
        +array
        +int
        +long
        +integer
        +double
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "setup"],
        +	["keyword", "if"],
        +	["keyword", "else"],
        +	["keyword", "while"],
        +	["keyword", "do"],
        +	["keyword", "for"],
        +	["keyword", "return"],
        +	["keyword", "in"],
        +	["keyword", "instanceof"],
        +	["keyword", "default"],
        +	["keyword", "function"],
        +	["keyword", "loop"],
        +	["keyword", "goto"],
        +	["keyword", "switch"],
        +	["keyword", "case"],
        +	["keyword", "new"],
        +	["keyword", "try"],
        +	["keyword", "throw"],
        +	["keyword", "catch"],
        +	["keyword", "finally"],
        +	["keyword", "null"],
        +	["keyword", "break"],
        +	["keyword", "continue"],
        +	["keyword", "boolean"],
        +	["keyword", "bool"],
        +	["keyword", "void"],
        +	["keyword", "byte"],
        +	["keyword", "word"],
        +	["keyword", "string"],
        +	["keyword", "String"],
        +	["keyword", "array"],
        +	["keyword", "int"],
        +	["keyword", "long"],
        +	["keyword", "integer"],
        +	["keyword", "double"]
        +]
        diff --git a/tests/languages/asciidoc/entity_feature.html.test b/tests/languages/asciidoc/entity_feature.html.test
        new file mode 100644
        index 0000000000..6d21274793
        --- /dev/null
        +++ b/tests/languages/asciidoc/entity_feature.html.test
        @@ -0,0 +1,7 @@
        +➊
        +¶
        +
        +----------------------------------------------------
        +
        +&#x278a;
        +&#182;
        diff --git a/tests/languages/asciidoc/entity_feature.js b/tests/languages/asciidoc/entity_feature.js
        deleted file mode 100644
        index 2e99cd10ef..0000000000
        --- a/tests/languages/asciidoc/entity_feature.js
        +++ /dev/null
        @@ -1,4 +0,0 @@
        -module.exports = {
        -	'➊': '&#x278a;',
        -	'¶': '&#182;'
        -};
        \ No newline at end of file
        diff --git a/tests/languages/asm6502/number_feature.test b/tests/languages/asm6502/number_feature.test
        index 55262f67bd..7b5fd3b020 100644
        --- a/tests/languages/asm6502/number_feature.test
        +++ b/tests/languages/asm6502/number_feature.test
        @@ -1,18 +1,17 @@
         LDA #127
         STA $8000
        +STA #$1
         LDX #%10001010
         
        --------------------------
        +----------------------------------------------------
         
         [
        -  ["opcode", "LDA"],
        -  ["decimalnumber", "#127"],
        -  ["opcode", "STA"],
        -  ["hexnumber", "$8000"],
        -  ["opcode", "LDX"],
        -  ["binarynumber", "#%10001010"]
        +	["op-code", "LDA"], ["decimal-number", "#127"],
        +	["op-code", "STA"], ["hex-number", "$8000"],
        +	["op-code", "STA"], ["hex-number", "#$1"],
        +	["op-code", "LDX"], ["binary-number", "#%10001010"]
         ]
         
        --------------------------
        +----------------------------------------------------
         
         Check for numbers
        diff --git a/tests/languages/asm6502/opcode_feature.test b/tests/languages/asm6502/opcode_feature.test
        index 75e7b42806..178d0179d6 100644
        --- a/tests/languages/asm6502/opcode_feature.test
        +++ b/tests/languages/asm6502/opcode_feature.test
        @@ -1,17 +1,233 @@
        -LDA
        -BNE
        -inx
        +adc
        +and
        +asl
        +bcc
        +bcs
        +beq
        +bit
        +bmi
        +bne
        +bpl
        +brk
        +bvc
        +bvs
         clc
        +cld
        +cli
        +clv
        +cmp
        +cpx
        +cpy
        +dec
        +dex
        +dey
        +eor
        +inc
        +inx
        +iny
        +jmp
        +jsr
        +lda
        +ldx
        +ldy
        +lsr
        +nop
        +ora
        +pha
        +php
        +pla
        +plp
        +rol
        +ror
        +rti
        +rts
        +sbc
        +sec
        +sed
        +sei
        +sta
        +stx
        +sty
        +tax
        +tay
        +tsx
        +txa
        +txs
        +tya
        +ADC
        +AND
        +ASL
        +BCC
        +BCS
        +BEQ
        +BIT
        +BMI
        +BNE
        +BPL
        +BRK
        +BVC
        +BVS
        +CLC
        +CLD
        +CLI
        +CLV
        +CMP
        +CPX
        +CPY
        +DEC
        +DEX
        +DEY
        +EOR
        +INC
        +INX
        +INY
        +JMP
        +JSR
        +LDA
        +LDX
        +LDY
        +LSR
        +NOP
        +ORA
        +PHA
        +PHP
        +PLA
        +PLP
        +ROL
        +ROR
        +RTI
        +RTS
        +SBC
        +SEC
        +SED
        +SEI
        +STA
        +STX
        +STY
        +TAX
        +TAY
        +TSX
        +TXA
        +TXS
        +TYA
         
        --------------------------------------
        +----------------------------------------------------
         
         [
        -  ["opcode", "LDA"],
        -  ["opcode", "BNE"],
        -  ["opcode", "inx"],
        -  ["opcode", "clc"]
        +	["op-code", "adc"],
        +	["op-code", "and"],
        +	["op-code", "asl"],
        +	["op-code", "bcc"],
        +	["op-code", "bcs"],
        +	["op-code", "beq"],
        +	["op-code", "bit"],
        +	["op-code", "bmi"],
        +	["op-code", "bne"],
        +	["op-code", "bpl"],
        +	["op-code", "brk"],
        +	["op-code", "bvc"],
        +	["op-code", "bvs"],
        +	["op-code", "clc"],
        +	["op-code", "cld"],
        +	["op-code", "cli"],
        +	["op-code", "clv"],
        +	["op-code", "cmp"],
        +	["op-code", "cpx"],
        +	["op-code", "cpy"],
        +	["op-code", "dec"],
        +	["op-code", "dex"],
        +	["op-code", "dey"],
        +	["op-code", "eor"],
        +	["op-code", "inc"],
        +	["op-code", "inx"],
        +	["op-code", "iny"],
        +	["op-code", "jmp"],
        +	["op-code", "jsr"],
        +	["op-code", "lda"],
        +	["op-code", "ldx"],
        +	["op-code", "ldy"],
        +	["op-code", "lsr"],
        +	["op-code", "nop"],
        +	["op-code", "ora"],
        +	["op-code", "pha"],
        +	["op-code", "php"],
        +	["op-code", "pla"],
        +	["op-code", "plp"],
        +	["op-code", "rol"],
        +	["op-code", "ror"],
        +	["op-code", "rti"],
        +	["op-code", "rts"],
        +	["op-code", "sbc"],
        +	["op-code", "sec"],
        +	["op-code", "sed"],
        +	["op-code", "sei"],
        +	["op-code", "sta"],
        +	["op-code", "stx"],
        +	["op-code", "sty"],
        +	["op-code", "tax"],
        +	["op-code", "tay"],
        +	["op-code", "tsx"],
        +	["op-code", "txa"],
        +	["op-code", "txs"],
        +	["op-code", "tya"],
        +	["op-code", "ADC"],
        +	["op-code", "AND"],
        +	["op-code", "ASL"],
        +	["op-code", "BCC"],
        +	["op-code", "BCS"],
        +	["op-code", "BEQ"],
        +	["op-code", "BIT"],
        +	["op-code", "BMI"],
        +	["op-code", "BNE"],
        +	["op-code", "BPL"],
        +	["op-code", "BRK"],
        +	["op-code", "BVC"],
        +	["op-code", "BVS"],
        +	["op-code", "CLC"],
        +	["op-code", "CLD"],
        +	["op-code", "CLI"],
        +	["op-code", "CLV"],
        +	["op-code", "CMP"],
        +	["op-code", "CPX"],
        +	["op-code", "CPY"],
        +	["op-code", "DEC"],
        +	["op-code", "DEX"],
        +	["op-code", "DEY"],
        +	["op-code", "EOR"],
        +	["op-code", "INC"],
        +	["op-code", "INX"],
        +	["op-code", "INY"],
        +	["op-code", "JMP"],
        +	["op-code", "JSR"],
        +	["op-code", "LDA"],
        +	["op-code", "LDX"],
        +	["op-code", "LDY"],
        +	["op-code", "LSR"],
        +	["op-code", "NOP"],
        +	["op-code", "ORA"],
        +	["op-code", "PHA"],
        +	["op-code", "PHP"],
        +	["op-code", "PLA"],
        +	["op-code", "PLP"],
        +	["op-code", "ROL"],
        +	["op-code", "ROR"],
        +	["op-code", "RTI"],
        +	["op-code", "RTS"],
        +	["op-code", "SBC"],
        +	["op-code", "SEC"],
        +	["op-code", "SED"],
        +	["op-code", "SEI"],
        +	["op-code", "STA"],
        +	["op-code", "STX"],
        +	["op-code", "STY"],
        +	["op-code", "TAX"],
        +	["op-code", "TAY"],
        +	["op-code", "TSX"],
        +	["op-code", "TXA"],
        +	["op-code", "TXS"],
        +	["op-code", "TYA"]
         ]
         
        --------------------------------------
        +----------------------------------------------------
         
         Check for opcodes
        diff --git a/tests/languages/asm6502/punctuation_feature.test b/tests/languages/asm6502/punctuation_feature.test
        new file mode 100644
        index 0000000000..b0a75ee6f6
        --- /dev/null
        +++ b/tests/languages/asm6502/punctuation_feature.test
        @@ -0,0 +1,10 @@
        +( ) , :
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ","],
        +	["punctuation", ":"]
        +]
        diff --git a/tests/languages/asm6502/register_feature.test b/tests/languages/asm6502/register_feature.test
        index 91ec7c42be..10002bedc0 100644
        --- a/tests/languages/asm6502/register_feature.test
        +++ b/tests/languages/asm6502/register_feature.test
        @@ -1,17 +1,18 @@
         LDA $8000,x
         ASL A
         
        --------------------------
        +----------------------------------------------------
         
         [
        -  ["opcode", "LDA"],
        -  ["hexnumber", "$8000"],
        -  ",",
        -  ["register", "x"],
        -  ["opcode", "ASL"],
        -  ["register", "A"]
        +	["op-code", "LDA"],
        +	["hex-number", "$8000"],
        +	["punctuation", ","],
        +	["register", "x"],
        +
        +	["op-code", "ASL"],
        +	["register", "A"]
         ]
         
        --------------------------
        +----------------------------------------------------
         
         Check for registers
        diff --git a/tests/languages/asmatmel/comment_feature.test b/tests/languages/asmatmel/comment_feature.test
        new file mode 100644
        index 0000000000..1d5bc02c8a
        --- /dev/null
        +++ b/tests/languages/asmatmel/comment_feature.test
        @@ -0,0 +1,13 @@
        +;
        +; foo bar baz
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", ";"],
        +	["comment", "; foo bar baz"]
        +]
        +
        +----------------------------------------------------
        +
        +Check for comments
        diff --git a/tests/languages/asmatmel/constant_feature.test b/tests/languages/asmatmel/constant_feature.test
        new file mode 100644
        index 0000000000..9ed01f0b4f
        --- /dev/null
        +++ b/tests/languages/asmatmel/constant_feature.test
        @@ -0,0 +1,70 @@
        +OUT PORTD,x
        +ldi r17,PD06
        +ldi	r19,(1<
         ----------------------------------------------------
         
         [
        -	["asp comment", "<%----%>"],
        -	["asp comment", "<%--foo--%>"],
        -	["asp comment", "<%-- foo\r\nbar --%>"]
        +	["asp-comment", "<%----%>"],
        +	["asp-comment", "<%--foo--%>"],
        +	["asp-comment", "<%-- foo\r\nbar --%>"]
         ]
         
         ----------------------------------------------------
         
        -Checks for comments.
        \ No newline at end of file
        +Checks for comments.
        diff --git a/tests/languages/aspnet/page-directive_feature.test b/tests/languages/aspnet/page-directive_feature.test
        index 3d79dae938..a65a5c591e 100644
        --- a/tests/languages/aspnet/page-directive_feature.test
        +++ b/tests/languages/aspnet/page-directive_feature.test
        @@ -13,8 +13,8 @@
         ----------------------------------------------------
         
         [
        -	["page-directive tag", [
        -		["page-directive tag", "<%@Assembly"],
        +	["page-directive", [
        +		["page-directive", "<%@Assembly"],
         		["attr-name", [
         			"foo"
         		]],
        @@ -24,69 +24,69 @@
         			"bar",
         			["punctuation", "\""]
         		]],
        -		["page-directive tag", "%>"]
        +		["page-directive", "%>"]
         	]],
         
        -	["page-directive tag", [
        -        ["page-directive tag", "<% @Control"],
        -        ["attr-name", [
        -            "foo"
        -        ]],
        -        ["attr-value", [
        -            ["punctuation", "="],
        -            ["punctuation", "\""],
        -            "bar",
        -            ["punctuation", "\""]
        -        ]],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<% @Control"],
        +		["attr-name", [
        +			"foo"
        +		]],
        +		["attr-value", [
        +			["punctuation", "="],
        +			["punctuation", "\""],
        +			"bar",
        +			["punctuation", "\""]
        +		]],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@ Implements"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@ Implements"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@Import"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@Import"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@Master"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@Master"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@MasterType"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@MasterType"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@OutputCache"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@OutputCache"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@Page"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@Page"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@PreviousPageType"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@PreviousPageType"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@Reference"],
        -        ["page-directive tag", "%>"]
        -    ]],
        +	["page-directive", [
        +		["page-directive", "<%@Reference"],
        +		["page-directive", "%>"]
        +	]],
         
        -    ["page-directive tag", [
        -        ["page-directive tag", "<%@Register"],
        -        ["page-directive tag", "%>"]
        -    ]]
        +	["page-directive", [
        +		["page-directive", "<%@Register"],
        +		["page-directive", "%>"]
        +	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for all page directives.
        \ No newline at end of file
        +Checks for all page directives.
        diff --git a/tests/languages/autohotkey/builtin_feature.test b/tests/languages/autohotkey/builtin_feature.test
        index afbe8d3325..976d38aa95 100644
        --- a/tests/languages/autohotkey/builtin_feature.test
        +++ b/tests/languages/autohotkey/builtin_feature.test
        @@ -7,11 +7,22 @@ ceil
         chr
         class
         cos
        +comobjactive
        +comobjarray
        +comobjconnect
        +comobjcreate
        +comobjerror
        +comobjflags
        +comobjget
        +comobjquery
        +comobjtype
        +comobjvalue
         dllcall
         exp
         fileexist
         Fileopen
         floor
        +format
         il_add
         il_create
         il_destroy
        @@ -22,6 +33,8 @@ islabel
         IsObject
         ln
         log
        +ltrim
        +rtrim
         lv_add
         lv_delete
         lv_deletecol
        @@ -45,6 +58,7 @@ sin
         tan
         sqrt
         strlen
        +strreplace
         sb_seticon
         sb_setparts
         sb_settext
        @@ -80,11 +94,22 @@ __Set
         	["builtin", "chr"],
         	["builtin", "class"],
         	["builtin", "cos"],
        +	["builtin", "comobjactive"],
        +	["builtin", "comobjarray"],
        +	["builtin", "comobjconnect"],
        +	["builtin", "comobjcreate"],
        +	["builtin", "comobjerror"],
        +	["builtin", "comobjflags"],
        +	["builtin", "comobjget"],
        +	["builtin", "comobjquery"],
        +	["builtin", "comobjtype"],
        +	["builtin", "comobjvalue"],
         	["builtin", "dllcall"],
         	["builtin", "exp"],
         	["builtin", "fileexist"],
         	["builtin", "Fileopen"],
         	["builtin", "floor"],
        +	["builtin", "format"],
         	["builtin", "il_add"],
         	["builtin", "il_create"],
         	["builtin", "il_destroy"],
        @@ -95,6 +120,8 @@ __Set
         	["builtin", "IsObject"],
         	["builtin", "ln"],
         	["builtin", "log"],
        +	["builtin", "ltrim"],
        +	["builtin", "rtrim"],
         	["builtin", "lv_add"],
         	["builtin", "lv_delete"],
         	["builtin", "lv_deletecol"],
        @@ -118,6 +145,7 @@ __Set
         	["builtin", "tan"],
         	["builtin", "sqrt"],
         	["builtin", "strlen"],
        +	["builtin", "strreplace"],
         	["builtin", "sb_seticon"],
         	["builtin", "sb_setparts"],
         	["builtin", "sb_settext"],
        diff --git a/tests/languages/autohotkey/comment_feature.test b/tests/languages/autohotkey/comment_feature.test
        index 5b00ce20db..912bc895b2 100644
        --- a/tests/languages/autohotkey/comment_feature.test
        +++ b/tests/languages/autohotkey/comment_feature.test
        @@ -1,13 +1,38 @@
         ;foo
         ; bar
         
        +nota;comment
        +
        +; comments break strings
        +" ;"
        +
        +/*
        +0
        +*/
        +/*1*/
        +	  */
        +/*
        +1 ;
        +2 */
        +foo
        +
         ----------------------------------------------------
         
         [
         	["comment", ";foo"],
        -	["comment", "; bar"]
        +	["comment", "; bar"],
        +
        +	"\r\n\r\nnota;comment\r\n\r\n",
        +
        +	["comment", "; comments break strings"],
        +	"\r\n\" ",
        +	["comment", ";\""],
        +
        +	["comment", "/*\r\n0\r\n*/"],
        +	["comment", "/*1*/\r\n\t  */"],
        +	["comment", "/*\r\n1 ;\r\n2 */\r\nfoo"]
         ]
         
         ----------------------------------------------------
         
        -Checks for comments.
        \ No newline at end of file
        +Checks for comments.
        diff --git a/tests/languages/autohotkey/constant_feature.test b/tests/languages/autohotkey/constant_feature.test
        index ab11673488..e50bc3b5d8 100644
        --- a/tests/languages/autohotkey/constant_feature.test
        +++ b/tests/languages/autohotkey/constant_feature.test
        @@ -20,6 +20,7 @@ a_detecthiddenwindows
         a_endchar
         a_eventinfo
         a_exitreason
        +a_fileencoding
         a_formatfloat
         a_formatinteger
         a_gui
        @@ -40,6 +41,7 @@ a_ipaddress1
         a_ipaddress2
         a_ipaddress3
         a_ipaddress4
        +a_is64bitos
         a_isadmin
         a_iscompiled
         a_iscritical
        @@ -87,11 +89,16 @@ a_numbatchlines
         a_ostype
         a_osversion
         a_priorhotkey
        +a_priorkey
         programfiles
         a_programfiles
         a_programs
         a_programscommon
        +a_ptrsize
        +a_regview
        +a_screendpi
         a_screenheight
        +a_scripthwnd
         a_screenwidth
         a_scriptdir
         a_scriptfullpath
        @@ -157,6 +164,7 @@ errorlevel
         	["constant", "a_endchar"],
         	["constant", "a_eventinfo"],
         	["constant", "a_exitreason"],
        +	["constant", "a_fileencoding"],
         	["constant", "a_formatfloat"],
         	["constant", "a_formatinteger"],
         	["constant", "a_gui"],
        @@ -177,6 +185,7 @@ errorlevel
         	["constant", "a_ipaddress2"],
         	["constant", "a_ipaddress3"],
         	["constant", "a_ipaddress4"],
        +	["constant", "a_is64bitos"],
         	["constant", "a_isadmin"],
         	["constant", "a_iscompiled"],
         	["constant", "a_iscritical"],
        @@ -224,11 +233,16 @@ errorlevel
         	["constant", "a_ostype"],
         	["constant", "a_osversion"],
         	["constant", "a_priorhotkey"],
        +	["constant", "a_priorkey"],
         	["constant", "programfiles"],
         	["constant", "a_programfiles"],
         	["constant", "a_programs"],
         	["constant", "a_programscommon"],
        +	["constant", "a_ptrsize"],
        +	["constant", "a_regview"],
        +	["constant", "a_screendpi"],
         	["constant", "a_screenheight"],
        +	["constant", "a_scripthwnd"],
         	["constant", "a_screenwidth"],
         	["constant", "a_scriptdir"],
         	["constant", "a_scriptfullpath"],
        diff --git a/tests/languages/autohotkey/function_feature.test b/tests/languages/autohotkey/function_feature.test
        index f38a186f69..2fe744d222 100644
        --- a/tests/languages/autohotkey/function_feature.test
        +++ b/tests/languages/autohotkey/function_feature.test
        @@ -1,15 +1,22 @@
         foo(
         foo_bar(
         
        +; not a function
        +if(
        +
         ----------------------------------------------------
         
         [
         	["function", "foo"],
         	["punctuation", "("],
         	["function", "foo_bar"],
        +	["punctuation", "("],
        +
        +	["comment", "; not a function"],
        +	["keyword", "if"],
         	["punctuation", "("]
         ]
         
         ----------------------------------------------------
         
        -Checks for functions.
        \ No newline at end of file
        +Checks for functions.
        diff --git a/tests/languages/autohotkey/important_feature.test b/tests/languages/autohotkey/important_feature.test
        index aa9cbeb5d6..910015d93f 100644
        --- a/tests/languages/autohotkey/important_feature.test
        +++ b/tests/languages/autohotkey/important_feature.test
        @@ -1,32 +1,37 @@
         #AllowSameLineComments
         #ClipboardTimeout
         #CommentFlag
        +#DerefChar
         #ErrorStdOut
         #EscapeChar
         #HotkeyInterval
         #HotkeyModifierTimeout
         #Hotstring
        +#If
        +#IfTimeout
         #IfWinActive
         #IfWinExist
         #IfWinNotActive
         #IfWinNotExist
         #Include
         #IncludeAgain
        +#InputLevel
         #InstallKeybdHook
         #InstallMouseHook
         #KeyHistory
        -#LTrim
         #MaxHotkeysPerInterval
         #MaxMem
         #MaxThreads
         #MaxThreadsBuffer
         #MaxThreadsPerHotkey
        +#MenuMaskKey
         #NoEnv
         #NoTrayIcon
         #Persistent
         #SingleInstance
         #UseHook
         #WinActivateForce
        +#Warn
         
         ----------------------------------------------------
         
        @@ -34,32 +39,37 @@
         	["important", "#AllowSameLineComments"],
         	["important", "#ClipboardTimeout"],
         	["important", "#CommentFlag"],
        +	["important", "#DerefChar"],
         	["important", "#ErrorStdOut"],
         	["important", "#EscapeChar"],
         	["important", "#HotkeyInterval"],
         	["important", "#HotkeyModifierTimeout"],
         	["important", "#Hotstring"],
        +	["important", "#If"],
        +	["important", "#IfTimeout"],
         	["important", "#IfWinActive"],
         	["important", "#IfWinExist"],
         	["important", "#IfWinNotActive"],
         	["important", "#IfWinNotExist"],
         	["important", "#Include"],
         	["important", "#IncludeAgain"],
        +	["important", "#InputLevel"],
         	["important", "#InstallKeybdHook"],
         	["important", "#InstallMouseHook"],
         	["important", "#KeyHistory"],
        -	["important", "#LTrim"],
         	["important", "#MaxHotkeysPerInterval"],
         	["important", "#MaxMem"],
         	["important", "#MaxThreads"],
         	["important", "#MaxThreadsBuffer"],
         	["important", "#MaxThreadsPerHotkey"],
        +	["important", "#MenuMaskKey"],
         	["important", "#NoEnv"],
         	["important", "#NoTrayIcon"],
         	["important", "#Persistent"],
         	["important", "#SingleInstance"],
         	["important", "#UseHook"],
        -	["important", "#WinActivateForce"]
        +	["important", "#WinActivateForce"],
        +	["important", "#Warn"]
         ]
         
         ----------------------------------------------------
        diff --git a/tests/languages/autohotkey/issue2911.test b/tests/languages/autohotkey/issue2911.test
        new file mode 100644
        index 0000000000..fac458c014
        --- /dev/null
        +++ b/tests/languages/autohotkey/issue2911.test
        @@ -0,0 +1,43 @@
        +A.invert({1:"a", 2:"A"})
        +; => {"a":2}
        +
        +NormalLabel:
        +; do something
        +return
        +	TabbedLabel:
        +	; do something
        +	return
        +Sus{}//[]Label:
        +; do something
        +return
        +
        +----------------------------------------------------
        +
        +[
        +	"A",
        +	["operator", "."],
        +	["function", "invert"],
        +	["punctuation", "("],
        +	["punctuation", "{"],
        +	["number", "1"],
        +	["punctuation", ":"],
        +	["string", "\"a\""],
        +	["punctuation", ","],
        +	["number", "2"],
        +	["punctuation", ":"],
        +	["string", "\"A\""],
        +	["punctuation", "}"],
        +	["punctuation", ")"],
        +
        +	["comment", "; => {\"a\":2}"],
        +
        +	["tag", "NormalLabel"], ["punctuation", ":"],
        +	["comment", "; do something"],
        +	["selector", "return"],
        +	["tag", "TabbedLabel"], ["punctuation", ":"],
        +	["comment", "; do something"],
        +	["selector", "return"],
        +	["tag", "Sus{}//[]Label"], ["punctuation", ":"],
        +	["comment", "; do something"],
        +	["selector", "return"]
        +]
        diff --git a/tests/languages/autohotkey/keyword_feature.test b/tests/languages/autohotkey/keyword_feature.test
        index 91671355fd..705f6763e2 100644
        --- a/tests/languages/autohotkey/keyword_feature.test
        +++ b/tests/languages/autohotkey/keyword_feature.test
        @@ -2,6 +2,7 @@ Abort
         AboveNormal
         Add
         ahk_class
        +ahk_exe
         ahk_group
         ahk_id
         ahk_pid
        @@ -29,6 +30,7 @@ Bold
         Border
         Button
         ByRef
        +Catch
         Checkbox
         Checked
         CheckedGray
        @@ -63,6 +65,7 @@ Exist
         Expand
         ExStyle
         FileSystem
        +Finally
         First
         Flash
         Float
        @@ -223,6 +226,7 @@ Tab2
         TabStop
         Text
         Theme
        +Throw
         Tile
         ToggleCheck
         ToggleEnable
        @@ -233,12 +237,14 @@ TransColor
         Transparent
         Tray
         TreeView
        +Try
         TryAgain
         Type
         UnCheck
         underline
         Unicode
         Unlock
        +Until
         UpDown
         Upper
         Uppercase
        @@ -270,6 +276,7 @@ ys
         	["keyword", "AboveNormal"],
         	["keyword", "Add"],
         	["keyword", "ahk_class"],
        +	["keyword", "ahk_exe"],
         	["keyword", "ahk_group"],
         	["keyword", "ahk_id"],
         	["keyword", "ahk_pid"],
        @@ -297,6 +304,7 @@ ys
         	["keyword", "Border"],
         	["keyword", "Button"],
         	["keyword", "ByRef"],
        +	["keyword", "Catch"],
         	["keyword", "Checkbox"],
         	["keyword", "Checked"],
         	["keyword", "CheckedGray"],
        @@ -331,6 +339,7 @@ ys
         	["keyword", "Expand"],
         	["keyword", "ExStyle"],
         	["keyword", "FileSystem"],
        +	["keyword", "Finally"],
         	["keyword", "First"],
         	["keyword", "Flash"],
         	["keyword", "Float"],
        @@ -491,6 +500,7 @@ ys
         	["keyword", "TabStop"],
         	["keyword", "Text"],
         	["keyword", "Theme"],
        +	["keyword", "Throw"],
         	["keyword", "Tile"],
         	["keyword", "ToggleCheck"],
         	["keyword", "ToggleEnable"],
        @@ -501,12 +511,14 @@ ys
         	["keyword", "Transparent"],
         	["keyword", "Tray"],
         	["keyword", "TreeView"],
        +	["keyword", "Try"],
         	["keyword", "TryAgain"],
         	["keyword", "Type"],
         	["keyword", "UnCheck"],
         	["keyword", "underline"],
         	["keyword", "Unicode"],
         	["keyword", "Unlock"],
        +	["keyword", "Until"],
         	["keyword", "UpDown"],
         	["keyword", "Upper"],
         	["keyword", "Uppercase"],
        diff --git a/tests/languages/autohotkey/selector_feature.test b/tests/languages/autohotkey/selector_feature.test
        index 29210c265b..7f84f51a49 100644
        --- a/tests/languages/autohotkey/selector_feature.test
        +++ b/tests/languages/autohotkey/selector_feature.test
        @@ -118,6 +118,7 @@ SetFormat
         SetKeyDelay
         SetMouseDelay
         SetNumlockState
        +SetRegView
         SetScrollLockState
         SetStoreCapslockMode
         SetTimer
        @@ -308,6 +309,7 @@ WinWaitNotActive
         	["selector", "SetKeyDelay"],
         	["selector", "SetMouseDelay"],
         	["selector", "SetNumlockState"],
        +	["selector", "SetRegView"],
         	["selector", "SetScrollLockState"],
         	["selector", "SetStoreCapslockMode"],
         	["selector", "SetTimer"],
        diff --git a/tests/languages/autohotkey/tag_feature.test b/tests/languages/autohotkey/tag_feature.test
        index 0ca92589e4..72097a166e 100644
        --- a/tests/languages/autohotkey/tag_feature.test
        +++ b/tests/languages/autohotkey/tag_feature.test
        @@ -1,15 +1,25 @@
         foo:
         foo_bar:
         
        +validLabel: ; a comment
        +/* multiline comment
        +*/ validLabel:
        +
         ----------------------------------------------------
         
         [
        -	["tag", "foo"],
        +	["tag", "foo"], ["punctuation", ":"],
        +	["tag", "foo_bar"], ["punctuation", ":"],
        +
        +	["tag", "validLabel"],
         	["punctuation", ":"],
        -	["tag", "foo_bar"],
        +	["comment", "; a comment"],
        +
        +	["comment", "/* multiline comment\r\n*/"],
        +	["tag", "validLabel"],
         	["punctuation", ":"]
         ]
         
         ----------------------------------------------------
         
        -Checks for tags (labels).
        \ No newline at end of file
        +Checks for tags (labels).
        diff --git a/tests/languages/autoit/directive_feature.test b/tests/languages/autoit/directive_feature.test
        index 9219f700a0..af7e4ece85 100644
        --- a/tests/languages/autoit/directive_feature.test
        +++ b/tests/languages/autoit/directive_feature.test
        @@ -1,13 +1,17 @@
         #NoTrayIcon
         #OnAutoItStartRegister "Example"
        +#include-once
        +#include 
         
         ----------------------------------------------------
         
         [
         	["directive", "#NoTrayIcon"],
        -	["directive", "#OnAutoItStartRegister"], ["string", ["\"Example\""]]
        +	["directive", "#OnAutoItStartRegister"], ["string", ["\"Example\""]],
        +	["directive", "#include-once"],
        +	["directive", "#include"], ["url", ""]
         ]
         
         ----------------------------------------------------
         
        -Checks for directives.
        \ No newline at end of file
        +Checks for directives.
        diff --git a/tests/languages/avisynth/clipproperties_feature.test b/tests/languages/avisynth/clipproperties_feature.test
        new file mode 100644
        index 0000000000..d4335a2e5b
        --- /dev/null
        +++ b/tests/languages/avisynth/clipproperties_feature.test
        @@ -0,0 +1,117 @@
        +hasaudio
        +hasvideo
        +width
        +height
        +framecount
        +framerate
        +frameratenumerator
        +frameratedenominator
        +isfieldbased
        +isframebased
        +getparity
        +
        +pixeltype
        +isplanar
        +isinterleaved
        +isrgb
        +isrgb24
        +isrgb32
        +isyuv
        +isyuy2
        +isy8
        +isyv12
        +isyv16
        +isyv24
        +isyv411
        +is420
        +is422
        +is444
        +isy
        +isyuva
        +isrgb48
        +isrgb64
        +ispackedrgb
        +isplanarrgb
        +isplanarrgba
        +hasalpha
        +componentsize
        +numcomponents
        +bitspercomponent
        +
        +audiorate
        +audioduration
        +audiolength
        +audiolengthf
        +audiolengths
        +audiolengthlo
        +audiolengthhi
        +audiochannels
        +audiobits
        +isaudiofloat
        +isaudioint
        +
        +xyzisaudiointxyz
        +
        +----------------------------------------------------
        +
        +[
        +	["builtin-function", "hasaudio"],
        +	["builtin-function", "hasvideo"],
        +	["builtin-function", "width"],
        +	["builtin-function", "height"],
        +	["builtin-function", "framecount"],
        +	["builtin-function", "framerate"],
        +	["builtin-function", "frameratenumerator"],
        +	["builtin-function", "frameratedenominator"],
        +	["builtin-function", "isfieldbased"],
        +	["builtin-function", "isframebased"],
        +	["builtin-function", "getparity"],
        +
        +	["builtin-function", "pixeltype"],
        +	["builtin-function", "isplanar"],
        +	["builtin-function", "isinterleaved"],
        +	["builtin-function", "isrgb"],
        +	["builtin-function", "isrgb24"],
        +	["builtin-function", "isrgb32"],
        +	["builtin-function", "isyuv"],
        +	["builtin-function", "isyuy2"],
        +	["builtin-function", "isy8"],
        +	["builtin-function", "isyv12"],
        +	["builtin-function", "isyv16"],
        +	["builtin-function", "isyv24"],
        +	["builtin-function", "isyv411"],
        +	["builtin-function", "is420"],
        +	["builtin-function", "is422"],
        +	["builtin-function", "is444"],
        +	["builtin-function", "isy"],
        +	["builtin-function", "isyuva"],
        +	["builtin-function", "isrgb48"],
        +	["builtin-function", "isrgb64"],
        +	["builtin-function", "ispackedrgb"],
        +	["builtin-function", "isplanarrgb"],
        +	["builtin-function", "isplanarrgba"],
        +	["builtin-function", "hasalpha"],
        +	["builtin-function", "componentsize"],
        +	["builtin-function", "numcomponents"],
        +	["builtin-function", "bitspercomponent"],
        +
        +	["builtin-function", "audiorate"],
        +	["builtin-function", "audioduration"],
        +	["builtin-function", "audiolength"],
        +	["builtin-function", "audiolengthf"],
        +	["builtin-function", "audiolengths"],
        +	["builtin-function", "audiolengthlo"],
        +	["builtin-function", "audiolengthhi"],
        +	["builtin-function", "audiochannels"],
        +	["builtin-function", "audiobits"],
        +	["builtin-function", "isaudiofloat"],
        +	["builtin-function", "isaudioint"],
        +
        +	"\r\n\r\nxyzisaudiointxyz"
        +]
        +
        +----------------------------------------------------
        +
        +All internal functions, filters, and properties can be used in the following formats:
        +intFunc == intFunc() == last.intFunc == last.intFunc()
        +They must not appear within other words.
        diff --git a/tests/languages/avisynth/comments_strings_predefines_feature.test b/tests/languages/avisynth/comments_strings_predefines_feature.test
        new file mode 100644
        index 0000000000..b6575acf5d
        --- /dev/null
        +++ b/tests/languages/avisynth/comments_strings_predefines_feature.test
        @@ -0,0 +1,131 @@
        +[* comment [* global *] DEFAULT_MT_MODE *]
        +
        +notacomment
        +
        +/* comment
        +global "a string"
        +DEFAULT_MT_MODE */
        +
        +notacomment
        +
        +# comment global DEFAULT_MT_MODE
        +
        +notacomment
        +
        +"a simple string"
        +
        +"""a
        +complex
        +string"""
        +
        +"DEFAULT_MT_MODE"
        +"SCRIPTDIR"
        +"MAINSCRIPTDIR"
        +"PROGRAMDIR"
        +"USER_PLUS_PLUGINS"
        +"MACHINE_PLUS_PLUGINS"
        +"USER_CLASSIC_PLUGINS"
        +"MACHINE_CLASSIC_PLUGINS"
        +
        +"default_mt_mode"
        +"scriptdir"
        +"mainscriptdir"
        +"programdir"
        +"user_plus_plugins"
        +"machine_plus_plugins"
        +"user_classic_plugins"
        +"machine_classic_plugins"
        +
        +DEFAULT_MT_MODE
        +# SCRIPTDIR is also an internal function
        +MAINSCRIPTDIR
        +PROGRAMDIR
        +USER_PLUS_PLUGINS
        +MACHINE_PLUS_PLUGINS
        +USER_CLASSIC_PLUGINS
        +MACHINE_CLASSIC_PLUGINS
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "[* comment [* global *] DEFAULT_MT_MODE *]"],
        +
        +	"\r\n\r\nnotacomment\r\n\r\n",
        +
        +	["comment", "/* comment\r\nglobal \"a string\"\r\nDEFAULT_MT_MODE */"],
        +
        +	"\r\n\r\nnotacomment\r\n\r\n",
        +
        +	["comment", "# comment global DEFAULT_MT_MODE"],
        +
        +	"\r\n\r\nnotacomment\r\n\r\n",
        +
        +	["string", ["\"a simple string\""]],
        +
        +	["string", "\"\"\"a\r\ncomplex\r\nstring\"\"\""],
        +
        +	["string", [
        +		"\"",
        +		["constant", "DEFAULT_MT_MODE"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["constant", "SCRIPTDIR"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["constant", "MAINSCRIPTDIR"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["constant", "PROGRAMDIR"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["constant", "USER_PLUS_PLUGINS"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["constant", "MACHINE_PLUS_PLUGINS"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["constant", "USER_CLASSIC_PLUGINS"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["constant", "MACHINE_CLASSIC_PLUGINS"],
        +		"\""
        +	]],
        +
        +	["string", ["\"default_mt_mode\""]],
        +	["string", ["\"scriptdir\""]],
        +	["string", ["\"mainscriptdir\""]],
        +	["string", ["\"programdir\""]],
        +	["string", ["\"user_plus_plugins\""]],
        +	["string", ["\"machine_plus_plugins\""]],
        +	["string", ["\"user_classic_plugins\""]],
        +	["string", ["\"machine_classic_plugins\""]],
        +
        +	"\r\n\r\nDEFAULT_MT_MODE\r\n",
        +	["comment", "# SCRIPTDIR is also an internal function"],
        +	"\r\nMAINSCRIPTDIR\r\nPROGRAMDIR\r\nUSER_PLUS_PLUGINS\r\nMACHINE_PLUS_PLUGINS\r\nUSER_CLASSIC_PLUGINS\r\nMACHINE_CLASSIC_PLUGINS"
        +]
        +
        +----------------------------------------------------
        +
        +Block comments should not allow any other tokens within them, and should work over multiple lines.
        +Single line comments are the same, but just one line.
        +Known issue: square bracket block comments can be nested, but regular languages can't do that.
        +
        +Single line strings should be surrounded by double quotes, and allow no tokens within them except for predefined symbols.
        +Triple quote strings can span multiple lines and allow no tokens within them.
        +
        +Predefined symbols must appear within single line strings. They are case sensitive.
        diff --git a/tests/languages/avisynth/intenalfuncs_feature.test b/tests/languages/avisynth/intenalfuncs_feature.test
        new file mode 100644
        index 0000000000..730e9f557f
        --- /dev/null
        +++ b/tests/languages/avisynth/intenalfuncs_feature.test
        @@ -0,0 +1,391 @@
        +isbool
        +isclip
        +isfloat
        +isint
        +isstring
        +exist
        +defined
        +functionexists
        +internalfunctionexists
        +varexist
        +
        +apply
        +eval
        +import
        +select
        +default
        +assert
        +nop
        +undefined
        +
        +setmemorymax
        +setcachemode
        +setmaxcpu
        +setworkingdir
        +setplanarlegacyalignment
        +opt_allowfloataudio
        +opt_usewaveextensible
        +opt_dwchannelmask
        +opt_avipadscanlines
        +opt_vdubplanarhack
        +opt_enable_v210
        +opt_enable_y3_10_10
        +opt_enable_y3_10_16
        +opt_enable_b64a
        +opt_enable_planartopackedrgb
        +
        +value
        +hexvalue
        +hex
        +
        +max
        +min
        +muldiv
        +floor
        +ceil
        +round
        +fmod
        +pi
        +exp
        +log
        +log10
        +pow
        +sqrt
        +abs
        +sign
        +frac
        +rand
        +spline
        +continuednumerator
        +continueddenominator
        +
        +sin
        +cos
        +tan
        +asin
        +acos
        +atan
        +atan2
        +sinh
        +cosh
        +tanh
        +
        +bitand
        +bitnot
        +bitor
        +bitxor
        +bitlshift
        +bitshl
        +bitsal
        +bitrshifta
        +bitrshifts
        +bitsar
        +bitrshiftl
        +bitrshiftu
        +bitshr
        +bitlrotate
        +bitrol
        +bitrrotatel
        +bitror
        +bittest
        +bittst
        +bitset
        +bitsetcount
        +bitclear
        +bitclr
        +bitchange
        +bitchg
        +
        +averageluma
        +averagechromau
        +averagechromav
        +averageb
        +averageg
        +averager
        +lumadifference
        +chromaudifference
        +chromavdifference
        +rgbdifference
        +bdifference
        +gdifference
        +rdifference
        +ydifferencefromprevious
        +udifferencefromprevious
        +vdifferencefromprevious
        +rgbdifferencefromprevious
        +bdifferencefromprevious
        +gdifferencefromprevious
        +rdifferencefromprevious
        +ydifferencetonext
        +udifferencetonext
        +vdifferencetonext
        +rgbdifferencetonext
        +rdifferencetonext
        +gdifferencetonext
        +bdifferencetonext
        +yplanemedian
        +uplanemedian
        +vplanemedian
        +bplanemedian
        +gplanemedian
        +rplanemedian
        +yplanemin
        +uplanemin
        +vplanemin
        +bplanemin
        +gplanemin
        +rplanemin
        +yplanemax
        +uplanemax
        +vplanemax
        +bplanemax
        +gplanemax
        +rplanemax
        +yplaneminmaxdifference
        +uplaneminmaxdifference
        +vplaneminmaxdifference
        +bplaneminmaxdifference
        +gplaneminmaxdifference
        +rplaneminmaxdifference
        +
        +scriptname
        +scriptnameutf8
        +scriptfile
        +scriptfileutf8
        +scriptdir
        +scriptdirutf8
        +setlogparams
        +logmsg
        +getprocessinfo
        +
        +lcase
        +ucase
        +strtoutf8
        +strfromutf8
        +strlen
        +revstr
        +leftstr
        +rightstr
        +midstr
        +findstr
        +replacestr
        +format
        +fillstr
        +strcmp
        +strcmpi
        +trimleft
        +trimright
        +trimall
        +chr
        +ord
        +time
        +
        +versionnumber
        +versionstring
        +isversionorgreater
        +
        +buildpixeltype
        +colorspacenametopixeltype
        +
        +kevincosner
        +
        +----------------------------------------------------
        +
        +[
        +	["builtin-function", "isbool"],
        +	["builtin-function", "isclip"],
        +	["builtin-function", "isfloat"],
        +	["builtin-function", "isint"],
        +	["builtin-function", "isstring"],
        +	["builtin-function", "exist"],
        +	["builtin-function", "defined"],
        +	["builtin-function", "functionexists"],
        +	["builtin-function", "internalfunctionexists"],
        +	["builtin-function", "varexist"],
        +
        +	["builtin-function", "apply"],
        +	["builtin-function", "eval"],
        +	["builtin-function", "import"],
        +	["builtin-function", "select"],
        +	["builtin-function", "default"],
        +	["builtin-function", "assert"],
        +	["builtin-function", "nop"],
        +	["builtin-function", "undefined"],
        +
        +	["builtin-function", "setmemorymax"],
        +	["builtin-function", "setcachemode"],
        +	["builtin-function", "setmaxcpu"],
        +	["builtin-function", "setworkingdir"],
        +	["builtin-function", "setplanarlegacyalignment"],
        +	["builtin-function", "opt_allowfloataudio"],
        +	["builtin-function", "opt_usewaveextensible"],
        +	["builtin-function", "opt_dwchannelmask"],
        +	["builtin-function", "opt_avipadscanlines"],
        +	["builtin-function", "opt_vdubplanarhack"],
        +	["builtin-function", "opt_enable_v210"],
        +	["builtin-function", "opt_enable_y3_10_10"],
        +	["builtin-function", "opt_enable_y3_10_16"],
        +	["builtin-function", "opt_enable_b64a"],
        +	["builtin-function", "opt_enable_planartopackedrgb"],
        +
        +	["builtin-function", "value"],
        +	["builtin-function", "hexvalue"],
        +	["builtin-function", "hex"],
        +
        +	["builtin-function", "max"],
        +	["builtin-function", "min"],
        +	["builtin-function", "muldiv"],
        +	["builtin-function", "floor"],
        +	["builtin-function", "ceil"],
        +	["builtin-function", "round"],
        +	["builtin-function", "fmod"],
        +	["builtin-function", "pi"],
        +	["builtin-function", "exp"],
        +	["builtin-function", "log"],
        +	["builtin-function", "log10"],
        +	["builtin-function", "pow"],
        +	["builtin-function", "sqrt"],
        +	["builtin-function", "abs"],
        +	["builtin-function", "sign"],
        +	["builtin-function", "frac"],
        +	["builtin-function", "rand"],
        +	["builtin-function", "spline"],
        +	["builtin-function", "continuednumerator"],
        +	["builtin-function", "continueddenominator"],
        +
        +	["builtin-function", "sin"],
        +	["builtin-function", "cos"],
        +	["builtin-function", "tan"],
        +	["builtin-function", "asin"],
        +	["builtin-function", "acos"],
        +	["builtin-function", "atan"],
        +	["builtin-function", "atan2"],
        +	["builtin-function", "sinh"],
        +	["builtin-function", "cosh"],
        +	["builtin-function", "tanh"],
        +
        +	["builtin-function", "bitand"],
        +	["builtin-function", "bitnot"],
        +	["builtin-function", "bitor"],
        +	["builtin-function", "bitxor"],
        +	["builtin-function", "bitlshift"],
        +	["builtin-function", "bitshl"],
        +	["builtin-function", "bitsal"],
        +	["builtin-function", "bitrshifta"],
        +	["builtin-function", "bitrshifts"],
        +	["builtin-function", "bitsar"],
        +	["builtin-function", "bitrshiftl"],
        +	["builtin-function", "bitrshiftu"],
        +	["builtin-function", "bitshr"],
        +	["builtin-function", "bitlrotate"],
        +	["builtin-function", "bitrol"],
        +	["builtin-function", "bitrrotatel"],
        +	["builtin-function", "bitror"],
        +	["builtin-function", "bittest"],
        +	["builtin-function", "bittst"],
        +	["builtin-function", "bitset"],
        +	["builtin-function", "bitsetcount"],
        +	["builtin-function", "bitclear"],
        +	["builtin-function", "bitclr"],
        +	["builtin-function", "bitchange"],
        +	["builtin-function", "bitchg"],
        +
        +	["builtin-function", "averageluma"],
        +	["builtin-function", "averagechromau"],
        +	["builtin-function", "averagechromav"],
        +	["builtin-function", "averageb"],
        +	["builtin-function", "averageg"],
        +	["builtin-function", "averager"],
        +	["builtin-function", "lumadifference"],
        +	["builtin-function", "chromaudifference"],
        +	["builtin-function", "chromavdifference"],
        +	["builtin-function", "rgbdifference"],
        +	["builtin-function", "bdifference"],
        +	["builtin-function", "gdifference"],
        +	["builtin-function", "rdifference"],
        +	["builtin-function", "ydifferencefromprevious"],
        +	["builtin-function", "udifferencefromprevious"],
        +	["builtin-function", "vdifferencefromprevious"],
        +	["builtin-function", "rgbdifferencefromprevious"],
        +	["builtin-function", "bdifferencefromprevious"],
        +	["builtin-function", "gdifferencefromprevious"],
        +	["builtin-function", "rdifferencefromprevious"],
        +	["builtin-function", "ydifferencetonext"],
        +	["builtin-function", "udifferencetonext"],
        +	["builtin-function", "vdifferencetonext"],
        +	["builtin-function", "rgbdifferencetonext"],
        +	["builtin-function", "rdifferencetonext"],
        +	["builtin-function", "gdifferencetonext"],
        +	["builtin-function", "bdifferencetonext"],
        +	["builtin-function", "yplanemedian"],
        +	["builtin-function", "uplanemedian"],
        +	["builtin-function", "vplanemedian"],
        +	["builtin-function", "bplanemedian"],
        +	["builtin-function", "gplanemedian"],
        +	["builtin-function", "rplanemedian"],
        +	["builtin-function", "yplanemin"],
        +	["builtin-function", "uplanemin"],
        +	["builtin-function", "vplanemin"],
        +	["builtin-function", "bplanemin"],
        +	["builtin-function", "gplanemin"],
        +	["builtin-function", "rplanemin"],
        +	["builtin-function", "yplanemax"],
        +	["builtin-function", "uplanemax"],
        +	["builtin-function", "vplanemax"],
        +	["builtin-function", "bplanemax"],
        +	["builtin-function", "gplanemax"],
        +	["builtin-function", "rplanemax"],
        +	["builtin-function", "yplaneminmaxdifference"],
        +	["builtin-function", "uplaneminmaxdifference"],
        +	["builtin-function", "vplaneminmaxdifference"],
        +	["builtin-function", "bplaneminmaxdifference"],
        +	["builtin-function", "gplaneminmaxdifference"],
        +	["builtin-function", "rplaneminmaxdifference"],
        +
        +	["builtin-function", "scriptname"],
        +	["builtin-function", "scriptnameutf8"],
        +	["builtin-function", "scriptfile"],
        +	["builtin-function", "scriptfileutf8"],
        +	["builtin-function", "scriptdir"],
        +	["builtin-function", "scriptdirutf8"],
        +	["builtin-function", "setlogparams"],
        +	["builtin-function", "logmsg"],
        +	["builtin-function", "getprocessinfo"],
        +
        +	["builtin-function", "lcase"],
        +	["builtin-function", "ucase"],
        +	["builtin-function", "strtoutf8"],
        +	["builtin-function", "strfromutf8"],
        +	["builtin-function", "strlen"],
        +	["builtin-function", "revstr"],
        +	["builtin-function", "leftstr"],
        +	["builtin-function", "rightstr"],
        +	["builtin-function", "midstr"],
        +	["builtin-function", "findstr"],
        +	["builtin-function", "replacestr"],
        +	["builtin-function", "format"],
        +	["builtin-function", "fillstr"],
        +	["builtin-function", "strcmp"],
        +	["builtin-function", "strcmpi"],
        +	["builtin-function", "trimleft"],
        +	["builtin-function", "trimright"],
        +	["builtin-function", "trimall"],
        +	["builtin-function", "chr"],
        +	["builtin-function", "ord"],
        +	["builtin-function", "time"],
        +
        +	["builtin-function", "versionnumber"],
        +	["builtin-function", "versionstring"],
        +	["builtin-function", "isversionorgreater"],
        +
        +	["builtin-function", "buildpixeltype"],
        +	["builtin-function", "colorspacenametopixeltype"],
        +
        +	"\r\n\r\nkevincosner"
        +]
        +
        +----------------------------------------------------
        +
        +All internal functions, filters, and properties can be used in the following formats:
        +intFunc == intFunc() == last.intFunc == last.intFunc()
        +They must not appear within other words.
        diff --git a/tests/languages/avisynth/internalfilters_feature.test b/tests/languages/avisynth/internalfilters_feature.test
        new file mode 100644
        index 0000000000..375da954a8
        --- /dev/null
        +++ b/tests/languages/avisynth/internalfilters_feature.test
        @@ -0,0 +1,429 @@
        +avisource
        +avifilesource
        +opendmlsource
        +directshowsource
        +imagereader
        +imagesource
        +imagesourceanim
        +segmentedavisource
        +segmenteddirectshowsource
        +wavsource
        +
        +coloryuv
        +convertbacktoyuy2
        +converttorgb
        +converttorgb24
        +converttorgb32
        +converttorgb48
        +converttorgb64
        +converttoplanarrgb
        +converttoplanarrgba
        +converttoyuy2
        +converttoyv24
        +converttoyv16
        +converttoyv12
        +converttoy8
        +converttoyuv444
        +converttoyuv422
        +converttoyuv420
        +converttoyuva444
        +converttoyuva422
        +converttoyuva420
        +converttoyuv411
        +fixluminance
        +greyscale
        +grayscale
        +invert
        +levels
        +limiter
        +mergergb
        +mergeargb
        +mergeluma
        +mergechroma
        +rgbadjust
        +showred
        +showgreen
        +showblue
        +showalpha
        +swapuv
        +tweak
        +utoy
        +utoy8
        +vtoy
        +vtoy8
        +ytouv
        +
        +colorkeymask
        +layer
        +mask
        +maskhs
        +merge
        +overlay
        +resetmask
        +subtract
        +
        +addborders
        +crop
        +cropbottom
        +fliphorizontal
        +flipvertical
        +letterbox
        +horizontalreduceby2
        +verticalreduceby2
        +reduceby2
        +bicubicresize
        +bilinearresize
        +blackmanresize
        +gaussresize
        +lanczosresize
        +lanczos4resize
        +pointresize
        +sincresize
        +spline16resize
        +spline36resize
        +spline64resize
        +
        +skewrows
        +turnleft
        +turnright
        +turn180
        +
        +blur
        +sharpen
        +generalconvolution
        +spatialsoften
        +temporalsoften
        +fixbrokenchromaupsampling
        +
        +alignedsplice
        +unalignedsplice
        +assumefps
        +assumescaledfps
        +changefps
        +convertfps
        +deleteframe
        +dissolve
        +duplicateframe
        +fadein0
        +fadein
        +fadein2
        +fadeout0
        +fadeout
        +fadeout2
        +fadeio0
        +fadeio
        +fadeio2
        +freezeframe
        +interleave
        +loop
        +reverse
        +selecteven
        +selectodd
        +selectevery
        +selectrangeevery
        +trim
        +
        +assumeframebased
        +assumefieldbased
        +assumebff
        +assumetff
        +bob
        +complementparity
        +doubleweave
        +peculiarblend
        +pulldown
        +separatecolumns
        +separaterows
        +separatefields
        +swapfields
        +weave
        +weavecolumns
        +weaverows
        +
        +amplify
        +amplifydb
        +assumesamplerate
        +audiodub
        +audiodubex
        +audiotrim
        +convertaudioto8bit
        +convertaudioto16bit
        +convertaudioto24bit
        +convertaudioto32bit
        +convertaudiotofloat
        +converttomono
        +delayaudio
        +ensurevbrmp3sync
        +getchannel
        +getleftchannel
        +getrightchannel
        +killaudio
        +killvideo
        +mergechannels
        +mixaudio
        +monotostereo
        +normalize
        +resampleaudio
        +supereq
        +ssrc
        +timestretch
        +
        +conditionalfilter
        +frameevaluate
        +scriptclip
        +conditionalselect
        +conditionalreader
        +writefile
        +writefileif
        +writefilestart
        +writefileend
        +animate
        +applyrange
        +tcpserver
        +tcpsource
        +
        +imagewriter
        +
        +blankclip
        +blackness
        +colorbars
        +colorbarshd
        +compare
        +dumpfiltergraph
        +setgraphanalysis
        +echo
        +histogram
        +info
        +messageclip
        +preroll
        +showfiveversions
        +showframenumber
        +showsmpte
        +showtime
        +stackhorizontal
        +stackvertical
        +subtitle
        +tone
        +version
        +
        +pantone
        +
        +----------------------------------------------------
        +
        +[
        +	["builtin-function", "avisource"],
        +	["builtin-function", "avifilesource"],
        +	["builtin-function", "opendmlsource"],
        +	["builtin-function", "directshowsource"],
        +	["builtin-function", "imagereader"],
        +	["builtin-function", "imagesource"],
        +	["builtin-function", "imagesourceanim"],
        +	["builtin-function", "segmentedavisource"],
        +	["builtin-function", "segmenteddirectshowsource"],
        +	["builtin-function", "wavsource"],
        +
        +	["builtin-function", "coloryuv"],
        +	["builtin-function", "convertbacktoyuy2"],
        +	["builtin-function", "converttorgb"],
        +	["builtin-function", "converttorgb24"],
        +	["builtin-function", "converttorgb32"],
        +	["builtin-function", "converttorgb48"],
        +	["builtin-function", "converttorgb64"],
        +	["builtin-function", "converttoplanarrgb"],
        +	["builtin-function", "converttoplanarrgba"],
        +	["builtin-function", "converttoyuy2"],
        +	["builtin-function", "converttoyv24"],
        +	["builtin-function", "converttoyv16"],
        +	["builtin-function", "converttoyv12"],
        +	["builtin-function", "converttoy8"],
        +	["builtin-function", "converttoyuv444"],
        +	["builtin-function", "converttoyuv422"],
        +	["builtin-function", "converttoyuv420"],
        +	["builtin-function", "converttoyuva444"],
        +	["builtin-function", "converttoyuva422"],
        +	["builtin-function", "converttoyuva420"],
        +	["builtin-function", "converttoyuv411"],
        +	["builtin-function", "fixluminance"],
        +	["builtin-function", "greyscale"],
        +	["builtin-function", "grayscale"],
        +	["builtin-function", "invert"],
        +	["builtin-function", "levels"],
        +	["builtin-function", "limiter"],
        +	["builtin-function", "mergergb"],
        +	["builtin-function", "mergeargb"],
        +	["builtin-function", "mergeluma"],
        +	["builtin-function", "mergechroma"],
        +	["builtin-function", "rgbadjust"],
        +	["builtin-function", "showred"],
        +	["builtin-function", "showgreen"],
        +	["builtin-function", "showblue"],
        +	["builtin-function", "showalpha"],
        +	["builtin-function", "swapuv"],
        +	["builtin-function", "tweak"],
        +	["builtin-function", "utoy"],
        +	["builtin-function", "utoy8"],
        +	["builtin-function", "vtoy"],
        +	["builtin-function", "vtoy8"],
        +	["builtin-function", "ytouv"],
        +
        +	["builtin-function", "colorkeymask"],
        +	["builtin-function", "layer"],
        +	["builtin-function", "mask"],
        +	["builtin-function", "maskhs"],
        +	["builtin-function", "merge"],
        +	["builtin-function", "overlay"],
        +	["builtin-function", "resetmask"],
        +	["builtin-function", "subtract"],
        +
        +	["builtin-function", "addborders"],
        +	["builtin-function", "crop"],
        +	["builtin-function", "cropbottom"],
        +	["builtin-function", "fliphorizontal"],
        +	["builtin-function", "flipvertical"],
        +	["builtin-function", "letterbox"],
        +	["builtin-function", "horizontalreduceby2"],
        +	["builtin-function", "verticalreduceby2"],
        +	["builtin-function", "reduceby2"],
        +	["builtin-function", "bicubicresize"],
        +	["builtin-function", "bilinearresize"],
        +	["builtin-function", "blackmanresize"],
        +	["builtin-function", "gaussresize"],
        +	["builtin-function", "lanczosresize"],
        +	["builtin-function", "lanczos4resize"],
        +	["builtin-function", "pointresize"],
        +	["builtin-function", "sincresize"],
        +	["builtin-function", "spline16resize"],
        +	["builtin-function", "spline36resize"],
        +	["builtin-function", "spline64resize"],
        +
        +	["builtin-function", "skewrows"],
        +	["builtin-function", "turnleft"],
        +	["builtin-function", "turnright"],
        +	["builtin-function", "turn180"],
        +
        +	["builtin-function", "blur"],
        +	["builtin-function", "sharpen"],
        +	["builtin-function", "generalconvolution"],
        +	["builtin-function", "spatialsoften"],
        +	["builtin-function", "temporalsoften"],
        +	["builtin-function", "fixbrokenchromaupsampling"],
        +
        +	["builtin-function", "alignedsplice"],
        +	["builtin-function", "unalignedsplice"],
        +	["builtin-function", "assumefps"],
        +	["builtin-function", "assumescaledfps"],
        +	["builtin-function", "changefps"],
        +	["builtin-function", "convertfps"],
        +	["builtin-function", "deleteframe"],
        +	["builtin-function", "dissolve"],
        +	["builtin-function", "duplicateframe"],
        +	["builtin-function", "fadein0"],
        +	["builtin-function", "fadein"],
        +	["builtin-function", "fadein2"],
        +	["builtin-function", "fadeout0"],
        +	["builtin-function", "fadeout"],
        +	["builtin-function", "fadeout2"],
        +	["builtin-function", "fadeio0"],
        +	["builtin-function", "fadeio"],
        +	["builtin-function", "fadeio2"],
        +	["builtin-function", "freezeframe"],
        +	["builtin-function", "interleave"],
        +	["builtin-function", "loop"],
        +	["builtin-function", "reverse"],
        +	["builtin-function", "selecteven"],
        +	["builtin-function", "selectodd"],
        +	["builtin-function", "selectevery"],
        +	["builtin-function", "selectrangeevery"],
        +	["builtin-function", "trim"],
        +
        +	["builtin-function", "assumeframebased"],
        +	["builtin-function", "assumefieldbased"],
        +	["builtin-function", "assumebff"],
        +	["builtin-function", "assumetff"],
        +	["builtin-function", "bob"],
        +	["builtin-function", "complementparity"],
        +	["builtin-function", "doubleweave"],
        +	["builtin-function", "peculiarblend"],
        +	["builtin-function", "pulldown"],
        +	["builtin-function", "separatecolumns"],
        +	["builtin-function", "separaterows"],
        +	["builtin-function", "separatefields"],
        +	["builtin-function", "swapfields"],
        +	["builtin-function", "weave"],
        +	["builtin-function", "weavecolumns"],
        +	["builtin-function", "weaverows"],
        +
        +	["builtin-function", "amplify"],
        +	["builtin-function", "amplifydb"],
        +	["builtin-function", "assumesamplerate"],
        +	["builtin-function", "audiodub"],
        +	["builtin-function", "audiodubex"],
        +	["builtin-function", "audiotrim"],
        +	["builtin-function", "convertaudioto8bit"],
        +	["builtin-function", "convertaudioto16bit"],
        +	["builtin-function", "convertaudioto24bit"],
        +	["builtin-function", "convertaudioto32bit"],
        +	["builtin-function", "convertaudiotofloat"],
        +	["builtin-function", "converttomono"],
        +	["builtin-function", "delayaudio"],
        +	["builtin-function", "ensurevbrmp3sync"],
        +	["builtin-function", "getchannel"],
        +	["builtin-function", "getleftchannel"],
        +	["builtin-function", "getrightchannel"],
        +	["builtin-function", "killaudio"],
        +	["builtin-function", "killvideo"],
        +	["builtin-function", "mergechannels"],
        +	["builtin-function", "mixaudio"],
        +	["builtin-function", "monotostereo"],
        +	["builtin-function", "normalize"],
        +	["builtin-function", "resampleaudio"],
        +	["builtin-function", "supereq"],
        +	["builtin-function", "ssrc"],
        +	["builtin-function", "timestretch"],
        +
        +	["builtin-function", "conditionalfilter"],
        +	["builtin-function", "frameevaluate"],
        +	["builtin-function", "scriptclip"],
        +	["builtin-function", "conditionalselect"],
        +	["builtin-function", "conditionalreader"],
        +	["builtin-function", "writefile"],
        +	["builtin-function", "writefileif"],
        +	["builtin-function", "writefilestart"],
        +	["builtin-function", "writefileend"],
        +	["builtin-function", "animate"],
        +	["builtin-function", "applyrange"],
        +	["builtin-function", "tcpserver"],
        +	["builtin-function", "tcpsource"],
        +
        +	["builtin-function", "imagewriter"],
        +
        +	["builtin-function", "blankclip"],
        +	["builtin-function", "blackness"],
        +	["builtin-function", "colorbars"],
        +	["builtin-function", "colorbarshd"],
        +	["builtin-function", "compare"],
        +	["builtin-function", "dumpfiltergraph"],
        +	["builtin-function", "setgraphanalysis"],
        +	["builtin-function", "echo"],
        +	["builtin-function", "histogram"],
        +	["builtin-function", "info"],
        +	["builtin-function", "messageclip"],
        +	["builtin-function", "preroll"],
        +	["builtin-function", "showfiveversions"],
        +	["builtin-function", "showframenumber"],
        +	["builtin-function", "showsmpte"],
        +	["builtin-function", "showtime"],
        +	["builtin-function", "stackhorizontal"],
        +	["builtin-function", "stackvertical"],
        +	["builtin-function", "subtitle"],
        +	["builtin-function", "tone"],
        +	["builtin-function", "version"],
        +
        +	"\r\n\r\npantone"
        +]
        +
        +----------------------------------------------------
        +
        +All internal functions, filters, and properties can be used in the following formats:
        +intFunc == intFunc() == last.intFunc == last.intFunc()
        +They must not appear within other words.
        diff --git a/tests/languages/avisynth/keywords_constants_bools_last_feature.test b/tests/languages/avisynth/keywords_constants_bools_last_feature.test
        new file mode 100644
        index 0000000000..3b28abc86f
        --- /dev/null
        +++ b/tests/languages/avisynth/keywords_constants_bools_last_feature.test
        @@ -0,0 +1,78 @@
        +function
        +global
        +return
        +try
        +catch
        +if
        +else
        +while
        +for
        +__END__
        +
        +
        +MT_NICE_FILTER
        +MT_MULTI_INSTANCE
        +MT_SERIALIZED
        +MT_SPECIAL_MT
        +
        +mt_nice_filter
        +mt_multi_instance
        +mt_serialized
        +mt_special_mt
        +
        +TEXTMT_NICE_FILTERTEXT
        +
        +true
        +FALSE
        +yEs
        +no
        +
        +knot
        +
        +laST
        +
        +blasted
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "function"],
        +	["keyword", "global"],
        +	["keyword", "return"],
        +	["keyword", "try"],
        +	["keyword", "catch"],
        +	["keyword", "if"],
        +	["keyword", "else"],
        +	["keyword", "while"],
        +	["keyword", "for"],
        +	["keyword", "__END__"],
        +
        +	["constant", "MT_NICE_FILTER"],
        +	["constant", "MT_MULTI_INSTANCE"],
        +	["constant", "MT_SERIALIZED"],
        +	["constant", "MT_SPECIAL_MT"],
        +
        +	"\r\n\r\nmt_nice_filter\r\nmt_multi_instance\r\nmt_serialized\r\nmt_special_mt\r\n\r\nTEXTMT_NICE_FILTERTEXT\r\n\r\n",
        +
        +	["boolean", "true"],
        +	["boolean", "FALSE"],
        +	["boolean", "yEs"],
        +	["boolean", "no"],
        +
        +	"\r\n\r\nknot\r\n\r\n",
        +
        +	["variable", "laST"],
        +
        +	"\r\n\r\nblasted"
        +]
        +
        +----------------------------------------------------
        +
        +Keywords just have word boundaries. Keywords can actually be used as parameter names in functions, but this
        +scenario is an extreme edge and we do not bother handling it.
        +
        +Constants are case sensitive, and must not appear within other words.
        +
        +Bools are case insensitive, come in 4 flavors, and must not appear within other words.
        +
        +The Last special variable is case insensitive, and must not appear within other words.
        diff --git a/tests/languages/avisynth/operators_numbers_punctuation.test b/tests/languages/avisynth/operators_numbers_punctuation.test
        new file mode 100644
        index 0000000000..1cc4c2b50c
        --- /dev/null
        +++ b/tests/languages/avisynth/operators_numbers_punctuation.test
        @@ -0,0 +1,88 @@
        ++
        +++
        +-
        +!
        +!=
        +<
        +<=
        +>
        +>=
        +=
        +==
        +&&
        +||
        +?
        +:
        +%
        +/
        +*
        +
        +$abcdef
        +$89abcdef
        +123.89032
        +.902834
        +
        +$9abcdef
        +a$123456a
        +
        +()
        +{}
        +[]
        +;
        +,
        +.
        +\
        +
        +\ 1.0 \
        +
        +1.0 \ 1.0
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "++"],
        +	["operator", "-"],
        +	["operator", "!"],
        +	["operator", "!="],
        +	["operator", "<"],
        +	["operator", "<="],
        +	["operator", ">"],
        +	["operator", ">="],
        +	["operator", "="],
        +	["operator", "=="],
        +	["operator", "&&"],
        +	["operator", "||"],
        +	["operator", "?"],
        +	["operator", ":"],
        +	["operator", "%"],
        +	["operator", "/"],
        +	["operator", "*"],
        +
        +	["number", "$abcdef"],
        +	["number", "$89abcdef"],
        +	["number", "123.89032"],
        +	["number", ".902834"],
        +
        +	"\r\n\r\n$9abcdef\r\na$123456a\r\n\r\n",
        +
        +	["punctuation", "("], ["punctuation", ")"],
        +	["punctuation", "{"], ["punctuation", "}"],
        +	["punctuation", "["], ["punctuation", "]"],
        +	["punctuation", ";"],
        +	["punctuation", ","],
        +	["punctuation", "."],
        +	["line-continuation", "\\"],
        +
        +	["line-continuation", "\\"], ["number", "1.0"], ["line-continuation", "\\"],
        +
        +	["number", "1.0"], " \\ ", ["number", "1.0"]
        +]
        +
        +----------------------------------------------------
        +
        +Numbers can be specified in decimal form, with or without a leading value. So 0.0 and .0 both work.
        +Numbers can also be specified as 6- or 8- digit hexadecimal strings for colors. They begin with a $.
        +Numbers can not be bounded by words.
        +
        +Line continuations must be either the first or last character in a line, less some whitespace.
        diff --git a/tests/languages/avisynth/types_arguments_feature.test b/tests/languages/avisynth/types_arguments_feature.test
        new file mode 100644
        index 0000000000..aa1660b227
        --- /dev/null
        +++ b/tests/languages/avisynth/types_arguments_feature.test
        @@ -0,0 +1,119 @@
        +function test(clip input, int interleavedFields, float precision, string "floatingDesync", bool "useQTGMC", val "chromaNoise")
        +{
        +	castTest = clip(chromaNoise)
        +	castTest = int(chromaNoise)
        +	castTest = float(chromaNoise)
        +	castTest = string(chromaNoise)
        +	castTest = bool(chromaNoise)
        +	castTest = val(chromaNoise)
        +
        +	return interleavedClip
        +}
        +
        +test(5, 0.5, floatingDesync="progressive")
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "function"],
        +	["function", "test"],
        +	["punctuation", "("],
        +	["argument", [
        +		["keyword", "clip"],
        +		" input"
        +	]],
        +	["punctuation", ","],
        +	["argument", [
        +		["keyword", "int"],
        +		" interleavedFields"
        +	]],
        +	["punctuation", ","],
        +	["argument", [
        +		["keyword", "float"],
        +		" precision"
        +	]],
        +	["punctuation", ","],
        +	["argument", [
        +		["keyword", "string"],
        +		" \"floatingDesync\""
        +	]],
        +	["punctuation", ","],
        +	["argument", [
        +		["keyword", "bool"],
        +		" \"useQTGMC\""
        +	]],
        +	["punctuation", ","],
        +	["argument", [
        +		["keyword", "val"],
        +		" \"chromaNoise\""
        +	]],
        +	["punctuation", ")"],
        +
        +	["punctuation", "{"],
        +
        +	"\r\n\tcastTest ",
        +	["operator", "="],
        +	["type-cast", "clip"],
        +	["punctuation", "("],
        +	"chromaNoise",
        +	["punctuation", ")"],
        +
        +	"\r\n\tcastTest ",
        +	["operator", "="],
        +	["type-cast", "int"],
        +	["punctuation", "("],
        +	"chromaNoise",
        +	["punctuation", ")"],
        +
        +	"\r\n\tcastTest ",
        +	["operator", "="],
        +	["type-cast", "float"],
        +	["punctuation", "("],
        +	"chromaNoise",
        +	["punctuation", ")"],
        +
        +	"\r\n\tcastTest ",
        +	["operator", "="],
        +	["type-cast", "string"],
        +	["punctuation", "("],
        +	"chromaNoise",
        +	["punctuation", ")"],
        +
        +	"\r\n\tcastTest ",
        +	["operator", "="],
        +	["type-cast", "bool"],
        +	["punctuation", "("],
        +	"chromaNoise",
        +	["punctuation", ")"],
        +
        +	"\r\n\tcastTest ",
        +	["operator", "="],
        +	["type-cast", "val"],
        +	["punctuation", "("],
        +	"chromaNoise",
        +	["punctuation", ")"],
        +
        +	["keyword", "return"], " interleavedClip\r\n",
        +	["punctuation", "}"],
        +
        +	["function", "test"],
        +	["punctuation", "("],
        +	["number", "5"],
        +	["punctuation", ","],
        +	["number", "0.5"],
        +	["punctuation", ","],
        +	["argument-label", [
        +		["argument-name", "floatingDesync"],
        +		["punctuation", "="]
        +	]],
        +	["string", ["\"progressive\""]],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Optional arguments check for preceeding types to match before getting matched as a string, and should not be matched as strings.
        +Incidental names of types in an arguments list (such as "interleavedFields" containing "int") should not get highlighted.
        +Types can be used as casts, and should not be highlighted as user-functions.
        +Incidental names of types elsewhere (such as "interleavedClip" in a function body) should not get highlighted.
        +Explicitly-named optional arguments in function calls get lowlighted (including the '=').
        diff --git a/tests/languages/avisynth/userfunctions_feature.test b/tests/languages/avisynth/userfunctions_feature.test
        new file mode 100644
        index 0000000000..d6226cd996
        --- /dev/null
        +++ b/tests/languages/avisynth/userfunctions_feature.test
        @@ -0,0 +1,53 @@
        +function CustomUserFunction() {
        +
        +QTGMC()
        +last.QTGMC
        +last.QTGMC()
        +
        +QTGMC
        +1func()
        +last.1func
        +last.1func()
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "function"],
        +	["function", "CustomUserFunction"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +
        +	["function", "QTGMC"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	["variable", "last"],
        +	["punctuation", "."],
        +	["function", "QTGMC"],
        +
        +	["variable", "last"],
        +	["punctuation", "."],
        +	["function", "QTGMC"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	"\r\n\r\nQTGMC\r\n1func",
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	["variable", "last"],
        +	["punctuation", "."],
        +	"1func\r\n",
        +
        +	["variable", "last"],
        +	["punctuation", "."],
        +	"1func",
        +	["punctuation", "("],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Valid identifiers (starts with [a-zA-Z_]) proceeding a '.', preceeding a '(', or both are user/external functions.
        +User/external functions that don't match the above are technically valid but indistinguisable from variables.
        diff --git a/tests/languages/avro-idl/annotation_feature.test b/tests/languages/avro-idl/annotation_feature.test
        new file mode 100644
        index 0000000000..35a359c4d8
        --- /dev/null
        +++ b/tests/languages/avro-idl/annotation_feature.test
        @@ -0,0 +1,76 @@
        +record MyRecord {
        +  string @order("ascending") myAscendingSortField;
        +  string @order("descending")  myDescendingField;
        +  string @order("ignore") myIgnoredField;
        +}
        +
        +@java-class("java.util.ArrayList") array myStrings;
        +
        +@namespace("org.apache.avro.firstNamespace")
        +
        +union { MD5, null} @aliases(["hash"]) nullableHash;
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "record"],
        +	["class-name", "MyRecord"],
        +	["punctuation", "{"],
        +
        +	["keyword", "string"],
        +	["annotation", "@order"],
        +	["punctuation", "("],
        +	["string", "\"ascending\""],
        +	["punctuation", ")"],
        +	" myAscendingSortField",
        +	["punctuation", ";"],
        +
        +	["keyword", "string"],
        +	["annotation", "@order"],
        +	["punctuation", "("],
        +	["string", "\"descending\""],
        +	["punctuation", ")"],
        +	"  myDescendingField",
        +	["punctuation", ";"],
        +
        +	["keyword", "string"],
        +	["annotation", "@order"],
        +	["punctuation", "("],
        +	["string", "\"ignore\""],
        +	["punctuation", ")"],
        +	" myIgnoredField",
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +
        +	["annotation", "@java-class"],
        +	["punctuation", "("],
        +	["string", "\"java.util.ArrayList\""],
        +	["punctuation", ")"],
        +	["keyword", "array"],
        +	["punctuation", "<"],
        +	["keyword", "string"],
        +	["punctuation", ">"],
        +	" myStrings",
        +	["punctuation", ";"],
        +
        +	["annotation", "@namespace"],
        +	["punctuation", "("],
        +	["string", "\"org.apache.avro.firstNamespace\""],
        +	["punctuation", ")"],
        +
        +	["keyword", "union"],
        +	["punctuation", "{"],
        +	" MD5",
        +	["punctuation", ","],
        +	["keyword", "null"],
        +	["punctuation", "}"],
        +	["annotation", "@aliases"],
        +	["punctuation", "("],
        +	["punctuation", "["],
        +	["string", "\"hash\""],
        +	["punctuation", "]"],
        +	["punctuation", ")"],
        +	" nullableHash",
        +	["punctuation", ";"]
        +]
        diff --git a/tests/languages/avro-idl/class-name_feature.test b/tests/languages/avro-idl/class-name_feature.test
        new file mode 100644
        index 0000000000..4e4e549aa2
        --- /dev/null
        +++ b/tests/languages/avro-idl/class-name_feature.test
        @@ -0,0 +1,52 @@
        +protocol MyProto {
        +  @namespace("org.apache.avro.someOtherNamespace")
        +  record Foo {}
        +
        +  record Bar {}
        +
        +  enum Kind {
        +    FOO,
        +    BAR, // the bar enum value
        +    BAZ
        +  }
        +
        +  error TestError {
        +    string message;
        +  }
        +
        +}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "protocol"],
        +	["class-name", "MyProto"],
        +	["punctuation", "{"],
        +
        +	["annotation", "@namespace"],
        +	["punctuation", "("],
        +	["string", "\"org.apache.avro.someOtherNamespace\""],
        +	["punctuation", ")"],
        +
        +	["keyword", "record"],
        +	["class-name", "Foo"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "record"],
        +	["class-name", "Bar"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "enum"], ["class-name", "Kind"], ["punctuation", "{"],
        +	"\r\n    FOO", ["punctuation", ","],
        +	"\r\n    BAR", ["punctuation", ","], ["comment", "// the bar enum value"],
        +	"\r\n    BAZ\r\n  ",
        +	["punctuation", "}"],
        +
        +	["keyword", "error"], ["class-name", "TestError"], ["punctuation", "{"],
        +	["keyword", "string"], " message", ["punctuation", ";"],
        +	["punctuation", "}"],
        +
        +	["punctuation", "}"]
        +]
        diff --git a/tests/languages/avro-idl/comment_feature.test b/tests/languages/avro-idl/comment_feature.test
        new file mode 100644
        index 0000000000..8a6e067fbe
        --- /dev/null
        +++ b/tests/languages/avro-idl/comment_feature.test
        @@ -0,0 +1,15 @@
        +/* comment */
        +/*
        + comment
        + */
        +
        +// comment
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "/* comment */"],
        +	["comment", "/*\r\n comment\r\n */"],
        +
        +	["comment", "// comment"]
        +]
        diff --git a/tests/languages/avro-idl/function_feature.test b/tests/languages/avro-idl/function_feature.test
        new file mode 100644
        index 0000000000..3f1dae07dd
        --- /dev/null
        +++ b/tests/languages/avro-idl/function_feature.test
        @@ -0,0 +1,57 @@
        +int add(int foo, int bar = 0);
        +
        +void logMessage(string message);
        +
        +void goKaboom() throws Kaboom;
        +
        +void fireAndForget(string message) oneway;
        +
        +void `error`();
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "int"],
        +	["function", "add"],
        +	["punctuation", "("],
        +	["keyword", "int"],
        +	" foo",
        +	["punctuation", ","],
        +	["keyword", "int"],
        +	" bar ",
        +	["operator", "="],
        +	["number", "0"],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "void"],
        +	["function", "logMessage"],
        +	["punctuation", "("],
        +	["keyword", "string"],
        +	" message",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "void"],
        +	["function", "goKaboom"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["keyword", "throws"],
        +	["class-name", "Kaboom"],
        +	["punctuation", ";"],
        +
        +	["keyword", "void"],
        +	["function", "fireAndForget"],
        +	["punctuation", "("],
        +	["keyword", "string"],
        +	" message",
        +	["punctuation", ")"],
        +	["keyword", "oneway"],
        +	["punctuation", ";"],
        +
        +	["keyword", "void"],
        +	["function-identifier", "`error`"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"]
        +]
        diff --git a/tests/languages/avro-idl/keyword_feature.test b/tests/languages/avro-idl/keyword_feature.test
        new file mode 100644
        index 0000000000..e1ede9c750
        --- /dev/null
        +++ b/tests/languages/avro-idl/keyword_feature.test
        @@ -0,0 +1,65 @@
        +array;
        +boolean;
        +bytes;
        +date;
        +decimal;
        +double;
        +enum;
        +error;
        +false;
        +fixed;
        +float;
        +idl;
        +import;
        +int;
        +local_timestamp_ms;
        +long;
        +map;
        +null;
        +oneway;
        +protocol;
        +record;
        +schema;
        +string;
        +throws;
        +time_ms;
        +timestamp_ms;
        +true;
        +union;
        +uuid;
        +void;
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "array"], ["punctuation", ";"],
        +	["keyword", "boolean"], ["punctuation", ";"],
        +	["keyword", "bytes"], ["punctuation", ";"],
        +	["keyword", "date"], ["punctuation", ";"],
        +	["keyword", "decimal"], ["punctuation", ";"],
        +	["keyword", "double"], ["punctuation", ";"],
        +	["keyword", "enum"], ["punctuation", ";"],
        +	["keyword", "error"], ["punctuation", ";"],
        +	["keyword", "false"], ["punctuation", ";"],
        +	["keyword", "fixed"], ["punctuation", ";"],
        +	["keyword", "float"], ["punctuation", ";"],
        +	["keyword", "idl"], ["punctuation", ";"],
        +	["keyword", "import"], ["punctuation", ";"],
        +	["keyword", "int"], ["punctuation", ";"],
        +	["keyword", "local_timestamp_ms"], ["punctuation", ";"],
        +	["keyword", "long"], ["punctuation", ";"],
        +	["keyword", "map"], ["punctuation", ";"],
        +	["keyword", "null"], ["punctuation", ";"],
        +	["keyword", "oneway"], ["punctuation", ";"],
        +	["keyword", "protocol"], ["punctuation", ";"],
        +	["keyword", "record"], ["punctuation", ";"],
        +	["keyword", "schema"], ["punctuation", ";"],
        +	["keyword", "string"], ["punctuation", ";"],
        +	["keyword", "throws"], ["punctuation", ";"],
        +	["keyword", "time_ms"], ["punctuation", ";"],
        +	["keyword", "timestamp_ms"], ["punctuation", ";"],
        +	["keyword", "true"], ["punctuation", ";"],
        +	["keyword", "union"], ["punctuation", ";"],
        +	["keyword", "uuid"], ["punctuation", ";"],
        +	["keyword", "void"], ["punctuation", ";"]
        +]
        diff --git a/tests/languages/avro-idl/number_feature.test b/tests/languages/avro-idl/number_feature.test
        new file mode 100644
        index 0000000000..87869c9b4d
        --- /dev/null
        +++ b/tests/languages/avro-idl/number_feature.test
        @@ -0,0 +1,43 @@
        +0
        +123
        +0xFFF
        +-0
        +-123
        +-0xFF
        +12343324234L
        +0xFFFFFFFFFl
        +
        +0.342e4
        +0.342e-4f
        +0.342e-4d
        +.324
        +123.
        +0x.2Fp+323f
        +0x234.p+323d
        +
        +NaN
        +Infinity
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "0"],
        +	["number", "123"],
        +	["number", "0xFFF"],
        +	["number", "-0"],
        +	["number", "-123"],
        +	["number", "-0xFF"],
        +	["number", "12343324234L"],
        +	["number", "0xFFFFFFFFFl"],
        +
        +	["number", "0.342e4"],
        +	["number", "0.342e-4f"],
        +	["number", "0.342e-4d"],
        +	["number", ".324"],
        +	["number", "123."],
        +	["number", "0x.2Fp+323f"],
        +	["number", "0x234.p+323d"],
        +
        +	["number", "NaN"],
        +	["number", "Infinity"]
        +]
        diff --git a/tests/languages/avro-idl/operator_feature.test b/tests/languages/avro-idl/operator_feature.test
        new file mode 100644
        index 0000000000..27b9165afc
        --- /dev/null
        +++ b/tests/languages/avro-idl/operator_feature.test
        @@ -0,0 +1,7 @@
        +=
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "="]
        +]
        diff --git a/tests/languages/avro-idl/punctuation_feature.test b/tests/languages/avro-idl/punctuation_feature.test
        new file mode 100644
        index 0000000000..f73a56287d
        --- /dev/null
        +++ b/tests/languages/avro-idl/punctuation_feature.test
        @@ -0,0 +1,20 @@
        +( ) [ ] { } < >
        +. : , ;
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", "<"],
        +	["punctuation", ">"],
        +
        +	["punctuation", "."],
        +	["punctuation", ":"],
        +	["punctuation", ","],
        +	["punctuation", ";"]
        +]
        diff --git a/tests/languages/avro-idl/string_feature.test b/tests/languages/avro-idl/string_feature.test
        new file mode 100644
        index 0000000000..d93a89eabe
        --- /dev/null
        +++ b/tests/languages/avro-idl/string_feature.test
        @@ -0,0 +1,13 @@
        +""
        +"foo"
        +"\""
        +"\n\n"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"\""],
        +	["string", "\"foo\""],
        +	["string", "\"\\\"\""],
        +	["string", "\"\\n\\n\""]
        +]
        diff --git a/tests/languages/bash/arithmetic_environment_feature.test b/tests/languages/bash/arithmetic_environment_feature.test
        index a9c5663dc1..c356977d03 100644
        --- a/tests/languages/bash/arithmetic_environment_feature.test
        +++ b/tests/languages/bash/arithmetic_environment_feature.test
        @@ -50,4 +50,4 @@ for (( NUM=1 ; NUM<=1000 ; NUM++ ))
         
         ----------------------------------------------------
         
        -Checks arithmetic environments
        \ No newline at end of file
        +Checks arithmetic environments
        diff --git a/tests/languages/bash/assign-left_feature.test b/tests/languages/bash/assign-left_feature.test
        new file mode 100644
        index 0000000000..54b64a5ba9
        --- /dev/null
        +++ b/tests/languages/bash/assign-left_feature.test
        @@ -0,0 +1,25 @@
        +foo=12
        +bar+='xyz'
        +foo+=('xyz')
        +
        +----------------------------------------------------
        +
        +[
        +	["assign-left", ["foo"]],
        +	["operator", ["="]],
        +	["number", "12"],
        +
        +	["assign-left", ["bar"]],
        +	["operator", ["+="]],
        +	["string", "'xyz'"],
        +
        +	["assign-left", ["foo"]],
        +	["operator", ["+="]],
        +	["punctuation", "("],
        +	["string", "'xyz'"],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for variable assignments.
        diff --git a/tests/languages/bash/builtin_feature.test b/tests/languages/bash/builtin_feature.test
        new file mode 100644
        index 0000000000..8edce483c9
        --- /dev/null
        +++ b/tests/languages/bash/builtin_feature.test
        @@ -0,0 +1,95 @@
        +.
        +:
        +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
        +
        +----------------------------------------------------
        +
        +[
        +	["builtin", "."],
        +	["builtin", ":"],
        +	["builtin", "break"],
        +	["builtin", "cd"],
        +	["builtin", "continue"],
        +	["builtin", "eval"],
        +	["builtin", "exec"],
        +	["builtin", "exit"],
        +	["builtin", "export"],
        +	["builtin", "getopts"],
        +	["builtin", "hash"],
        +	["builtin", "pwd"],
        +	["builtin", "readonly"],
        +	["builtin", "return"],
        +	["builtin", "shift"],
        +	["builtin", "test"],
        +	["builtin", "times"],
        +	["builtin", "trap"],
        +	["builtin", "umask"],
        +	["builtin", "unset"],
        +	["builtin", "alias"],
        +	["builtin", "bind"],
        +	["builtin", "builtin"],
        +	["builtin", "caller"],
        +	["builtin", "command"],
        +	["builtin", "declare"],
        +	["builtin", "echo"],
        +	["builtin", "enable"],
        +	["builtin", "help"],
        +	["builtin", "let"],
        +	["builtin", "local"],
        +	["builtin", "logout"],
        +	["builtin", "mapfile"],
        +	["builtin", "printf"],
        +	["builtin", "read"],
        +	["builtin", "readarray"],
        +	["builtin", "source"],
        +	["builtin", "type"],
        +	["builtin", "typeset"],
        +	["builtin", "ulimit"],
        +	["builtin", "unalias"],
        +	["builtin", "set"],
        +	["builtin", "shopt"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all builtins.
        diff --git a/tests/languages/bash/command_substitution_feature.test b/tests/languages/bash/command_substitution_feature.test
        index 2b78b51851..b81c2a82cf 100644
        --- a/tests/languages/bash/command_substitution_feature.test
        +++ b/tests/languages/bash/command_substitution_feature.test
        @@ -8,13 +8,13 @@ $(echo "foo")
         [
         	["variable", [
         		["variable", "$("],
        -		["keyword", "echo"], 
        +		["builtin", "echo"], 
         		["string", ["\"foo\""]],
         		["variable", ")"]
         	]],
         	["variable", [
         		["variable", "`"],
        -		["keyword", "echo"], 
        +		["builtin", "echo"], 
         		["string", ["\"foo\""]],
         		["variable", "`"]
         	]],
        @@ -22,7 +22,7 @@ $(echo "foo")
         		"\"",
         		["variable", [
         			["variable", "$("],
        -			["keyword", "echo"], 
        +			["builtin", "echo"], 
         			["string", ["\"foo\""]],
         			["variable", ")"]
         		]],
        @@ -32,7 +32,7 @@ $(echo "foo")
         		"\"",
         		["variable", [
         			["variable", "`"],
        -			["keyword", "echo"],
        +			["builtin", "echo"],
         			["string", ["\"foo\""]],
         			["variable", "`"]
         		]],
        @@ -42,4 +42,4 @@ $(echo "foo")
         
         ----------------------------------------------------
         
        -Checks for command substitution.
        \ No newline at end of file
        +Checks for command substitution.
        diff --git a/tests/languages/bash/comment_feature.test b/tests/languages/bash/comment_feature.test
        index 58249096f0..116063749c 100644
        --- a/tests/languages/bash/comment_feature.test
        +++ b/tests/languages/bash/comment_feature.test
        @@ -1,13 +1,23 @@
         #foo
         # bar
        +$(
        +	# foo
        +	bar
        +)
         
         ----------------------------------------------------
         
         [
         	["comment", "#foo"],
        -	["comment", "# bar"]
        +	["comment", "# bar"],
        +	["variable", [
        +		["variable", "$("],
        +		["comment", "# foo"],
        +		"\r\n\tbar\r\n",
        +		["variable", ")"]
        +	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for comments.
        \ No newline at end of file
        +Checks for comments.
        diff --git a/tests/languages/bash/entities_in_strings_feature.test b/tests/languages/bash/entities_in_strings_feature.test
        new file mode 100644
        index 0000000000..f4d7dcb911
        --- /dev/null
        +++ b/tests/languages/bash/entities_in_strings_feature.test
        @@ -0,0 +1,67 @@
        +$'1\a2\b3\c4\e5\f6\n7\r8\t9\v'
        +$'1234\056789'
        +$'123\456789'
        +"abc\xdef"
        +"\uABCDEFG"
        +"a\"b"
        +
        +'1\a2\b3\c4\e5\f6\n7\r8\t9\v'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", [
        +		"$'1",
        +		["entity", "\\a"],
        +		"2",
        +		["entity", "\\b"],
        +		"3",
        +		["entity", "\\c"],
        +		"4",
        +		["entity", "\\e"],
        +		"5",
        +		["entity", "\\f"],
        +		"6",
        +		["entity", "\\n"],
        +		"7",
        +		["entity", "\\r"],
        +		"8",
        +		["entity", "\\t"],
        +		"9",
        +		["entity", "\\v"],
        +		"'"
        +	]],
        +	["string", [
        +		"$'1234",
        +		["entity", "\\056"],
        +		"789'"
        +	]],
        +	["string", [
        +		"$'123",
        +		["entity", "\\456"],
        +		"789'"
        +	]],
        +	["string", [
        +		"\"abc",
        +		["entity", "\\xde"],
        +		"f\""
        +	]],
        +	["string", [
        +		"\"",
        +		["entity", "\\uABCD"],
        +		"EFG\""
        +	]],
        +	["string", [
        +		"\"a",
        +		["entity", "\\\""],
        +		"b\""
        +	]],
        +
        +	["string", "'1\\a2\\b3\\c4\\e5\\f6\\n7\\r8\\t9\\v'"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for entities in strings, mainly according to echo and printf's manuals.
        +Note that in some cases (“\x”, “\u”…) there's a limit to the number of
        +characters that can be used afterwards to specify the bytes, etc.
        diff --git a/tests/languages/bash/environment_feature.test b/tests/languages/bash/environment_feature.test
        new file mode 100644
        index 0000000000..4bf4b268a9
        --- /dev/null
        +++ b/tests/languages/bash/environment_feature.test
        @@ -0,0 +1,247 @@
        +$foo
        +$IFS
        +IFS=a
        +"$PS1"
        +"${PS1}"
        +$BASH
        +$BASHOPTS
        +$BASH_ALIASES
        +$BASH_ARGC
        +$BASH_ARGV
        +$BASH_CMDS
        +$BASH_COMPLETION_COMPAT_DIR
        +$BASH_LINENO
        +$BASH_REMATCH
        +$BASH_SOURCE
        +$BASH_VERSINFO
        +$BASH_VERSION
        +$COLORTERM
        +$COLUMNS
        +$COMP_WORDBREAKS
        +$DBUS_SESSION_BUS_ADDRESS
        +$DEFAULTS_PATH
        +$DESKTOP_SESSION
        +$DIRSTACK
        +$DISPLAY
        +$EUID
        +$GDMSESSION
        +$GDM_LANG
        +$GNOME_KEYRING_CONTROL
        +$GNOME_KEYRING_PID
        +$GPG_AGENT_INFO
        +$GROUPS
        +$HISTCONTROL
        +$HISTFILE
        +$HISTFILESIZE
        +$HISTSIZE
        +$HOME
        +$HOSTNAME
        +$HOSTTYPE
        +$IFS
        +$INSTANCE
        +$JOB
        +$LANG
        +$LANGUAGE
        +$LC_ADDRESS
        +$LC_ALL
        +$LC_IDENTIFICATION
        +$LC_MEASUREMENT
        +$LC_MONETARY
        +$LC_NAME
        +$LC_NUMERIC
        +$LC_PAPER
        +$LC_TELEPHONE
        +$LC_TIME
        +$LESSCLOSE
        +$LESSOPEN
        +$LINES
        +$LOGNAME
        +$LS_COLORS
        +$MACHTYPE
        +$MAILCHECK
        +$MANDATORY_PATH
        +$NO_AT_BRIDGE
        +$OLDPWD
        +$OPTERR
        +$OPTIND
        +$ORBIT_SOCKETDIR
        +$OSTYPE
        +$PAPERSIZE
        +$PATH
        +$PIPESTATUS
        +$PPID
        +$PS1
        +$PS2
        +$PS3
        +$PS4
        +$PWD
        +$RANDOM
        +$REPLY
        +$SECONDS
        +$SELINUX_INIT
        +$SESSION
        +$SESSIONTYPE
        +$SESSION_MANAGER
        +$SHELL
        +$SHELLOPTS
        +$SHLVL
        +$SSH_AUTH_SOCK
        +$TERM
        +$UID
        +$UPSTART_EVENTS
        +$UPSTART_INSTANCE
        +$UPSTART_JOB
        +$UPSTART_SESSION
        +$USER
        +$WINDOWID
        +$XAUTHORITY
        +$XDG_CONFIG_DIRS
        +$XDG_CURRENT_DESKTOP
        +$XDG_DATA_DIRS
        +$XDG_GREETER_DATA_DIR
        +$XDG_MENU_PREFIX
        +$XDG_RUNTIME_DIR
        +$XDG_SEAT
        +$XDG_SEAT_PATH
        +$XDG_SESSION_DESKTOP
        +$XDG_SESSION_ID
        +$XDG_SESSION_PATH
        +$XDG_SESSION_TYPE
        +$XDG_VTNR
        +$XMODIFIERS
        +
        +----------------------------------------------------
        +
        +[
        +	["variable", "$foo"],
        +	["environment", "$IFS"],
        +	["assign-left", [
        +		["environment", "IFS"]
        +	]],
        +	["operator", ["="]],
        +	"a\r\n",
        +	["string", [
        +		"\"",
        +		["environment", "$PS1"],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["variable", [
        +			"${",
        +			["environment", "PS1"],
        +			"}"
        +		]],
        +		"\""
        +	]],
        +	["environment", "$BASH"],
        +	["environment", "$BASHOPTS"],
        +	["environment", "$BASH_ALIASES"],
        +	["environment", "$BASH_ARGC"],
        +	["environment", "$BASH_ARGV"],
        +	["environment", "$BASH_CMDS"],
        +	["environment", "$BASH_COMPLETION_COMPAT_DIR"],
        +	["environment", "$BASH_LINENO"],
        +	["environment", "$BASH_REMATCH"],
        +	["environment", "$BASH_SOURCE"],
        +	["environment", "$BASH_VERSINFO"],
        +	["environment", "$BASH_VERSION"],
        +	["environment", "$COLORTERM"],
        +	["environment", "$COLUMNS"],
        +	["environment", "$COMP_WORDBREAKS"],
        +	["environment", "$DBUS_SESSION_BUS_ADDRESS"],
        +	["environment", "$DEFAULTS_PATH"],
        +	["environment", "$DESKTOP_SESSION"],
        +	["environment", "$DIRSTACK"],
        +	["environment", "$DISPLAY"],
        +	["environment", "$EUID"],
        +	["environment", "$GDMSESSION"],
        +	["environment", "$GDM_LANG"],
        +	["environment", "$GNOME_KEYRING_CONTROL"],
        +	["environment", "$GNOME_KEYRING_PID"],
        +	["environment", "$GPG_AGENT_INFO"],
        +	["environment", "$GROUPS"],
        +	["environment", "$HISTCONTROL"],
        +	["environment", "$HISTFILE"],
        +	["environment", "$HISTFILESIZE"],
        +	["environment", "$HISTSIZE"],
        +	["environment", "$HOME"],
        +	["environment", "$HOSTNAME"],
        +	["environment", "$HOSTTYPE"],
        +	["environment", "$IFS"],
        +	["environment", "$INSTANCE"],
        +	["environment", "$JOB"],
        +	["environment", "$LANG"],
        +	["environment", "$LANGUAGE"],
        +	["environment", "$LC_ADDRESS"],
        +	["environment", "$LC_ALL"],
        +	["environment", "$LC_IDENTIFICATION"],
        +	["environment", "$LC_MEASUREMENT"],
        +	["environment", "$LC_MONETARY"],
        +	["environment", "$LC_NAME"],
        +	["environment", "$LC_NUMERIC"],
        +	["environment", "$LC_PAPER"],
        +	["environment", "$LC_TELEPHONE"],
        +	["environment", "$LC_TIME"],
        +	["environment", "$LESSCLOSE"],
        +	["environment", "$LESSOPEN"],
        +	["environment", "$LINES"],
        +	["environment", "$LOGNAME"],
        +	["environment", "$LS_COLORS"],
        +	["environment", "$MACHTYPE"],
        +	["environment", "$MAILCHECK"],
        +	["environment", "$MANDATORY_PATH"],
        +	["environment", "$NO_AT_BRIDGE"],
        +	["environment", "$OLDPWD"],
        +	["environment", "$OPTERR"],
        +	["environment", "$OPTIND"],
        +	["environment", "$ORBIT_SOCKETDIR"],
        +	["environment", "$OSTYPE"],
        +	["environment", "$PAPERSIZE"],
        +	["environment", "$PATH"],
        +	["environment", "$PIPESTATUS"],
        +	["environment", "$PPID"],
        +	["environment", "$PS1"],
        +	["environment", "$PS2"],
        +	["environment", "$PS3"],
        +	["environment", "$PS4"],
        +	["environment", "$PWD"],
        +	["environment", "$RANDOM"],
        +	["environment", "$REPLY"],
        +	["environment", "$SECONDS"],
        +	["environment", "$SELINUX_INIT"],
        +	["environment", "$SESSION"],
        +	["environment", "$SESSIONTYPE"],
        +	["environment", "$SESSION_MANAGER"],
        +	["environment", "$SHELL"],
        +	["environment", "$SHELLOPTS"],
        +	["environment", "$SHLVL"],
        +	["environment", "$SSH_AUTH_SOCK"],
        +	["environment", "$TERM"],
        +	["environment", "$UID"],
        +	["environment", "$UPSTART_EVENTS"],
        +	["environment", "$UPSTART_INSTANCE"],
        +	["environment", "$UPSTART_JOB"],
        +	["environment", "$UPSTART_SESSION"],
        +	["environment", "$USER"],
        +	["environment", "$WINDOWID"],
        +	["environment", "$XAUTHORITY"],
        +	["environment", "$XDG_CONFIG_DIRS"],
        +	["environment", "$XDG_CURRENT_DESKTOP"],
        +	["environment", "$XDG_DATA_DIRS"],
        +	["environment", "$XDG_GREETER_DATA_DIR"],
        +	["environment", "$XDG_MENU_PREFIX"],
        +	["environment", "$XDG_RUNTIME_DIR"],
        +	["environment", "$XDG_SEAT"],
        +	["environment", "$XDG_SEAT_PATH"],
        +	["environment", "$XDG_SESSION_DESKTOP"],
        +	["environment", "$XDG_SESSION_ID"],
        +	["environment", "$XDG_SESSION_PATH"],
        +	["environment", "$XDG_SESSION_TYPE"],
        +	["environment", "$XDG_VTNR"],
        +	["environment", "$XMODIFIERS"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for environment variables.
        diff --git a/tests/languages/bash/for-or-select_feature.test b/tests/languages/bash/for-or-select_feature.test
        new file mode 100644
        index 0000000000..c57675ec94
        --- /dev/null
        +++ b/tests/languages/bash/for-or-select_feature.test
        @@ -0,0 +1,25 @@
        +for var in a b c
        +do :; done
        +select var in a b c
        +do :; done
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "for"],
        +	["for-or-select", "var"],
        +	["keyword", "in"], " a b c\r\n", ["keyword", "do"],
        +	["builtin", ":"],
        +	["punctuation", ";"],
        +	["keyword", "done"],
        +	["keyword", "select"],
        +	["for-or-select", "var"],
        +	["keyword", "in"], " a b c\r\n", ["keyword", "do"],
        +	["builtin", ":"],
        +	["punctuation", ";"],
        +	["keyword", "done"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for variable names in “for” and “select” loops.
        diff --git a/tests/languages/bash/function-name_feature.test b/tests/languages/bash/function-name_feature.test
        new file mode 100644
        index 0000000000..82cb197960
        --- /dev/null
        +++ b/tests/languages/bash/function-name_feature.test
        @@ -0,0 +1,48 @@
        +function foo { :; }
        +function foo-bar { :; }
        +bar() { :; }
        +function foo() { :; }
        +# Not a function:
        +bar { :; }
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "function"],
        +	["function-name", "foo"],
        +	["punctuation", "{"],
        +	["builtin", ":"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +	["keyword", "function"],
        +	["function-name", "foo-bar"],
        +	["punctuation", "{"],
        +	["builtin", ":"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +	["function-name", "bar"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["builtin", ":"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +	["keyword", "function"],
        +	["function-name", "foo"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["builtin", ":"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +	["comment", "# Not a function:"],
        +	"\r\nbar ",
        +	["punctuation", "{"],
        +	["builtin", ":"],
        +	["punctuation", ";"],
        +	["punctuation", "}"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for function definitions.
        diff --git a/tests/languages/bash/function_feature.test b/tests/languages/bash/function_feature.test
        index 7ebc374b3d..16471489b6 100644
        --- a/tests/languages/bash/function_feature.test
        +++ b/tests/languages/bash/function_feature.test
        @@ -1,101 +1,341 @@
        -alias apropos apt-get aptitude aspell
        -awk basename bash bc bg
        -builtin bzip2 cal cat cd
        -cfdisk chgrp chmod chown chroot
        -chkconfig cksum clear cmp comm
        -command cp cron crontab csplit
        -curl cut date dc dd ddrescue
        -df diff diff3 dig dir dircolors
        -dirname dirs dmesg du
        -egrep eject enable env ethtool
        -eval exec expand expect
        -export expr fdformat fdisk
        -fg fgrep file find fmt
        -fold format free fsck ftp
        -fuser gawk getopts git grep
        -groupadd groupdel groupmod groups
        -gzip hash head help hg history
        -hostname htop iconv id ifconfig
        -ifdown ifup import install jobs
        -join kill killall less link ln
        -locate logname logout look lpc lpr
        -lprint lprintd lprintq lprm ls
        -lsof make man mkdir mkfifo
        -mkisofs mknod more most mount
        -mtools mtr mv mmv nano netstat
        -nice nl nohup notify-send nslookup
        -open op passwd paste pathchk ping
        -pkill popd pr printcap printenv
        -printf ps pushd pv pwd quota
        -quotacheck quotactl ram rar rcp
        -read readarray readonly reboot
        -rename renice remsync rev rm
        -rmdir rsync screen scp sdiff sed
        -seq service sftp shift
        -shopt shutdown sleep slocate
        -sort source split ssh stat strace
        -su sudo sum suspend sync tail tar
        -tee test time timeout times
        -touch top traceroute trap tr
        -tsort tty type ulimit umask
        -umount unalias uname unexpand uniq
        -units unrar unshar uptime
        -useradd userdel usermod users uuencode
        -uudecode v vdir vi vmstat wait watch
        -wc wget whereis which who whoami write
        -xargs xdg-open yes zip
        -
        -----------------------------------------------------
        -
        -[
        -	["function", "alias"], ["function", "apropos"], ["function", "apt-get"], ["function", "aptitude"], ["function", "aspell"],
        -	["function", "awk"], ["function", "basename"], ["function", "bash"], ["function", "bc"], ["function", "bg"],
        -	["function", "builtin"], ["function", "bzip2"], ["function", "cal"], ["function", "cat"], ["function", "cd"],
        -	["function", "cfdisk"], ["function", "chgrp"], ["function", "chmod"], ["function", "chown"], ["function", "chroot"],
        -	["function", "chkconfig"], ["function", "cksum"], ["function", "clear"], ["function", "cmp"], ["function", "comm"],
        -	["function", "command"], ["function", "cp"], ["function", "cron"], ["function", "crontab"], ["function", "csplit"],
        -	["function", "curl"], ["function", "cut"], ["function", "date"], ["function", "dc"], ["function", "dd"], ["function", "ddrescue"],
        -	["function", "df"], ["function", "diff"], ["function", "diff3"], ["function", "dig"], ["function", "dir"], ["function", "dircolors"],
        -	["function", "dirname"], ["function", "dirs"], ["function", "dmesg"], ["function", "du"],
        -	["function", "egrep"], ["function", "eject"], ["function", "enable"], ["function", "env"], ["function", "ethtool"],
        -	["function", "eval"], ["function", "exec"], ["function", "expand"], ["function", "expect"],
        -	["function", "export"], ["function", "expr"], ["function", "fdformat"], ["function", "fdisk"],
        -	["function", "fg"], ["function", "fgrep"], ["function", "file"], ["function", "find"], ["function", "fmt"],
        -	["function", "fold"], ["function", "format"], ["function", "free"], ["function", "fsck"], ["function", "ftp"],
        -	["function", "fuser"], ["function", "gawk"], ["function", "getopts"], ["function", "git"], ["function", "grep"],
        -	["function", "groupadd"], ["function", "groupdel"], ["function", "groupmod"], ["function", "groups"],
        -	["function", "gzip"], ["function", "hash"], ["function", "head"], ["function", "help"], ["function", "hg"], ["function", "history"],
        -	["function", "hostname"], ["function", "htop"], ["function", "iconv"], ["function", "id"], ["function", "ifconfig"],
        -	["function", "ifdown"], ["function", "ifup"], ["function", "import"], ["function", "install"], ["function", "jobs"],
        -	["function", "join"], ["function", "kill"], ["function", "killall"], ["function", "less"], ["function", "link"], ["function", "ln"],
        -	["function", "locate"], ["function", "logname"], ["function", "logout"], ["function", "look"], ["function", "lpc"], ["function", "lpr"],
        -	["function", "lprint"], ["function", "lprintd"], ["function", "lprintq"], ["function", "lprm"], ["function", "ls"],
        -	["function", "lsof"], ["function", "make"], ["function", "man"], ["function", "mkdir"], ["function", "mkfifo"],
        -	["function", "mkisofs"], ["function", "mknod"], ["function", "more"], ["function", "most"], ["function", "mount"],
        -	["function", "mtools"], ["function", "mtr"], ["function", "mv"], ["function", "mmv"], ["function", "nano"], ["function", "netstat"],
        -	["function", "nice"], ["function", "nl"], ["function", "nohup"], ["function", "notify-send"], ["function", "nslookup"],
        -	["function", "open"], ["function", "op"], ["function", "passwd"], ["function", "paste"], ["function", "pathchk"], ["function", "ping"],
        -	["function", "pkill"], ["function", "popd"], ["function", "pr"], ["function", "printcap"], ["function", "printenv"],
        -	["function", "printf"], ["function", "ps"], ["function", "pushd"], ["function", "pv"], ["function", "pwd"], ["function", "quota"],
        -	["function", "quotacheck"], ["function", "quotactl"], ["function", "ram"], ["function", "rar"], ["function", "rcp"],
        -	["function", "read"], ["function", "readarray"], ["function", "readonly"], ["function", "reboot"],
        -	["function", "rename"], ["function", "renice"], ["function", "remsync"], ["function", "rev"], ["function", "rm"],
        -	["function", "rmdir"], ["function", "rsync"], ["function", "screen"], ["function", "scp"], ["function", "sdiff"], ["function", "sed"],
        -	["function", "seq"], ["function", "service"], ["function", "sftp"], ["function", "shift"],
        -	["function", "shopt"], ["function", "shutdown"], ["function", "sleep"], ["function", "slocate"],
        -	["function", "sort"], ["function", "source"], ["function", "split"], ["function", "ssh"], ["function", "stat"], ["function", "strace"],
        -	["function", "su"], ["function", "sudo"], ["function", "sum"], ["function", "suspend"], ["function", "sync"], ["function", "tail"], ["function", "tar"],
        -	["function", "tee"], ["function", "test"], ["function", "time"], ["function", "timeout"], ["function", "times"],
        -	["function", "touch"], ["function", "top"], ["function", "traceroute"], ["function", "trap"], ["function", "tr"],
        -	["function", "tsort"], ["function", "tty"], ["function", "type"], ["function", "ulimit"], ["function", "umask"],
        -	["function", "umount"], ["function", "unalias"], ["function", "uname"], ["function", "unexpand"], ["function", "uniq"],
        -	["function", "units"], ["function", "unrar"], ["function", "unshar"], ["function", "uptime"],
        -	["function", "useradd"], ["function", "userdel"], ["function", "usermod"], ["function", "users"], ["function", "uuencode"],
        -	["function", "uudecode"], ["function", "v"], ["function", "vdir"], ["function", "vi"], ["function", "vmstat"], ["function", "wait"], ["function", "watch"],
        -	["function", "wc"], ["function", "wget"], ["function", "whereis"], ["function", "which"], ["function", "who"], ["function", "whoami"], ["function", "write"],
        -	["function", "xargs"], ["function", "xdg-open"], ["function", "yes"], ["function", "zip"]
        -]
        -
        -----------------------------------------------------
        -
        -Checks for all functions.
        \ No newline at end of file
        +add
        +apropos
        +apt
        +aptitude
        +apt-cache
        +apt-get
        +aspell
        +automysqlbackup
        +awk
        +basename
        +bash
        +bc
        +bconsole
        +bg
        +bzip2
        +cal
        +cat
        +cfdisk
        +chgrp
        +chkconfig
        +chmod
        +chown
        +chroot
        +cksum
        +clear
        +cmp
        +column
        +comm
        +composer
        +cp
        +cron
        +crontab
        +csplit
        +curl
        +cut
        +date
        +dc
        +dd
        +ddrescue
        +debootstrap
        +df
        +diff
        +diff3
        +dig
        +dir
        +dircolors
        +dirname
        +dirs
        +dmesg
        +du
        +egrep
        +eject
        +env
        +ethtool
        +expand
        +expect
        +expr
        +fdformat
        +fdisk
        +fg
        +fgrep
        +file
        +find
        +fmt
        +fold
        +format
        +free
        +fsck
        +ftp
        +fuser
        +gawk
        +git
        +gparted
        +grep
        +groupadd
        +groupdel
        +groupmod
        +groups
        +grub-mkconfig
        +gzip
        +halt
        +head
        +hg
        +history
        +host
        +hostname
        +htop
        +iconv
        +id
        +ifconfig
        +ifdown
        +ifup
        +import
        +install
        +ip
        +jobs
        +join
        +kill
        +killall
        +less
        +link
        +ln
        +locate
        +logname
        +logrotate
        +look
        +lpc
        +lpr
        +lprint
        +lprintd
        +lprintq
        +lprm
        +ls
        +lsof
        +lynx
        +make
        +man
        +mc
        +mdadm
        +mkconfig
        +mkdir
        +mke2fs
        +mkfifo
        +mkfs
        +mkisofs
        +mknod
        +mkswap
        +mmv
        +more
        +most
        +mount
        +mtools
        +mtr
        +mutt
        +mv
        +nano
        +nc
        +netstat
        +nice
        +nl
        +nohup
        +notify-send
        +npm
        +nslookup
        +op
        +open
        +parted
        +passwd
        +paste
        +pathchk
        +ping
        +pkill
        +pnpm
        +popd
        +pr
        +printcap
        +printenv
        +ps
        +pushd
        +pv
        +quota
        +quotacheck
        +quotactl
        +ram
        +rar
        +rcp
        +reboot
        +remsync
        +rename
        +renice
        +rev
        +rm
        +rmdir
        +rpm
        +rsync
        +scp
        +screen
        +sdiff
        +sed
        +sendmail
        +seq
        +service
        +sftp
        +sh
        +shellcheck
        +shuf
        +shutdown
        +sleep
        +slocate
        +sort
        +split
        +ssh
        +stat
        +strace
        +su
        +sudo
        +sum
        +suspend
        +swapon
        +sync
        +tac
        +tail
        +tar
        +tee
        +time
        +timeout
        +top
        +touch
        +tr
        +traceroute
        +tsort
        +tty
        +umount
        +uname
        +unexpand
        +uniq
        +units
        +unrar
        +unshar
        +unzip
        +update-grub
        +uptime
        +useradd
        +userdel
        +usermod
        +users
        +uudecode
        +uuencode
        +v
        +vdir
        +vi
        +vim
        +virsh
        +vmstat
        +wait
        +watch
        +wc
        +wget
        +whereis
        +which
        +who
        +whoami
        +write
        +xargs
        +xdg-open
        +yarn
        +yes
        +zenity
        +zip
        +zsh
        +zypper
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "add"], ["function", "apropos"], ["function", "apt"], ["function", "aptitude"], 
        +	["function", "apt-cache"], ["function", "apt-get"], ["function", "aspell"], 
        +	["function", "automysqlbackup"], ["function", "awk"], ["function", 
        +	"basename"], ["function", "bash"], ["function", "bc"], ["function", 
        +	"bconsole"], ["function", "bg"], ["function", "bzip2"], ["function", 
        +	"cal"], ["function", "cat"], ["function", "cfdisk"], ["function", "chgrp"], 
        +	["function", "chkconfig"], ["function", "chmod"], ["function", "chown"], 
        +	["function", "chroot"], ["function", "cksum"], ["function", "clear"], 
        +	["function", "cmp"], ["function", "column"], ["function", "comm"], ["function", "composer"], 
        +	["function", "cp"], ["function", "cron"], ["function", "crontab"], 
        +	["function", "csplit"], ["function", "curl"], ["function", "cut"], 
        +	["function", "date"], ["function", "dc"], ["function", "dd"], ["function", 
        +	"ddrescue"], ["function", "debootstrap"], ["function", "df"], ["function", 
        +	"diff"], ["function", "diff3"], ["function", "dig"], ["function", "dir"], 
        +	["function", "dircolors"], ["function", "dirname"], ["function", "dirs"], 
        +	["function", "dmesg"], ["function", "du"], ["function", "egrep"], 
        +	["function", "eject"], ["function", "env"], ["function", "ethtool"], 
        +	["function", "expand"], ["function", "expect"], ["function", "expr"], 
        +	["function", "fdformat"], ["function", "fdisk"], ["function", "fg"], 
        +	["function", "fgrep"], ["function", "file"], ["function", "find"], 
        +	["function", "fmt"], ["function", "fold"], ["function", "format"], 
        +	["function", "free"], ["function", "fsck"], ["function", "ftp"], 
        +	["function", "fuser"], ["function", "gawk"], ["function", "git"], 
        +	["function", "gparted"], ["function", "grep"], ["function", "groupadd"], 
        +	["function", "groupdel"], ["function", "groupmod"], ["function", "groups"], 
        +	["function", "grub-mkconfig"], ["function", "gzip"], ["function", "halt"], 
        +	["function", "head"], ["function", "hg"], ["function", "history"], 
        +	["function", "host"], ["function", "hostname"], ["function", "htop"], 
        +	["function", "iconv"], ["function", "id"], ["function", "ifconfig"], 
        +	["function", "ifdown"], ["function", "ifup"], ["function", "import"], 
        +	["function", "install"], ["function", "ip"], ["function", "jobs"], 
        +	["function", "join"], ["function", "kill"], ["function", "killall"], 
        +	["function", "less"], ["function", "link"], ["function", "ln"], 
        +	["function", "locate"], ["function", "logname"], ["function", "logrotate"], 
        +	["function", "look"], ["function", "lpc"], ["function", "lpr"], 
        +	["function", "lprint"], ["function", "lprintd"], ["function", "lprintq"], 
        +	["function", "lprm"], ["function", "ls"], ["function", "lsof"], 
        +	["function", "lynx"], ["function", "make"], ["function", "man"], 
        +	["function", "mc"], ["function", "mdadm"], ["function", "mkconfig"], 
        +	["function", "mkdir"], ["function", "mke2fs"], ["function", "mkfifo"], 
        +	["function", "mkfs"], ["function", "mkisofs"], ["function", "mknod"], 
        +	["function", "mkswap"], ["function", "mmv"], ["function", "more"], 
        +	["function", "most"], ["function", "mount"], ["function", "mtools"], 
        +	["function", "mtr"], ["function", "mutt"], ["function", "mv"], ["function", 
        +	"nano"], ["function", "nc"], ["function", "netstat"], ["function", "nice"], 
        +	["function", "nl"], ["function", "nohup"], ["function", "notify-send"], 
        +	["function", "npm"], ["function", "nslookup"], ["function", "op"], 
        +	["function", "open"], ["function", "parted"], ["function", "passwd"], 
        +	["function", "paste"], ["function", "pathchk"], ["function", "ping"], 
        +	["function", "pkill"], ["function", "pnpm"], ["function", "popd"], ["function", "pr"], 
        +	["function", "printcap"], ["function", "printenv"], ["function", "ps"], 
        +	["function", "pushd"], ["function", "pv"], ["function", "quota"], 
        +	["function", "quotacheck"], ["function", "quotactl"], ["function", "ram"], 
        +	["function", "rar"], ["function", "rcp"], ["function", "reboot"], 
        +	["function", "remsync"], ["function", "rename"], ["function", "renice"], 
        +	["function", "rev"], ["function", "rm"], ["function", "rmdir"], 
        +	["function", "rpm"], ["function", "rsync"], ["function", "scp"], 
        +	["function", "screen"], ["function", "sdiff"], ["function", "sed"], 
        +	["function", "sendmail"], ["function", "seq"], ["function", "service"], 
        +	["function", "sftp"], ["function", "sh"], ["function", "shellcheck"], 
        +	["function", "shuf"], ["function", "shutdown"], ["function", "sleep"], 
        +	["function", "slocate"], ["function", "sort"], ["function", "split"], 
        +	["function", "ssh"], ["function", "stat"], ["function", "strace"], 
        +	["function", "su"], ["function", "sudo"], ["function", "sum"], ["function", 
        +	"suspend"], ["function", "swapon"], ["function", "sync"], ["function", 
        +	"tac"], ["function", "tail"], ["function", "tar"], ["function", "tee"], 
        +	["function", "time"], ["function", "timeout"], ["function", "top"], 
        +	["function", "touch"], ["function", "tr"], ["function", "traceroute"], 
        +	["function", "tsort"], ["function", "tty"], ["function", "umount"], 
        +	["function", "uname"], ["function", "unexpand"], ["function", "uniq"], 
        +	["function", "units"], ["function", "unrar"], ["function", "unshar"], 
        +	["function", "unzip"], ["function", "update-grub"], ["function", "uptime"], 
        +	["function", "useradd"], ["function", "userdel"], ["function", "usermod"], 
        +	["function", "users"], ["function", "uudecode"], ["function", "uuencode"], 
        +	["function", "v"], ["function", "vdir"], ["function", "vi"], ["function", 
        +	"vim"], ["function", "virsh"], ["function", "vmstat"], ["function", 
        +	"wait"], ["function", "watch"], ["function", "wc"], ["function", "wget"], 
        +	["function", "whereis"], ["function", "which"], ["function", "who"], 
        +	["function", "whoami"], ["function", "write"], ["function", "xargs"], 
        +	["function", "xdg-open"], ["function", "yarn"], ["function", "yes"], ["function", "zenity"], 
        +	["function", "zip"], ["function", "zsh"], ["function", "zypper"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all functions.
        diff --git a/tests/languages/bash/issue2436.test b/tests/languages/bash/issue2436.test
        new file mode 100644
        index 0000000000..76568aac62
        --- /dev/null
        +++ b/tests/languages/bash/issue2436.test
        @@ -0,0 +1,24 @@
        +echo $'module.exports = {\n  extends: [\n    // add more generic rulesets here, such as:\n    // 'eslint:recommended',\n    "plugin:vue/vue3-recommended",\n    "prettier",\n    "prettier/vue",\n  ],\n  rules: {\n    // override/add rules settings here, such as:\n    // 'vue/no-unused-vars': 'error'\n  },\n};' > .eslintrc.js
        +
        +----------------------------------------------------
        +
        +[
        +	["builtin", "echo"],
        +	["string", [
        +		"$'module.exports = {",
        +		["entity", "\\n"],
        +		"  extends: [",
        +		["entity", "\\n"],
        +		"    // add more generic rulesets here, such as:",
        +		["entity", "\\n"],
        +		"    // '"
        +	]],
        +	"eslint:recommended",
        +	["string", "',\\n    \"plugin:vue/vue3-recommended\",\\n    \"prettier\",\\n    \"prettier/vue\",\\n  ],\\n  rules: {\\n    // override/add rules settings here, such as:\\n    // '"],
        +	"vue/no-unused-vars",
        +	["string", "': '"],
        +	"error",
        +	["string", "'\\n  },\\n};'"],
        +	["operator", [">"]],
        +	" .eslintrc.js"
        +]
        \ No newline at end of file
        diff --git a/tests/languages/bash/keyword_feature.test b/tests/languages/bash/keyword_feature.test
        index b3bacf55af..c731402def 100644
        --- a/tests/languages/bash/keyword_feature.test
        +++ b/tests/languages/bash/keyword_feature.test
        @@ -1,20 +1,37 @@
        -if then else elif fi
        -for break continue while
        -in case function select
        -do done until echo exit
        -return set declare
        -. :
        +if
        +then
        +else
        +elif
        +fi
        +for x in a
        +while
        +case
        +esac
        +function
        +select x in a
        +do
        +done
        +until
        +
         ----------------------------------------------------
         
         [
        -	["keyword", "if"], ["keyword", "then"], ["keyword", "else"], ["keyword", "elif"], ["keyword", "fi"],
        -	["keyword", "for"], ["keyword", "break"], ["keyword", "continue"], ["keyword", "while"],
        -	["keyword", "in"], ["keyword", "case"], ["keyword", "function"], ["keyword", "select"],
        -	["keyword", "do"], ["keyword", "done"], ["keyword", "until"], ["keyword", "echo"], ["keyword", "exit"],
        -	["keyword", "return"], ["keyword", "set"], ["keyword", "declare"],
        -	["keyword", "."], ["keyword", ":"]
        +	["keyword", "if"],
        +	["keyword", "then"],
        +	["keyword", "else"],
        +	["keyword", "elif"],
        +	["keyword", "fi"],
        +	["keyword", "for"], ["for-or-select", "x"], ["keyword", "in"], " a\r\n",
        +	["keyword", "while"], 
        +	["keyword", "case"],
        +	["keyword", "esac"],
        +	["keyword", "function"],
        +	["keyword", "select"], ["for-or-select", "x"], ["keyword", "in"], " a\r\n",
        +	["keyword", "do"],
        +	["keyword", "done"], 
        +	["keyword", "until"]
         ]
         
         ----------------------------------------------------
         
        -Checks for all keywords.
        \ No newline at end of file
        +Checks for all keywords.
        diff --git a/tests/languages/bash/operator_feature.test b/tests/languages/bash/operator_feature.test
        new file mode 100644
        index 0000000000..6eb5bdbddc
        --- /dev/null
        +++ b/tests/languages/bash/operator_feature.test
        @@ -0,0 +1,68 @@
        +a |& b &> c
        +a >&2
        +a 2<&
        +a <> b
        +a &>> b
        +a && b || c
        +
        +<(yes) <(if true; then :; fi) <(echo) <(true)
        +<(for x in a b; do :; done)
        +<(select x in a b; do :; done)
        +>(yes) >(if true; then :; fi) >(echo) >(true)
        +>(for x in a b; do :; done)
        +>(select x in a b; do :; done)
        +
        +${x:1:2} ${x:-a} ${x:=a} ${x:?a} ${x:+a}
        +${!x} ${x/a/b}
        +${x#*a} ${x##*a} ${x%a*} ${x%%a*}
        +${x^a} ${x^^a} ${x,a} ${x,,a}
        +
        +----------------------------------------------------
        +
        +[
        +	"a ", ["operator", ["|&"]], " b ", ["operator", ["&>"]], " c\r\na ",
        +	["operator", [">"]], ["file-descriptor", "&2"], "\r\na ",
        +	["operator", [
        +		["file-descriptor", "2"], "<&"
        +	]],
        +	"\r\na ", ["operator", ["<>"]], " b\r\na ",
        +	["operator", ["&>>"]], " b\r\na ",
        +	["operator", ["&&"]], " b ", ["operator", ["||"]], " c\r\n\r\n",
        +	["operator", ["<"]], ["punctuation", "("], ["function", "yes"], ["punctuation", ")"],
        +	["operator", ["<"]], ["punctuation", "("], ["keyword", "if"], ["boolean", "true"], ["punctuation", ";"],
        +	["keyword", "then"], ["builtin", ":"], ["punctuation", ";"], ["keyword", "fi"], ["punctuation", ")"],
        +	["operator", ["<"]], ["punctuation", "("], ["builtin", "echo"], ["punctuation", ")"],
        +	["operator", ["<"]], ["punctuation", "("], ["boolean", "true"], ["punctuation", ")"],
        +	["operator", ["<"]], ["punctuation", "("], ["keyword", "for"], ["for-or-select", "x"], ["keyword", "in"], " a b", ["punctuation", ";"],
        +	["keyword", "do"], ["builtin", ":"], ["punctuation", ";"], ["keyword", "done"], ["punctuation", ")"],
        +	["operator", ["<"]], ["punctuation", "("], ["keyword", "select"], ["for-or-select", "x"], ["keyword", "in"], " a b", ["punctuation", ";"],
        +	["keyword", "do"], ["builtin", ":"], ["punctuation", ";"], ["keyword", "done"], ["punctuation", ")"],
        +	["operator", [">"]], ["punctuation", "("], ["function", "yes"], ["punctuation", ")"],
        +	["operator", [">"]], ["punctuation", "("], ["keyword", "if"], ["boolean", "true"], ["punctuation", ";"],
        +	["keyword", "then"], ["builtin", ":"], ["punctuation", ";"], ["keyword", "fi"], ["punctuation", ")"],
        +	["operator", [">"]], ["punctuation", "("], ["builtin", "echo"], ["punctuation", ")"],
        +	["operator", [">"]], ["punctuation", "("], ["boolean", "true"], ["punctuation", ")"],
        +	["operator", [">"]], ["punctuation", "("], ["keyword", "for"], ["for-or-select", "x"], ["keyword", "in"], " a b", ["punctuation", ";"],
        +	["keyword", "do"], ["builtin", ":"], ["punctuation", ";"], ["keyword", "done"], ["punctuation", ")"],
        +	["operator", [">"]], ["punctuation", "("], ["keyword", "select"], ["for-or-select", "x"], ["keyword", "in"], " a b", ["punctuation", ";"],
        +	["keyword", "do"], ["builtin", ":"], ["punctuation", ";"], ["keyword", "done"], ["punctuation", ")"],
        +	["variable", ["${x", ["operator", ":"], "1", ["operator", ":"], "2}"]],
        +	["variable", ["${x", ["operator", ":-"], "a}"]],
        +	["variable", ["${x", ["operator", ":="], "a}"]],
        +	["variable", ["${x", ["operator", ":?"], "a}"]],
        +	["variable", ["${x", ["operator", ":+"], "a}"]],
        +	["variable", ["${", ["operator", "!"], "x}"]],
        +	["variable", ["${x", ["operator", "/"], "a", ["operator", "/"], "b}"]],
        +	["variable", ["${x", ["operator", "#"], "*a}"]],
        +	["variable", ["${x", ["operator", "##"], "*a}"]],
        +	["variable", ["${x", ["operator", "%"], "a*}"]],
        +	["variable", ["${x", ["operator", "%%"], "a*}"]],
        +	["variable", ["${x", ["operator", "^"], "a}"]],
        +	["variable", ["${x", ["operator", "^^"], "a}"]],
        +	["variable", ["${x", ["operator", ","], "a}"]],
        +	["variable", ["${x", ["operator", ",,"], "a}"]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/bash/shebang_feature.test b/tests/languages/bash/shebang_feature.test
        index c41860d026..f113bc0176 100644
        --- a/tests/languages/bash/shebang_feature.test
        +++ b/tests/languages/bash/shebang_feature.test
        @@ -1,11 +1,13 @@
        -#!/bin/bash
        +#! /usr/bin/env bash
        +#/bin/bash
         
         ----------------------------------------------------
         
         [
        -	["shebang", "#!/bin/bash"]
        +	["shebang", "#! /usr/bin/env bash"],
        +	["comment", "#/bin/bash"]
         ]
         
         ----------------------------------------------------
         
        -Checks for shebang.
        \ No newline at end of file
        +Checks for shebang.
        diff --git a/tests/languages/bash/string_feature.test b/tests/languages/bash/string_feature.test
        index fd2a30317d..bdcfc762fe 100644
        --- a/tests/languages/bash/string_feature.test
        +++ b/tests/languages/bash/string_feature.test
        @@ -10,58 +10,85 @@ bar'
         '"bar"'
         "$@"
         "${foo}"
        +\\"foo"
        +\'a # ' not a string
        +
         << STRING_END
         foo
         bar
         STRING_END
        +
        +<<- STRING_END
        +foo
        +bar
        +STRING_END
        +
         <<   EOF
         foo $@
         bar
         EOF
        +
         << 'EOF'
         'single quoted string'
         "double quoted string"
         EOF
        +
         << "EOF"
         foo
        -bar
        +$bar
         EOF
        +
         << STRING_END
         # comment
         STRING_END
        +
         "  # comment  "
         
         ----------------------------------------------------
         
         [
         	["string", ["\"\""]],
        -	["string", ["''"]],
        +	["string", "''"],
         	["string", ["\"foo\""]],
        -	["string", ["'foo'"]],
        +	["string", "'foo'"],
         	["string", ["\"foo\r\nbar\""]],
        -	["string", ["'foo\r\nbar'"]],
        +	["string", "'foo\r\nbar'"],
         	["string", ["\"'foo'\""]],
        -	["string", ["'\"bar\"'"]],
        +	["string", "'\"bar\"'"],
        +	["string", [
        +		"\"",
        +		["variable", "$@"],
        +		"\""
        +	]],
         	["string", [
        -		"\"", ["variable", "$@"], "\""
        +		"\"",
        +		["variable", ["${foo}"]],
        +		"\""
         	]],
        +	["punctuation", "\\"], ["punctuation", "\\"], ["string", ["\"foo\""]],
        +	["punctuation", "\\"], "'a ", ["comment", "# ' not a string"],
        +
        +	["operator", ["<<"]], ["string", ["STRING_END\r\nfoo\r\nbar\r\nSTRING_END"]],
        +
        +	["operator", ["<<-"]], ["string", ["STRING_END\r\nfoo\r\nbar\r\nSTRING_END"]],
        +
        +	["operator", ["<<"]],
         	["string", [
        -		"\"", ["variable", "${foo}"], "\""
        +		"EOF\r\nfoo ", ["variable", "$@"],
        +		"\r\nbar\r\nEOF"
         	]],
        -	["operator", "<<"],
        -	["string", ["STRING_END\r\nfoo\r\nbar\r\nSTRING_END"]],
        -	["operator", "<<"],
        -	["string", ["EOF\r\nfoo ", ["variable", "$@"], "\r\nbar\r\nEOF"]],
        -	["operator", "<<"],
        +
        +	["operator", ["<<"]],
         	["string", ["'EOF'\r\n'single quoted string'\r\n\"double quoted string\"\r\nEOF"]],
        -	["operator", "<<"],
        -	["string", ["\"EOF\"\r\nfoo\r\nbar\r\nEOF"]],
        -	["operator", "<<"],
        -	["string", ["STRING_END\r\n# comment\r\nSTRING_END"]],
        +
        +	["operator", ["<<"]], ["string", ["\"EOF\"\r\nfoo\r\n$bar\r\nEOF"]],
        +
        +	["operator", ["<<"]], ["string", ["STRING_END\r\n# comment\r\nSTRING_END"]],
        +
         	["string", ["\"  # comment  \""]]
         ]
         
         ----------------------------------------------------
         
         Checks for single-quoted and double-quoted strings.
        -Also checks for variables in strings.
        \ No newline at end of file
        +Also checks for variables in strings.
        diff --git a/tests/languages/bash/variable_feature.test b/tests/languages/bash/variable_feature.test
        index 16b7448aa3..546631e156 100644
        --- a/tests/languages/bash/variable_feature.test
        +++ b/tests/languages/bash/variable_feature.test
        @@ -1,15 +1,28 @@
         $foo
        -$@
        -${foo bar}
        +$* $@ $# $? $$ $! $0
        +${foo}
        +$!!!! $????
         
         ----------------------------------------------------
         
         [
         	["variable", "$foo"],
        +	["variable", "$*"],
         	["variable", "$@"],
        -	["variable", "${foo bar}"]
        +	["variable", "$#"],
        +	["variable", "$?"],
        +	["variable", "$$"],
        +	["variable", "$!"],
        +	["variable", "$0"],
        +	["variable", ["${foo}"]],
        +	["variable", "$!"],
        +	["operator", ["!"]],
        +	["operator", ["!"]],
        +	["operator", ["!"]],
        +	["variable", "$?"],
        +	"???"
         ]
         
         ----------------------------------------------------
         
        -Checks for variables.
        \ No newline at end of file
        +Checks for variables.
        diff --git a/tests/languages/bash/variable_operator_feature.test b/tests/languages/bash/variable_operator_feature.test
        new file mode 100644
        index 0000000000..4cec4fab7d
        --- /dev/null
        +++ b/tests/languages/bash/variable_operator_feature.test
        @@ -0,0 +1,70 @@
        +"$((
        +
        ++ - * / % ^ & |
        ++= -= *= /= %= ^= &= |=
        +-- ++ ** && ||
        +
        +>> >>= << <<=
        +
        +== != > >= < <=
        += ! ~ ? :
        +
        +
        +
        +))"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", [
        +		"\"",
        +		["variable", [
        +			["variable", "$(("],
        +
        +			["operator", "+"],
        +			["operator", "-"],
        +			["operator", "*"],
        +			["operator", "/"],
        +			["operator", "%"],
        +			["operator", "^"],
        +			["operator", "&"],
        +			["operator", "|"],
        +
        +			["operator", "+="],
        +			["operator", "-="],
        +			["operator", "*="],
        +			["operator", "/="],
        +			["operator", "%="],
        +			["operator", "^="],
        +			["operator", "&="],
        +			["operator", "|="],
        +
        +			["operator", "--"],
        +			["operator", "++"],
        +			["operator", "**"],
        +			["operator", "&&"],
        +			["operator", "||"],
        +
        +			["operator", ">>"],
        +			["operator", ">>="],
        +			["operator", "<<"],
        +			["operator", "<<="],
        +
        +			["operator", "=="],
        +			["operator", "!="],
        +			["operator", ">"],
        +			["operator", ">="],
        +			["operator", "<"],
        +			["operator", "<="],
        +
        +			["operator", "="],
        +			["operator", "!"],
        +			["operator", "~"],
        +			["operator", "?"],
        +			["operator", ":"],
        +
        +			["variable", "))"]
        +		]],
        +		"\""
        +	]]
        +]
        diff --git a/tests/languages/basic/punctuation_feature.test b/tests/languages/basic/punctuation_feature.test
        new file mode 100644
        index 0000000000..318275a6e6
        --- /dev/null
        +++ b/tests/languages/basic/punctuation_feature.test
        @@ -0,0 +1,11 @@
        +, ; : ( )
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", ","],
        +	["punctuation", ";"],
        +	["punctuation", ":"],
        +	["punctuation", "("],
        +	["punctuation", ")"]
        +]
        diff --git a/tests/languages/batch/command_feature.test b/tests/languages/batch/command_feature.test
        index 350788a8bd..77c928ca4b 100644
        --- a/tests/languages/batch/command_feature.test
        +++ b/tests/languages/batch/command_feature.test
        @@ -1,10 +1,19 @@
         FOR /l %%a in (5,-1,1) do (TITLE %title% -- closing in %%as)
        +
        +FOR /F %%A IN ('TYPE "%InFile%"^|find /v /c ""')
        +
         SET title=%~n0
        +
         echo.Hello World
        +
         @ECHO OFF
        +
         if not defined ProgressFormat set "ProgressFormat=[PPPP]"
        +
         EXIT /b
        +
         set /a ProgressCnt+=1
        +
         IF "%~1" NEQ "" (SET %~1=%new%) ELSE (echo.%new%)
         
         ----------------------------------------------------
        @@ -12,13 +21,18 @@ IF "%~1" NEQ "" (SET %~1=%new%) ELSE (echo.%new%)
         [
         	["command", [
         		["keyword", "FOR"],
        -		["parameter", ["/l"]],
        +		["parameter", [
        +			"/l"
        +		]],
         		["variable", "%%a"],
         		["keyword", "in"],
         		["punctuation", "("],
        -		["number", "5"], ["punctuation", ","],
        -		["number", "-1"], ["punctuation", ","],
        -		["number", "1"], ["punctuation", ")"],
        +		["number", "5"],
        +		["punctuation", ","],
        +		["number", "-1"],
        +		["punctuation", ","],
        +		["number", "1"],
        +		["punctuation", ")"],
         		["keyword", "do"]
         	]],
         	["punctuation", "("],
        @@ -30,6 +44,27 @@ IF "%~1" NEQ "" (SET %~1=%new%) ELSE (echo.%new%)
         	]],
         	["punctuation", ")"],
         
        +	["command", [
        +		["keyword", "FOR"],
        +		["parameter", [
        +			"/F"
        +		]],
        +		["variable", "%%A"],
        +		" IN ('TYPE ",
        +		["string", "\"%InFile%\""],
        +		["operator", "^"],
        +		"|find ",
        +		["parameter", [
        +			"/v"
        +		]],
        +		["parameter", [
        +			"/c"
        +		]],
        +		["string", "\"\""],
        +		"'"
        +	]],
        +	["punctuation", ")"],
        +
         	["command", [
         		["keyword", "SET"],
         		["variable", "title"],
        @@ -61,12 +96,16 @@ IF "%~1" NEQ "" (SET %~1=%new%) ELSE (echo.%new%)
         
         	["command", [
         		["keyword", "EXIT"],
        -		["parameter", ["/b"]]
        +		["parameter", [
        +			"/b"
        +		]]
         	]],
         
         	["command", [
         		["keyword", "set"],
        -		["parameter", ["/a"]],
        +		["parameter", [
        +			"/a"
        +		]],
         		["variable", "ProgressCnt"],
         		["operator", "+="],
         		["number", "1"]
        @@ -100,4 +139,4 @@ IF "%~1" NEQ "" (SET %~1=%new%) ELSE (echo.%new%)
         
         ----------------------------------------------------
         
        -Checks for commands.
        \ No newline at end of file
        +Checks for commands.
        diff --git a/tests/languages/batch/label_feature.test b/tests/languages/batch/label_feature.test
        index a672ba0cc3..547bda0200 100644
        --- a/tests/languages/batch/label_feature.test
        +++ b/tests/languages/batch/label_feature.test
        @@ -1,13 +1,18 @@
         :foo
         :Foo_Bar
        +GOTO:eof
         
         ----------------------------------------------------
         
         [
         	["label", ":foo"],
        -	["label", ":Foo_Bar"]
        +	["label", ":Foo_Bar"],
        +	["command", [
        +		["keyword", "GOTO"],
        +		["label", ":eof"]
        +	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for labels.
        \ No newline at end of file
        +Checks for labels.
        diff --git a/tests/languages/batch/string_feature.test b/tests/languages/batch/string_feature.test
        new file mode 100644
        index 0000000000..83aaaf9138
        --- /dev/null
        +++ b/tests/languages/batch/string_feature.test
        @@ -0,0 +1,29 @@
        +cmd ""
        +cmd "f\"oo"
        +cmd "f\\"oo"
        +cmd "print(""hello"")"
        +
        +----------------------------------------------------
        +
        +[
        +	["command", [
        +		["keyword", "cmd"],
        +		["string", "\"\""]
        +	]],
        +	["command", [
        +		["keyword", "cmd"],
        +		["string", "\"f\\\"oo\""]
        +	]],
        +	["command", [
        +		["keyword", "cmd"],
        +		["string", "\"f\\\\\"oo\""]
        +	]],
        +	["command", [
        +		["keyword", "cmd"],
        +		["string", "\"print(\"\"hello\"\")\""]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        \ No newline at end of file
        diff --git a/tests/languages/bbcode/tag_feature.test b/tests/languages/bbcode/tag_feature.test
        new file mode 100644
        index 0000000000..e64f179f6c
        --- /dev/null
        +++ b/tests/languages/bbcode/tag_feature.test
        @@ -0,0 +1,248 @@
        +[list]
        +  [*]Entry A
        +  [*]Entry B
        +[/list]
        +
        +[list=1]
        +  [*]Entry 1
        +  [*]Entry 2
        +[/list]
        +
        +[style color="fuchsia"]Text in fuchsia[/style] or
        +[style color=#FF00FF]Text in fuchsia[/style] or
        +[color=#FF00FF]Text in fuchsia[/color]
        +[quote]quoted text[/quote]
        +[quote="author"]quoted text[/quote]
        +
        +[:-)]
        +
        +[url]https://en.wikipedia.org[/url]
        +[url=https://en.wikipedia.org]English Wikipedia[/url]
        +
        +----------------------------------------------------
        +
        +[
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"list"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"*"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"Entry A\r\n  ",
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"*"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"Entry B\r\n",
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"list"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"list"
        +		]],
        +		["attr-value", [
        +			["punctuation", "="],
        +			"1"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"*"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"Entry 1\r\n  ",
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"*"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"Entry 2\r\n",
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"list"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"style"
        +		]],
        +		["attr-name", "color"],
        +		["attr-value", [
        +			["punctuation", "="],
        +			["punctuation", "\""],
        +			"fuchsia",
        +			["punctuation", "\""]
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"Text in fuchsia",
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"style"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	" or\r\n",
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"style"
        +		]],
        +		["attr-name", "color"],
        +		["attr-value", [
        +			["punctuation", "="],
        +			"#FF00FF"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"Text in fuchsia",
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"style"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	" or\r\n",
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"color"
        +		]],
        +		["attr-value", [
        +			["punctuation", "="],
        +			"#FF00FF"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"Text in fuchsia",
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"color"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"quote"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"quoted text",
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"quote"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"quote"
        +		]],
        +		["attr-value", [
        +			["punctuation", "="],
        +			["punctuation", "\""],
        +			"author",
        +			["punctuation", "\""]
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"quoted text",
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"quote"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			":-)"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"url"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"https://en.wikipedia.org",
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"url"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +
        +	["tag", [
        +		["tag", [
        +			["punctuation", "["],
        +			"url"
        +		]],
        +		["attr-value", [
        +			["punctuation", "="],
        +			"https://en.wikipedia.org"
        +		]],
        +		["punctuation", "]"]
        +	]],
        +	"English Wikipedia",
        +	["tag", [
        +		["tag", [
        +			["punctuation", "[/"],
        +			"url"
        +		]],
        +		["punctuation", "]"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for tags.
        diff --git a/tests/languages/bicep/boolean_feature.test b/tests/languages/bicep/boolean_feature.test
        new file mode 100644
        index 0000000000..a40f8d95d2
        --- /dev/null
        +++ b/tests/languages/bicep/boolean_feature.test
        @@ -0,0 +1,13 @@
        +true
        +false
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "true"],
        +	["boolean", "false"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for booleans.
        \ No newline at end of file
        diff --git a/tests/languages/bicep/comment_feature.test b/tests/languages/bicep/comment_feature.test
        new file mode 100644
        index 0000000000..3d3a84ce63
        --- /dev/null
        +++ b/tests/languages/bicep/comment_feature.test
        @@ -0,0 +1,18 @@
        +// this is a comment
        +
        +/* this
        +is a
        +multi line comment */
        +
        +/* so is
        +this */
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// this is a comment"],
        +
        +	["comment", "/* this\r\nis a\r\nmulti line comment */"],
        +
        +	["comment", "/* so is\r\nthis */"]
        +]
        diff --git a/tests/languages/bicep/datatype_feature.test b/tests/languages/bicep/datatype_feature.test
        new file mode 100644
        index 0000000000..882430f6fd
        --- /dev/null
        +++ b/tests/languages/bicep/datatype_feature.test
        @@ -0,0 +1,47 @@
        +param myString string
        +param myInt int
        +param myBool bool
        +param myObject object
        +param myArray array
        +
        +output myHardcodedOutput int = 42
        +output myLoopyOutput array = [for myItem in myArray: {
        +  myProperty: myItem.myOtherProperty
        +}]
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "param"], " myString ", ["datatype", "string"],
        +	["keyword", "param"], " myInt ", ["datatype", "int"],
        +	["keyword", "param"], " myBool ", ["datatype", "bool"],
        +	["keyword", "param"], " myObject ", ["datatype", "object"],
        +	["keyword", "param"], " myArray ", ["datatype", "array"],
        +
        +	["keyword", "output"],
        +	" myHardcodedOutput ",
        +	["datatype", "int"],
        +	["operator", "="],
        +	["number", "42"],
        +
        +	["keyword", "output"],
        +	" myLoopyOutput ",
        +	["datatype", "array"],
        +	["operator", "="],
        +	["punctuation", "["],
        +	["keyword", "for"],
        +	" myItem ",
        +	["keyword", "in"],
        +	" myArray",
        +	["operator", ":"],
        +	["punctuation", "{"],
        +
        +	["property", "myProperty"],
        +	["operator", ":"],
        +	" myItem",
        +	["punctuation", "."],
        +	"myOtherProperty\r\n",
        +
        +	["punctuation", "}"],
        +	["punctuation", "]"]
        +]
        diff --git a/tests/languages/bicep/decorator_feature.test b/tests/languages/bicep/decorator_feature.test
        new file mode 100644
        index 0000000000..36d29bc222
        --- /dev/null
        +++ b/tests/languages/bicep/decorator_feature.test
        @@ -0,0 +1,61 @@
        +@secure()
        +param demoPassword string
        +@allowed([
        +  'one'
        +  'two'
        +])
        +param demoEnum string
        +
        +@minLength(3)
        +@maxLength(24)
        +@description('Name of the storage account')
        +param storageAccountName string = concat(uniqueString(resourceGroup().id), 'sa')
        +
        +----------------------------------------------------
        +
        +[
        +	["decorator", "@secure"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "param"], " demoPassword ", ["datatype", "string"],
        +	["decorator", "@allowed"], ["punctuation", "("], ["punctuation", "["],
        +	["string", "'one'"],
        +	["string", "'two'"],
        +	["punctuation", "]"], ["punctuation", ")"],
        +	["keyword", "param"], " demoEnum ", ["datatype", "string"],
        +
        +	["decorator", "@minLength"],
        +	["punctuation", "("],
        +	["number", "3"],
        +	["punctuation", ")"],
        +
        +	["decorator", "@maxLength"],
        +	["punctuation", "("],
        +	["number", "24"],
        +	["punctuation", ")"],
        +
        +	["decorator", "@description"],
        +	["punctuation", "("],
        +	["string", "'Name of the storage account'"],
        +	["punctuation", ")"],
        +
        +	["keyword", "param"],
        +	" storageAccountName ",
        +	["datatype", "string"],
        +	["operator", "="],
        +	["function", "concat"],
        +	["punctuation", "("],
        +	["function", "uniqueString"],
        +	["punctuation", "("],
        +	["function", "resourceGroup"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "."],
        +	"id",
        +	["punctuation", ")"],
        +	["punctuation", ","],
        +	["string", "'sa'"],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for functions. Also checks for unicode characters in identifiers.
        diff --git a/tests/languages/bicep/function_feature.test b/tests/languages/bicep/function_feature.test
        new file mode 100644
        index 0000000000..91b75bf547
        --- /dev/null
        +++ b/tests/languages/bicep/function_feature.test
        @@ -0,0 +1,62 @@
        +param location string = resourceGroup().location
        +var hostingPlanName = 'hostingplan${uniqueString(resourceGroup().id)}'
        +
        +array(parameters('stringToConvert'))
        +createArray(1, 2, 3)
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "param"],
        +	" location ",
        +	["datatype", "string"],
        +	["operator", "="],
        +	["function", "resourceGroup"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "."],
        +	"location\r\n",
        +
        +	["keyword", "var"],
        +	" hostingPlanName ",
        +	["operator", "="],
        +	["interpolated-string", [
        +		["string", "'hostingplan"],
        +		["interpolation", [
        +			["punctuation", "${"],
        +			["expression", [
        +				["function", "uniqueString"],
        +				["punctuation", "("],
        +				["function", "resourceGroup"],
        +				["punctuation", "("],
        +				["punctuation", ")"],
        +				["punctuation", "."],
        +				"id",
        +				["punctuation", ")"]
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", "'"]
        +	]],
        +
        +	["function", "array"],
        +	["punctuation", "("],
        +	["function", "parameters"],
        +	["punctuation", "("],
        +	["string", "'stringToConvert'"],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +
        +	["function", "createArray"],
        +	["punctuation", "("],
        +	["number", "1"],
        +	["punctuation", ","],
        +	["number", "2"],
        +	["punctuation", ","],
        +	["number", "3"],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for functions. Based upon https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-array
        diff --git a/tests/languages/bicep/keyword_feature.test b/tests/languages/bicep/keyword_feature.test
        new file mode 100644
        index 0000000000..9a548ae875
        --- /dev/null
        +++ b/tests/languages/bicep/keyword_feature.test
        @@ -0,0 +1,87 @@
        +targetScope
        +resource appServicePlan 'Microsoft.Web/serverfarms@2020-09-01' existing =  = if (diagnosticsEnabled) {
        +  name: logAnalyticsWsName
        +}
        +module cosmosDb './cosmosdb.bicep' = {
        +  name: 'cosmosDbDeploy'
        +}
        +param env string
        +var oneNumber = 123
        +output databaseName string = cosmosdbDatabaseName
        +for item in cosmosdbAllowedIpAddresses: {
        +	ipAddressOrRange: item
        +}
        +if
        +null
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "targetScope"],
        +
        +	["keyword", "resource"],
        +	" appServicePlan ",
        +	["string", "'Microsoft.Web/serverfarms@2020-09-01'"],
        +	["keyword", "existing"],
        +	["operator", "="],
        +	["operator", "="],
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	"diagnosticsEnabled",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +
        +	["property", "name"],
        +	["operator", ":"],
        +	" logAnalyticsWsName\r\n",
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "module"],
        +	" cosmosDb ",
        +	["string", "'./cosmosdb.bicep'"],
        +	["operator", "="],
        +	["punctuation", "{"],
        +
        +	["property", "name"],
        +	["operator", ":"],
        +	["string", "'cosmosDbDeploy'"],
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "param"],
        +	" env ",
        +	["datatype", "string"],
        +
        +	["keyword", "var"],
        +	" oneNumber ",
        +	["operator", "="],
        +	["number", "123"],
        +
        +	["keyword", "output"],
        +	" databaseName ",
        +	["datatype", "string"],
        +	["operator", "="],
        +	" cosmosdbDatabaseName\r\n",
        +
        +	["keyword", "for"],
        +	" item ",
        +	["keyword", "in"],
        +	" cosmosdbAllowedIpAddresses",
        +	["operator", ":"],
        +	["punctuation", "{"],
        +
        +	["property", "ipAddressOrRange"],
        +	["operator", ":"],
        +	" item\r\n",
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "if"],
        +
        +	["keyword", "null"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all keywords.
        diff --git a/tests/languages/bicep/number_feature.test b/tests/languages/bicep/number_feature.test
        new file mode 100644
        index 0000000000..99431b21a8
        --- /dev/null
        +++ b/tests/languages/bicep/number_feature.test
        @@ -0,0 +1,73 @@
        +42
        +3.14159
        +4e10
        +3.2E+6
        +2.1e-10
        +0b1101
        +0o571
        +0xbabe
        +0xBABE
        +
        +NaN
        +Infinity
        +
        +123n
        +0x123n
        +
        +1_000_000_000_000
        +1_000_000.220_720
        +0b0101_0110_0011_1000
        +0o12_34_56
        +0x40_76_38_6A_73
        +4_642_473_943_484_686_707n
        +0.000_001
        +1e10_000
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "42"],
        +	["number", "3.14159"],
        +	["number", "4e10"],
        +	["number", "3.2E+6"],
        +	["number", "2.1e-10"],
        +	["number", "0"], "b1101\r\n",
        +	["number", "0"], "o571\r\n",
        +	["number", "0"], "xbabe\r\n",
        +	["number", "0"], "xBABE\r\n\r\nNaN\r\nInfinity\r\n\r\n",
        +
        +	["number", "123"], "n\r\n",
        +	["number", "0"], "x123n\r\n\r\n",
        +
        +	["number", "1"],
        +	"_000_000_000_000\r\n",
        +
        +	["number", "1"],
        +	"_000_000",
        +	["punctuation", "."],
        +	["number", "220"],
        +	"_720\r\n",
        +
        +	["number", "0"],
        +	"b0101_0110_0011_1000\r\n",
        +
        +	["number", "0"],
        +	"o12_34_56\r\n",
        +
        +	["number", "0"],
        +	"x40_76_38_6A_73\r\n",
        +
        +	["number", "4"],
        +	"_642_473_943_484_686_707n\r\n",
        +
        +	["number", "0.000"],
        +	"_001\r\n",
        +
        +	["number", "1e10"],
        +	"_000"
        +]
        +
        +----------------------------------------------------
        +
        +Checks for decimal numbers, binary numbers, octal numbers, hexadecimal numbers.
        +Also checks for keywords representing numbers.
        diff --git a/tests/languages/bicep/operator_feature.test b/tests/languages/bicep/operator_feature.test
        new file mode 100644
        index 0000000000..b5ad0f6334
        --- /dev/null
        +++ b/tests/languages/bicep/operator_feature.test
        @@ -0,0 +1,35 @@
        +- -- -=
        ++ ++ +=
        +< <= << <<=
        +> >= >> >>= >>> >>>=
        += == === =>
        +! != !==
        +& && &= &&=
        +| || |= ||=
        +* ** *= **=
        +/ /= ~
        +^ ^= % %=
        +? : ...
        +?? ?. ??=
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "-"], ["operator", "--"], ["operator", "-="],
        +	["operator", "+"], ["operator", "++"], ["operator", "+="],
        +	["operator", "<"], ["operator", "<="], ["operator", "<<"], ["operator", "<<="],
        +	["operator", ">"], ["operator", ">="], ["operator", ">>"], ["operator", ">>="], ["operator", ">>>"], ["operator", ">>>="],
        +	["operator", "="], ["operator", "=="], ["operator", "==="], ["operator", "=>"],
        +	["operator", "!"], ["operator", "!="], ["operator", "!=="],
        +	["operator", "&"], ["operator", "&&"], ["operator", "&="], ["operator", "&&="],
        +	["operator", "|"], ["operator", "||"], ["operator", "|="], ["operator", "||="],
        +	["operator", "*"], ["operator", "**"], ["operator", "*="], ["operator", "**="],
        +	["operator", "/"], ["operator", "/="], ["operator", "~"],
        +	["operator", "^"], ["operator", "^="], ["operator", "%"], ["operator", "%="],
        +	["operator", "?"], ["operator", ":"], ["operator", "..."],
        +	["operator", "??"], ["operator", "?."], ["operator", "??="]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all operators.
        diff --git a/tests/languages/bicep/property_feature.test b/tests/languages/bicep/property_feature.test
        new file mode 100644
        index 0000000000..4bb02cdde2
        --- /dev/null
        +++ b/tests/languages/bicep/property_feature.test
        @@ -0,0 +1,23 @@
        +var myObjWithSpecialChars = {
        +  '$special\tchars!': true
        +  normalKey: 'val'
        +}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "var"],
        +	" myObjWithSpecialChars ",
        +	["operator", "="],
        +	["punctuation", "{"],
        +
        +	["property", "'$special\\tchars!'"],
        +	["operator", ":"],
        +	["boolean", "true"],
        +
        +	["property", "normalKey"],
        +	["operator", ":"],
        +	["string", "'val'"],
        +
        +	["punctuation", "}"]
        +]
        diff --git a/tests/languages/bicep/string_feature.test b/tests/languages/bicep/string_feature.test
        new file mode 100644
        index 0000000000..7d69ba79e1
        --- /dev/null
        +++ b/tests/languages/bicep/string_feature.test
        @@ -0,0 +1,73 @@
        +''
        +'hello!'
        +'what\'s up?'
        +'steve'
        +'hello ${name}!'
        +'😁\u{1F642}'
        +'Microsoft.Web/sites/config@2020-12-01'
        +'https://${frontDoorName}.azurefd.net/.auth/login/aad/callback'
        +
        +'''hello!'''
        +var myVar2 = '''
        +hello!'''
        +'''
        +hello!
        +'''
        +'''
        +  this
        +    is
        +      indented
        +'''
        +
        +'''
        +comments // are included
        +/* because everything is read as-is */
        +'''
        +
        +'''interpolation
        +is ${blocked}'''
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "''"],
        +	["string", "'hello!'"],
        +	["string", "'what\\'s up?'"],
        +	["string", "'steve'"],
        +	["interpolated-string", [
        +		["string", "'hello "],
        +		["interpolation", [
        +			["punctuation", "${"],
        +			["expression", ["name"]],
        +			["punctuation", "}"]
        +		]],
        +		["string", "!'"]
        +	]],
        +	["string", "'😁\\u{1F642}'"],
        +	["string", "'Microsoft.Web/sites/config@2020-12-01'"],
        +	["interpolated-string", [
        +		["string", "'https://"],
        +		["interpolation", [
        +			["punctuation", "${"],
        +			["expression", ["frontDoorName"]],
        +			["punctuation", "}"]
        +		]],
        +		["string", ".azurefd.net/.auth/login/aad/callback'"]
        +	]],
        +
        +	["string", "'''hello!'''"],
        +	["keyword", "var"],
        +	" myVar2 ",
        +	["operator", "="],
        +	["string", "'''\r\nhello!'''"],
        +	["string", "'''\r\nhello!\r\n'''"],
        +	["string", "'''\r\n  this\r\n    is\r\n      indented\r\n'''"],
        +
        +	["string", "'''\r\ncomments // are included\r\n/* because everything is read as-is */\r\n'''"],
        +
        +	["string", "'''interpolation\r\nis ${blocked}'''"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/bicep/var_feature.test b/tests/languages/bicep/var_feature.test
        new file mode 100644
        index 0000000000..87c0a888e2
        --- /dev/null
        +++ b/tests/languages/bicep/var_feature.test
        @@ -0,0 +1,25 @@
        +var oneString = 'abc'
        +var oneNumber = 123
        +var numbers = [
        +  123
        +]
        +var oneObject = {
        +	abc: 123
        +}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "var"], " oneString ", ["operator", "="], ["string", "'abc'"],
        +	["keyword", "var"], " oneNumber ", ["operator", "="], ["number", "123"],
        +	["keyword", "var"], " numbers ", ["operator", "="], ["punctuation", "["],
        +	["number", "123"],
        +	["punctuation", "]"],
        +	["keyword", "var"], " oneObject ", ["operator", "="], ["punctuation", "{"],
        +	["property", "abc"], ["operator", ":"], ["number", "123"],
        +	["punctuation", "}"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for vars.
        diff --git a/tests/languages/birb/class-name_feature.test b/tests/languages/birb/class-name_feature.test
        new file mode 100644
        index 0000000000..946c751f70
        --- /dev/null
        +++ b/tests/languages/birb/class-name_feature.test
        @@ -0,0 +1,63 @@
        +class Birb {
        +	String name = "Birb";
        +	int age = 5;
        +	bool isMale = true;
        +
        +	String getName() {
        +		return name;
        +	}
        +}
        +
        +List list = ["Seeb", 10, false];
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "class"],
        +	["class-name", "Birb"],
        +	["punctuation", "{"],
        +
        +	["class-name", "String"],
        +	["variable", "name"],
        +	["operator", "="],
        +	["string", "\"Birb\""],
        +	["punctuation", ";"],
        +
        +	["class-name", "int"],
        +	["variable", "age"],
        +	["operator", "="],
        +	["number", "5"],
        +	["punctuation", ";"],
        +
        +	["class-name", "bool"],
        +	["variable", "isMale"],
        +	["operator", "="],
        +	["boolean", "true"],
        +	["punctuation", ";"],
        +
        +	["class-name", "String"],
        +	["function", "getName"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +
        +	["class-name", "return"],
        +	["variable", "name"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +
        +	["punctuation", "}"],
        +
        +	["class-name", "List"],
        +	["variable", "list"],
        +	["operator", "="],
        +	["punctuation", "["],
        +	["string", "\"Seeb\""],
        +	["punctuation", ","],
        +	["number", "10"],
        +	["punctuation", ","],
        +	["boolean", "false"],
        +	["punctuation", "]"],
        +	["punctuation", ";"]
        +]
        diff --git a/tests/languages/birb/function_feature.test b/tests/languages/birb/function_feature.test
        new file mode 100644
        index 0000000000..ab0b6f823e
        --- /dev/null
        +++ b/tests/languages/birb/function_feature.test
        @@ -0,0 +1,25 @@
        +void foo(int a) {}
        +foo(0);
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "void"],
        +	["function", "foo"],
        +	["punctuation", "("],
        +	["class-name", "int"],
        +	["variable", "a"],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["function", "foo"],
        +	["punctuation", "("],
        +	["number", "0"],
        +	["punctuation", ")"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for functions.
        diff --git a/tests/languages/birb/keyword_feature.test b/tests/languages/birb/keyword_feature.test
        new file mode 100644
        index 0000000000..3105071968
        --- /dev/null
        +++ b/tests/languages/birb/keyword_feature.test
        @@ -0,0 +1,57 @@
        +assert;
        +break;
        +case;
        +class;
        +const;
        +default;
        +else;
        +enum;
        +final;
        +follows;
        +for;
        +grab;
        +if;
        +nest;
        +next;
        +new;
        +noSeeb;
        +return;
        +static;
        +switch;
        +throw;
        +var;
        +void;
        +while;
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "assert"], ["punctuation", ";"],
        +	["keyword", "break"], ["punctuation", ";"],
        +	["keyword", "case"], ["punctuation", ";"],
        +	["keyword", "class"], ["punctuation", ";"],
        +	["keyword", "const"], ["punctuation", ";"],
        +	["keyword", "default"], ["punctuation", ";"],
        +	["keyword", "else"], ["punctuation", ";"],
        +	["keyword", "enum"], ["punctuation", ";"],
        +	["keyword", "final"], ["punctuation", ";"],
        +	["keyword", "follows"], ["punctuation", ";"],
        +	["keyword", "for"], ["punctuation", ";"],
        +	["keyword", "grab"], ["punctuation", ";"],
        +	["keyword", "if"], ["punctuation", ";"],
        +	["keyword", "nest"], ["punctuation", ";"],
        +	["keyword", "next"], ["punctuation", ";"],
        +	["keyword", "new"], ["punctuation", ";"],
        +	["keyword", "noSeeb"], ["punctuation", ";"],
        +	["keyword", "return"], ["punctuation", ";"],
        +	["keyword", "static"], ["punctuation", ";"],
        +	["keyword", "switch"], ["punctuation", ";"],
        +	["keyword", "throw"], ["punctuation", ";"],
        +	["keyword", "var"], ["punctuation", ";"],
        +	["keyword", "void"], ["punctuation", ";"],
        +	["keyword", "while"], ["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all keywords.
        diff --git a/tests/languages/birb/metadata_feature.test b/tests/languages/birb/metadata_feature.test
        new file mode 100644
        index 0000000000..e87e28d8be
        --- /dev/null
        +++ b/tests/languages/birb/metadata_feature.test
        @@ -0,0 +1,11 @@
        +
        +
        +----------------------------------------------------
        +
        +[
        +	["metadata", ""]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for metadata.
        \ No newline at end of file
        diff --git a/tests/languages/birb/operator_feature.test b/tests/languages/birb/operator_feature.test
        new file mode 100644
        index 0000000000..4017c74c45
        --- /dev/null
        +++ b/tests/languages/birb/operator_feature.test
        @@ -0,0 +1,27 @@
        +++ --
        +* / % ~/
        ++ - ! ~
        +<< >> ? :
        +& ^ |
        +>= > <= <
        +== != && ||
        += *= /=
        +%= += -=
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "++"], ["operator", "--"],
        +	["operator", "*"], ["operator", "/"], ["operator", "%"], ["operator", "~/"],
        +	["operator", "+"], ["operator", "-"], ["operator", "!"], ["operator", "~"],
        +	["operator", "<<"], ["operator", ">>"], ["operator", "?"], ["operator", ":"],
        +	["operator", "&"], ["operator", "^"], ["operator", "|"],
        +	["operator", ">="], ["operator", ">"], ["operator", "<="], ["operator", "<"],
        +	["operator", "=="], ["operator", "!="], ["operator", "&&"], ["operator", "||"],
        +	["operator", "="], ["operator", "*="], ["operator", "/="],
        +	["operator", "%="], ["operator", "+="], ["operator", "-="]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all operators.
        \ No newline at end of file
        diff --git a/tests/languages/birb/string_feature.test b/tests/languages/birb/string_feature.test
        new file mode 100644
        index 0000000000..b3f40ddb7b
        --- /dev/null
        +++ b/tests/languages/birb/string_feature.test
        @@ -0,0 +1,21 @@
        +"" ''
        +r"" r''
        +"fo\"o" 'fo\'o'
        +'foo
        +bar'
        +"foo
        +bar"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"\""], ["string", "''"],
        +	["string", "r\"\""], ["string", "r''"],
        +	["string", "\"fo\\\"o\""], ["string", "'fo\\'o'"],
        +	["string", "'foo\r\nbar'"],
        +	["string", "\"foo\r\nbar\""]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for single quoted, double quoted, and multiline strings
        \ No newline at end of file
        diff --git a/tests/languages/bison/c_feature.test b/tests/languages/bison/c_feature.test
        index 4d8be839d5..6732d96992 100644
        --- a/tests/languages/bison/c_feature.test
        +++ b/tests/languages/bison/c_feature.test
        @@ -21,30 +21,74 @@ exp:
         	["bison", [
         		["c", [
         			["delimiter", "%{"],
        -			["macro", ["#", ["directive", "include"], ["string", ""]]],
        +			["macro", [
        +				["directive-hash", "#"],
        +				["directive", "include"],
        +				["string", ""]
        +			]],
         			["delimiter", "%}"]
         		]],
         		["keyword", "%code"],
         		["c", [
         			["delimiter", "{"],
        -			["keyword", "if"], ["punctuation", "("], "foo", ["punctuation", ")"],
        -			["punctuation", "{"], ["punctuation", "}"],
        +			["keyword", "if"],
        +			["punctuation", "("],
        +			"foo",
        +			["punctuation", ")"],
        +			["punctuation", "{"],
        +
        +			["punctuation", "}"],
         			["delimiter", "}"]
         		]],
         		["punctuation", "%%"],
        -		["property", "exp"], ["punctuation", ":"],
        +		["property", "exp"],
        +		["punctuation", ":"],
         		"\r\n\tNUM ",
         		["c", [
         			["delimiter", "{"],
        -			["bison-variable", ["$$"]], ["operator", "="],
        -			["function", "f"], ["punctuation", "("],
        -			["bison-variable", ["$3"]], ["punctuation", ","],
        -			["bison-variable", ["$4"]], ["punctuation", ")"], ["punctuation", ";"],
        -			["bison-variable", ["@$"]], ["punctuation", "."], "first_column ", ["operator", "="],
        -			["bison-variable", ["@1"]], ["punctuation", "."], "first_column", ["punctuation", ";"],
        -			["bison-variable", ["$result"]], ["operator", "="],
        -			["bison-variable", ["$left"]], ["operator", "+"],
        -			["bison-variable", ["$", ["punctuation", "<"], "itype", ["punctuation", ">"], "1"]], ["punctuation", ";"],
        +			["bison-variable", [
        +				"$$"
        +			]],
        +			["operator", "="],
        +			["function", "f"],
        +			["punctuation", "("],
        +			["bison-variable", [
        +				"$3"
        +			]],
        +			["punctuation", ","],
        +			["bison-variable", [
        +				"$4"
        +			]],
        +			["punctuation", ")"],
        +			["punctuation", ";"],
        +			["bison-variable", [
        +				"@$"
        +			]],
        +			["punctuation", "."],
        +			"first_column ",
        +			["operator", "="],
        +			["bison-variable", [
        +				"@1"
        +			]],
        +			["punctuation", "."],
        +			"first_column",
        +			["punctuation", ";"],
        +			["bison-variable", [
        +				"$result"
        +			]],
        +			["operator", "="],
        +			["bison-variable", [
        +				"$left"
        +			]],
        +			["operator", "+"],
        +			["bison-variable", [
        +				"$",
        +				["punctuation", "<"],
        +				"itype",
        +				["punctuation", ">"],
        +				"1"
        +			]],
        +			["punctuation", ";"],
         			["delimiter", "}"]
         		]],
         		["punctuation", "%%"]
        @@ -53,4 +97,4 @@ exp:
         
         ----------------------------------------------------
         
        -Checks for C inside Bison, along with special Bison variables.
        \ No newline at end of file
        +Checks for C inside Bison, along with special Bison variables.
        diff --git a/tests/languages/bison/char_feature.test b/tests/languages/bison/char_feature.test
        new file mode 100644
        index 0000000000..da4b00afc7
        --- /dev/null
        +++ b/tests/languages/bison/char_feature.test
        @@ -0,0 +1,9 @@
        +'+'
        +'\''
        +
        +----------------------------------------------------
        +
        +[
        +	["char", "'+'"],
        +	["char", "'\\''"]
        +]
        diff --git a/tests/languages/bison/number_feature.test b/tests/languages/bison/number_feature.test
        index ddbacff94b..3b8e397c61 100644
        --- a/tests/languages/bison/number_feature.test
        +++ b/tests/languages/bison/number_feature.test
        @@ -1,3 +1,9 @@
        +%%
        +42
        +0
        +0xBadFace
        +%%
        +
         42
         0
         0xBadFace
        @@ -5,6 +11,14 @@
         ----------------------------------------------------
         
         [
        +	["bison", [
        +		["punctuation", "%%"],
        +		["number", "42"],
        +		["number", "0"],
        +		["number", "0xBadFace"],
        +		["punctuation", "%%"]
        +	]],
        +
         	["number", "42"],
         	["number", "0"],
         	["number", "0xBadFace"]
        @@ -12,4 +26,4 @@
         
         ----------------------------------------------------
         
        -Checks for numbers.
        \ No newline at end of file
        +Checks for numbers.
        diff --git a/tests/languages/bison/string_feature.test b/tests/languages/bison/string_feature.test
        index 3f3f6c0d58..31289cde05 100644
        --- a/tests/languages/bison/string_feature.test
        +++ b/tests/languages/bison/string_feature.test
        @@ -1,6 +1,6 @@
         %%
        -foo: 'foo' "foo";
        -bar: '\'' "\"";
        +foo: "foo";
        +bar: "\"";
         %%
         
         ----------------------------------------------------
        @@ -8,14 +8,21 @@ bar: '\'' "\"";
         [
         	["bison", [
         		["punctuation", "%%"],
        -		["property", "foo"], ["punctuation", ":"],
        -		["string", "'foo'"], ["string", "\"foo\""], ["punctuation", ";"],
        -		["property", "bar"], ["punctuation", ":"],
        -		["string", "'\\''"], ["string", "\"\\\"\""], ["punctuation", ";"],
        +
        +		["property", "foo"],
        +		["punctuation", ":"],
        +		["string", "\"foo\""],
        +		["punctuation", ";"],
        +
        +		["property", "bar"],
        +		["punctuation", ":"],
        +		["string", "\"\\\"\""],
        +		["punctuation", ";"],
        +
         		["punctuation", "%%"]
         	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for strings.
        \ No newline at end of file
        +Checks for strings.
        diff --git a/tests/languages/bnf/definition_feature.test b/tests/languages/bnf/definition_feature.test
        new file mode 100644
        index 0000000000..bf2aeadcfa
        --- /dev/null
        +++ b/tests/languages/bnf/definition_feature.test
        @@ -0,0 +1,17 @@
        + ::= "a"
        +
        +----------------------------------------------------
        +
        +[
        +	["definition", [
        +		["punctuation", "<"],
        +		"foo",
        +		["punctuation", ">"]
        +	]],
        +	["operator", "::="],
        +	["string", "\"a\""]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for definitions.
        diff --git a/tests/languages/bnf/operator_feature.test b/tests/languages/bnf/operator_feature.test
        new file mode 100644
        index 0000000000..92a7bc911e
        --- /dev/null
        +++ b/tests/languages/bnf/operator_feature.test
        @@ -0,0 +1,28 @@
        +::= |
        +() [] {}
        +* + ?
        +...
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "::="],
        +	["operator", "|"],
        +
        +	["operator", "("],
        +	["operator", ")"],
        +	["operator", "["],
        +	["operator", "]"],
        +	["operator", "{"],
        +	["operator", "}"],
        +
        +	["operator", "*"],
        +	["operator", "+"],
        +	["operator", "?"],
        +
        +	["operator", "..."]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/bnf/rule_feature.test b/tests/languages/bnf/rule_feature.test
        new file mode 100644
        index 0000000000..40a0b8ef07
        --- /dev/null
        +++ b/tests/languages/bnf/rule_feature.test
        @@ -0,0 +1,21 @@
        +
        +<öäüß>
        +
        +----------------------------------------------------
        +
        +[
        +	["rule", [
        +		["punctuation", "<"],
        +		"foo-bar",
        +		["punctuation", ">"]
        +	]],
        +	["rule", [
        +		["punctuation", "<"],
        +		"öäüß",
        +		["punctuation", ">"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for rules.
        diff --git a/tests/languages/bnf/string_featrue.test b/tests/languages/bnf/string_featrue.test
        new file mode 100644
        index 0000000000..016e753f0d
        --- /dev/null
        +++ b/tests/languages/bnf/string_featrue.test
        @@ -0,0 +1,21 @@
        +""
        +''
        +"'"
        +'"'
        +"foo"
        +'bar|::=()'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"\""],
        +	["string", "''"],
        +	["string", "\"'\""],
        +	["string", "'\"'"],
        +	["string", "\"foo\""],
        +	["string", "'bar|::=()'"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/brightscript/boolean_feature.test b/tests/languages/brightscript/boolean_feature.test
        new file mode 100644
        index 0000000000..ca34f1814d
        --- /dev/null
        +++ b/tests/languages/brightscript/boolean_feature.test
        @@ -0,0 +1,13 @@
        +true
        +false
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "true"],
        +	["boolean", "false"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for booleans.
        diff --git a/tests/languages/brightscript/class-name_feature.test b/tests/languages/brightscript/class-name_feature.test
        new file mode 100644
        index 0000000000..4283c294a4
        --- /dev/null
        +++ b/tests/languages/brightscript/class-name_feature.test
        @@ -0,0 +1,31 @@
        +Function Foo(a as Object, b=1+1 as Integer) as Void
        +End Function
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "Function"],
        +	["function", "Foo"],
        +	["punctuation", "("],
        +	"a ",
        +	["keyword", "as"],
        +	["class-name", "Object"],
        +	["punctuation", ","],
        +	" b",
        +	["operator", "="],
        +	["number", "1"],
        +	["operator", "+"],
        +	["number", "1"],
        +	["keyword", "as"],
        +	["class-name", "Integer"],
        +	["punctuation", ")"],
        +	["keyword", "as"],
        +	["class-name", "Void"],
        +
        +	["keyword", "End"],
        +	["keyword", "Function"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for class names.
        diff --git a/tests/languages/brightscript/comment_feature.test b/tests/languages/brightscript/comment_feature.test
        new file mode 100644
        index 0000000000..59804b929d
        --- /dev/null
        +++ b/tests/languages/brightscript/comment_feature.test
        @@ -0,0 +1,13 @@
        +REM I'm a comment
        +' me too!
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "REM I'm a comment"],
        +	["comment", "' me too!"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        diff --git a/tests/languages/brightscript/constant_feature.test b/tests/languages/brightscript/constant_feature.test
        new file mode 100644
        index 0000000000..f381187282
        --- /dev/null
        +++ b/tests/languages/brightscript/constant_feature.test
        @@ -0,0 +1,11 @@
        +LINE_NUM
        +
        +----------------------------------------------------
        +
        +[
        +	["constant", "LINE_NUM"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for constants.
        diff --git a/tests/languages/brightscript/directive-statement_feature.test b/tests/languages/brightscript/directive-statement_feature.test
        new file mode 100644
        index 0000000000..4ababbbe7e
        --- /dev/null
        +++ b/tests/languages/brightscript/directive-statement_feature.test
        @@ -0,0 +1,67 @@
        +#const someFlag = true
        +#const anotherFlag = false
        +#const someOtherFlag = someFlag
        +
        +#if FeatureA
        +#else if FeatureB
        +#else
        +#end if
        +
        +#error Your device cannot support this feature.
        +
        +----------------------------------------------------
        +
        +[
        +	["directive-statement", [
        +		["directive", "#const"],
        +		["expression", [
        +			" someFlag ",
        +			["operator", "="],
        +			["boolean", "true"]
        +		]]
        +	]],
        +	["directive-statement", [
        +		["directive", "#const"],
        +		["expression", [
        +			" anotherFlag ",
        +			["operator", "="],
        +			["boolean", "false"]
        +		]]
        +	]],
        +	["directive-statement", [
        +		["directive", "#const"],
        +		["expression", [
        +			" someOtherFlag ",
        +			["operator", "="],
        +			" someFlag"
        +		]]
        +	]],
        +
        +	["directive-statement", [
        +		["directive", "#if"],
        +		["expression", [
        +			" FeatureA"
        +		]]
        +	]],
        +	["directive-statement", [
        +		["directive", "#else if"],
        +		["expression", [
        +			" FeatureB"
        +		]]
        +	]],
        +	["directive-statement", [
        +		["directive", "#else"]
        +	]],
        +	["directive-statement", [
        +		["directive", "#end if"]
        +	]],
        +
        +	["directive-statement", [
        +		["directive", "#error"],
        +		["error-message", " Your device cannot support this feature."]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for directives (conditional compilation).
        diff --git a/tests/languages/brightscript/keyword_feature.test b/tests/languages/brightscript/keyword_feature.test
        new file mode 100644
        index 0000000000..ac263b8d14
        --- /dev/null
        +++ b/tests/languages/brightscript/keyword_feature.test
        @@ -0,0 +1,50 @@
        +As;
        +Dim
        +Each
        +Else
        +Elseif
        +End
        +Exit
        +For
        +Function
        +Goto
        +If
        +In
        +Print
        +Return
        +Step
        +Stop
        +Sub
        +Then
        +To
        +While
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "As"],
        +	["punctuation", ";"],
        +	["keyword", "Dim"],
        +	["keyword", "Each"],
        +	["keyword", "Else"],
        +	["keyword", "Elseif"],
        +	["keyword", "End"],
        +	["keyword", "Exit"],
        +	["keyword", "For"],
        +	["keyword", "Function"],
        +	["keyword", "Goto"],
        +	["keyword", "If"],
        +	["keyword", "In"],
        +	["keyword", "Print"],
        +	["keyword", "Return"],
        +	["keyword", "Step"],
        +	["keyword", "Stop"],
        +	["keyword", "Sub"],
        +	["keyword", "Then"],
        +	["keyword", "To"],
        +	["keyword", "While"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for keywords.
        diff --git a/tests/languages/brightscript/number_feature.test b/tests/languages/brightscript/number_feature.test
        new file mode 100644
        index 0000000000..0e594d17ff
        --- /dev/null
        +++ b/tests/languages/brightscript/number_feature.test
        @@ -0,0 +1,29 @@
        +123
        +&hBAD
        +
        +1.23e-4
        +1.23D+45
        +
        +123%
        +123&
        +123!
        +123#
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "123"],
        +	["number", "&hBAD"],
        +
        +	["number", "1.23e-4"],
        +	["number", "1.23D+45"],
        +
        +	["number", "123%"],
        +	["number", "123&"],
        +	["number", "123!"],
        +	["number", "123#"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for numbers.
        diff --git a/tests/languages/brightscript/operator_feature.test b/tests/languages/brightscript/operator_feature.test
        new file mode 100644
        index 0000000000..389e9e1a0d
        --- /dev/null
        +++ b/tests/languages/brightscript/operator_feature.test
        @@ -0,0 +1,53 @@
        ++ - * / \ ^ ++ --
        ++= -= *= /= \=
        +
        +>> >>= << <<=
        +
        +< > <= >= <> =
        +
        +: ?
        +
        +Mod
        +And Or Not
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "\\"],
        +	["operator", "^"],
        +	["operator", "++"],
        +	["operator", "--"],
        +	["operator", "+="],
        +	["operator", "-="],
        +	["operator", "*="],
        +	["operator", "/="],
        +	["operator", "\\="],
        +
        +	["operator", ">>"],
        +	["operator", ">>="],
        +	["operator", "<<"],
        +	["operator", "<<="],
        +
        +	["operator", "<"],
        +	["operator", ">"],
        +	["operator", "<="],
        +	["operator", ">="],
        +	["operator", "<>"],
        +	["operator", "="],
        +
        +	["operator", ":"],
        +	["operator", "?"],
        +
        +	["operator", "Mod"],
        +	["operator", "And"],
        +	["operator", "Or"],
        +	["operator", "Not"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/brightscript/property_feature.test b/tests/languages/brightscript/property_feature.test
        new file mode 100644
        index 0000000000..a26a06300c
        --- /dev/null
        +++ b/tests/languages/brightscript/property_feature.test
        @@ -0,0 +1,35 @@
        +{
        +	foo: 4
        +	"bar": 5
        +}
        +
        +a = { foo: 5, bar: 6, "foo bar": 7 }
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "{"],
        +	["property", "foo"], ["operator", ":"], ["number", "4"],
        +	["property", "\"bar\""], ["operator", ":"], ["number", "5"],
        +	["punctuation", "}"],
        +
        +	"\r\n\r\na ",
        +	["operator", "="],
        +	["punctuation", "{"],
        +	["property", "foo"],
        +	["operator", ":"],
        +	["number", "5"],
        +	["punctuation", ","],
        +	["property", "bar"],
        +	["operator", ":"],
        +	["number", "6"],
        +	["punctuation", ","],
        +	["property", "\"foo bar\""],
        +	["operator", ":"],
        +	["number", "7"],
        +	["punctuation", "}"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for properties.
        diff --git a/tests/languages/clojure/operator_and_punctuation.test b/tests/languages/brightscript/punctuation_feature.test
        similarity index 51%
        rename from tests/languages/clojure/operator_and_punctuation.test
        rename to tests/languages/brightscript/punctuation_feature.test
        index e90acb631d..d23dc3c824 100644
        --- a/tests/languages/clojure/operator_and_punctuation.test
        +++ b/tests/languages/brightscript/punctuation_feature.test
        @@ -1,20 +1,20 @@
        -(::example [x y] (:kebab-case x y))
        +() [] {}
        +. , ;
         
         ----------------------------------------------------
         
         [
         	["punctuation", "("],
        -	["operator", "::example"],
        +	["punctuation", ")"],
         	["punctuation", "["],
        -	"x y",
         	["punctuation", "]"],
        -	["punctuation", "("],
        -	["operator", ":kebab-case"],
        -	" x y",
        -	["punctuation", ")"],
        -	["punctuation", ")"]
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", "."],
        +	["punctuation", ","],
        +	["punctuation", ";"]
         ]
         
         ----------------------------------------------------
         
        -Checks for operators and punctuation.
        \ No newline at end of file
        +Checks for punctuation.
        diff --git a/tests/languages/brightscript/string_feature.test b/tests/languages/brightscript/string_feature.test
        new file mode 100644
        index 0000000000..e76f4ca1e3
        --- /dev/null
        +++ b/tests/languages/brightscript/string_feature.test
        @@ -0,0 +1,13 @@
        +"foo bar"
        +""""
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"foo bar\""],
        +	["string", "\"\"\"\""]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/bro/function_feature.test b/tests/languages/bro/function_feature.test
        index a10d792acc..a46f9abfd3 100644
        --- a/tests/languages/bro/function_feature.test
        +++ b/tests/languages/bro/function_feature.test
        @@ -8,14 +8,14 @@ event foo::bar
         ----------------------------------------------------
         
         [
        -	["function", [["keyword", "function"], " foo"]],
        -	["function", [["keyword", "hook"], " foo"]],
        -	["function", [["keyword", "event"], " foo"]],
        -	["function", [["keyword", "function"], " foo::bar"]],
        -	["function", [["keyword", "hook"], " foo::bar"]],
        -	["function", [["keyword", "event"], " foo::bar"]]
        +	["keyword", "function"], ["function", "foo"],
        +	["keyword", "hook"], ["function", "foo"],
        +	["keyword", "event"], ["function", "foo"],
        +	["keyword", "function"], ["function", "foo::bar"],
        +	["keyword", "hook"], ["function", "foo::bar"],
        +	["keyword", "event"], ["function", "foo::bar"]
         ]
         
         ----------------------------------------------------
         
        -Checks for the function feature
        \ No newline at end of file
        +Checks for the function feature
        diff --git a/tests/languages/bro/variable_feature.test b/tests/languages/bro/variable_feature.test
        index daf51203ba..f84b66e4cb 100644
        --- a/tests/languages/bro/variable_feature.test
        +++ b/tests/languages/bro/variable_feature.test
        @@ -7,14 +7,23 @@ local baz = 66;
         ----------------------------------------------------
         
         [
        -	["variable", [["keyword", "local"], " foo"]],
        -	["variable", [["keyword", "global"], " foo"]],
        -	["variable", [["keyword", "local"], " bool"]],
        +	["keyword", "local"],
        +	" foo\r\n",
        +
        +	["keyword", "global"],
        +	" foo\r\n",
        +
        +	["keyword", "local"],
        +	["keyword", "bool"],
         	["operator", "="],
         	["boolean", "T"],
         	["punctuation", ";"],
        -	["constant", [["keyword", "const"], " bar"]],
        -	["variable", [["keyword", "local"], " baz"]],
        +
        +	["keyword", "const"],
        +	["constant", "bar"],
        +
        +	["keyword", "local"],
        +	" baz ",
         	["operator", "="],
         	["number", "66"],
         	["punctuation", ";"]
        @@ -22,4 +31,4 @@ local baz = 66;
         
         ----------------------------------------------------
         
        -Checks for the highlighting of variables
        \ No newline at end of file
        +Checks for the highlighting of variables
        diff --git a/tests/languages/bsl/comment_feature.test b/tests/languages/bsl/comment_feature.test
        new file mode 100644
        index 0000000000..a5ec83d1e7
        --- /dev/null
        +++ b/tests/languages/bsl/comment_feature.test
        @@ -0,0 +1,13 @@
        +//
        +// foobar
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "//"],
        +	["comment", "// foobar"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        \ No newline at end of file
        diff --git a/tests/languages/bsl/directive_feature.test b/tests/languages/bsl/directive_feature.test
        new file mode 100644
        index 0000000000..df0b91ee07
        --- /dev/null
        +++ b/tests/languages/bsl/directive_feature.test
        @@ -0,0 +1,13 @@
        +&Client
        +
        +#If Server Then
        +#EndIf
        +
        +----------------------------------------------------
        +
        +[
        +	["directive", "&Client"],
        +
        +	["directive", "#If Server Then"],
        +	["directive", "#EndIf"]
        +]
        diff --git a/tests/languages/bsl/keyword_feature.test b/tests/languages/bsl/keyword_feature.test
        new file mode 100644
        index 0000000000..6ae1cc431b
        --- /dev/null
        +++ b/tests/languages/bsl/keyword_feature.test
        @@ -0,0 +1,37 @@
        +пока для новый прервать попытка
        +исключение вызватьисключение иначе конецпопытки неопределено
        +функция перем возврат конецфункции
        +если иначеесли процедура конецпроцедуры тогда
        +знач экспорт конецесли
        +из каждого истина по
        +цикл конеццикла выполнить
        +while for new break try
        +except raise else endtry undefined 
        +function var return endfunction null
        +if elseif procedure endprocedure then
        +val export endif
        +in each true false to
        +do enddo execute
        +----------------------------------------------------
        +
        +[	
        +	["keyword", "пока"], ["keyword", "для"], ["keyword", "новый"], ["keyword", "прервать"], ["keyword", "попытка"],
        +	["keyword", "исключение"], ["keyword", "вызватьисключение"], ["keyword", "иначе"], ["keyword", "конецпопытки"], ["keyword", "неопределено"],
        +	["keyword", "функция"], ["keyword", "перем"], ["keyword", "возврат"], ["keyword", "конецфункции"],
        +	["keyword", "если"], ["keyword", "иначеесли"], ["keyword", "процедура"], ["keyword", "конецпроцедуры"], ["keyword", "тогда"],
        +	["keyword", "знач"], ["keyword", "экспорт"], ["keyword", "конецесли"],
        +	["keyword", "из"], ["keyword", "каждого"], ["keyword", "истина"], ["keyword", "по"],
        +	["keyword", "цикл"], ["keyword", "конеццикла"], ["keyword", "выполнить"],	
        +	
        +	["keyword", "while"], ["keyword", "for"], ["keyword", "new"], ["keyword", "break"], ["keyword", "try"],
        +	["keyword", "except"], ["keyword", "raise"], ["keyword", "else"], ["keyword", "endtry"], ["keyword", "undefined"],
        +	["keyword", "function"], ["keyword", "var"], ["keyword", "return"], ["keyword", "endfunction"], ["keyword", "null"],
        +	["keyword", "if"], ["keyword", "elseif"], ["keyword", "procedure"], ["keyword", "endprocedure"], ["keyword", "then"],
        +	["keyword", "val"], ["keyword", "export"], ["keyword", "endif"],
        +	["keyword", "in"], ["keyword", "each"], ["keyword", "true"], ["keyword", "false"], ["keyword", "to"],
        +	["keyword", "do"], ["keyword", "enddo"], ["keyword", "execute"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all keywords.
        \ No newline at end of file
        diff --git a/tests/languages/bsl/number_feature.test b/tests/languages/bsl/number_feature.test
        new file mode 100644
        index 0000000000..eab59e397c
        --- /dev/null
        +++ b/tests/languages/bsl/number_feature.test
        @@ -0,0 +1,13 @@
        +42
        +3.14159
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "42"],
        +	["number", "3.14159"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for decimal.
        \ No newline at end of file
        diff --git a/tests/languages/bsl/operator_feature.test b/tests/languages/bsl/operator_feature.test
        new file mode 100644
        index 0000000000..5a93288c29
        --- /dev/null
        +++ b/tests/languages/bsl/operator_feature.test
        @@ -0,0 +1,17 @@
        +< <= > >=
        ++ - * /
        +% =
        +and or not и или не
        +----------------------------------------------------
        +
        +[	
        +	["operator", "<"], ["operator", "<="], ["operator", ">"], ["operator", ">="],
        +	["operator", "+"], ["operator", "-"], ["operator", "*"], ["operator", "/"],
        +	["operator", "%"], ["operator", "="],	
        +	["operator", "and"], ["operator", "or"], ["operator", "not"], ["operator", "и"], ["operator", "или"], ["operator", "не"]
        +	
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        \ No newline at end of file
        diff --git a/tests/languages/bsl/punctuation_feature.test b/tests/languages/bsl/punctuation_feature.test
        new file mode 100644
        index 0000000000..9a6f11899f
        --- /dev/null
        +++ b/tests/languages/bsl/punctuation_feature.test
        @@ -0,0 +1,18 @@
        +(. .)
        +( ) [ ] : ; , .
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "(."],
        +	["punctuation", ".)"],
        +
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", ":"],
        +	["punctuation", ";"],
        +	["punctuation", ","],
        +	["punctuation", "."]
        +]
        diff --git a/tests/languages/bsl/string_feature.test b/tests/languages/bsl/string_feature.test
        new file mode 100644
        index 0000000000..abb8b2dba4
        --- /dev/null
        +++ b/tests/languages/bsl/string_feature.test
        @@ -0,0 +1,19 @@
        +""
        +"fo"
        +
        +''
        +'foo'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"\""],
        +	["string", "\"fo\""],
        +
        +	["string", "''"],
        +	["string", "'foo'"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings and chars.
        diff --git a/tests/languages/c/char_feature.test b/tests/languages/c/char_feature.test
        new file mode 100644
        index 0000000000..aea75234eb
        --- /dev/null
        +++ b/tests/languages/c/char_feature.test
        @@ -0,0 +1,35 @@
        +'a'
        +'\n'
        +'\13'
        +'🍌'
        +'ab'
        +
        +u'a'
        +u'¢'
        +u'猫'
        +U'猫'
        +L'猫'
        +
        +'\1\2\3\4'
        +'\xFF'
        +u'\U0001f34c'
        +
        +----------------------------------------------------
        +
        +[
        +	["char", "'a'"],
        +	["char", "'\\n'"],
        +	["char", "'\\13'"],
        +	["char", "'🍌'"],
        +	["char", "'ab'"],
        +
        +	"\r\n\r\nu", ["char", "'a'"],
        +	"\r\nu", ["char", "'¢'"],
        +	"\r\nu", ["char", "'猫'"],
        +	"\r\nU", ["char", "'猫'"],
        +	"\r\nL", ["char", "'猫'"],
        +
        +	["char", "'\\1\\2\\3\\4'"],
        +	["char", "'\\xFF'"],
        +	"\r\nu", ["char", "'\\U0001f34c'"]
        +]
        diff --git a/tests/languages/c/class-name_feature.test b/tests/languages/c/class-name_feature.test
        new file mode 100644
        index 0000000000..664611624b
        --- /dev/null
        +++ b/tests/languages/c/class-name_feature.test
        @@ -0,0 +1,59 @@
        +struct foo;
        +enum bar;
        +
        +struct foo var;
        +struct __attribute__ ((aligned (8))) S { short f[3]; };
        +
        +// by name
        +uint32_t foo;
        +static dtrace_helptrace_t *bar;
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "struct"],
        +	["class-name", "foo"],
        +	["punctuation", ";"],
        +	["keyword", "enum"],
        +	["class-name", "bar"],
        +	["punctuation", ";"],
        +
        +	["keyword", "struct"],
        +	["class-name", "foo"],
        +	" var",
        +	["punctuation", ";"],
        +	["keyword", "struct"],
        +	["keyword", "__attribute__"],
        +	["punctuation", "("],
        +	["punctuation", "("],
        +	["function", "aligned"],
        +	["punctuation", "("],
        +	["number", "8"],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +	["class-name", "S"],
        +	["punctuation", "{"],
        +	["keyword", "short"],
        +	" f",
        +	["punctuation", "["],
        +	["number", "3"],
        +	["punctuation", "]"],
        +	["punctuation", ";"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["comment", "// by name"],
        +	["class-name", "uint32_t"],
        +	" foo",
        +	["punctuation", ";"],
        +	["keyword", "static"],
        +	["class-name", "dtrace_helptrace_t"],
        +	["operator", "*"],
        +	"bar",
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for structs and enums.
        \ No newline at end of file
        diff --git a/tests/languages/c/comment_feature.test b/tests/languages/c/comment_feature.test
        new file mode 100644
        index 0000000000..6370e5daba
        --- /dev/null
        +++ b/tests/languages/c/comment_feature.test
        @@ -0,0 +1,26 @@
        +//
        +// comment
        +// the comment \
        +   continues!
        +
        +/**/
        +/*
        + * comment
        + */
        +
        +/* open-ended comment
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "//"],
        +	["comment", "// comment"],
        +	["comment", "// the comment \\\r\n   continues!"],
        +	["comment", "/**/"],
        +	["comment", "/*\r\n * comment\r\n */"],
        +	["comment", "/* open-ended comment"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        diff --git a/tests/languages/c/function_feature.test b/tests/languages/c/function_feature.test
        new file mode 100644
        index 0000000000..4f141a9a09
        --- /dev/null
        +++ b/tests/languages/c/function_feature.test
        @@ -0,0 +1,24 @@
        +foo(void);
        +bar
        +(1, 2);
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "foo"],
        +	["punctuation", "("],
        +	["keyword", "void"],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["function", "bar"],
        +	["punctuation", "("],
        +	["number", "1"],
        +	["punctuation", ","],
        +	["number", "2"],
        +	["punctuation", ")"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for functions.
        diff --git a/tests/languages/c/keyword_feature.test b/tests/languages/c/keyword_feature.test
        index feb9ff9377..0e00a72944 100644
        --- a/tests/languages/c/keyword_feature.test
        +++ b/tests/languages/c/keyword_feature.test
        @@ -1,29 +1,35 @@
        +__attribute__
         _Alignas _Alignof _Atomic _Bool
         _Complex _Generic _Imaginary
         _Noreturn _Static_assert _Thread_local
         asm typeof inline auto break
         case char const continue default
        -do double else enum extern
        +do double else enum;
        +extern
         float for goto if int
         long register return short signed
        -sizeof static struct switch typedef
        +sizeof static struct;
        +switch typedef
         union unsigned void volatile while
         
         ----------------------------------------------------
         
         [
        +	["keyword", "__attribute__"],
         	["keyword", "_Alignas"], ["keyword", "_Alignof"], ["keyword", "_Atomic"], ["keyword", "_Bool"],
        -    ["keyword", "_Complex"], ["keyword", "_Generic"], ["keyword", "_Imaginary"],
        -    ["keyword", "_Noreturn"], ["keyword", "_Static_assert"], ["keyword", "_Thread_local"],
        +	["keyword", "_Complex"], ["keyword", "_Generic"], ["keyword", "_Imaginary"],
        +	["keyword", "_Noreturn"], ["keyword", "_Static_assert"], ["keyword", "_Thread_local"],
         	["keyword", "asm"], ["keyword", "typeof"], ["keyword", "inline"], ["keyword", "auto"], ["keyword", "break"],
         	["keyword", "case"], ["keyword", "char"], ["keyword", "const"], ["keyword", "continue"], ["keyword", "default"],
        -	["keyword", "do"], ["keyword", "double"], ["keyword", "else"], ["keyword", "enum"], ["keyword", "extern"],
        +	["keyword", "do"], ["keyword", "double"], ["keyword", "else"], ["keyword", "enum"], ["punctuation", ";"],
        +	["keyword", "extern"],
         	["keyword", "float"], ["keyword", "for"], ["keyword", "goto"], ["keyword", "if"], ["keyword", "int"],
         	["keyword", "long"], ["keyword", "register"], ["keyword", "return"], ["keyword", "short"], ["keyword", "signed"],
        -	["keyword", "sizeof"], ["keyword", "static"], ["keyword", "struct"], ["keyword", "switch"], ["keyword", "typedef"],
        +	["keyword", "sizeof"], ["keyword", "static"], ["keyword", "struct"], ["punctuation", ";"],
        +	["keyword", "switch"], ["keyword", "typedef"],
         	["keyword", "union"], ["keyword", "unsigned"], ["keyword", "void"], ["keyword", "volatile"], ["keyword", "while"]
         ]
         
         ----------------------------------------------------
         
        -Checks for all keywords.
        \ No newline at end of file
        +Checks for all keywords.
        diff --git a/tests/languages/c/macro_feature.test b/tests/languages/c/macro_feature.test
        index 6e65d9d590..5c20083342 100644
        --- a/tests/languages/c/macro_feature.test
        +++ b/tests/languages/c/macro_feature.test
        @@ -1,5 +1,6 @@
         # include 
        -  #define PG_locked 0
        +# include "stdio.h"
        +	#define PG_locked 0
         
         #defined
         #elif
        @@ -16,28 +17,184 @@
         #undef
         #using
         
        +#somethingunknown
        +
        +#define FOO /*
        + comment
        +*/ 1
        +
        +#define FOO 1 // trailing comment
        +#define FOO (1 + 1)
        +
        +#define MAX(a, b) \
        +	((a) < (b) ? (b) : (a))
        +
        +#define BAR(s) no_##s
        +
         ----------------------------------------------------
         
         [
         	["macro", [
        -		"# ", ["directive", "include"],
        +		["directive-hash", "#"],
        +		["directive", "include"],
         		["string", ""]
         	]],
        -	["macro", ["#", ["directive", "define"], " PG_locked 0"]],
        -	["macro", ["#", ["directive", "defined"]]],
        -	["macro", ["#", ["directive", "elif"]]],
        -	["macro", ["#", ["directive", "else"]]],
        -    ["macro", ["#", ["directive", "endif"]]],
        -    ["macro", ["#", ["directive", "error"]]],
        -    ["macro", ["#", ["directive", "ifdef"]]],
        -    ["macro", ["#", ["directive", "ifndef"]]],
        -    ["macro", ["#", ["directive", "if"]]],
        -    ["macro", ["#", ["directive", "import"]]],
        -    ["macro", ["#", ["directive", "include"]]],
        -    ["macro", ["#", ["directive", "line"]]],
        -    ["macro", ["#", ["directive", "pragma"]]],
        -    ["macro", ["#", ["directive", "undef"]]],
        -    ["macro", ["#", ["directive", "using"]]]
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "include"],
        +		["string", "\"stdio.h\""]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "define"],
        +		["macro-name", "PG_locked"],
        +		["expression", [
        +			["number", "0"]
        +		]]
        +	]],
        +
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "defined"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "elif"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "else"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "endif"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "error"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "ifdef"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "ifndef"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "if"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "import"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "include"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "line"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "pragma"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "undef"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "using"]
        +	]],
        +
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "somethingunknown"]
        +	]],
        +
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "define"],
        +		["macro-name", "FOO"],
        +		["comment", "/*\r\n comment\r\n*/"],
        +		["expression", [
        +			["number", "1"]
        +		]]
        +	]],
        +
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "define"],
        +		["macro-name", "FOO"],
        +		["expression", [
        +			["number", "1"]
        +		]],
        +		["comment", "// trailing comment"]
        +	]],
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "define"],
        +		["macro-name", "FOO"],
        +		["expression", [
        +			["punctuation", "("],
        +			["number", "1"],
        +			["operator", "+"],
        +			["number", "1"],
        +			["punctuation", ")"]
        +		]]
        +	]],
        +
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "define"],
        +		["macro-name", "MAX"],
        +		["expression", [
        +			["punctuation", "("],
        +			"a",
        +			["punctuation", ","],
        +			" b",
        +			["punctuation", ")"]
        +		]],
        +		["punctuation", "\\"],
        +		["expression", [
        +			["punctuation", "("],
        +			["punctuation", "("],
        +			"a",
        +			["punctuation", ")"],
        +			["operator", "<"],
        +			["punctuation", "("],
        +			"b",
        +			["punctuation", ")"],
        +			["operator", "?"],
        +			["punctuation", "("],
        +			"b",
        +			["punctuation", ")"],
        +			["operator", ":"],
        +			["punctuation", "("],
        +			"a",
        +			["punctuation", ")"],
        +			["punctuation", ")"]
        +		]]
        +	]],
        +
        +	["macro", [
        +		["directive-hash", "#"],
        +		["directive", "define"],
        +		["macro-name", "BAR"],
        +		["expression", [
        +			["punctuation", "("],
        +			"s",
        +			["punctuation", ")"],
        +			" no_"
        +		]],
        +		["punctuation", "##"],
        +		["expression", [
        +			"s"
        +		]]
        +	]]
         ]
         
         ----------------------------------------------------
        diff --git a/tests/languages/c/number_feature.test b/tests/languages/c/number_feature.test
        index 0542683404..c2975870c6 100644
        --- a/tests/languages/c/number_feature.test
        +++ b/tests/languages/c/number_feature.test
        @@ -5,6 +5,9 @@
         0.4e+2
         0xbabe
         0xBABE
        +0x1.2
        +0x0.3p-3
        +0x0.3p4L
         42f
         42F
         42u
        @@ -22,6 +25,9 @@
         	["number", "0.4e+2"],
         	["number", "0xbabe"],
         	["number", "0xBABE"],
        +	["number", "0x1.2"],
        +	["number", "0x0.3p-3"],
        +	["number", "0x0.3p4L"],
         	["number", "42f"],
         	["number", "42F"],
         	["number", "42u"],
        @@ -32,4 +38,4 @@
         
         ----------------------------------------------------
         
        -Checks for decimal numbers and hexadecimal numbers.
        \ No newline at end of file
        +Checks for decimal numbers and hexadecimal numbers.
        diff --git a/tests/languages/c/operator_feature.test b/tests/languages/c/operator_feature.test
        index fdcfb19e99..95cef64674 100644
        --- a/tests/languages/c/operator_feature.test
        +++ b/tests/languages/c/operator_feature.test
        @@ -1,19 +1,61 @@
        -+ - ++ -- ! !=
        -< << <= <<=
        -> >> >= >>=
        --> == ^ ~ %
        -& && | || ? * /
        ++ - * / % -- ++
        +>> <<
        +~ & | ^
        ++= -= *= /= %= >>= <<= &= |= ^=
        +! && ||
        +-> ::
        +? :
        += == != < > <= >=
         
         ----------------------------------------------------
         
         [
        -	["operator", "+"], ["operator", "-"], ["operator", "++"], ["operator", "--"], ["operator", "!"], ["operator", "!="],
        -	["operator", "<"], ["operator", "<<"], ["operator", "<="], ["operator", "<<="],
        -	["operator", ">"], ["operator", ">>"], ["operator", ">="], ["operator", ">>="],
        -	["operator", "->"], ["operator", "=="], ["operator", "^"], ["operator", "~"], ["operator", "%"],
        -	["operator", "&"], ["operator", "&&"], ["operator", "|"], ["operator", "||"], ["operator", "?"], ["operator", "*"], ["operator", "/"]
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "%"],
        +	["operator", "--"],
        +	["operator", "++"],
        +
        +	["operator", ">>"],
        +	["operator", "<<"],
        +
        +	["operator", "~"],
        +	["operator", "&"],
        +	["operator", "|"],
        +	["operator", "^"],
        +
        +	["operator", "+="],
        +	["operator", "-="],
        +	["operator", "*="],
        +	["operator", "/="],
        +	["operator", "%="],
        +	["operator", ">>="],
        +	["operator", "<<="],
        +	["operator", "&="],
        +	["operator", "|="],
        +	["operator", "^="],
        +
        +	["operator", "!"],
        +	["operator", "&&"],
        +	["operator", "||"],
        +
        +	["operator", "->"],
        +	["operator", "::"],
        +
        +	["operator", "?"],
        +	["operator", ":"],
        +
        +	["operator", "="],
        +	["operator", "=="],
        +	["operator", "!="],
        +	["operator", "<"],
        +	["operator", ">"],
        +	["operator", "<="],
        +	["operator", ">="]
         ]
         
         ----------------------------------------------------
         
        -Checks for all operators
        \ No newline at end of file
        +Checks for all operators
        diff --git a/tests/languages/c/string_feature.test b/tests/languages/c/string_feature.test
        new file mode 100644
        index 0000000000..a1e7ec4d3f
        --- /dev/null
        +++ b/tests/languages/c/string_feature.test
        @@ -0,0 +1,34 @@
        +""
        +"foo"
        +"\x12"
        +"3"
        +
        +"\xff""f"
        +
        +"foo\
        +bar"
        +
        +"a猫🍌"
        +u8"a猫🍌"
        +u"a猫🍌"
        +U"a猫🍌"
        +L"a猫🍌"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"\""],
        +	["string", "\"foo\""],
        +	["string", "\"\\x12\""],
        +	["string", "\"3\""],
        +
        +	["string", "\"\\xff\""], ["string", "\"f\""],
        +
        +	["string", "\"foo\\\r\nbar\""],
        +
        +	["string", "\"a猫🍌\""],
        +	"\r\nu8", ["string", "\"a猫🍌\""],
        +	"\r\nu", ["string", "\"a猫🍌\""],
        +	"\r\nU", ["string", "\"a猫🍌\""],
        +	"\r\nL", ["string", "\"a猫🍌\""]
        +]
        diff --git a/tests/languages/cfscript/comment_feature.test b/tests/languages/cfscript/comment_feature.test
        new file mode 100644
        index 0000000000..b6ae720792
        --- /dev/null
        +++ b/tests/languages/cfscript/comment_feature.test
        @@ -0,0 +1,23 @@
        +// foobar
        +/**/
        +/* foo
        +bar */
        +/**
        +* @product.hint
        +*/
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// foobar"],
        +	["comment", ["/**/"]],
        +	["comment", ["/* foo\r\nbar */"]],
        +	["comment", [
        +		"/**\r\n*", ["annotation", " @product.hint"],
        +		"\r\n*/"
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for single-line and multi-line comments along with annotation
        diff --git a/tests/languages/cfscript/function-variable_feature.test b/tests/languages/cfscript/function-variable_feature.test
        new file mode 100644
        index 0000000000..2d13bfa1bc
        --- /dev/null
        +++ b/tests/languages/cfscript/function-variable_feature.test
        @@ -0,0 +1,137 @@
        +foo = function (  ) {}
        +foo = function ( x, y) {}
        +{foo: function () {}}
        +fooBar = x => x
        +fooBar = ( x, y ) => x
        +ಠ_ಠ = () => {}
        +d = function Example({ props: { a: _A, b} } = Props) {}
        +f = function (x = fun()) {}
        +l = (x = fun(), y) => {}
        +a = function () {}, b = () => {}
        +
        +----------------------------------------------------
        +
        +[
        +	["function-variable", "foo"],
        +	["operator", "="],
        +	["keyword", "function"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["function-variable", "foo"],
        +	["operator", "="],
        +	["keyword", "function"],
        +	["punctuation", "("],
        +	" x",
        +	["punctuation", ","],
        +	" y",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["punctuation", "{"],
        +	["function-variable", "foo"],
        +	["operator", ":"],
        +	["keyword", "function"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", "}"],
        +
        +	["function-variable", "fooBar"],
        +	["operator", "="],
        +	" x ",
        +	["operator", "=>"],
        +	" x\r\n",
        +
        +	["function-variable", "fooBar"],
        +	["operator", "="],
        +	["punctuation", "("],
        +	" x",
        +	["punctuation", ","],
        +	" y ",
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +	" x\r\n",
        +
        +	["function-variable", "ಠ_ಠ"],
        +	["operator", "="],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["function-variable", "d"],
        +	["operator", "="],
        +	["keyword", "function"],
        +	["function", "Example"],
        +	["punctuation", "("],
        +	["punctuation", "{"],
        +	" props",
        +	["operator", ":"],
        +	["punctuation", "{"],
        +	" a",
        +	["operator", ":"],
        +	" _A",
        +	["punctuation", ","],
        +	" b",
        +	["punctuation", "}"],
        +	["punctuation", "}"],
        +	["operator", "="],
        +	" Props",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["function-variable", "f"],
        +	["operator", "="],
        +	["keyword", "function"],
        +	["punctuation", "("],
        +	"x ",
        +	["operator", "="],
        +	["function", "fun"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["function-variable", "l"],
        +	["operator", "="],
        +	["punctuation", "("],
        +	"x ",
        +	["operator", "="],
        +	["function", "fun"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ","],
        +	" y",
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["function-variable", "a"],
        +	["operator", "="],
        +	["keyword", "function"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ","],
        +	["function-variable", "b"],
        +	["operator", "="],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for variables obviously containing functions.
        diff --git a/tests/languages/cfscript/keyword_feature.test b/tests/languages/cfscript/keyword_feature.test
        new file mode 100644
        index 0000000000..0791a3bf9d
        --- /dev/null
        +++ b/tests/languages/cfscript/keyword_feature.test
        @@ -0,0 +1,71 @@
        +abstract
        +break
        +catch
        +component
        +continue
        +default
        +do
        +else
        +extends
        +final
        +finally
        +for
        +function
        +if
        +in
        +include
        +package
        +private
        +property
        +public
        +remote
        +required
        +rethrow
        +return
        +static
        +switch
        +throw
        +try
        +var
        +while
        +xml
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "abstract"],
        +	["keyword", "break"],
        +	["keyword", "catch"],
        +	["keyword", "component"],
        +	["keyword", "continue"],
        +	["keyword", "default"],
        +	["keyword", "do"],
        +	["keyword", "else"],
        +	["keyword", "extends"],
        +	["keyword", "final"],
        +	["keyword", "finally"],
        +	["keyword", "for"],
        +	["keyword", "function"],
        +	["keyword", "if"],
        +	["keyword", "in"],
        +	["keyword", "include"],
        +	["keyword", "package"],
        +	["keyword", "private"],
        +	["keyword", "property"],
        +	["keyword", "public"],
        +	["keyword", "remote"],
        +	["keyword", "required"],
        +	["keyword", "rethrow"],
        +	["keyword", "return"],
        +	["keyword", "static"],
        +	["keyword", "switch"],
        +	["keyword", "throw"],
        +	["keyword", "try"],
        +	["keyword", "var"],
        +	["keyword", "while"],
        +	["keyword", "xml"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all keywords.
        diff --git a/tests/languages/cfscript/operator_feature.test b/tests/languages/cfscript/operator_feature.test
        new file mode 100644
        index 0000000000..54fe40ae53
        --- /dev/null
        +++ b/tests/languages/cfscript/operator_feature.test
        @@ -0,0 +1,71 @@
        ++ ++ +=
        +- -- -=
        +! !=
        +< <=
        +> >=
        += ==
        +=== !==
        +& && &=
        +| ||
        +: ::
        +? ?. ?:
        +^ ^=
        +* *=
        +/ /=
        +% %=
        +
        +and
        +contains
        +eq
        +equal
        +eqv
        +gt
        +gte
        +imp
        +is
        +lt
        +lte
        +mod
        +not
        +or
        +xor
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"], ["operator", "++"], ["operator", "+="],
        +	["operator", "-"], ["operator", "--"], ["operator", "-="],
        +	["operator", "!"], ["operator", "!="],
        +	["operator", "<"], ["operator", "<="],
        +	["operator", ">"], ["operator", ">="],
        +	["operator", "="], ["operator", "=="],
        +	["operator", "==="], ["operator", "!=="],
        +	["operator", "&"], ["operator", "&&"], ["operator", "&="],
        +	["operator", "|"], ["operator", "||"],
        +	["operator", ":"], ["operator", "::"],
        +	["operator", "?"], ["operator", "?."], ["operator", "?:"],
        +	["operator", "^"], ["operator", "^="],
        +	["operator", "*"], ["operator", "*="],
        +	["operator", "/"], ["operator", "/="],
        +	["operator", "%"], ["operator", "%="],
        +
        +	["operator", "and"],
        +	["operator", "contains"],
        +	["operator", "eq"],
        +	["operator", "equal"],
        +	["operator", "eqv"],
        +	["operator", "gt"],
        +	["operator", "gte"],
        +	["operator", "imp"],
        +	["operator", "is"],
        +	["operator", "lt"],
        +	["operator", "lte"],
        +	["operator", "mod"],
        +	["operator", "not"],
        +	["operator", "or"],
        +	["operator", "xor"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all operators.
        diff --git a/tests/languages/cfscript/scope_feature.test b/tests/languages/cfscript/scope_feature.test
        new file mode 100644
        index 0000000000..70dfb96d8a
        --- /dev/null
        +++ b/tests/languages/cfscript/scope_feature.test
        @@ -0,0 +1,29 @@
        +application
        +arguments
        +cgi
        +client
        +cookie
        +local
        +session
        +super
        +this
        +variables
        +
        +----------------------------------------------------
        +
        +[
        +	["scope", "application"],
        +	["scope", "arguments"],
        +	["scope", "cgi"],
        +	["scope", "client"],
        +	["scope", "cookie"],
        +	["scope", "local"],
        +	["scope", "session"],
        +	["scope", "super"],
        +	["scope", "this"],
        +	["scope", "variables"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all scopes.
        diff --git a/tests/languages/cfscript/type_feature.test b/tests/languages/cfscript/type_feature.test
        new file mode 100644
        index 0000000000..120ab7b911
        --- /dev/null
        +++ b/tests/languages/cfscript/type_feature.test
        @@ -0,0 +1,35 @@
        +any
        +array
        +binary
        +boolean
        +date
        +guid
        +numeric
        +query
        +string
        +struct
        +uuid
        +void
        +xml=
        +
        +----------------------------------------------------
        +
        +[
        +	["type", "any"],
        +	["type", "array"],
        +	["type", "binary"],
        +	["type", "boolean"],
        +	["type", "date"],
        +	["type", "guid"],
        +	["type", "numeric"],
        +	["type", "query"],
        +	["type", "string"],
        +	["type", "struct"],
        +	["type", "uuid"],
        +	["type", "void"],
        +	["type", "xml"], ["operator", "="]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all types.
        diff --git a/tests/languages/chaiscript/boolean_feature.test b/tests/languages/chaiscript/boolean_feature.test
        new file mode 100644
        index 0000000000..9f981c0d79
        --- /dev/null
        +++ b/tests/languages/chaiscript/boolean_feature.test
        @@ -0,0 +1,9 @@
        +true
        +false
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "true"],
        +	["boolean", "false"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/chaiscript/comment_feature.test b/tests/languages/chaiscript/comment_feature.test
        new file mode 100644
        index 0000000000..992ea69656
        --- /dev/null
        +++ b/tests/languages/chaiscript/comment_feature.test
        @@ -0,0 +1,16 @@
        +// comment
        +/*
        + comment
        +*/
        +
        +/*
        + comment
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// comment"],
        +	["comment", "/*\r\n comment\r\n*/"],
        +
        +	["comment", "/*\r\n comment"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/chaiscript/function_feature.test b/tests/languages/chaiscript/function_feature.test
        new file mode 100644
        index 0000000000..9f8b389dc6
        --- /dev/null
        +++ b/tests/languages/chaiscript/function_feature.test
        @@ -0,0 +1,190 @@
        +attr Rectangle::height
        +attr Rectangle::width
        +def Rectangle::Rectangle() { this.height = 10; this.width = 20 }
        +def Rectangle::area() { this.height * this.width }
        +var rect = Rectangle()
        +rect.height = 30
        +print(rect.area())
        +
        +class Rectangle {
        +  attr height
        +  attr width
        +  def Rectangle() { this.height = 10; this.width = 20 }
        +  def area() { this.height * this.width }
        +}
        +var rect = Rectangle()
        +rect.height = 30
        +print(rect.area())
        +
        +def update(dt) {
        +  x = x + 20.0f * dt
        +}
        +
        +def foo(int x, Vector y) {}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "attr"],
        +	["class-name", "Rectangle"],
        +	["operator", "::"],
        +	"height\r\n",
        +
        +	["keyword", "attr"],
        +	["class-name", "Rectangle"],
        +	["operator", "::"],
        +	"width\r\n",
        +
        +	["keyword", "def"],
        +	["class-name", "Rectangle"],
        +	["operator", "::"],
        +	["function", "Rectangle"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"height ",
        +	["operator", "="],
        +	["number", "10"],
        +	["punctuation", ";"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"width ",
        +	["operator", "="],
        +	["number", "20"],
        +	["punctuation", "}"],
        +
        +	["keyword", "def"],
        +	["class-name", "Rectangle"],
        +	["operator", "::"],
        +	["function", "area"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"height ",
        +	["operator", "*"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"width ",
        +	["punctuation", "}"],
        +
        +	["keyword", "var"],
        +	" rect ",
        +	["operator", "="],
        +	["function", "Rectangle"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	"\r\nrect",
        +	["punctuation", "."],
        +	"height ",
        +	["operator", "="],
        +	["number", "30"],
        +
        +	["function", "print"],
        +	["punctuation", "("],
        +	"rect",
        +	["punctuation", "."],
        +	["function", "area"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +
        +	["keyword", "class"],
        +	["class-name", "Rectangle"],
        +	["punctuation", "{"],
        +
        +	["keyword", "attr"],
        +	" height\r\n  ",
        +
        +	["keyword", "attr"],
        +	" width\r\n  ",
        +
        +	["keyword", "def"],
        +	["function", "Rectangle"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"height ",
        +	["operator", "="],
        +	["number", "10"],
        +	["punctuation", ";"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"width ",
        +	["operator", "="],
        +	["number", "20"],
        +	["punctuation", "}"],
        +
        +	["keyword", "def"],
        +	["function", "area"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"height ",
        +	["operator", "*"],
        +	["keyword", "this"],
        +	["punctuation", "."],
        +	"width ",
        +	["punctuation", "}"],
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "var"],
        +	" rect ",
        +	["operator", "="],
        +	["function", "Rectangle"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	"\r\nrect",
        +	["punctuation", "."],
        +	"height ",
        +	["operator", "="],
        +	["number", "30"],
        +
        +	["function", "print"],
        +	["punctuation", "("],
        +	"rect",
        +	["punctuation", "."],
        +	["function", "area"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +
        +	["keyword", "def"],
        +	["function", "update"],
        +	["punctuation", "("],
        +	"dt",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +
        +	"\r\n  x ",
        +	["operator", "="],
        +	" x ",
        +	["operator", "+"],
        +	["number", "20.0f"],
        +	["operator", "*"],
        +	" dt\r\n",
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "def"],
        +	["function", "foo"],
        +	["punctuation", "("],
        +	["parameter-type", "int"],
        +	" x",
        +	["punctuation", ","],
        +	["parameter-type", "Vector"],
        +	" y",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/chaiscript/keyword_feature.test b/tests/languages/chaiscript/keyword_feature.test
        new file mode 100644
        index 0000000000..f317447617
        --- /dev/null
        +++ b/tests/languages/chaiscript/keyword_feature.test
        @@ -0,0 +1,47 @@
        +attr;
        +auto;
        +break;
        +case;
        +catch;
        +class;
        +continue;
        +def;
        +default;
        +else;
        +finally;
        +for;
        +fun;
        +global;
        +if;
        +return;
        +switch;
        +this;
        +try;
        +var;
        +while;
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "attr"], ["punctuation", ";"],
        +	["keyword", "auto"], ["punctuation", ";"],
        +	["keyword", "break"], ["punctuation", ";"],
        +	["keyword", "case"], ["punctuation", ";"],
        +	["keyword", "catch"], ["punctuation", ";"],
        +	["keyword", "class"], ["punctuation", ";"],
        +	["keyword", "continue"], ["punctuation", ";"],
        +	["keyword", "def"], ["punctuation", ";"],
        +	["keyword", "default"], ["punctuation", ";"],
        +	["keyword", "else"], ["punctuation", ";"],
        +	["keyword", "finally"], ["punctuation", ";"],
        +	["keyword", "for"], ["punctuation", ";"],
        +	["keyword", "fun"], ["punctuation", ";"],
        +	["keyword", "global"], ["punctuation", ";"],
        +	["keyword", "if"], ["punctuation", ";"],
        +	["keyword", "return"], ["punctuation", ";"],
        +	["keyword", "switch"], ["punctuation", ";"],
        +	["keyword", "this"], ["punctuation", ";"],
        +	["keyword", "try"], ["punctuation", ";"],
        +	["keyword", "var"], ["punctuation", ";"],
        +	["keyword", "while"], ["punctuation", ";"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/chaiscript/number_feature.test b/tests/languages/chaiscript/number_feature.test
        new file mode 100644
        index 0000000000..22798cad88
        --- /dev/null
        +++ b/tests/languages/chaiscript/number_feature.test
        @@ -0,0 +1,19 @@
        +Infinity
        +NaN
        +
        +1e-5
        +35.5E+8
        +0.01e19
        +1.2f
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "Infinity"],
        +	["number", "NaN"],
        +
        +	["number", "1e-5"],
        +	["number", "35.5E+8"],
        +	["number", "0.01e19"],
        +	["number", "1.2f"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/chaiscript/operator_feature.test b/tests/languages/chaiscript/operator_feature.test
        new file mode 100644
        index 0000000000..063d0a94e3
        --- /dev/null
        +++ b/tests/languages/chaiscript/operator_feature.test
        @@ -0,0 +1,74 @@
        +?
        +|| &&
        +| ^ &
        +== !=
        +< <= > >=
        +<< >>
        ++ -
        +* / %
        +++ -- - + ! ~
        +
        += :=
        ++= -= *= /= %= <<= >>= &= ^= |=
        +: ::
        +
        +// operator references
        +`+`
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "?"],
        +
        +	["operator", "||"],
        +	["operator", "&&"],
        +
        +	["operator", "|"],
        +	["operator", "^"],
        +	["operator", "&"],
        +
        +	["operator", "=="],
        +	["operator", "!="],
        +
        +	["operator", "<"],
        +	["operator", "<="],
        +	["operator", ">"],
        +	["operator", ">="],
        +
        +	["operator", "<<"],
        +	["operator", ">>"],
        +
        +	["operator", "+"],
        +	["operator", "-"],
        +
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "%"],
        +
        +	["operator", "++"],
        +	["operator", "--"],
        +	["operator", "-"],
        +	["operator", "+"],
        +	["operator", "!"],
        +	["operator", "~"],
        +
        +	["operator", "="],
        +	["operator", ":="],
        +
        +	["operator", "+="],
        +	["operator", "-="],
        +	["operator", "*="],
        +	["operator", "/="],
        +	["operator", "%="],
        +	["operator", "<<="],
        +	["operator", ">>="],
        +	["operator", "&="],
        +	["operator", "^="],
        +	["operator", "|="],
        +
        +	["operator", ":"],
        +	["operator", "::"],
        +
        +	["comment", "// operator references"],
        +	["operator", "`+`"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/chaiscript/punctuation_feature.test b/tests/languages/chaiscript/punctuation_feature.test
        new file mode 100644
        index 0000000000..cfdd322901
        --- /dev/null
        +++ b/tests/languages/chaiscript/punctuation_feature.test
        @@ -0,0 +1,17 @@
        +( ) [ ] { }
        +; , .
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["punctuation", ";"],
        +	["punctuation", ","],
        +	["punctuation", "."]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/chaiscript/string_feature.test b/tests/languages/chaiscript/string_feature.test
        new file mode 100644
        index 0000000000..fdc72461da
        --- /dev/null
        +++ b/tests/languages/chaiscript/string_feature.test
        @@ -0,0 +1,71 @@
        +"string"
        +"lhs: ${lhs}, rhs: ${rhs}"
        +"${3 + 5} is 8"
        +"method_missing(${i}, ${name}), ${v.size()} params"
        +
        +'f'
        +
        +----------------------------------------------------
        +
        +[
        +	["string-interpolation", [
        +		["string", "\"string\""]
        +	]],
        +	["string-interpolation", [
        +		["string", "\"lhs: "],
        +		["interpolation", [
        +			["interpolation-punctuation", "${"],
        +			["interpolation-expression", ["lhs"]],
        +			["interpolation-punctuation", "}"]
        +		]],
        +		["string", ", rhs: "],
        +		["interpolation", [
        +			["interpolation-punctuation", "${"],
        +			["interpolation-expression", ["rhs"]],
        +			["interpolation-punctuation", "}"]
        +		]],
        +		["string", "\""]
        +	]],
        +	["string-interpolation", [
        +		["string", "\""],
        +		["interpolation", [
        +			["interpolation-punctuation", "${"],
        +			["interpolation-expression", [
        +				["number", "3"],
        +				["operator", "+"],
        +				["number", "5"]
        +			]],
        +			["interpolation-punctuation", "}"]
        +		]],
        +		["string", " is 8\""]
        +	]],
        +	["string-interpolation", [
        +		["string", "\"method_missing("],
        +		["interpolation", [
        +			["interpolation-punctuation", "${"],
        +			["interpolation-expression", ["i"]],
        +			["interpolation-punctuation", "}"]
        +		]],
        +		["string", ", "],
        +		["interpolation", [
        +			["interpolation-punctuation", "${"],
        +			["interpolation-expression", ["name"]],
        +			["interpolation-punctuation", "}"]
        +		]],
        +		["string", "), "],
        +		["interpolation", [
        +			["interpolation-punctuation", "${"],
        +			["interpolation-expression", [
        +				"v",
        +				["punctuation", "."],
        +				["function", "size"],
        +				["punctuation", "("],
        +				["punctuation", ")"]
        +			]],
        +			["interpolation-punctuation", "}"]
        +		]],
        +		["string", " params\""]
        +	]],
        +
        +	["string", "'f'"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cil/asm_reference.test b/tests/languages/cil/asm_reference.test
        new file mode 100644
        index 0000000000..991f998cc2
        --- /dev/null
        +++ b/tests/languages/cil/asm_reference.test
        @@ -0,0 +1,11 @@
        +[mscorlib]
        +
        +--------------------------------------------------------
        +
        +[
        +	[ "variable", "[mscorlib]" ]
        +]
        +
        +--------------------------------------------------------
        +
        +Tests assembly references
        diff --git a/tests/languages/cil/boolean.test b/tests/languages/cil/boolean.test
        new file mode 100644
        index 0000000000..c6cfe746fd
        --- /dev/null
        +++ b/tests/languages/cil/boolean.test
        @@ -0,0 +1,14 @@
        +
        +true
        +false
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "true"],
        +	["boolean", "false"]
        +]
        +
        +----------------------------------------------------
        +
        +Tests booleans.
        diff --git a/tests/languages/cil/comment.test b/tests/languages/cil/comment.test
        new file mode 100644
        index 0000000000..97a30a459f
        --- /dev/null
        +++ b/tests/languages/cil/comment.test
        @@ -0,0 +1,11 @@
        +// this is a test
        +
        +--------------------------------------------------------
        +
        +[
        +	[ "comment", "// this is a test" ]
        +]
        +
        +--------------------------------------------------------
        +
        +Tests comments
        diff --git a/tests/languages/cil/directive_feature.test b/tests/languages/cil/directive_feature.test
        new file mode 100644
        index 0000000000..452b558c95
        --- /dev/null
        +++ b/tests/languages/cil/directive_feature.test
        @@ -0,0 +1,15 @@
        +.class public Foo {
        +.method
        +.maxstack 2
        +
        +----------------------------------------------------
        +
        +[
        +	["directive", ".class"],
        +	["keyword", "public"],
        +	" Foo ",
        +	["punctuation", "{"],
        +	["directive", ".method"],
        +	["directive", ".maxstack"],
        +	["number", "2"]
        +]
        diff --git a/tests/languages/cil/instructions.test b/tests/languages/cil/instructions.test
        new file mode 100644
        index 0000000000..fc01826c81
        --- /dev/null
        +++ b/tests/languages/cil/instructions.test
        @@ -0,0 +1,457 @@
        +add
        +add.ovf
        +add.ovf.un
        +and
        +arglist
        +beq
        +beq.s
        +bge
        +bge.s
        +bge.un
        +bge.un.s
        +bgt
        +bgt.s
        +bgt.un
        +bgt.un.s
        +ble
        +ble.s
        +ble.un
        +ble.un.s
        +blt
        +blt.s
        +blt.un
        +blt.un.s
        +bne.un
        +bne.un.s
        +box
        +br
        +br.s
        +break
        +brfalse
        +brfalse.s
        +brinst
        +brinst.s
        +brnull
        +brnull.s
        +brtrue
        +brtrue.s
        +brzero
        +brzero.s
        +call
        +calli
        +callvirt
        +castclass
        +ceq
        +cgt
        +cgt.un
        +ckfinite
        +clt
        +clt.un
        +conv.i
        +conv.i1
        +conv.i2
        +conv.i4
        +conv.i8
        +conv.ovf.i
        +conv.ovf.i.un
        +conv.ovf.i1
        +conv.ovf.i1.un
        +conv.ovf.i2
        +conv.ovf.i2.un
        +conv.ovf.i4
        +conv.ovf.i4.un
        +conv.ovf.i8
        +conv.ovf.i8.un
        +conv.ovf.u
        +conv.ovf.u.un
        +conv.ovf.u1
        +conv.ovf.u1.un
        +conv.ovf.u2
        +conv.ovf.u2.un
        +conv.ovf.u4
        +conv.ovf.u4.un
        +conv.ovf.u8
        +conv.ovf.u8.un
        +conv.r.un
        +conv.r4
        +conv.r8
        +conv.u
        +conv.u1
        +conv.u2
        +conv.u4
        +conv.u8
        +cpblk
        +cpobj
        +div
        +div.un
        +dup
        +endfault
        +endfilter
        +endfinally
        +initblk
        +initobj
        +isinst
        +jmp
        +ldarg
        +ldarg.0
        +ldarg.1
        +ldarg.2
        +ldarg.3
        +ldarg.s
        +ldarga
        +ldarga.s
        +ldc.i4
        +ldc.i4.0
        +ldc.i4.1
        +ldc.i4.2
        +ldc.i4.3
        +ldc.i4.4
        +ldc.i4.5
        +ldc.i4.6
        +ldc.i4.7
        +ldc.i4.8
        +ldc.i4.m1
        +ldc.i4.M1
        +ldc.i4.s
        +ldc.i8
        +ldc.r4
        +ldc.r8
        +ldelem
        +ldelem.i
        +ldelem.i1
        +ldelem.i2
        +ldelem.i4
        +ldelem.i8
        +ldelem.r4
        +ldelem.r8
        +ldelem.ref
        +ldelem.u1
        +ldelem.u2
        +ldelem.u4
        +ldelem.u8
        +ldelema
        +ldfld
        +ldflda
        +ldftn
        +ldind.i
        +ldind.i1
        +ldind.i2
        +ldind.i4
        +ldind.i8
        +ldind.r4
        +ldind.r8
        +ldind.ref
        +ldind.u1
        +ldind.u2
        +ldind.u4
        +ldind.u8
        +ldlen
        +ldloc
        +ldloc.0
        +ldloc.1
        +ldloc.2
        +ldloc.3
        +ldloc.s
        +ldloca
        +ldloca.s
        +ldnull
        +ldobj
        +ldsfld
        +ldsflda
        +ldstr
        +ldtoken
        +ldvirtftn
        +leave
        +leave.s
        +localloc
        +mkrefany
        +mul
        +mul.ovf
        +mul.ovf.un
        +neg
        +newarr
        +newobj
        +nop
        +not
        +or
        +pop
        +refanytype
        +refanyval
        +rem
        +rem.un
        +ret
        +rethrow
        +shl
        +shr
        +shr.un
        +sizeof
        +starg
        +starg.s
        +stelem
        +stelem.i
        +stelem.i1
        +stelem.i2
        +stelem.i4
        +stelem.i8
        +stelem.r4
        +stelem.r8
        +stelem.ref
        +stfld
        +stind.i
        +stind.i1
        +stind.i2
        +stind.i4
        +stind.i8
        +stind.r4
        +stind.r8
        +stind.ref
        +stloc
        +stloc.0
        +stloc.1
        +stloc.2
        +stloc.3
        +stloc.s
        +stobj
        +stsfld
        +sub
        +sub.ovf
        +sub.ovf.un
        +switch
        +throw
        +alignment
        +unbox
        +unbox.any
        +xor
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "add"],
        +	["function", "add.ovf"],
        +	["function", "add.ovf.un"],
        +	["function", "and"],
        +	["function", "arglist"],
        +	["function", "beq"],
        +	["function", "beq.s"],
        +	["function", "bge"],
        +	["function", "bge.s"],
        +	["function", "bge.un"],
        +	["function", "bge.un.s"],
        +	["function", "bgt"],
        +	["function", "bgt.s"],
        +	["function", "bgt.un"],
        +	["function", "bgt.un.s"],
        +	["function", "ble"],
        +	["function", "ble.s"],
        +	["function", "ble.un"],
        +	["function", "ble.un.s"],
        +	["function", "blt"],
        +	["function", "blt.s"],
        +	["function", "blt.un"],
        +	["function", "blt.un.s"],
        +	["function", "bne.un"],
        +	["function", "bne.un.s"],
        +	["function", "box"],
        +	["function", "br"],
        +	["function", "br.s"],
        +	["function", "break"],
        +	["function", "brfalse"],
        +	["function", "brfalse.s"],
        +	["function", "brinst"],
        +	["function", "brinst.s"],
        +	["function", "brnull"],
        +	["function", "brnull.s"],
        +	["function", "brtrue"],
        +	["function", "brtrue.s"],
        +	["function", "brzero"],
        +	["function", "brzero.s"],
        +	["function", "call"],
        +	["function", "calli"],
        +	["function", "callvirt"],
        +	["function", "castclass"],
        +	["function", "ceq"],
        +	["function", "cgt"],
        +	["function", "cgt.un"],
        +	["function", "ckfinite"],
        +	["function", "clt"],
        +	["function", "clt.un"],
        +	["function", "conv.i"],
        +	["function", "conv.i1"],
        +	["function", "conv.i2"],
        +	["function", "conv.i4"],
        +	["function", "conv.i8"],
        +	["function", "conv.ovf.i"],
        +	["function", "conv.ovf.i.un"],
        +	["function", "conv.ovf.i1"],
        +	["function", "conv.ovf.i1.un"],
        +	["function", "conv.ovf.i2"],
        +	["function", "conv.ovf.i2.un"],
        +	["function", "conv.ovf.i4"],
        +	["function", "conv.ovf.i4.un"],
        +	["function", "conv.ovf.i8"],
        +	["function", "conv.ovf.i8.un"],
        +	["function", "conv.ovf.u"],
        +	["function", "conv.ovf.u.un"],
        +	["function", "conv.ovf.u1"],
        +	["function", "conv.ovf.u1.un"],
        +	["function", "conv.ovf.u2"],
        +	["function", "conv.ovf.u2.un"],
        +	["function", "conv.ovf.u4"],
        +	["function", "conv.ovf.u4.un"],
        +	["function", "conv.ovf.u8"],
        +	["function", "conv.ovf.u8.un"],
        +	["function", "conv.r.un"],
        +	["function", "conv.r4"],
        +	["function", "conv.r8"],
        +	["function", "conv.u"],
        +	["function", "conv.u1"],
        +	["function", "conv.u2"],
        +	["function", "conv.u4"],
        +	["function", "conv.u8"],
        +	["function", "cpblk"],
        +	["function", "cpobj"],
        +	["function", "div"],
        +	["function", "div.un"],
        +	["function", "dup"],
        +	["function", "endfault"],
        +	["function", "endfilter"],
        +	["function", "endfinally"],
        +	["function", "initblk"],
        +	["function", "initobj"],
        +	["function", "isinst"],
        +	["function", "jmp"],
        +	["function", "ldarg"],
        +	["function", "ldarg.0"],
        +	["function", "ldarg.1"],
        +	["function", "ldarg.2"],
        +	["function", "ldarg.3"],
        +	["function", "ldarg.s"],
        +	["function", "ldarga"],
        +	["function", "ldarga.s"],
        +	["function", "ldc.i4"],
        +	["function", "ldc.i4.0"],
        +	["function", "ldc.i4.1"],
        +	["function", "ldc.i4.2"],
        +	["function", "ldc.i4.3"],
        +	["function", "ldc.i4.4"],
        +	["function", "ldc.i4.5"],
        +	["function", "ldc.i4.6"],
        +	["function", "ldc.i4.7"],
        +	["function", "ldc.i4.8"],
        +	["function", "ldc.i4.m1"],
        +	["function", "ldc.i4.M1"],
        +	["function", "ldc.i4.s"],
        +	["function", "ldc.i8"],
        +	["function", "ldc.r4"],
        +	["function", "ldc.r8"],
        +	["function", "ldelem"],
        +	["function", "ldelem.i"],
        +	["function", "ldelem.i1"],
        +	["function", "ldelem.i2"],
        +	["function", "ldelem.i4"],
        +	["function", "ldelem.i8"],
        +	["function", "ldelem.r4"],
        +	["function", "ldelem.r8"],
        +	["function", "ldelem.ref"],
        +	["function", "ldelem.u1"],
        +	["function", "ldelem.u2"],
        +	["function", "ldelem.u4"],
        +	["function", "ldelem.u8"],
        +	["function", "ldelema"],
        +	["function", "ldfld"],
        +	["function", "ldflda"],
        +	["function", "ldftn"],
        +	["function", "ldind.i"],
        +	["function", "ldind.i1"],
        +	["function", "ldind.i2"],
        +	["function", "ldind.i4"],
        +	["function", "ldind.i8"],
        +	["function", "ldind.r4"],
        +	["function", "ldind.r8"],
        +	["function", "ldind.ref"],
        +	["function", "ldind.u1"],
        +	["function", "ldind.u2"],
        +	["function", "ldind.u4"],
        +	["function", "ldind.u8"],
        +	["function", "ldlen"],
        +	["function", "ldloc"],
        +	["function", "ldloc.0"],
        +	["function", "ldloc.1"],
        +	["function", "ldloc.2"],
        +	["function", "ldloc.3"],
        +	["function", "ldloc.s"],
        +	["function", "ldloca"],
        +	["function", "ldloca.s"],
        +	["function", "ldnull"],
        +	["function", "ldobj"],
        +	["function", "ldsfld"],
        +	["function", "ldsflda"],
        +	["function", "ldstr"],
        +	["function", "ldtoken"],
        +	["function", "ldvirtftn"],
        +	["function", "leave"],
        +	["function", "leave.s"],
        +	["function", "localloc"],
        +	["function", "mkrefany"],
        +	["function", "mul"],
        +	["function", "mul.ovf"],
        +	["function", "mul.ovf.un"],
        +	["function", "neg"],
        +	["function", "newarr"],
        +	["function", "newobj"],
        +	["function", "nop"],
        +	["function", "not"],
        +	["function", "or"],
        +	["function", "pop"],
        +	["function", "refanytype"],
        +	["function", "refanyval"],
        +	["function", "rem"],
        +	["function", "rem.un"],
        +	["function", "ret"],
        +	["function", "rethrow"],
        +	["function", "shl"],
        +	["function", "shr"],
        +	["function", "shr.un"],
        +	["function", "sizeof"],
        +	["function", "starg"],
        +	["function", "starg.s"],
        +	["function", "stelem"],
        +	["function", "stelem.i"],
        +	["function", "stelem.i1"],
        +	["function", "stelem.i2"],
        +	["function", "stelem.i4"],
        +	["function", "stelem.i8"],
        +	["function", "stelem.r4"],
        +	["function", "stelem.r8"],
        +	["function", "stelem.ref"],
        +	["function", "stfld"],
        +	["function", "stind.i"],
        +	["function", "stind.i1"],
        +	["function", "stind.i2"],
        +	["function", "stind.i4"],
        +	["function", "stind.i8"],
        +	["function", "stind.r4"],
        +	["function", "stind.r8"],
        +	["function", "stind.ref"],
        +	["function", "stloc"],
        +	["function", "stloc.0"],
        +	["function", "stloc.1"],
        +	["function", "stloc.2"],
        +	["function", "stloc.3"],
        +	["function", "stloc.s"],
        +	["function", "stobj"],
        +	["function", "stsfld"],
        +	["function", "sub"],
        +	["function", "sub.ovf"],
        +	["function", "sub.ovf.un"],
        +	["function", "switch"],
        +	["function", "throw"],
        +	["function", "alignment"],
        +	["function", "unbox"],
        +	["function", "unbox.any"],
        +	["function", "xor"]
        +]
        +
        +----------------------------------------------------
        +
        +Tests instruction names
        diff --git a/tests/languages/cil/keywords.test b/tests/languages/cil/keywords.test
        new file mode 100644
        index 0000000000..53a4645a25
        --- /dev/null
        +++ b/tests/languages/cil/keywords.test
        @@ -0,0 +1,161 @@
        +abstract
        +ansi
        +assembly
        +auto
        +autochar
        +beforefieldinit
        +bool
        +bstr
        +byvalstr
        +cil
        +char
        +class
        +currency
        +date
        +decimal
        +default
        +enum
        +error
        +explicit
        +extends
        +extern
        +famandassem
        +family
        +famorassem
        +final
        +float32
        +float64
        +hidebysig
        +iant
        +idispatch
        +import
        +initonly
        +instance
        +int
        +int16
        +int32
        +int64
        +int8
        +uint
        +uint16
        +uint32
        +uint64
        +uint8
        +interface
        +iunknown
        +lpstr
        +lpstruct
        +lptstr
        +lpwstr
        +managed
        +nativeType
        +nested
        +newslot
        +objectref
        +pinvokeimpl
        +private
        +privatescope
        +public
        +reqsecobj
        +rtspecialname
        +sealed
        +sequential
        +serializable
        +specialname
        +static
        +string
        +struct
        +syschar
        +tbstr
        +unicode
        +unmanagedexp
        +unsigned
        +value
        +variant
        +virtual
        +void
        +
        +--------------------------------------------------------
        +
        +[
        +	[ "keyword", "abstract" ],
        +	[ "keyword", "ansi" ],
        +	[ "keyword", "assembly" ],
        +	[ "keyword", "auto" ],
        +	[ "keyword", "autochar" ],
        +	[ "keyword", "beforefieldinit" ],
        +	[ "keyword", "bool" ],
        +	[ "keyword", "bstr" ],
        +	[ "keyword", "byvalstr" ],
        +	[ "keyword", "cil" ],
        +	[ "keyword", "char" ],
        +	[ "keyword", "class" ],
        +	[ "keyword", "currency" ],
        +	[ "keyword", "date" ],
        +	[ "keyword", "decimal" ],
        +	[ "keyword", "default" ],
        +	[ "keyword", "enum" ],
        +	[ "keyword", "error" ],
        +	[ "keyword", "explicit" ],
        +	[ "keyword", "extends" ],
        +	[ "keyword", "extern" ],
        +	[ "keyword", "famandassem" ],
        +	[ "keyword", "family" ],
        +	[ "keyword", "famorassem" ],
        +	[ "keyword", "final" ],
        +	[ "keyword", "float32" ],
        +	[ "keyword", "float64" ],
        +	[ "keyword", "hidebysig" ],
        +	[ "keyword", "iant" ],
        +	[ "keyword", "idispatch" ],
        +	[ "keyword", "import" ],
        +	[ "keyword", "initonly" ],
        +	[ "keyword", "instance" ],
        +	[ "keyword", "int" ],
        +	[ "keyword", "int16" ],
        +	[ "keyword", "int32" ],
        +	[ "keyword", "int64" ],
        +	[ "keyword", "int8" ],
        +	[ "keyword", "uint" ],
        +	[ "keyword", "uint16" ],
        +	[ "keyword", "uint32" ],
        +	[ "keyword", "uint64" ],
        +	[ "keyword", "uint8" ],
        +	[ "keyword", "interface" ],
        +	[ "keyword", "iunknown" ],
        +	[ "keyword", "lpstr" ],
        +	[ "keyword", "lpstruct" ],
        +	[ "keyword", "lptstr" ],
        +	[ "keyword", "lpwstr" ],
        +	[ "keyword", "managed" ],
        +	[ "keyword", "nativeType" ],
        +	[ "keyword", "nested" ],
        +	[ "keyword", "newslot" ],
        +	[ "keyword", "objectref" ],
        +	[ "keyword", "pinvokeimpl" ],
        +	[ "keyword", "private" ],
        +	[ "keyword", "privatescope" ],
        +	[ "keyword", "public" ],
        +	[ "keyword", "reqsecobj" ],
        +	[ "keyword", "rtspecialname" ],
        +	[ "keyword", "sealed" ],
        +	[ "keyword", "sequential" ],
        +	[ "keyword", "serializable" ],
        +	[ "keyword", "specialname" ],
        +	[ "keyword", "static" ],
        +	[ "keyword", "string" ],
        +	[ "keyword", "struct" ],
        +	[ "keyword", "syschar" ],
        +	[ "keyword", "tbstr" ],
        +	[ "keyword", "unicode" ],
        +	[ "keyword", "unmanagedexp" ],
        +	[ "keyword", "unsigned" ],
        +	[ "keyword", "value" ],
        +	[ "keyword", "variant" ],
        +	[ "keyword", "virtual" ],
        +	[ "keyword", "void"]
        +]
        +
        +--------------------------------------------------------
        +
        +Tests keywords
        diff --git a/tests/languages/cil/number_feature.test b/tests/languages/cil/number_feature.test
        new file mode 100644
        index 0000000000..fe3fe8900a
        --- /dev/null
        +++ b/tests/languages/cil/number_feature.test
        @@ -0,0 +1,13 @@
        +0x0
        +0xFF.5F
        +-0x1
        +-0xFF.5F
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "0x0"],
        +	["number", "0xFF.5F"],
        +	"\r\n-", ["number", "0x1"],
        +	"\r\n-", ["number", "0xFF.5F"]
        +]
        diff --git a/tests/languages/cil/punctuation_feature.test b/tests/languages/cil/punctuation_feature.test
        new file mode 100644
        index 0000000000..57d6604dc0
        --- /dev/null
        +++ b/tests/languages/cil/punctuation_feature.test
        @@ -0,0 +1,21 @@
        +( ) [ ] { }
        +; , : =
        +
        +IL_001f
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +	["punctuation", ","],
        +	["punctuation", ":"],
        +	["punctuation", "="],
        +
        +	["punctuation", "IL_001f"]
        +]
        diff --git a/tests/languages/cil/strings.test b/tests/languages/cil/strings.test
        new file mode 100644
        index 0000000000..da2de2c73b
        --- /dev/null
        +++ b/tests/languages/cil/strings.test
        @@ -0,0 +1,11 @@
        +"testing! £$%^&*"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"testing! £$%^&*\""]
        +]
        +
        +----------------------------------------------------
        +
        +Tests strings.
        diff --git a/tests/languages/clojure/function_feature.test b/tests/languages/clojure/function_feature.test
        new file mode 100644
        index 0000000000..28fd4a5f83
        --- /dev/null
        +++ b/tests/languages/clojure/function_feature.test
        @@ -0,0 +1,13 @@
        +(foo args)
        +
        +; not a function
        +'(a b c)
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("], ["function", "foo"], " args", ["punctuation", ")"],
        +
        +	["comment", "; not a function"],
        +	"\r\n'", ["punctuation", "("], "a b c", ["punctuation", ")"]
        +]
        diff --git a/tests/languages/clojure/number_feature.test b/tests/languages/clojure/number_feature.test
        new file mode 100644
        index 0000000000..7ca0213914
        --- /dev/null
        +++ b/tests/languages/clojure/number_feature.test
        @@ -0,0 +1,27 @@
        +123
        +01234
        +0xFFF
        +2r0101011
        +8r52
        +36r16
        +1.0
        +1M
        +2/3
        +0.6666666666666666
        +36786883868216818816N
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "123"],
        +	["number", "01234"],
        +	["number", "0xFFF"],
        +	["number", "2r0101011"],
        +	["number", "8r52"],
        +	["number", "36r16"],
        +	["number", "1.0"],
        +	["number", "1M"],
        +	["number", "2/3"],
        +	["number", "0.6666666666666666"],
        +	["number", "36786883868216818816N"]
        +]
        diff --git a/tests/languages/clojure/operator_feature.test b/tests/languages/clojure/operator_feature.test
        new file mode 100644
        index 0000000000..7c57567c97
        --- /dev/null
        +++ b/tests/languages/clojure/operator_feature.test
        @@ -0,0 +1,11 @@
        +# @ ^ ` ~
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "#"],
        +	["operator", "@"],
        +	["operator", "^"],
        +	["operator", "`"],
        +	["operator", "~"]
        +]
        diff --git a/tests/languages/clojure/punctuation_feature.test b/tests/languages/clojure/punctuation_feature.test
        new file mode 100644
        index 0000000000..ea9bbc2188
        --- /dev/null
        +++ b/tests/languages/clojure/punctuation_feature.test
        @@ -0,0 +1,15 @@
        +{ } [ ] ( )
        +,
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	["punctuation", ","]
        +]
        diff --git a/tests/languages/clojure/string_feature.test b/tests/languages/clojure/string_feature.test
        index 13a966cf7e..718b652acc 100644
        --- a/tests/languages/clojure/string_feature.test
        +++ b/tests/languages/clojure/string_feature.test
        @@ -1,13 +1,18 @@
         ""
         "Fo\"obar"
        +"multi-line
        +string"
        +\NewLine
         
         ----------------------------------------------------
         
         [
         	["string", "\"\""],
        -	["string", "\"Fo\\\"obar\""]
        +	["string", "\"Fo\\\"obar\""],
        +	["string", "\"multi-line\r\nstring\""],
        +	["char", "\\NewLine"]
         ]
         
         ----------------------------------------------------
         
        -Checks for strings.
        \ No newline at end of file
        +Checks for strings.
        diff --git a/tests/languages/clojure/symbol_feature.test b/tests/languages/clojure/symbol_feature.test
        new file mode 100644
        index 0000000000..e43df4fd9c
        --- /dev/null
        +++ b/tests/languages/clojure/symbol_feature.test
        @@ -0,0 +1,11 @@
        +:foo
        +:foo/bar-baz
        +::foo
        +
        +----------------------------------------------------
        +
        +[
        +	["symbol", ":foo"],
        +	["symbol", ":foo/bar-baz"],
        +	["symbol", "::foo"]
        +]
        diff --git a/tests/languages/cmake/boolean_feature.test b/tests/languages/cmake/boolean_feature.test
        new file mode 100644
        index 0000000000..2fe7dcb2e4
        --- /dev/null
        +++ b/tests/languages/cmake/boolean_feature.test
        @@ -0,0 +1,17 @@
        +ON
        +OFF
        +TRUE
        +FALSE
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "ON"],
        +	["boolean", "OFF"],
        +	["boolean", "TRUE"],
        +	["boolean", "FALSE"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for booleans.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/comment_feature.test b/tests/languages/cmake/comment_feature.test
        new file mode 100644
        index 0000000000..4ef3ec4c8a
        --- /dev/null
        +++ b/tests/languages/cmake/comment_feature.test
        @@ -0,0 +1,13 @@
        +# standalone
        +add_library() # after code
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "# standalone"],
        +	["keyword", "add_library"], ["punctuation", "("], ["punctuation", ")"], ["comment", "# after code"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/function_feature.test b/tests/languages/cmake/function_feature.test
        new file mode 100644
        index 0000000000..defc0da0c0
        --- /dev/null
        +++ b/tests/languages/cmake/function_feature.test
        @@ -0,0 +1,17 @@
        +foobar()
        +baz()
        +Foobar()
        +FOOBAR()
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "foobar"], ["punctuation", "("], ["punctuation", ")"],
        +	["function", "baz"], ["punctuation", "("], ["punctuation", ")"],
        +	["function", "Foobar"], ["punctuation", "("], ["punctuation", ")"],
        +	["function", "FOOBAR"], ["punctuation", "("], ["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for functions.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/inserted_feature.test b/tests/languages/cmake/inserted_feature.test
        new file mode 100644
        index 0000000000..0428ec5488
        --- /dev/null
        +++ b/tests/languages/cmake/inserted_feature.test
        @@ -0,0 +1,15 @@
        +foo::bar
        +foo::foo
        +Foo::Bar
        +
        +----------------------------------------------------
        +
        +[
        +	["inserted", "foo::bar"],
        +	["inserted", "foo::foo"],
        +	["inserted", "Foo::Bar"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all namespaces.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/keyword_feature.test b/tests/languages/cmake/keyword_feature.test
        new file mode 100644
        index 0000000000..79d065a73b
        --- /dev/null
        +++ b/tests/languages/cmake/keyword_feature.test
        @@ -0,0 +1,253 @@
        +add_compile_definitions()
        +add_compile_options()
        +add_custom_command()
        +add_custom_target()
        +add_definitions()
        +add_dependencies()
        +add_executable()
        +add_library()
        +add_link_options()
        +add_subdirectory()
        +add_test()
        +aux_source_directory()
        +break()
        +build_command()
        +build_name()
        +cmake_host_system_information()
        +cmake_minimum_required()
        +cmake_parse_arguments()
        +cmake_policy()
        +configure_file()
        +continue()
        +create_test_sourcelist()
        +ctest_build()
        +ctest_configure()
        +ctest_coverage()
        +ctest_empty_binary_directory()
        +ctest_memcheck()
        +ctest_read_custom_files()
        +ctest_run_script()
        +ctest_sleep()
        +ctest_start()
        +ctest_submit()
        +ctest_test()
        +ctest_update()
        +ctest_upload()
        +define_property()
        +else()
        +elseif()
        +enable_language()
        +enable_testing()
        +endforeach()
        +endfunction()
        +endif()
        +endmacro()
        +endwhile()
        +exec_program()
        +execute_process()
        +export()
        +export_library_dependencies()
        +file()
        +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_guard()
        +include_regular_expression()
        +install()
        +install_files()
        +install_programs()
        +install_targets()
        +link_directories()
        +link_libraries()
        +list()
        +load_cache()
        +load_command()
        +macro()
        +make_directory()
        +mark_as_advanced()
        +math()
        +message()
        +option()
        +output_required_files()
        +project()
        +qt_wrap_cpp()
        +qt_wrap_ui()
        +remove()
        +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()
        +subdir_depends()
        +subdirs()
        +target_compile_definitions()
        +target_compile_features()
        +target_compile_options()
        +target_include_directories()
        +target_link_directories()
        +target_link_libraries()
        +target_link_options()
        +target_sources()
        +try_compile()
        +try_run()
        +unset()
        +use_mangled_mesa()
        +utility_source()
        +variable_requires()
        +variable_watch()
        +while()
        +write_file()
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "add_compile_definitions"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_compile_options"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_custom_command"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_custom_target"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_definitions"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_dependencies"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_executable"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_library"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_link_options"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_subdirectory"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "add_test"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "aux_source_directory"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "break"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "build_command"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "build_name"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "cmake_host_system_information"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "cmake_minimum_required"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "cmake_parse_arguments"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "cmake_policy"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "configure_file"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "continue"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "create_test_sourcelist"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_build"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_configure"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_coverage"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_empty_binary_directory"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_memcheck"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_read_custom_files"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_run_script"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_sleep"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_start"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_submit"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_test"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_update"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "ctest_upload"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "define_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "else"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "elseif"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "enable_language"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "enable_testing"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "endforeach"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "endfunction"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "endif"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "endmacro"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "endwhile"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "exec_program"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "execute_process"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "export"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "export_library_dependencies"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "file"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "find_file"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "find_library"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "find_package"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "find_path"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "find_program"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "fltk_wrap_ui"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "foreach"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "function"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "get_cmake_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "get_directory_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "get_filename_component"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "get_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "get_source_file_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "get_target_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "get_test_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "if"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "include"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "include_directories"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "include_external_msproject"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "include_guard"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "include_regular_expression"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "install"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "install_files"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "install_programs"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "install_targets"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "link_directories"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "link_libraries"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "list"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "load_cache"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "load_command"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "macro"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "make_directory"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "mark_as_advanced"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "math"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "message"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "option"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "output_required_files"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "project"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "qt_wrap_cpp"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "qt_wrap_ui"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "remove"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "remove_definitions"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "return"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "separate_arguments"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "set"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "set_directory_properties"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "set_property"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "set_source_files_properties"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "set_target_properties"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "set_tests_properties"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "site_name"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "source_group"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "string"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "subdir_depends"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "subdirs"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_compile_definitions"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_compile_features"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_compile_options"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_include_directories"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_link_directories"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_link_libraries"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_link_options"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "target_sources"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "try_compile"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "try_run"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "unset"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "use_mangled_mesa"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "utility_source"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "variable_requires"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "variable_watch"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "while"], ["punctuation", "("], ["punctuation", ")"],
        +	["keyword", "write_file"], ["punctuation", "("], ["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for keywords.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/namespace_feature.test b/tests/languages/cmake/namespace_feature.test
        new file mode 100644
        index 0000000000..b3f5aab214
        --- /dev/null
        +++ b/tests/languages/cmake/namespace_feature.test
        @@ -0,0 +1,23 @@
        +PROPERTIES
        +SHARED
        +PRIVATE
        +STATIC
        +PUBLIC
        +INTERFACE
        +TARGET_OBJECTS
        +
        +----------------------------------------------------
        +
        +[
        +	["namespace", "PROPERTIES"],
        +	["namespace", "SHARED"],
        +	["namespace", "PRIVATE"],
        +	["namespace", "STATIC"],
        +	["namespace", "PUBLIC"],
        +	["namespace", "INTERFACE"],
        +	["namespace", "TARGET_OBJECTS"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all namespaces.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/number_feature.test b/tests/languages/cmake/number_feature.test
        new file mode 100644
        index 0000000000..f4e80495b2
        --- /dev/null
        +++ b/tests/languages/cmake/number_feature.test
        @@ -0,0 +1,15 @@
        +1
        +2123
        +234234.23423
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "1"],
        +	["number", "2123"],
        +	["number", "234234.23423"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for numbers.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/operator_feature.test b/tests/languages/cmake/operator_feature.test
        new file mode 100644
        index 0000000000..df9119d623
        --- /dev/null
        +++ b/tests/languages/cmake/operator_feature.test
        @@ -0,0 +1,37 @@
        +NOT
        +AND
        +OR
        +MATCHES
        +LESS
        +GREATER
        +EQUAL
        +STRLESS
        +STRGREATER
        +STREQUAL
        +VERSION_LESS
        +VERSION_EQUAL
        +VERSION_GREATER
        +DEFINED
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "NOT"],
        +	["operator", "AND"],
        +	["operator", "OR"],
        +	["operator", "MATCHES"],
        +	["operator", "LESS"],
        +	["operator", "GREATER"],
        +	["operator", "EQUAL"],
        +	["operator", "STRLESS"],
        +	["operator", "STRGREATER"],
        +	["operator", "STREQUAL"],
        +	["operator", "VERSION_LESS"],
        +	["operator", "VERSION_EQUAL"],
        +	["operator", "VERSION_GREATER"],
        +	["operator", "DEFINED"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all operator.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/property_feature.test b/tests/languages/cmake/property_feature.test
        new file mode 100644
        index 0000000000..2ff2fac67c
        --- /dev/null
        +++ b/tests/languages/cmake/property_feature.test
        @@ -0,0 +1,937 @@
        +WHATEVER_OUTPUT_NAME
        +WHATEVER_POSTFIX
        +WHATEVER_CLANG_TIDY
        +WHATEVER_COMPILER_LAUNCHER
        +WHATEVER_CPPCHECK
        +WHATEVER_CPPLINT
        +WHATEVER_INCLUDE_WHAT_YOU_USE
        +WHATEVER_VISIBILITY_PRESET
        +ABSTRACT
        +ADDITIONAL_MAKE_CLEAN_FILES
        +ADVANCED
        +ALIASED_TARGET
        +ALLOW_DUPLICATE_CUSTOM_TARGETS
        +ANDROID_ANT_ADDITIONAL_OPTIONS
        +ANDROID_API
        +ANDROID_API_MIN
        +ANDROID_ARCH
        +ANDROID_ASSETS_DIRECTORIES
        +ANDROID_GUI
        +ANDROID_JAR_DEPENDENCIES
        +ANDROID_NATIVE_LIB_DEPENDENCIES
        +ANDROID_NATIVE_LIB_DIRECTORIES
        +ANDROID_PROCESS_MAX
        +ANDROID_PROGUARD
        +ANDROID_PROGUARD_CONFIG_PATH
        +ANDROID_SECURE_PROPS_PATH
        +ANDROID_SKIP_ANT_STEP
        +ANDROID_STL_TYPE
        +ARCHIVE_OUTPUT_DIRECTORY
        +ARCHIVE_OUTPUT_DIRECTORY_WHATEVER
        +ARCHIVE_OUTPUT_NAME
        +ARCHIVE_OUTPUT_NAME_WHATEVER
        +ATTACHED_FILES
        +ATTACHED_FILES_ON_FAIL
        +AUTOGEN_BUILD_DIR
        +AUTOGEN_ORIGIN_DEPENDS
        +AUTOGEN_PARALLEL
        +AUTOGEN_SOURCE_GROUP
        +AUTOGEN_TARGETS_FOLDER
        +AUTOGEN_TARGET_DEPENDS
        +AUTOMOC
        +AUTOMOC_COMPILER_PREDEFINES
        +AUTOMOC_DEPEND_FILTERS
        +AUTOMOC_EXECUTABLE
        +AUTOMOC_MACRO_NAMES
        +AUTOMOC_MOC_OPTIONS
        +AUTOMOC_SOURCE_GROUP
        +AUTOMOC_TARGETS_FOLDER
        +AUTORCC
        +AUTORCC_EXECUTABLE
        +AUTORCC_OPTIONS
        +AUTORCC_OPTIONS
        +AUTORCC_SOURCE_GROUP
        +AUTOUIC
        +AUTOUIC_EXECUTABLE
        +AUTOUIC_OPTIONS
        +AUTOUIC_OPTIONS
        +AUTOUIC_SEARCH_PATHS
        +BINARY_DIR
        +BINARY_DIR
        +BUILDSYSTEM_TARGETS
        +BUILD_RPATH
        +BUILD_RPATH_USE_ORIGIN
        +BUILD_WITH_INSTALL_NAME_DIR
        +BUILD_WITH_INSTALL_RPATH
        +BUNDLE
        +BUNDLE_EXTENSION
        +CACHE_VARIABLES
        +CLEAN_NO_CUSTOM
        +COMMON_LANGUAGE_RUNTIME
        +COMPATIBLE_INTERFACE_BOOL
        +COMPATIBLE_INTERFACE_NUMBER_MAX
        +COMPATIBLE_INTERFACE_NUMBER_MIN
        +COMPATIBLE_INTERFACE_STRING
        +COMPILE_DEFINITIONS
        +COMPILE_DEFINITIONS
        +COMPILE_DEFINITIONS
        +COMPILE_DEFINITIONS_WHATEVER
        +COMPILE_DEFINITIONS_WHATEVER
        +COMPILE_DEFINITIONS_WHATEVER
        +COMPILE_FEATURES
        +COMPILE_FLAGS
        +COMPILE_FLAGS
        +COMPILE_OPTIONS
        +COMPILE_OPTIONS
        +COMPILE_OPTIONS
        +COMPILE_PDB_NAME
        +COMPILE_PDB_NAME_WHATEVER
        +COMPILE_PDB_OUTPUT_DIRECTORY
        +COMPILE_PDB_OUTPUT_DIRECTORY_WHATEVER
        +COST
        +CPACK_DESKTOP_SHORTCUTS
        +CPACK_NEVER_OVERWRITE
        +CPACK_PERMANENT
        +CPACK_STARTUP_SHORTCUTS
        +CPACK_START_MENU_SHORTCUTS
        +CPACK_WIX_ACL
        +CROSSCOMPILING_EMULATOR
        +CUDA_EXTENSIONS
        +CUDA_PTX_COMPILATION
        +CUDA_RESOLVE_DEVICE_SYMBOLS
        +CUDA_SEPARABLE_COMPILATION
        +CUDA_STANDARD
        +CUDA_STANDARD_REQUIRED
        +CXX_EXTENSIONS
        +CXX_STANDARD
        +CXX_STANDARD_REQUIRED
        +C_EXTENSIONS
        +C_STANDARD
        +C_STANDARD_REQUIRED
        +DEBUG_CONFIGURATIONS
        +DEBUG_POSTFIX
        +DEFINE_SYMBOL
        +DEFINITIONS
        +DEPENDS
        +DEPLOYMENT_ADDITIONAL_FILES
        +DEPLOYMENT_REMOTE_DIRECTORY
        +DISABLED
        +DISABLED_FEATURES
        +ECLIPSE_EXTRA_CPROJECT_CONTENTS
        +ECLIPSE_EXTRA_NATURES
        +ENABLED_FEATURES
        +ENABLED_LANGUAGES
        +ENABLE_EXPORTS
        +ENVIRONMENT
        +EXCLUDE_FROM_ALL
        +EXCLUDE_FROM_ALL
        +EXCLUDE_FROM_DEFAULT_BUILD
        +EXCLUDE_FROM_DEFAULT_BUILD_WHATEVER
        +EXPORT_NAME
        +EXPORT_PROPERTIES
        +EXTERNAL_OBJECT
        +EchoString
        +FAIL_REGULAR_EXPRESSION
        +FIND_LIBRARY_USE_LIB32_PATHS
        +FIND_LIBRARY_USE_LIB64_PATHS
        +FIND_LIBRARY_USE_LIBX32_PATHS
        +FIND_LIBRARY_USE_OPENBSD_VERSIONING
        +FIXTURES_CLEANUP
        +FIXTURES_REQUIRED
        +FIXTURES_SETUP
        +FOLDER
        +FRAMEWORK
        +Fortran_FORMAT
        +Fortran_FORMAT
        +Fortran_MODULE_DIRECTORY
        +GENERATED
        +GENERATOR_FILE_NAME
        +GENERATOR_IS_MULTI_CONFIG
        +GHS_INTEGRITY_APP
        +GHS_NO_SOURCE_GROUP_FILE
        +GLOBAL_DEPENDS_DEBUG_MODE
        +GLOBAL_DEPENDS_NO_CYCLES
        +GNUtoMS
        +HAS_CXX
        +HEADER_FILE_ONLY
        +HELPSTRING
        +IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
        +IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
        +IMPORTED
        +IMPORTED_COMMON_LANGUAGE_RUNTIME
        +IMPORTED_CONFIGURATIONS
        +IMPORTED_GLOBAL
        +IMPORTED_IMPLIB
        +IMPORTED_IMPLIB_WHATEVER
        +IMPORTED_LIBNAME
        +IMPORTED_LIBNAME_WHATEVER
        +IMPORTED_LINK_DEPENDENT_LIBRARIES
        +IMPORTED_LINK_DEPENDENT_LIBRARIES_WHATEVER
        +IMPORTED_LINK_INTERFACE_LANGUAGES
        +IMPORTED_LINK_INTERFACE_LANGUAGES_WHATEVER
        +IMPORTED_LINK_INTERFACE_LIBRARIES
        +IMPORTED_LINK_INTERFACE_LIBRARIES_WHATEVER
        +IMPORTED_LINK_INTERFACE_MULTIPLICITY
        +IMPORTED_LINK_INTERFACE_MULTIPLICITY_WHATEVER
        +IMPORTED_LOCATION
        +IMPORTED_LOCATION_WHATEVER
        +IMPORTED_NO_SONAME
        +IMPORTED_NO_SONAME_WHATEVER
        +IMPORTED_OBJECTS
        +IMPORTED_OBJECTS_WHATEVER
        +IMPORTED_SONAME
        +IMPORTED_SONAME_WHATEVER
        +IMPORT_PREFIX
        +IMPORT_SUFFIX
        +INCLUDE_DIRECTORIES
        +INCLUDE_DIRECTORIES
        +INCLUDE_DIRECTORIES
        +INCLUDE_REGULAR_EXPRESSION
        +INSTALL_NAME_DIR
        +INSTALL_RPATH
        +INSTALL_RPATH_USE_LINK_PATH
        +INTERFACE_AUTOUIC_OPTIONS
        +INTERFACE_COMPILE_DEFINITIONS
        +INTERFACE_COMPILE_FEATURES
        +INTERFACE_COMPILE_OPTIONS
        +INTERFACE_INCLUDE_DIRECTORIES
        +INTERFACE_LINK_DEPENDS
        +INTERFACE_LINK_DIRECTORIES
        +INTERFACE_LINK_LIBRARIES
        +INTERFACE_LINK_OPTIONS
        +INTERFACE_POSITION_INDEPENDENT_CODE
        +INTERFACE_SOURCES
        +INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
        +INTERPROCEDURAL_OPTIMIZATION
        +INTERPROCEDURAL_OPTIMIZATION
        +INTERPROCEDURAL_OPTIMIZATION_WHATEVER
        +INTERPROCEDURAL_OPTIMIZATION_WHATEVER
        +IN_TRY_COMPILE
        +IOS_INSTALL_COMBINED
        +JOB_POOLS
        +JOB_POOL_COMPILE
        +JOB_POOL_LINK
        +KEEP_EXTENSION
        +LABELS
        +LABELS
        +LABELS
        +LABELS
        +LANGUAGE
        +LIBRARY_OUTPUT_DIRECTORY
        +LIBRARY_OUTPUT_DIRECTORY_WHATEVER
        +LIBRARY_OUTPUT_NAME
        +LIBRARY_OUTPUT_NAME_WHATEVER
        +LINKER_LANGUAGE
        +LINK_DEPENDS
        +LINK_DEPENDS_NO_SHARED
        +LINK_DIRECTORIES
        +LINK_DIRECTORIES
        +LINK_FLAGS
        +LINK_FLAGS_WHATEVER
        +LINK_INTERFACE_LIBRARIES
        +LINK_INTERFACE_LIBRARIES_WHATEVER
        +LINK_INTERFACE_MULTIPLICITY
        +LINK_INTERFACE_MULTIPLICITY_WHATEVER
        +LINK_LIBRARIES
        +LINK_OPTIONS
        +LINK_OPTIONS
        +LINK_SEARCH_END_STATIC
        +LINK_SEARCH_START_STATIC
        +LINK_WHAT_YOU_USE
        +LISTFILE_STACK
        +LOCATION
        +LOCATION
        +LOCATION_WHATEVER
        +MACOSX_BUNDLE
        +MACOSX_BUNDLE_INFO_PLIST
        +MACOSX_FRAMEWORK_INFO_PLIST
        +MACOSX_PACKAGE_LOCATION
        +MACOSX_RPATH
        +MACROS
        +MANUALLY_ADDED_DEPENDENCIES
        +MAP_IMPORTED_CONFIG_WHATEVER
        +MEASUREMENT
        +MODIFIED
        +NAME
        +NO_SONAME
        +NO_SYSTEM_FROM_IMPORTED
        +OBJECT_DEPENDS
        +OBJECT_OUTPUTS
        +OSX_ARCHITECTURES
        +OSX_ARCHITECTURES_WHATEVER
        +OUTPUT_NAME
        +OUTPUT_NAME_WHATEVER
        +PACKAGES_FOUND
        +PACKAGES_NOT_FOUND
        +PARENT_DIRECTORY
        +PASS_REGULAR_EXPRESSION
        +PDB_NAME
        +PDB_NAME_WHATEVER
        +PDB_OUTPUT_DIRECTORY
        +PDB_OUTPUT_DIRECTORY_WHATEVER
        +POSITION_INDEPENDENT_CODE
        +POST_INSTALL_SCRIPT
        +PREDEFINED_TARGETS_FOLDER
        +PREFIX
        +PRE_INSTALL_SCRIPT
        +PRIVATE_HEADER
        +PROCESSORS
        +PROCESSOR_AFFINITY
        +PROJECT_LABEL
        +PUBLIC_HEADER
        +REPORT_UNDEFINED_PROPERTIES
        +REQUIRED_FILES
        +RESOURCE
        +RESOURCE_LOCK
        +RULE_LAUNCH_COMPILE
        +RULE_LAUNCH_COMPILE
        +RULE_LAUNCH_COMPILE
        +RULE_LAUNCH_CUSTOM
        +RULE_LAUNCH_CUSTOM
        +RULE_LAUNCH_CUSTOM
        +RULE_LAUNCH_LINK
        +RULE_LAUNCH_LINK
        +RULE_LAUNCH_LINK
        +RULE_MESSAGES
        +RUNTIME_OUTPUT_DIRECTORY
        +RUNTIME_OUTPUT_DIRECTORY_WHATEVER
        +RUNTIME_OUTPUT_NAME
        +RUNTIME_OUTPUT_NAME_WHATEVER
        +RUN_SERIAL
        +SKIP_AUTOGEN
        +SKIP_AUTOMOC
        +SKIP_AUTORCC
        +SKIP_AUTOUIC
        +SKIP_BUILD_RPATH
        +SKIP_RETURN_CODE
        +SOURCES
        +SOURCE_DIR
        +SOURCE_DIR
        +SOVERSION
        +STATIC_LIBRARY_FLAGS
        +STATIC_LIBRARY_FLAGS_WHATEVER
        +STATIC_LIBRARY_OPTIONS
        +STRINGS
        +SUBDIRECTORIES
        +SUFFIX
        +SYMBOLIC
        +TARGET_ARCHIVES_MAY_BE_SHARED_LIBS
        +TARGET_MESSAGES
        +TARGET_SUPPORTS_SHARED_LIBS
        +TESTS
        +TEST_INCLUDE_FILE
        +TEST_INCLUDE_FILES
        +TIMEOUT
        +TIMEOUT_AFTER_MATCH
        +TYPE
        +TYPE
        +USE_FOLDERS
        +VALUE
        +VARIABLES
        +VERSION
        +VISIBILITY_INLINES_HIDDEN
        +VS_CONFIGURATION_TYPE
        +VS_COPY_TO_OUT_DIR
        +VS_CSHARP_WHATEVER
        +VS_DEBUGGER_COMMAND
        +VS_DEBUGGER_COMMAND_ARGUMENTS
        +VS_DEBUGGER_ENVIRONMENT
        +VS_DEBUGGER_WORKING_DIRECTORY
        +VS_DEPLOYMENT_CONTENT
        +VS_DEPLOYMENT_LOCATION
        +VS_DOTNET_REFERENCEPROP_WHATEVER
        +VS_DOTNET_REFERENCES
        +VS_DOTNET_REFERENCES_COPY_LOCAL
        +VS_DOTNET_REFERENCE_WHATEVER
        +VS_GLOBAL_WHATEVER
        +VS_GLOBAL_KEYWORD
        +VS_GLOBAL_PROJECT_TYPES
        +VS_GLOBAL_ROOTNAMESPACE
        +VS_GLOBAL_SECTION_POST_WHATEVER
        +VS_GLOBAL_SECTION_PRE_WHATEVER
        +VS_INCLUDE_IN_VSIX
        +VS_IOT_STARTUP_TASK
        +VS_KEYWORD
        +VS_RESOURCE_GENERATOR
        +VS_SCC_AUXPATH
        +VS_SCC_LOCALPATH
        +VS_SCC_PROJECTNAME
        +VS_SCC_PROVIDER
        +VS_SDK_REFERENCES
        +VS_SHADER_DISABLE_OPTIMIZATIONS
        +VS_SHADER_ENABLE_DEBUG
        +VS_SHADER_ENTRYPOINT
        +VS_SHADER_FLAGS
        +VS_SHADER_MODEL
        +VS_SHADER_OBJECT_FILE_NAME
        +VS_SHADER_OUTPUT_HEADER_FILE
        +VS_SHADER_TYPE
        +VS_SHADER_VARIABLE_NAME
        +VS_STARTUP_PROJECT
        +VS_TOOL_OVERRIDE
        +VS_USER_PROPS
        +VS_WINRT_COMPONENT
        +VS_WINRT_EXTENSIONS
        +VS_WINRT_REFERENCES
        +VS_XAML_TYPE
        +WILL_FAIL
        +WIN32_EXECUTABLE
        +WINDOWS_EXPORT_ALL_SYMBOLS
        +WORKING_DIRECTORY
        +WRAP_EXCLUDE
        +XCODE_ATTRIBUTE_WHATEVER
        +XCODE_EMIT_EFFECTIVE_PLATFORM_NAME
        +XCODE_EXPLICIT_FILE_TYPE
        +XCODE_EXPLICIT_FILE_TYPE
        +XCODE_FILE_ATTRIBUTES
        +XCODE_LAST_KNOWN_FILE_TYPE
        +XCODE_PRODUCT_TYPE
        +XCODE_SCHEME_ADDRESS_SANITIZER
        +XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
        +XCODE_SCHEME_ARGUMENTS
        +XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
        +XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
        +XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
        +XCODE_SCHEME_ENVIRONMENT
        +XCODE_SCHEME_EXECUTABLE
        +XCODE_SCHEME_GUARD_MALLOC
        +XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
        +XCODE_SCHEME_MALLOC_GUARD_EDGES
        +XCODE_SCHEME_MALLOC_SCRIBBLE
        +XCODE_SCHEME_MALLOC_STACK
        +XCODE_SCHEME_THREAD_SANITIZER
        +XCODE_SCHEME_THREAD_SANITIZER_STOP
        +XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
        +XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
        +XCODE_SCHEME_ZOMBIE_OBJECTS
        +XCTEST
        +cxx_aggregate_default_initializers
        +cxx_alias_templates
        +cxx_alignas
        +cxx_alignof
        +cxx_attributes
        +cxx_attribute_deprecated
        +cxx_auto_type
        +cxx_binary_literals
        +cxx_constexpr
        +cxx_contextual_conversions
        +cxx_decltype_incomplete_return_types
        +cxx_decltype
        +cxx_decltype_auto
        +cxx_default_function_template_args
        +cxx_defaulted_functions
        +cxx_defaulted_move_initializers
        +cxx_delegating_constructors
        +cxx_deleted_functions
        +cxx_digit_separators
        +cxx_enum_forward_declarations
        +cxx_explicit_conversions
        +cxx_extended_friend_declarations
        +cxx_extern_templates
        +cxx_final
        +cxx_func_identifier
        +cxx_generalized_initializers
        +cxx_generic_lambdas
        +cxx_inheriting_constructors
        +cxx_inline_namespaces
        +cxx_lambdas
        +cxx_lambda_init_captures
        +cxx_local_type_template_args
        +cxx_long_long_type
        +cxx_noexcept
        +cxx_nonstatic_member_init
        +cxx_nullptr
        +cxx_override
        +cxx_range_for
        +cxx_raw_string_literals
        +cxx_reference_qualified_functions
        +cxx_relaxed_constexpr
        +cxx_return_type_deduction
        +cxx_right_angle_brackets
        +cxx_rvalue_references
        +cxx_sizeof_member
        +cxx_static_assert
        +cxx_strong_enums
        +cxx_thread_local
        +cxx_trailing_return_types
        +cxx_unicode_literals
        +cxx_uniform_initialization
        +cxx_unrestricted_unions
        +cxx_user_literals
        +cxx_variable_templates
        +cxx_variadic_macros
        +cxx_variadic_templates
        +cxx_template_template_parameters
        +
        +----------------------------------------------------
        +
        +[
        +	["property", "WHATEVER_OUTPUT_NAME"],
        +	["property", "WHATEVER_POSTFIX"],
        +	["property", "WHATEVER_CLANG_TIDY"],
        +	["property", "WHATEVER_COMPILER_LAUNCHER"],
        +	["property", "WHATEVER_CPPCHECK"],
        +	["property", "WHATEVER_CPPLINT"],
        +	["property", "WHATEVER_INCLUDE_WHAT_YOU_USE"],
        +	["property", "WHATEVER_VISIBILITY_PRESET"],
        +	["property", "ABSTRACT"],
        +	["property", "ADDITIONAL_MAKE_CLEAN_FILES"],
        +	["property", "ADVANCED"],
        +	["property", "ALIASED_TARGET"],
        +	["property", "ALLOW_DUPLICATE_CUSTOM_TARGETS"],
        +	["property", "ANDROID_ANT_ADDITIONAL_OPTIONS"],
        +	["property", "ANDROID_API"],
        +	["property", "ANDROID_API_MIN"],
        +	["property", "ANDROID_ARCH"],
        +	["property", "ANDROID_ASSETS_DIRECTORIES"],
        +	["property", "ANDROID_GUI"],
        +	["property", "ANDROID_JAR_DEPENDENCIES"],
        +	["property", "ANDROID_NATIVE_LIB_DEPENDENCIES"],
        +	["property", "ANDROID_NATIVE_LIB_DIRECTORIES"],
        +	["property", "ANDROID_PROCESS_MAX"],
        +	["property", "ANDROID_PROGUARD"],
        +	["property", "ANDROID_PROGUARD_CONFIG_PATH"],
        +	["property", "ANDROID_SECURE_PROPS_PATH"],
        +	["property", "ANDROID_SKIP_ANT_STEP"],
        +	["property", "ANDROID_STL_TYPE"],
        +	["property", "ARCHIVE_OUTPUT_DIRECTORY"],
        +	["property", "ARCHIVE_OUTPUT_DIRECTORY_WHATEVER"],
        +	["property", "ARCHIVE_OUTPUT_NAME"],
        +	["property", "ARCHIVE_OUTPUT_NAME_WHATEVER"],
        +	["property", "ATTACHED_FILES"],
        +	["property", "ATTACHED_FILES_ON_FAIL"],
        +	["property", "AUTOGEN_BUILD_DIR"],
        +	["property", "AUTOGEN_ORIGIN_DEPENDS"],
        +	["property", "AUTOGEN_PARALLEL"],
        +	["property", "AUTOGEN_SOURCE_GROUP"],
        +	["property", "AUTOGEN_TARGETS_FOLDER"],
        +	["property", "AUTOGEN_TARGET_DEPENDS"],
        +	["property", "AUTOMOC"],
        +	["property", "AUTOMOC_COMPILER_PREDEFINES"],
        +	["property", "AUTOMOC_DEPEND_FILTERS"],
        +	["property", "AUTOMOC_EXECUTABLE"],
        +	["property", "AUTOMOC_MACRO_NAMES"],
        +	["property", "AUTOMOC_MOC_OPTIONS"],
        +	["property", "AUTOMOC_SOURCE_GROUP"],
        +	["property", "AUTOMOC_TARGETS_FOLDER"],
        +	["property", "AUTORCC"],
        +	["property", "AUTORCC_EXECUTABLE"],
        +	["property", "AUTORCC_OPTIONS"],
        +	["property", "AUTORCC_OPTIONS"],
        +	["property", "AUTORCC_SOURCE_GROUP"],
        +	["property", "AUTOUIC"],
        +	["property", "AUTOUIC_EXECUTABLE"],
        +	["property", "AUTOUIC_OPTIONS"],
        +	["property", "AUTOUIC_OPTIONS"],
        +	["property", "AUTOUIC_SEARCH_PATHS"],
        +	["property", "BINARY_DIR"],
        +	["property", "BINARY_DIR"],
        +	["property", "BUILDSYSTEM_TARGETS"],
        +	["property", "BUILD_RPATH"],
        +	["property", "BUILD_RPATH_USE_ORIGIN"],
        +	["property", "BUILD_WITH_INSTALL_NAME_DIR"],
        +	["property", "BUILD_WITH_INSTALL_RPATH"],
        +	["property", "BUNDLE"],
        +	["property", "BUNDLE_EXTENSION"],
        +	["property", "CACHE_VARIABLES"],
        +	["property", "CLEAN_NO_CUSTOM"],
        +	["property", "COMMON_LANGUAGE_RUNTIME"],
        +	["property", "COMPATIBLE_INTERFACE_BOOL"],
        +	["property", "COMPATIBLE_INTERFACE_NUMBER_MAX"],
        +	["property", "COMPATIBLE_INTERFACE_NUMBER_MIN"],
        +	["property", "COMPATIBLE_INTERFACE_STRING"],
        +	["property", "COMPILE_DEFINITIONS"],
        +	["property", "COMPILE_DEFINITIONS"],
        +	["property", "COMPILE_DEFINITIONS"],
        +	["property", "COMPILE_DEFINITIONS_WHATEVER"],
        +	["property", "COMPILE_DEFINITIONS_WHATEVER"],
        +	["property", "COMPILE_DEFINITIONS_WHATEVER"],
        +	["property", "COMPILE_FEATURES"],
        +	["property", "COMPILE_FLAGS"],
        +	["property", "COMPILE_FLAGS"],
        +	["property", "COMPILE_OPTIONS"],
        +	["property", "COMPILE_OPTIONS"],
        +	["property", "COMPILE_OPTIONS"],
        +	["property", "COMPILE_PDB_NAME"],
        +	["property", "COMPILE_PDB_NAME_WHATEVER"],
        +	["property", "COMPILE_PDB_OUTPUT_DIRECTORY"],
        +	["property", "COMPILE_PDB_OUTPUT_DIRECTORY_WHATEVER"],
        +	["property", "COST"],
        +	["property", "CPACK_DESKTOP_SHORTCUTS"],
        +	["property", "CPACK_NEVER_OVERWRITE"],
        +	["property", "CPACK_PERMANENT"],
        +	["property", "CPACK_STARTUP_SHORTCUTS"],
        +	["property", "CPACK_START_MENU_SHORTCUTS"],
        +	["property", "CPACK_WIX_ACL"],
        +	["property", "CROSSCOMPILING_EMULATOR"],
        +	["property", "CUDA_EXTENSIONS"],
        +	["property", "CUDA_PTX_COMPILATION"],
        +	["property", "CUDA_RESOLVE_DEVICE_SYMBOLS"],
        +	["property", "CUDA_SEPARABLE_COMPILATION"],
        +	["property", "CUDA_STANDARD"],
        +	["property", "CUDA_STANDARD_REQUIRED"],
        +	["property", "CXX_EXTENSIONS"],
        +	["property", "CXX_STANDARD"],
        +	["property", "CXX_STANDARD_REQUIRED"],
        +	["property", "C_EXTENSIONS"],
        +	["property", "C_STANDARD"],
        +	["property", "C_STANDARD_REQUIRED"],
        +	["property", "DEBUG_CONFIGURATIONS"],
        +	["property", "DEBUG_POSTFIX"],
        +	["property", "DEFINE_SYMBOL"],
        +	["property", "DEFINITIONS"],
        +	["property", "DEPENDS"],
        +	["property", "DEPLOYMENT_ADDITIONAL_FILES"],
        +	["property", "DEPLOYMENT_REMOTE_DIRECTORY"],
        +	["property", "DISABLED"],
        +	["property", "DISABLED_FEATURES"],
        +	["property", "ECLIPSE_EXTRA_CPROJECT_CONTENTS"],
        +	["property", "ECLIPSE_EXTRA_NATURES"],
        +	["property", "ENABLED_FEATURES"],
        +	["property", "ENABLED_LANGUAGES"],
        +	["property", "ENABLE_EXPORTS"],
        +	["property", "ENVIRONMENT"],
        +	["property", "EXCLUDE_FROM_ALL"],
        +	["property", "EXCLUDE_FROM_ALL"],
        +	["property", "EXCLUDE_FROM_DEFAULT_BUILD"],
        +	["property", "EXCLUDE_FROM_DEFAULT_BUILD_WHATEVER"],
        +	["property", "EXPORT_NAME"],
        +	["property", "EXPORT_PROPERTIES"],
        +	["property", "EXTERNAL_OBJECT"],
        +	["property", "EchoString"],
        +	["property", "FAIL_REGULAR_EXPRESSION"],
        +	["property", "FIND_LIBRARY_USE_LIB32_PATHS"],
        +	["property", "FIND_LIBRARY_USE_LIB64_PATHS"],
        +	["property", "FIND_LIBRARY_USE_LIBX32_PATHS"],
        +	["property", "FIND_LIBRARY_USE_OPENBSD_VERSIONING"],
        +	["property", "FIXTURES_CLEANUP"],
        +	["property", "FIXTURES_REQUIRED"],
        +	["property", "FIXTURES_SETUP"],
        +	["property", "FOLDER"],
        +	["property", "FRAMEWORK"],
        +	["property", "Fortran_FORMAT"],
        +	["property", "Fortran_FORMAT"],
        +	["property", "Fortran_MODULE_DIRECTORY"],
        +	["property", "GENERATED"],
        +	["property", "GENERATOR_FILE_NAME"],
        +	["property", "GENERATOR_IS_MULTI_CONFIG"],
        +	["property", "GHS_INTEGRITY_APP"],
        +	["property", "GHS_NO_SOURCE_GROUP_FILE"],
        +	["property", "GLOBAL_DEPENDS_DEBUG_MODE"],
        +	["property", "GLOBAL_DEPENDS_NO_CYCLES"],
        +	["property", "GNUtoMS"],
        +	["property", "HAS_CXX"],
        +	["property", "HEADER_FILE_ONLY"],
        +	["property", "HELPSTRING"],
        +	["property", "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"],
        +	["property", "IMPLICIT_DEPENDS_INCLUDE_TRANSFORM"],
        +	["property", "IMPORTED"],
        +	["property", "IMPORTED_COMMON_LANGUAGE_RUNTIME"],
        +	["property", "IMPORTED_CONFIGURATIONS"],
        +	["property", "IMPORTED_GLOBAL"],
        +	["property", "IMPORTED_IMPLIB"],
        +	["property", "IMPORTED_IMPLIB_WHATEVER"],
        +	["property", "IMPORTED_LIBNAME"],
        +	["property", "IMPORTED_LIBNAME_WHATEVER"],
        +	["property", "IMPORTED_LINK_DEPENDENT_LIBRARIES"],
        +	["property", "IMPORTED_LINK_DEPENDENT_LIBRARIES_WHATEVER"],
        +	["property", "IMPORTED_LINK_INTERFACE_LANGUAGES"],
        +	["property", "IMPORTED_LINK_INTERFACE_LANGUAGES_WHATEVER"],
        +	["property", "IMPORTED_LINK_INTERFACE_LIBRARIES"],
        +	["property", "IMPORTED_LINK_INTERFACE_LIBRARIES_WHATEVER"],
        +	["property", "IMPORTED_LINK_INTERFACE_MULTIPLICITY"],
        +	["property", "IMPORTED_LINK_INTERFACE_MULTIPLICITY_WHATEVER"],
        +	["property", "IMPORTED_LOCATION"],
        +	["property", "IMPORTED_LOCATION_WHATEVER"],
        +	["property", "IMPORTED_NO_SONAME"],
        +	["property", "IMPORTED_NO_SONAME_WHATEVER"],
        +	["property", "IMPORTED_OBJECTS"],
        +	["property", "IMPORTED_OBJECTS_WHATEVER"],
        +	["property", "IMPORTED_SONAME"],
        +	["property", "IMPORTED_SONAME_WHATEVER"],
        +	["property", "IMPORT_PREFIX"],
        +	["property", "IMPORT_SUFFIX"],
        +	["property", "INCLUDE_DIRECTORIES"],
        +	["property", "INCLUDE_DIRECTORIES"],
        +	["property", "INCLUDE_DIRECTORIES"],
        +	["property", "INCLUDE_REGULAR_EXPRESSION"],
        +	["property", "INSTALL_NAME_DIR"],
        +	["property", "INSTALL_RPATH"],
        +	["property", "INSTALL_RPATH_USE_LINK_PATH"],
        +	["property", "INTERFACE_AUTOUIC_OPTIONS"],
        +	["property", "INTERFACE_COMPILE_DEFINITIONS"],
        +	["property", "INTERFACE_COMPILE_FEATURES"],
        +	["property", "INTERFACE_COMPILE_OPTIONS"],
        +	["property", "INTERFACE_INCLUDE_DIRECTORIES"],
        +	["property", "INTERFACE_LINK_DEPENDS"],
        +	["property", "INTERFACE_LINK_DIRECTORIES"],
        +	["property", "INTERFACE_LINK_LIBRARIES"],
        +	["property", "INTERFACE_LINK_OPTIONS"],
        +	["property", "INTERFACE_POSITION_INDEPENDENT_CODE"],
        +	["property", "INTERFACE_SOURCES"],
        +	["property", "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"],
        +	["property", "INTERPROCEDURAL_OPTIMIZATION"],
        +	["property", "INTERPROCEDURAL_OPTIMIZATION"],
        +	["property", "INTERPROCEDURAL_OPTIMIZATION_WHATEVER"],
        +	["property", "INTERPROCEDURAL_OPTIMIZATION_WHATEVER"],
        +	["property", "IN_TRY_COMPILE"],
        +	["property", "IOS_INSTALL_COMBINED"],
        +	["property", "JOB_POOLS"],
        +	["property", "JOB_POOL_COMPILE"],
        +	["property", "JOB_POOL_LINK"],
        +	["property", "KEEP_EXTENSION"],
        +	["property", "LABELS"],
        +	["property", "LABELS"],
        +	["property", "LABELS"],
        +	["property", "LABELS"],
        +	["property", "LANGUAGE"],
        +	["property", "LIBRARY_OUTPUT_DIRECTORY"],
        +	["property", "LIBRARY_OUTPUT_DIRECTORY_WHATEVER"],
        +	["property", "LIBRARY_OUTPUT_NAME"],
        +	["property", "LIBRARY_OUTPUT_NAME_WHATEVER"],
        +	["property", "LINKER_LANGUAGE"],
        +	["property", "LINK_DEPENDS"],
        +	["property", "LINK_DEPENDS_NO_SHARED"],
        +	["property", "LINK_DIRECTORIES"],
        +	["property", "LINK_DIRECTORIES"],
        +	["property", "LINK_FLAGS"],
        +	["property", "LINK_FLAGS_WHATEVER"],
        +	["property", "LINK_INTERFACE_LIBRARIES"],
        +	["property", "LINK_INTERFACE_LIBRARIES_WHATEVER"],
        +	["property", "LINK_INTERFACE_MULTIPLICITY"],
        +	["property", "LINK_INTERFACE_MULTIPLICITY_WHATEVER"],
        +	["property", "LINK_LIBRARIES"],
        +	["property", "LINK_OPTIONS"],
        +	["property", "LINK_OPTIONS"],
        +	["property", "LINK_SEARCH_END_STATIC"],
        +	["property", "LINK_SEARCH_START_STATIC"],
        +	["property", "LINK_WHAT_YOU_USE"],
        +	["property", "LISTFILE_STACK"],
        +	["property", "LOCATION"],
        +	["property", "LOCATION"],
        +	["property", "LOCATION_WHATEVER"],
        +	["property", "MACOSX_BUNDLE"],
        +	["property", "MACOSX_BUNDLE_INFO_PLIST"],
        +	["property", "MACOSX_FRAMEWORK_INFO_PLIST"],
        +	["property", "MACOSX_PACKAGE_LOCATION"],
        +	["property", "MACOSX_RPATH"],
        +	["property", "MACROS"],
        +	["property", "MANUALLY_ADDED_DEPENDENCIES"],
        +	["property", "MAP_IMPORTED_CONFIG_WHATEVER"],
        +	["property", "MEASUREMENT"],
        +	["property", "MODIFIED"],
        +	["property", "NAME"],
        +	["property", "NO_SONAME"],
        +	["property", "NO_SYSTEM_FROM_IMPORTED"],
        +	["property", "OBJECT_DEPENDS"],
        +	["property", "OBJECT_OUTPUTS"],
        +	["property", "OSX_ARCHITECTURES"],
        +	["property", "OSX_ARCHITECTURES_WHATEVER"],
        +	["property", "OUTPUT_NAME"],
        +	["property", "OUTPUT_NAME_WHATEVER"],
        +	["property", "PACKAGES_FOUND"],
        +	["property", "PACKAGES_NOT_FOUND"],
        +	["property", "PARENT_DIRECTORY"],
        +	["property", "PASS_REGULAR_EXPRESSION"],
        +	["property", "PDB_NAME"],
        +	["property", "PDB_NAME_WHATEVER"],
        +	["property", "PDB_OUTPUT_DIRECTORY"],
        +	["property", "PDB_OUTPUT_DIRECTORY_WHATEVER"],
        +	["property", "POSITION_INDEPENDENT_CODE"],
        +	["property", "POST_INSTALL_SCRIPT"],
        +	["property", "PREDEFINED_TARGETS_FOLDER"],
        +	["property", "PREFIX"],
        +	["property", "PRE_INSTALL_SCRIPT"],
        +	["property", "PRIVATE_HEADER"],
        +	["property", "PROCESSORS"],
        +	["property", "PROCESSOR_AFFINITY"],
        +	["property", "PROJECT_LABEL"],
        +	["property", "PUBLIC_HEADER"],
        +	["property", "REPORT_UNDEFINED_PROPERTIES"],
        +	["property", "REQUIRED_FILES"],
        +	["property", "RESOURCE"],
        +	["property", "RESOURCE_LOCK"],
        +	["property", "RULE_LAUNCH_COMPILE"],
        +	["property", "RULE_LAUNCH_COMPILE"],
        +	["property", "RULE_LAUNCH_COMPILE"],
        +	["property", "RULE_LAUNCH_CUSTOM"],
        +	["property", "RULE_LAUNCH_CUSTOM"],
        +	["property", "RULE_LAUNCH_CUSTOM"],
        +	["property", "RULE_LAUNCH_LINK"],
        +	["property", "RULE_LAUNCH_LINK"],
        +	["property", "RULE_LAUNCH_LINK"],
        +	["property", "RULE_MESSAGES"],
        +	["property", "RUNTIME_OUTPUT_DIRECTORY"],
        +	["property", "RUNTIME_OUTPUT_DIRECTORY_WHATEVER"],
        +	["property", "RUNTIME_OUTPUT_NAME"],
        +	["property", "RUNTIME_OUTPUT_NAME_WHATEVER"],
        +	["property", "RUN_SERIAL"],
        +	["property", "SKIP_AUTOGEN"],
        +	["property", "SKIP_AUTOMOC"],
        +	["property", "SKIP_AUTORCC"],
        +	["property", "SKIP_AUTOUIC"],
        +	["property", "SKIP_BUILD_RPATH"],
        +	["property", "SKIP_RETURN_CODE"],
        +	["property", "SOURCES"],
        +	["property", "SOURCE_DIR"],
        +	["property", "SOURCE_DIR"],
        +	["property", "SOVERSION"],
        +	["property", "STATIC_LIBRARY_FLAGS"],
        +	["property", "STATIC_LIBRARY_FLAGS_WHATEVER"],
        +	["property", "STATIC_LIBRARY_OPTIONS"],
        +	["property", "STRINGS"],
        +	["property", "SUBDIRECTORIES"],
        +	["property", "SUFFIX"],
        +	["property", "SYMBOLIC"],
        +	["property", "TARGET_ARCHIVES_MAY_BE_SHARED_LIBS"],
        +	["property", "TARGET_MESSAGES"],
        +	["property", "TARGET_SUPPORTS_SHARED_LIBS"],
        +	["property", "TESTS"],
        +	["property", "TEST_INCLUDE_FILE"],
        +	["property", "TEST_INCLUDE_FILES"],
        +	["property", "TIMEOUT"],
        +	["property", "TIMEOUT_AFTER_MATCH"],
        +	["property", "TYPE"],
        +	["property", "TYPE"],
        +	["property", "USE_FOLDERS"],
        +	["property", "VALUE"],
        +	["property", "VARIABLES"],
        +	["property", "VERSION"],
        +	["property", "VISIBILITY_INLINES_HIDDEN"],
        +	["property", "VS_CONFIGURATION_TYPE"],
        +	["property", "VS_COPY_TO_OUT_DIR"],
        +	["property", "VS_CSHARP_WHATEVER"],
        +	["property", "VS_DEBUGGER_COMMAND"],
        +	["property", "VS_DEBUGGER_COMMAND_ARGUMENTS"],
        +	["property", "VS_DEBUGGER_ENVIRONMENT"],
        +	["property", "VS_DEBUGGER_WORKING_DIRECTORY"],
        +	["property", "VS_DEPLOYMENT_CONTENT"],
        +	["property", "VS_DEPLOYMENT_LOCATION"],
        +	["property", "VS_DOTNET_REFERENCEPROP_WHATEVER"],
        +	["property", "VS_DOTNET_REFERENCES"],
        +	["property", "VS_DOTNET_REFERENCES_COPY_LOCAL"],
        +	["property", "VS_DOTNET_REFERENCE_WHATEVER"],
        +	["property", "VS_GLOBAL_WHATEVER"],
        +	["property", "VS_GLOBAL_KEYWORD"],
        +	["property", "VS_GLOBAL_PROJECT_TYPES"],
        +	["property", "VS_GLOBAL_ROOTNAMESPACE"],
        +	["property", "VS_GLOBAL_SECTION_POST_WHATEVER"],
        +	["property", "VS_GLOBAL_SECTION_PRE_WHATEVER"],
        +	["property", "VS_INCLUDE_IN_VSIX"],
        +	["property", "VS_IOT_STARTUP_TASK"],
        +	["property", "VS_KEYWORD"],
        +	["property", "VS_RESOURCE_GENERATOR"],
        +	["property", "VS_SCC_AUXPATH"],
        +	["property", "VS_SCC_LOCALPATH"],
        +	["property", "VS_SCC_PROJECTNAME"],
        +	["property", "VS_SCC_PROVIDER"],
        +	["property", "VS_SDK_REFERENCES"],
        +	["property", "VS_SHADER_DISABLE_OPTIMIZATIONS"],
        +	["property", "VS_SHADER_ENABLE_DEBUG"],
        +	["property", "VS_SHADER_ENTRYPOINT"],
        +	["property", "VS_SHADER_FLAGS"],
        +	["property", "VS_SHADER_MODEL"],
        +	["property", "VS_SHADER_OBJECT_FILE_NAME"],
        +	["property", "VS_SHADER_OUTPUT_HEADER_FILE"],
        +	["property", "VS_SHADER_TYPE"],
        +	["property", "VS_SHADER_VARIABLE_NAME"],
        +	["property", "VS_STARTUP_PROJECT"],
        +	["property", "VS_TOOL_OVERRIDE"],
        +	["property", "VS_USER_PROPS"],
        +	["property", "VS_WINRT_COMPONENT"],
        +	["property", "VS_WINRT_EXTENSIONS"],
        +	["property", "VS_WINRT_REFERENCES"],
        +	["property", "VS_XAML_TYPE"],
        +	["property", "WILL_FAIL"],
        +	["property", "WIN32_EXECUTABLE"],
        +	["property", "WINDOWS_EXPORT_ALL_SYMBOLS"],
        +	["property", "WORKING_DIRECTORY"],
        +	["property", "WRAP_EXCLUDE"],
        +	["property", "XCODE_ATTRIBUTE_WHATEVER"],
        +	["property", "XCODE_EMIT_EFFECTIVE_PLATFORM_NAME"],
        +	["property", "XCODE_EXPLICIT_FILE_TYPE"],
        +	["property", "XCODE_EXPLICIT_FILE_TYPE"],
        +	["property", "XCODE_FILE_ATTRIBUTES"],
        +	["property", "XCODE_LAST_KNOWN_FILE_TYPE"],
        +	["property", "XCODE_PRODUCT_TYPE"],
        +	["property", "XCODE_SCHEME_ADDRESS_SANITIZER"],
        +	["property", "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN"],
        +	["property", "XCODE_SCHEME_ARGUMENTS"],
        +	["property", "XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"],
        +	["property", "XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"],
        +	["property", "XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"],
        +	["property", "XCODE_SCHEME_ENVIRONMENT"],
        +	["property", "XCODE_SCHEME_EXECUTABLE"],
        +	["property", "XCODE_SCHEME_GUARD_MALLOC"],
        +	["property", "XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"],
        +	["property", "XCODE_SCHEME_MALLOC_GUARD_EDGES"],
        +	["property", "XCODE_SCHEME_MALLOC_SCRIBBLE"],
        +	["property", "XCODE_SCHEME_MALLOC_STACK"],
        +	["property", "XCODE_SCHEME_THREAD_SANITIZER"],
        +	["property", "XCODE_SCHEME_THREAD_SANITIZER_STOP"],
        +	["property", "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"],
        +	["property", "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"],
        +	["property", "XCODE_SCHEME_ZOMBIE_OBJECTS"],
        +	["property", "XCTEST"],
        +	["property", "cxx_aggregate_default_initializers"],
        +	["property", "cxx_alias_templates"],
        +	["property", "cxx_alignas"],
        +	["property", "cxx_alignof"],
        +	["property", "cxx_attributes"],
        +	["property", "cxx_attribute_deprecated"],
        +	["property", "cxx_auto_type"],
        +	["property", "cxx_binary_literals"],
        +	["property", "cxx_constexpr"],
        +	["property", "cxx_contextual_conversions"],
        +	["property", "cxx_decltype_incomplete_return_types"],
        +	["property", "cxx_decltype"],
        +	["property", "cxx_decltype_auto"],
        +	["property", "cxx_default_function_template_args"],
        +	["property", "cxx_defaulted_functions"],
        +	["property", "cxx_defaulted_move_initializers"],
        +	["property", "cxx_delegating_constructors"],
        +	["property", "cxx_deleted_functions"],
        +	["property", "cxx_digit_separators"],
        +	["property", "cxx_enum_forward_declarations"],
        +	["property", "cxx_explicit_conversions"],
        +	["property", "cxx_extended_friend_declarations"],
        +	["property", "cxx_extern_templates"],
        +	["property", "cxx_final"],
        +	["property", "cxx_func_identifier"],
        +	["property", "cxx_generalized_initializers"],
        +	["property", "cxx_generic_lambdas"],
        +	["property", "cxx_inheriting_constructors"],
        +	["property", "cxx_inline_namespaces"],
        +	["property", "cxx_lambdas"],
        +	["property", "cxx_lambda_init_captures"],
        +	["property", "cxx_local_type_template_args"],
        +	["property", "cxx_long_long_type"],
        +	["property", "cxx_noexcept"],
        +	["property", "cxx_nonstatic_member_init"],
        +	["property", "cxx_nullptr"],
        +	["property", "cxx_override"],
        +	["property", "cxx_range_for"],
        +	["property", "cxx_raw_string_literals"],
        +	["property", "cxx_reference_qualified_functions"],
        +	["property", "cxx_relaxed_constexpr"],
        +	["property", "cxx_return_type_deduction"],
        +	["property", "cxx_right_angle_brackets"],
        +	["property", "cxx_rvalue_references"],
        +	["property", "cxx_sizeof_member"],
        +	["property", "cxx_static_assert"],
        +	["property", "cxx_strong_enums"],
        +	["property", "cxx_thread_local"],
        +	["property", "cxx_trailing_return_types"],
        +	["property", "cxx_unicode_literals"],
        +	["property", "cxx_uniform_initialization"],
        +	["property", "cxx_unrestricted_unions"],
        +	["property", "cxx_user_literals"],
        +	["property", "cxx_variable_templates"],
        +	["property", "cxx_variadic_macros"],
        +	["property", "cxx_variadic_templates"],
        +	["property", "cxx_template_template_parameters"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all properties.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/punctuation_feature.test b/tests/languages/cmake/punctuation_feature.test
        new file mode 100644
        index 0000000000..e25101ec1e
        --- /dev/null
        +++ b/tests/languages/cmake/punctuation_feature.test
        @@ -0,0 +1,15 @@
        +${}
        +$<>
        +()
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "${"], ["punctuation", "}"],
        +	["punctuation", "$<"], ["punctuation", ">"],
        +	["punctuation", "("], ["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for punctuation.
        \ No newline at end of file
        diff --git a/tests/languages/cmake/string_feature.test b/tests/languages/cmake/string_feature.test
        new file mode 100644
        index 0000000000..717851d2ea
        --- /dev/null
        +++ b/tests/languages/cmake/string_feature.test
        @@ -0,0 +1,48 @@
        +"This is a string"
        +"This is 
        +multi
        +line
        +string"
        +"${VAR}with${BAR}"
        +"${FOO} with ${BAR}"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", ["\"This is a string\""]],
        +	["string", ["\"This is \r\nmulti\r\nline\r\nstring\""]],
        +	["string", [
        +		"\"",
        +		["interpolation", [
        +			["punctuation", "${"],
        +			["variable", "VAR"],
        +			["punctuation", "}"]
        +		]],
        +		"with",
        +		["interpolation", [
        +			["punctuation", "${"],
        +			["variable", "BAR"],
        +			["punctuation", "}"]
        +		]],
        +		"\""
        +	]],
        +	["string", [
        +		"\"",
        +		["interpolation", [
        +			["punctuation", "${"],
        +			["variable", "FOO"],
        +			["punctuation", "}"]
        +		]],
        +		" with ",
        +		["interpolation", [
        +			["punctuation", "${"],
        +			["variable", "BAR"],
        +			["punctuation", "}"]
        +		]],
        +		"\""
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for strings.
        diff --git a/tests/languages/cmake/variable_feature.test b/tests/languages/cmake/variable_feature.test
        new file mode 100644
        index 0000000000..2ab493ec13
        --- /dev/null
        +++ b/tests/languages/cmake/variable_feature.test
        @@ -0,0 +1,1091 @@
        +WHATEVER_BINARY_DIR
        +WHATEVER_DESCRIPTION
        +WHATEVER_HOMEPAGE_URL
        +WHATEVER_SOURCE_DIR
        +WHATEVER_VERSION
        +WHATEVER_VERSION_MAJOR
        +WHATEVER_VERSION_MINOR
        +WHATEVER_VERSION_PATCH
        +WHATEVER_VERSION_TWEAK
        +WHATEVER_ROOT
        +ANDROID
        +APPLE
        +BORLAND
        +BUILD_SHARED_LIBS
        +CACHE
        +CMAKE_WHATEVER_POSTFIX
        +CMAKE_WHATEVER_ANDROID_TOOLCHAIN_MACHINE
        +CMAKE_WHATEVER_ANDROID_TOOLCHAIN_PREFIX
        +CMAKE_WHATEVER_ANDROID_TOOLCHAIN_SUFFIX
        +CMAKE_WHATEVER_ARCHIVE_APPEND
        +CMAKE_WHATEVER_ARCHIVE_CREATE
        +CMAKE_WHATEVER_ARCHIVE_FINISH
        +CMAKE_WHATEVER_CLANG_TIDY
        +CMAKE_WHATEVER_COMPILER
        +CMAKE_WHATEVER_COMPILER_ABI
        +CMAKE_WHATEVER_COMPILER_AR
        +CMAKE_WHATEVER_COMPILER_ARCHITECTURE_ID
        +CMAKE_WHATEVER_COMPILER_EXTERNAL_TOOLCHAIN
        +CMAKE_WHATEVER_COMPILER_ID
        +CMAKE_WHATEVER_COMPILER_LAUNCHER
        +CMAKE_WHATEVER_COMPILER_LOADED
        +CMAKE_WHATEVER_COMPILER_PREDEFINES_COMMAND
        +CMAKE_WHATEVER_COMPILER_RANLIB
        +CMAKE_WHATEVER_COMPILER_TARGET
        +CMAKE_WHATEVER_COMPILER_VERSION
        +CMAKE_WHATEVER_COMPILER_VERSION_INTERNAL
        +CMAKE_WHATEVER_COMPILE_OBJECT
        +CMAKE_WHATEVER_CPPCHECK
        +CMAKE_WHATEVER_CPPLINT
        +CMAKE_WHATEVER_CREATE_SHARED_LIBRARY
        +CMAKE_WHATEVER_CREATE_SHARED_MODULE
        +CMAKE_WHATEVER_CREATE_STATIC_LIBRARY
        +CMAKE_WHATEVER_FLAGS
        +CMAKE_WHATEVER
        +CMAKE_WHATEVER_INIT
        +CMAKE_WHATEVER_FLAGS_DEBUG
        +CMAKE_WHATEVER_FLAGS_DEBUG_INIT
        +CMAKE_WHATEVER_FLAGS_INIT
        +CMAKE_WHATEVER_FLAGS_MINSIZEREL
        +CMAKE_WHATEVER_FLAGS_MINSIZEREL_INIT
        +CMAKE_WHATEVER_FLAGS_RELEASE
        +CMAKE_WHATEVER_FLAGS_RELEASE_INIT
        +CMAKE_WHATEVER_FLAGS_RELWITHDEBINFO
        +CMAKE_WHATEVER_FLAGS_RELWITHDEBINFO_INIT
        +CMAKE_WHATEVER_IGNORE_EXTENSIONS
        +CMAKE_WHATEVER_IMPLICIT_INCLUDE_DIRECTORIES
        +CMAKE_WHATEVER_IMPLICIT_LINK_DIRECTORIES
        +CMAKE_WHATEVER_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
        +CMAKE_WHATEVER_IMPLICIT_LINK_LIBRARIES
        +CMAKE_WHATEVER_INCLUDE_WHAT_YOU_USE
        +CMAKE_WHATEVER_LIBRARY_ARCHITECTURE
        +CMAKE_WHATEVER_LINKER_PREFERENCE
        +CMAKE_WHATEVER_LINKER_PREFERENCE_PROPAGATES
        +CMAKE_WHATEVER_LINKER_WRAPPER_FLAG
        +CMAKE_WHATEVER_LINKER_WRAPPER_FLAG_SEP
        +CMAKE_WHATEVER_LINK_EXECUTABLE
        +CMAKE_WHATEVER_OUTPUT_EXTENSION
        +CMAKE_WHATEVER_PLATFORM_ID
        +CMAKE_WHATEVER_SIMULATE_ID
        +CMAKE_WHATEVER_SIMULATE_VERSION
        +CMAKE_WHATEVER_SIZEOF_DATA_PTR
        +CMAKE_WHATEVER_SOURCE_FILE_EXTENSIONS
        +CMAKE_WHATEVER_STANDARD_INCLUDE_DIRECTORIES
        +CMAKE_WHATEVER_STANDARD_LIBRARIES
        +CMAKE_WHATEVER_VISIBILITY_PRESET
        +CMAKE_ABSOLUTE_DESTINATION_FILES
        +CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS
        +CMAKE_ANDROID_API
        +CMAKE_ANDROID_API_MIN
        +CMAKE_ANDROID_ARCH
        +CMAKE_ANDROID_ARCH_ABI
        +CMAKE_ANDROID_ARM_MODE
        +CMAKE_ANDROID_ARM_NEON
        +CMAKE_ANDROID_ASSETS_DIRECTORIES
        +CMAKE_ANDROID_GUI
        +CMAKE_ANDROID_JAR_DEPENDENCIES
        +CMAKE_ANDROID_JAR_DIRECTORIES
        +CMAKE_ANDROID_JAVA_SOURCE_DIR
        +CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES
        +CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES
        +CMAKE_ANDROID_NDK
        +CMAKE_ANDROID_NDK_DEPRECATED_HEADERS
        +CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG
        +CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION
        +CMAKE_ANDROID_PROCESS_MAX
        +CMAKE_ANDROID_PROGUARD
        +CMAKE_ANDROID_PROGUARD_CONFIG_PATH
        +CMAKE_ANDROID_SECURE_PROPS_PATH
        +CMAKE_ANDROID_SKIP_ANT_STEP
        +CMAKE_ANDROID_STANDALONE_TOOLCHAIN
        +CMAKE_ANDROID_STL_TYPE
        +CMAKE_APPBUNDLE_PATH
        +CMAKE_AR
        +CMAKE_ARCHIVE_OUTPUT_DIRECTORY
        +CMAKE_ARCHIVE_OUTPUT_DIRECTORY_WHATEVER
        +CMAKE_ARGC
        +CMAKE_ARGV0
        +CMAKE_AUTOGEN_ORIGIN_DEPENDS
        +CMAKE_AUTOGEN_PARALLEL
        +CMAKE_AUTOGEN_VERBOSE
        +CMAKE_AUTOMOC
        +CMAKE_AUTOMOC_COMPILER_PREDEFINES
        +CMAKE_AUTOMOC_DEPEND_FILTERS
        +CMAKE_AUTOMOC_MACRO_NAMES
        +CMAKE_AUTOMOC_MOC_OPTIONS
        +CMAKE_AUTOMOC_RELAXED_MODE
        +CMAKE_AUTORCC
        +CMAKE_AUTORCC_OPTIONS
        +CMAKE_AUTOUIC
        +CMAKE_AUTOUIC_OPTIONS
        +CMAKE_AUTOUIC_SEARCH_PATHS
        +CMAKE_BACKWARDS_COMPATIBILITY
        +CMAKE_BINARY_DIR
        +CMAKE_BUILD_RPATH
        +CMAKE_BUILD_RPATH_USE_ORIGIN
        +CMAKE_BUILD_TOOL
        +CMAKE_BUILD_TYPE
        +CMAKE_BUILD_WITH_INSTALL_NAME_DIR
        +CMAKE_BUILD_WITH_INSTALL_RPATH
        +CMAKE_CACHEFILE_DIR
        +CMAKE_CACHE_MAJOR_VERSION
        +CMAKE_CACHE_MINOR_VERSION
        +CMAKE_CACHE_PATCH_VERSION
        +CMAKE_CFG_INTDIR
        +CMAKE_CL_64
        +CMAKE_CODEBLOCKS_COMPILER_ID
        +CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES
        +CMAKE_CODELITE_USE_TARGETS
        +CMAKE_COLOR_MAKEFILE
        +CMAKE_COMMAND
        +CMAKE_COMPILER_2005
        +CMAKE_COMPILER_IS_GNUCC
        +CMAKE_COMPILER_IS_GNUCXX
        +CMAKE_COMPILER_IS_GNUG77
        +CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY
        +CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_WHATEVER
        +CMAKE_CONFIGURATION_TYPES
        +CMAKE_CPACK_COMMAND
        +CMAKE_CROSSCOMPILING
        +CMAKE_CROSSCOMPILING_EMULATOR
        +CMAKE_CTEST_COMMAND
        +CMAKE_CUDA_EXTENSIONS
        +CMAKE_CUDA_HOST_COMPILER
        +CMAKE_CUDA_SEPARABLE_COMPILATION
        +CMAKE_CUDA_STANDARD
        +CMAKE_CUDA_STANDARD_REQUIRED
        +CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES
        +CMAKE_CURRENT_BINARY_DIR
        +CMAKE_CURRENT_LIST_DIR
        +CMAKE_CURRENT_LIST_FILE
        +CMAKE_CURRENT_LIST_LINE
        +CMAKE_CURRENT_SOURCE_DIR
        +CMAKE_CXX_COMPILE_FEATURES
        +CMAKE_CXX_EXTENSIONS
        +CMAKE_CXX_STANDARD
        +CMAKE_CXX_STANDARD_REQUIRED
        +CMAKE_C_COMPILE_FEATURES
        +CMAKE_C_EXTENSIONS
        +CMAKE_C_STANDARD
        +CMAKE_C_STANDARD_REQUIRED
        +CMAKE_DEBUG_POSTFIX
        +CMAKE_DEBUG_TARGET_PROPERTIES
        +CMAKE_DEPENDS_IN_PROJECT_ONLY
        +CMAKE_DIRECTORY_LABELS
        +CMAKE_DISABLE_FIND_PACKAGE_WHATEVER
        +CMAKE_DL_LIBS
        +CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
        +CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES
        +CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT
        +CMAKE_ECLIPSE_MAKE_ARGUMENTS
        +CMAKE_ECLIPSE_VERSION
        +CMAKE_EDIT_COMMAND
        +CMAKE_ENABLE_EXPORTS
        +CMAKE_ERROR_DEPRECATED
        +CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
        +CMAKE_EXECUTABLE_SUFFIX
        +CMAKE_EXE_LINKER_FLAGS
        +CMAKE_EXE_LINKER_FLAGS_WHATEVER
        +CMAKE_EXE_LINKER_FLAGS_WHATEVER_INIT
        +CMAKE_EXE_LINKER_FLAGS_INIT
        +CMAKE_EXPORT_COMPILE_COMMANDS
        +CMAKE_EXPORT_NO_PACKAGE_REGISTRY
        +CMAKE_EXTRA_GENERATOR
        +CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES
        +CMAKE_FIND_APPBUNDLE
        +CMAKE_FIND_FRAMEWORK
        +CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX
        +CMAKE_FIND_LIBRARY_PREFIXES
        +CMAKE_FIND_LIBRARY_SUFFIXES
        +CMAKE_FIND_NO_INSTALL_PREFIX
        +CMAKE_FIND_PACKAGE_NAME
        +CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
        +CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
        +CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS
        +CMAKE_FIND_PACKAGE_SORT_DIRECTION
        +CMAKE_FIND_PACKAGE_SORT_ORDER
        +CMAKE_FIND_PACKAGE_WARN_NO_MODULE
        +CMAKE_FIND_ROOT_PATH
        +CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
        +CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
        +CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
        +CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
        +CMAKE_FOLDER
        +CMAKE_FRAMEWORK_PATH
        +CMAKE_Fortran_FORMAT
        +CMAKE_Fortran_MODDIR_DEFAULT
        +CMAKE_Fortran_MODDIR_FLAG
        +CMAKE_Fortran_MODOUT_FLAG
        +CMAKE_Fortran_MODULE_DIRECTORY
        +CMAKE_GENERATOR
        +CMAKE_GENERATOR_INSTANCE
        +CMAKE_GENERATOR_PLATFORM
        +CMAKE_GENERATOR_TOOLSET
        +CMAKE_GHS_NO_SOURCE_GROUP_FILE
        +CMAKE_GLOBAL_AUTOGEN_TARGET
        +CMAKE_GLOBAL_AUTOGEN_TARGET_NAME
        +CMAKE_GLOBAL_AUTORCC_TARGET
        +CMAKE_GLOBAL_AUTORCC_TARGET_NAME
        +CMAKE_GNUtoMS
        +CMAKE_HOME_DIRECTORY
        +CMAKE_HOST_APPLE
        +CMAKE_HOST_SOLARIS
        +CMAKE_HOST_SYSTEM
        +CMAKE_HOST_SYSTEM_NAME
        +CMAKE_HOST_SYSTEM_PROCESSOR
        +CMAKE_HOST_SYSTEM_VERSION
        +CMAKE_HOST_UNIX
        +CMAKE_HOST_WIN32
        +CMAKE_IGNORE_PATH
        +CMAKE_IMPORT_LIBRARY_PREFIX
        +CMAKE_IMPORT_LIBRARY_SUFFIX
        +CMAKE_INCLUDE_CURRENT_DIR
        +CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE
        +CMAKE_INCLUDE_DIRECTORIES_BEFORE
        +CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
        +CMAKE_INCLUDE_PATH
        +CMAKE_INSTALL_DEFAULT_COMPONENT_NAME
        +CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
        +CMAKE_INSTALL_MESSAGE
        +CMAKE_INSTALL_NAME_DIR
        +CMAKE_INSTALL_PREFIX
        +CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
        +CMAKE_INSTALL_RPATH
        +CMAKE_INSTALL_RPATH_USE_LINK_PATH
        +CMAKE_INTERNAL_PLATFORM_ABI
        +CMAKE_INTERPROCEDURAL_OPTIMIZATION
        +CMAKE_INTERPROCEDURAL_OPTIMIZATION_WHATEVER
        +CMAKE_IOS_INSTALL_COMBINED
        +CMAKE_JOB_POOLS
        +CMAKE_JOB_POOL_COMPILE
        +CMAKE_JOB_POOL_LINK
        +CMAKE_LIBRARY_ARCHITECTURE
        +CMAKE_LIBRARY_ARCHITECTURE_REGEX
        +CMAKE_LIBRARY_OUTPUT_DIRECTORY
        +CMAKE_LIBRARY_OUTPUT_DIRECTORY_WHATEVER
        +CMAKE_LIBRARY_PATH
        +CMAKE_LIBRARY_PATH_FLAG
        +CMAKE_LINK_DEF_FILE_FLAG
        +CMAKE_LINK_DEPENDS_NO_SHARED
        +CMAKE_LINK_DIRECTORIES_BEFORE
        +CMAKE_LINK_INTERFACE_LIBRARIES
        +CMAKE_LINK_LIBRARY_FILE_FLAG
        +CMAKE_LINK_LIBRARY_FLAG
        +CMAKE_LINK_LIBRARY_SUFFIX
        +CMAKE_LINK_SEARCH_END_STATIC
        +CMAKE_LINK_SEARCH_START_STATIC
        +CMAKE_LINK_WHAT_YOU_USE
        +CMAKE_MACOSX_BUNDLE
        +CMAKE_MACOSX_RPATH
        +CMAKE_MAJOR_VERSION
        +CMAKE_MAKE_PROGRAM
        +CMAKE_MAP_IMPORTED_CONFIG_WHATEVER
        +CMAKE_MATCH_WHATEVER
        +CMAKE_MATCH_COUNT
        +CMAKE_MAXIMUM_RECURSION_DEPTH
        +CMAKE_MFC_FLAG
        +CMAKE_MINIMUM_REQUIRED_VERSION
        +CMAKE_MINOR_VERSION
        +CMAKE_MODULE_LINKER_FLAGS
        +CMAKE_MODULE_LINKER_FLAGS_WHATEVER
        +CMAKE_MODULE_LINKER_FLAGS_WHATEVER_INIT
        +CMAKE_MODULE_LINKER_FLAGS_INIT
        +CMAKE_MODULE_PATH
        +CMAKE_MSVCIDE_RUN_PATH
        +CMAKE_NETRC
        +CMAKE_NETRC_FILE
        +CMAKE_NINJA_OUTPUT_PATH_PREFIX
        +CMAKE_NOT_USING_CONFIG_FLAGS
        +CMAKE_NO_BUILTIN_CHRPATH
        +CMAKE_NO_SYSTEM_FROM_IMPORTED
        +CMAKE_OBJECT_PATH_MAX
        +CMAKE_OSX_ARCHITECTURES
        +CMAKE_OSX_DEPLOYMENT_TARGET
        +CMAKE_OSX_SYSROOT
        +CMAKE_PARENT_LIST_FILE
        +CMAKE_PATCH_VERSION
        +CMAKE_PDB_OUTPUT_DIRECTORY
        +CMAKE_PDB_OUTPUT_DIRECTORY_WHATEVER
        +CMAKE_POLICY_DEFAULT_CMPWHATEVER
        +CMAKE_POLICY_WARNING_CMPWHATEVER
        +CMAKE_POSITION_INDEPENDENT_CODE
        +CMAKE_PREFIX_PATH
        +CMAKE_PROGRAM_PATH
        +CMAKE_PROJECT_WHATEVER_INCLUDE
        +CMAKE_PROJECT_DESCRIPTION
        +CMAKE_PROJECT_HOMEPAGE_URL
        +CMAKE_PROJECT_NAME
        +CMAKE_PROJECT_VERSION
        +CMAKE_PROJECT_VERSION_MAJOR
        +CMAKE_PROJECT_VERSION_MINOR
        +CMAKE_PROJECT_VERSION_PATCH
        +CMAKE_PROJECT_VERSION_TWEAK
        +CMAKE_RANLIB
        +CMAKE_ROOT
        +CMAKE_RULE_MESSAGES
        +CMAKE_RUNTIME_OUTPUT_DIRECTORY
        +CMAKE_RUNTIME_OUTPUT_DIRECTORY_WHATEVER
        +CMAKE_SCRIPT_MODE_FILE
        +CMAKE_SHARED_LIBRARY_PREFIX
        +CMAKE_SHARED_LIBRARY_SUFFIX
        +CMAKE_SHARED_LINKER_FLAGS
        +CMAKE_SHARED_LINKER_FLAGS_WHATEVER
        +CMAKE_SHARED_LINKER_FLAGS_WHATEVER_INIT
        +CMAKE_SHARED_LINKER_FLAGS_INIT
        +CMAKE_SHARED_MODULE_PREFIX
        +CMAKE_SHARED_MODULE_SUFFIX
        +CMAKE_SIZEOF_VOID_P
        +CMAKE_SKIP_BUILD_RPATH
        +CMAKE_SKIP_INSTALL_ALL_DEPENDENCY
        +CMAKE_SKIP_INSTALL_RPATH
        +CMAKE_SKIP_INSTALL_RULES
        +CMAKE_SKIP_RPATH
        +CMAKE_SOURCE_DIR
        +CMAKE_STAGING_PREFIX
        +CMAKE_STATIC_LIBRARY_PREFIX
        +CMAKE_STATIC_LIBRARY_SUFFIX
        +CMAKE_STATIC_LINKER_FLAGS
        +CMAKE_STATIC_LINKER_FLAGS_WHATEVER
        +CMAKE_STATIC_LINKER_FLAGS_WHATEVER_INIT
        +CMAKE_STATIC_LINKER_FLAGS_INIT
        +CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS
        +CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE
        +CMAKE_SUPPRESS_REGENERATION
        +CMAKE_SYSROOT
        +CMAKE_SYSROOT_COMPILE
        +CMAKE_SYSROOT_LINK
        +CMAKE_SYSTEM
        +CMAKE_SYSTEM_APPBUNDLE_PATH
        +CMAKE_SYSTEM_FRAMEWORK_PATH
        +CMAKE_SYSTEM_IGNORE_PATH
        +CMAKE_SYSTEM_INCLUDE_PATH
        +CMAKE_SYSTEM_LIBRARY_PATH
        +CMAKE_SYSTEM_NAME
        +CMAKE_SYSTEM_PREFIX_PATH
        +CMAKE_SYSTEM_PROCESSOR
        +CMAKE_SYSTEM_PROGRAM_PATH
        +CMAKE_SYSTEM_VERSION
        +CMAKE_Swift_LANGUAGE_VERSION
        +CMAKE_TOOLCHAIN_FILE
        +CMAKE_TRY_COMPILE_CONFIGURATION
        +CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
        +CMAKE_TRY_COMPILE_TARGET_TYPE
        +CMAKE_TWEAK_VERSION
        +CMAKE_USER_MAKE_RULES_OVERRIDE
        +CMAKE_USER_MAKE_RULES_OVERRIDE_WHATEVER
        +CMAKE_USE_RELATIVE_PATHS
        +CMAKE_VERBOSE_MAKEFILE
        +CMAKE_VERSION
        +CMAKE_VISIBILITY_INLINES_HIDDEN
        +CMAKE_VS_DEVENV_COMMAND
        +CMAKE_VS_GLOBALS
        +CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
        +CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD
        +CMAKE_VS_INTEL_Fortran_PROJECT_VERSION
        +CMAKE_VS_MSBUILD_COMMAND
        +CMAKE_VS_NsightTegra_VERSION
        +CMAKE_VS_PLATFORM_NAME
        +CMAKE_VS_PLATFORM_TOOLSET
        +CMAKE_VS_PLATFORM_TOOLSET_CUDA
        +CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
        +CMAKE_VS_PLATFORM_TOOLSET_VERSION
        +CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
        +CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES
        +CMAKE_VS_SDK_INCLUDE_DIRECTORIES
        +CMAKE_VS_SDK_LIBRARY_DIRECTORIES
        +CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES
        +CMAKE_VS_SDK_REFERENCE_DIRECTORIES
        +CMAKE_VS_SDK_SOURCE_DIRECTORIES
        +CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
        +CMAKE_VS_WINRT_BY_DEFAULT
        +CMAKE_WARN_DEPRECATED
        +CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
        +CMAKE_WIN32_EXECUTABLE
        +CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
        +CMAKE_XCODE_ATTRIBUTE_WHATEVER
        +CMAKE_XCODE_GENERATE_SCHEME
        +CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY
        +CMAKE_XCODE_PLATFORM_TOOLSET
        +CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER
        +CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
        +CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
        +CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
        +CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
        +CMAKE_XCODE_SCHEME_GUARD_MALLOC
        +CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
        +CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
        +CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
        +CMAKE_XCODE_SCHEME_MALLOC_STACK
        +CMAKE_XCODE_SCHEME_THREAD_SANITIZER
        +CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP
        +CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
        +CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
        +CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
        +CPACK_ABSOLUTE_DESTINATION_FILES
        +CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
        +CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
        +CPACK_INCLUDE_TOPLEVEL_DIRECTORY
        +CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
        +CPACK_INSTALL_SCRIPT
        +CPACK_PACKAGING_INSTALL_PREFIX
        +CPACK_SET_DESTDIR
        +CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
        +CTEST_BINARY_DIRECTORY
        +CTEST_BUILD_COMMAND
        +CTEST_BUILD_NAME
        +CTEST_BZR_COMMAND
        +CTEST_BZR_UPDATE_OPTIONS
        +CTEST_CHANGE_ID
        +CTEST_CHECKOUT_COMMAND
        +CTEST_CONFIGURATION_TYPE
        +CTEST_CONFIGURE_COMMAND
        +CTEST_COVERAGE_COMMAND
        +CTEST_COVERAGE_EXTRA_FLAGS
        +CTEST_CURL_OPTIONS
        +CTEST_CUSTOM_COVERAGE_EXCLUDE
        +CTEST_CUSTOM_ERROR_EXCEPTION
        +CTEST_CUSTOM_ERROR_MATCH
        +CTEST_CUSTOM_ERROR_POST_CONTEXT
        +CTEST_CUSTOM_ERROR_PRE_CONTEXT
        +CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE
        +CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS
        +CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS
        +CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE
        +CTEST_CUSTOM_MEMCHECK_IGNORE
        +CTEST_CUSTOM_POST_MEMCHECK
        +CTEST_CUSTOM_POST_TEST
        +CTEST_CUSTOM_PRE_MEMCHECK
        +CTEST_CUSTOM_PRE_TEST
        +CTEST_CUSTOM_TESTS_IGNORE
        +CTEST_CUSTOM_WARNING_EXCEPTION
        +CTEST_CUSTOM_WARNING_MATCH
        +CTEST_CVS_CHECKOUT
        +CTEST_CVS_COMMAND
        +CTEST_CVS_UPDATE_OPTIONS
        +CTEST_DROP_LOCATION
        +CTEST_DROP_METHOD
        +CTEST_DROP_SITE
        +CTEST_DROP_SITE_CDASH
        +CTEST_DROP_SITE_PASSWORD
        +CTEST_DROP_SITE_USER
        +CTEST_EXTRA_COVERAGE_GLOB
        +CTEST_GIT_COMMAND
        +CTEST_GIT_INIT_SUBMODULES
        +CTEST_GIT_UPDATE_CUSTOM
        +CTEST_GIT_UPDATE_OPTIONS
        +CTEST_HG_COMMAND
        +CTEST_HG_UPDATE_OPTIONS
        +CTEST_LABELS_FOR_SUBPROJECTS
        +CTEST_MEMORYCHECK_COMMAND
        +CTEST_MEMORYCHECK_COMMAND_OPTIONS
        +CTEST_MEMORYCHECK_SANITIZER_OPTIONS
        +CTEST_MEMORYCHECK_SUPPRESSIONS_FILE
        +CTEST_MEMORYCHECK_TYPE
        +CTEST_NIGHTLY_START_TIME
        +CTEST_P4_CLIENT
        +CTEST_P4_COMMAND
        +CTEST_P4_OPTIONS
        +CTEST_P4_UPDATE_OPTIONS
        +CTEST_RUN_CURRENT_SCRIPT
        +CTEST_SCP_COMMAND
        +CTEST_SITE
        +CTEST_SOURCE_DIRECTORY
        +CTEST_SUBMIT_URL
        +CTEST_SVN_COMMAND
        +CTEST_SVN_OPTIONS
        +CTEST_SVN_UPDATE_OPTIONS
        +CTEST_TEST_LOAD
        +CTEST_TEST_TIMEOUT
        +CTEST_TRIGGER_SITE
        +CTEST_UPDATE_COMMAND
        +CTEST_UPDATE_OPTIONS
        +CTEST_UPDATE_VERSION_ONLY
        +CTEST_USE_LAUNCHERS
        +CYGWIN
        +ENV
        +EXECUTABLE_OUTPUT_PATH
        +GHS-MULTI
        +IOS
        +LIBRARY_OUTPUT_PATH
        +MINGW
        +MSVC
        +MSVC10
        +MSVC11
        +MSVC12
        +MSVC14
        +MSVC60
        +MSVC70
        +MSVC71
        +MSVC80
        +MSVC90
        +MSVC_IDE
        +MSVC_TOOLSET_VERSION
        +MSVC_VERSION
        +MSYS
        +PROJECT_BINARY_DIR
        +PROJECT_DESCRIPTION
        +PROJECT_HOMEPAGE_URL
        +PROJECT_NAME
        +PROJECT_SOURCE_DIR
        +PROJECT_VERSION
        +PROJECT_VERSION_MAJOR
        +PROJECT_VERSION_MINOR
        +PROJECT_VERSION_PATCH
        +PROJECT_VERSION_TWEAK
        +UNIX
        +WIN32
        +WINCE
        +WINDOWS_PHONE
        +WINDOWS_STORE
        +XCODE
        +XCODE_VERSION
        +
        +----------------------------------------------------
        +
        +[
        +	["variable", "WHATEVER_BINARY_DIR"],
        +	["variable", "WHATEVER_DESCRIPTION"],
        +	["variable", "WHATEVER_HOMEPAGE_URL"],
        +	["variable", "WHATEVER_SOURCE_DIR"],
        +	["variable", "WHATEVER_VERSION"],
        +	["variable", "WHATEVER_VERSION_MAJOR"],
        +	["variable", "WHATEVER_VERSION_MINOR"],
        +	["variable", "WHATEVER_VERSION_PATCH"],
        +	["variable", "WHATEVER_VERSION_TWEAK"],
        +	["variable", "WHATEVER_ROOT"],
        +	["variable", "ANDROID"],
        +	["variable", "APPLE"],
        +	["variable", "BORLAND"],
        +	["variable", "BUILD_SHARED_LIBS"],
        +	["variable", "CACHE"],
        +	["variable", "CMAKE_WHATEVER_POSTFIX"],
        +	["variable", "CMAKE_WHATEVER_ANDROID_TOOLCHAIN_MACHINE"],
        +	["variable", "CMAKE_WHATEVER_ANDROID_TOOLCHAIN_PREFIX"],
        +	["variable", "CMAKE_WHATEVER_ANDROID_TOOLCHAIN_SUFFIX"],
        +	["variable", "CMAKE_WHATEVER_ARCHIVE_APPEND"],
        +	["variable", "CMAKE_WHATEVER_ARCHIVE_CREATE"],
        +	["variable", "CMAKE_WHATEVER_ARCHIVE_FINISH"],
        +	["variable", "CMAKE_WHATEVER_CLANG_TIDY"],
        +	["variable", "CMAKE_WHATEVER_COMPILER"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_ABI"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_AR"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_ARCHITECTURE_ID"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_EXTERNAL_TOOLCHAIN"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_ID"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_LAUNCHER"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_LOADED"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_PREDEFINES_COMMAND"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_RANLIB"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_TARGET"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_VERSION"],
        +	["variable", "CMAKE_WHATEVER_COMPILER_VERSION_INTERNAL"],
        +	["variable", "CMAKE_WHATEVER_COMPILE_OBJECT"],
        +	["variable", "CMAKE_WHATEVER_CPPCHECK"],
        +	["variable", "CMAKE_WHATEVER_CPPLINT"],
        +	["variable", "CMAKE_WHATEVER_CREATE_SHARED_LIBRARY"],
        +	["variable", "CMAKE_WHATEVER_CREATE_SHARED_MODULE"],
        +	["variable", "CMAKE_WHATEVER_CREATE_STATIC_LIBRARY"],
        +	["variable", "CMAKE_WHATEVER_FLAGS"],
        +	["variable", "CMAKE_WHATEVER"],
        +	["variable", "CMAKE_WHATEVER_INIT"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_DEBUG"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_DEBUG_INIT"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_INIT"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_MINSIZEREL"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_MINSIZEREL_INIT"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_RELEASE"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_RELEASE_INIT"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_RELWITHDEBINFO"],
        +	["variable", "CMAKE_WHATEVER_FLAGS_RELWITHDEBINFO_INIT"],
        +	["variable", "CMAKE_WHATEVER_IGNORE_EXTENSIONS"],
        +	["variable", "CMAKE_WHATEVER_IMPLICIT_INCLUDE_DIRECTORIES"],
        +	["variable", "CMAKE_WHATEVER_IMPLICIT_LINK_DIRECTORIES"],
        +	["variable", "CMAKE_WHATEVER_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"],
        +	["variable", "CMAKE_WHATEVER_IMPLICIT_LINK_LIBRARIES"],
        +	["variable", "CMAKE_WHATEVER_INCLUDE_WHAT_YOU_USE"],
        +	["variable", "CMAKE_WHATEVER_LIBRARY_ARCHITECTURE"],
        +	["variable", "CMAKE_WHATEVER_LINKER_PREFERENCE"],
        +	["variable", "CMAKE_WHATEVER_LINKER_PREFERENCE_PROPAGATES"],
        +	["variable", "CMAKE_WHATEVER_LINKER_WRAPPER_FLAG"],
        +	["variable", "CMAKE_WHATEVER_LINKER_WRAPPER_FLAG_SEP"],
        +	["variable", "CMAKE_WHATEVER_LINK_EXECUTABLE"],
        +	["variable", "CMAKE_WHATEVER_OUTPUT_EXTENSION"],
        +	["variable", "CMAKE_WHATEVER_PLATFORM_ID"],
        +	["variable", "CMAKE_WHATEVER_SIMULATE_ID"],
        +	["variable", "CMAKE_WHATEVER_SIMULATE_VERSION"],
        +	["variable", "CMAKE_WHATEVER_SIZEOF_DATA_PTR"],
        +	["variable", "CMAKE_WHATEVER_SOURCE_FILE_EXTENSIONS"],
        +	["variable", "CMAKE_WHATEVER_STANDARD_INCLUDE_DIRECTORIES"],
        +	["variable", "CMAKE_WHATEVER_STANDARD_LIBRARIES"],
        +	["variable", "CMAKE_WHATEVER_VISIBILITY_PRESET"],
        +	["variable", "CMAKE_ABSOLUTE_DESTINATION_FILES"],
        +	["variable", "CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS"],
        +	["variable", "CMAKE_ANDROID_API"],
        +	["variable", "CMAKE_ANDROID_API_MIN"],
        +	["variable", "CMAKE_ANDROID_ARCH"],
        +	["variable", "CMAKE_ANDROID_ARCH_ABI"],
        +	["variable", "CMAKE_ANDROID_ARM_MODE"],
        +	["variable", "CMAKE_ANDROID_ARM_NEON"],
        +	["variable", "CMAKE_ANDROID_ASSETS_DIRECTORIES"],
        +	["variable", "CMAKE_ANDROID_GUI"],
        +	["variable", "CMAKE_ANDROID_JAR_DEPENDENCIES"],
        +	["variable", "CMAKE_ANDROID_JAR_DIRECTORIES"],
        +	["variable", "CMAKE_ANDROID_JAVA_SOURCE_DIR"],
        +	["variable", "CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES"],
        +	["variable", "CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES"],
        +	["variable", "CMAKE_ANDROID_NDK"],
        +	["variable", "CMAKE_ANDROID_NDK_DEPRECATED_HEADERS"],
        +	["variable", "CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG"],
        +	["variable", "CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION"],
        +	["variable", "CMAKE_ANDROID_PROCESS_MAX"],
        +	["variable", "CMAKE_ANDROID_PROGUARD"],
        +	["variable", "CMAKE_ANDROID_PROGUARD_CONFIG_PATH"],
        +	["variable", "CMAKE_ANDROID_SECURE_PROPS_PATH"],
        +	["variable", "CMAKE_ANDROID_SKIP_ANT_STEP"],
        +	["variable", "CMAKE_ANDROID_STANDALONE_TOOLCHAIN"],
        +	["variable", "CMAKE_ANDROID_STL_TYPE"],
        +	["variable", "CMAKE_APPBUNDLE_PATH"],
        +	["variable", "CMAKE_AR"],
        +	["variable", "CMAKE_ARCHIVE_OUTPUT_DIRECTORY"],
        +	["variable", "CMAKE_ARCHIVE_OUTPUT_DIRECTORY_WHATEVER"],
        +	["variable", "CMAKE_ARGC"],
        +	["variable", "CMAKE_ARGV0"],
        +	["variable", "CMAKE_AUTOGEN_ORIGIN_DEPENDS"],
        +	["variable", "CMAKE_AUTOGEN_PARALLEL"],
        +	["variable", "CMAKE_AUTOGEN_VERBOSE"],
        +	["variable", "CMAKE_AUTOMOC"],
        +	["variable", "CMAKE_AUTOMOC_COMPILER_PREDEFINES"],
        +	["variable", "CMAKE_AUTOMOC_DEPEND_FILTERS"],
        +	["variable", "CMAKE_AUTOMOC_MACRO_NAMES"],
        +	["variable", "CMAKE_AUTOMOC_MOC_OPTIONS"],
        +	["variable", "CMAKE_AUTOMOC_RELAXED_MODE"],
        +	["variable", "CMAKE_AUTORCC"],
        +	["variable", "CMAKE_AUTORCC_OPTIONS"],
        +	["variable", "CMAKE_AUTOUIC"],
        +	["variable", "CMAKE_AUTOUIC_OPTIONS"],
        +	["variable", "CMAKE_AUTOUIC_SEARCH_PATHS"],
        +	["variable", "CMAKE_BACKWARDS_COMPATIBILITY"],
        +	["variable", "CMAKE_BINARY_DIR"],
        +	["variable", "CMAKE_BUILD_RPATH"],
        +	["variable", "CMAKE_BUILD_RPATH_USE_ORIGIN"],
        +	["variable", "CMAKE_BUILD_TOOL"],
        +	["variable", "CMAKE_BUILD_TYPE"],
        +	["variable", "CMAKE_BUILD_WITH_INSTALL_NAME_DIR"],
        +	["variable", "CMAKE_BUILD_WITH_INSTALL_RPATH"],
        +	["variable", "CMAKE_CACHEFILE_DIR"],
        +	["variable", "CMAKE_CACHE_MAJOR_VERSION"],
        +	["variable", "CMAKE_CACHE_MINOR_VERSION"],
        +	["variable", "CMAKE_CACHE_PATCH_VERSION"],
        +	["variable", "CMAKE_CFG_INTDIR"],
        +	["variable", "CMAKE_CL_64"],
        +	["variable", "CMAKE_CODEBLOCKS_COMPILER_ID"],
        +	["variable", "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"],
        +	["variable", "CMAKE_CODELITE_USE_TARGETS"],
        +	["variable", "CMAKE_COLOR_MAKEFILE"],
        +	["variable", "CMAKE_COMMAND"],
        +	["variable", "CMAKE_COMPILER_2005"],
        +	["variable", "CMAKE_COMPILER_IS_GNUCC"],
        +	["variable", "CMAKE_COMPILER_IS_GNUCXX"],
        +	["variable", "CMAKE_COMPILER_IS_GNUG77"],
        +	["variable", "CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY"],
        +	["variable", "CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_WHATEVER"],
        +	["variable", "CMAKE_CONFIGURATION_TYPES"],
        +	["variable", "CMAKE_CPACK_COMMAND"],
        +	["variable", "CMAKE_CROSSCOMPILING"],
        +	["variable", "CMAKE_CROSSCOMPILING_EMULATOR"],
        +	["variable", "CMAKE_CTEST_COMMAND"],
        +	["variable", "CMAKE_CUDA_EXTENSIONS"],
        +	["variable", "CMAKE_CUDA_HOST_COMPILER"],
        +	["variable", "CMAKE_CUDA_SEPARABLE_COMPILATION"],
        +	["variable", "CMAKE_CUDA_STANDARD"],
        +	["variable", "CMAKE_CUDA_STANDARD_REQUIRED"],
        +	["variable", "CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES"],
        +	["variable", "CMAKE_CURRENT_BINARY_DIR"],
        +	["variable", "CMAKE_CURRENT_LIST_DIR"],
        +	["variable", "CMAKE_CURRENT_LIST_FILE"],
        +	["variable", "CMAKE_CURRENT_LIST_LINE"],
        +	["variable", "CMAKE_CURRENT_SOURCE_DIR"],
        +	["variable", "CMAKE_CXX_COMPILE_FEATURES"],
        +	["variable", "CMAKE_CXX_EXTENSIONS"],
        +	["variable", "CMAKE_CXX_STANDARD"],
        +	["variable", "CMAKE_CXX_STANDARD_REQUIRED"],
        +	["variable", "CMAKE_C_COMPILE_FEATURES"],
        +	["variable", "CMAKE_C_EXTENSIONS"],
        +	["variable", "CMAKE_C_STANDARD"],
        +	["variable", "CMAKE_C_STANDARD_REQUIRED"],
        +	["variable", "CMAKE_DEBUG_POSTFIX"],
        +	["variable", "CMAKE_DEBUG_TARGET_PROPERTIES"],
        +	["variable", "CMAKE_DEPENDS_IN_PROJECT_ONLY"],
        +	["variable", "CMAKE_DIRECTORY_LABELS"],
        +	["variable", "CMAKE_DISABLE_FIND_PACKAGE_WHATEVER"],
        +	["variable", "CMAKE_DL_LIBS"],
        +	["variable", "CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION"],
        +	["variable", "CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES"],
        +	["variable", "CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT"],
        +	["variable", "CMAKE_ECLIPSE_MAKE_ARGUMENTS"],
        +	["variable", "CMAKE_ECLIPSE_VERSION"],
        +	["variable", "CMAKE_EDIT_COMMAND"],
        +	["variable", "CMAKE_ENABLE_EXPORTS"],
        +	["variable", "CMAKE_ERROR_DEPRECATED"],
        +	["variable", "CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION"],
        +	["variable", "CMAKE_EXECUTABLE_SUFFIX"],
        +	["variable", "CMAKE_EXE_LINKER_FLAGS"],
        +	["variable", "CMAKE_EXE_LINKER_FLAGS_WHATEVER"],
        +	["variable", "CMAKE_EXE_LINKER_FLAGS_WHATEVER_INIT"],
        +	["variable", "CMAKE_EXE_LINKER_FLAGS_INIT"],
        +	["variable", "CMAKE_EXPORT_COMPILE_COMMANDS"],
        +	["variable", "CMAKE_EXPORT_NO_PACKAGE_REGISTRY"],
        +	["variable", "CMAKE_EXTRA_GENERATOR"],
        +	["variable", "CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES"],
        +	["variable", "CMAKE_FIND_APPBUNDLE"],
        +	["variable", "CMAKE_FIND_FRAMEWORK"],
        +	["variable", "CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX"],
        +	["variable", "CMAKE_FIND_LIBRARY_PREFIXES"],
        +	["variable", "CMAKE_FIND_LIBRARY_SUFFIXES"],
        +	["variable", "CMAKE_FIND_NO_INSTALL_PREFIX"],
        +	["variable", "CMAKE_FIND_PACKAGE_NAME"],
        +	["variable", "CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY"],
        +	["variable", "CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY"],
        +	["variable", "CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS"],
        +	["variable", "CMAKE_FIND_PACKAGE_SORT_DIRECTION"],
        +	["variable", "CMAKE_FIND_PACKAGE_SORT_ORDER"],
        +	["variable", "CMAKE_FIND_PACKAGE_WARN_NO_MODULE"],
        +	["variable", "CMAKE_FIND_ROOT_PATH"],
        +	["variable", "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE"],
        +	["variable", "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY"],
        +	["variable", "CMAKE_FIND_ROOT_PATH_MODE_PACKAGE"],
        +	["variable", "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM"],
        +	["variable", "CMAKE_FOLDER"],
        +	["variable", "CMAKE_FRAMEWORK_PATH"],
        +	["variable", "CMAKE_Fortran_FORMAT"],
        +	["variable", "CMAKE_Fortran_MODDIR_DEFAULT"],
        +	["variable", "CMAKE_Fortran_MODDIR_FLAG"],
        +	["variable", "CMAKE_Fortran_MODOUT_FLAG"],
        +	["variable", "CMAKE_Fortran_MODULE_DIRECTORY"],
        +	["variable", "CMAKE_GENERATOR"],
        +	["variable", "CMAKE_GENERATOR_INSTANCE"],
        +	["variable", "CMAKE_GENERATOR_PLATFORM"],
        +	["variable", "CMAKE_GENERATOR_TOOLSET"],
        +	["variable", "CMAKE_GHS_NO_SOURCE_GROUP_FILE"],
        +	["variable", "CMAKE_GLOBAL_AUTOGEN_TARGET"],
        +	["variable", "CMAKE_GLOBAL_AUTOGEN_TARGET_NAME"],
        +	["variable", "CMAKE_GLOBAL_AUTORCC_TARGET"],
        +	["variable", "CMAKE_GLOBAL_AUTORCC_TARGET_NAME"],
        +	["variable", "CMAKE_GNUtoMS"],
        +	["variable", "CMAKE_HOME_DIRECTORY"],
        +	["variable", "CMAKE_HOST_APPLE"],
        +	["variable", "CMAKE_HOST_SOLARIS"],
        +	["variable", "CMAKE_HOST_SYSTEM"],
        +	["variable", "CMAKE_HOST_SYSTEM_NAME"],
        +	["variable", "CMAKE_HOST_SYSTEM_PROCESSOR"],
        +	["variable", "CMAKE_HOST_SYSTEM_VERSION"],
        +	["variable", "CMAKE_HOST_UNIX"],
        +	["variable", "CMAKE_HOST_WIN32"],
        +	["variable", "CMAKE_IGNORE_PATH"],
        +	["variable", "CMAKE_IMPORT_LIBRARY_PREFIX"],
        +	["variable", "CMAKE_IMPORT_LIBRARY_SUFFIX"],
        +	["variable", "CMAKE_INCLUDE_CURRENT_DIR"],
        +	["variable", "CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE"],
        +	["variable", "CMAKE_INCLUDE_DIRECTORIES_BEFORE"],
        +	["variable", "CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"],
        +	["variable", "CMAKE_INCLUDE_PATH"],
        +	["variable", "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"],
        +	["variable", "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"],
        +	["variable", "CMAKE_INSTALL_MESSAGE"],
        +	["variable", "CMAKE_INSTALL_NAME_DIR"],
        +	["variable", "CMAKE_INSTALL_PREFIX"],
        +	["variable", "CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT"],
        +	["variable", "CMAKE_INSTALL_RPATH"],
        +	["variable", "CMAKE_INSTALL_RPATH_USE_LINK_PATH"],
        +	["variable", "CMAKE_INTERNAL_PLATFORM_ABI"],
        +	["variable", "CMAKE_INTERPROCEDURAL_OPTIMIZATION"],
        +	["variable", "CMAKE_INTERPROCEDURAL_OPTIMIZATION_WHATEVER"],
        +	["variable", "CMAKE_IOS_INSTALL_COMBINED"],
        +	["variable", "CMAKE_JOB_POOLS"],
        +	["variable", "CMAKE_JOB_POOL_COMPILE"],
        +	["variable", "CMAKE_JOB_POOL_LINK"],
        +	["variable", "CMAKE_LIBRARY_ARCHITECTURE"],
        +	["variable", "CMAKE_LIBRARY_ARCHITECTURE_REGEX"],
        +	["variable", "CMAKE_LIBRARY_OUTPUT_DIRECTORY"],
        +	["variable", "CMAKE_LIBRARY_OUTPUT_DIRECTORY_WHATEVER"],
        +	["variable", "CMAKE_LIBRARY_PATH"],
        +	["variable", "CMAKE_LIBRARY_PATH_FLAG"],
        +	["variable", "CMAKE_LINK_DEF_FILE_FLAG"],
        +	["variable", "CMAKE_LINK_DEPENDS_NO_SHARED"],
        +	["variable", "CMAKE_LINK_DIRECTORIES_BEFORE"],
        +	["variable", "CMAKE_LINK_INTERFACE_LIBRARIES"],
        +	["variable", "CMAKE_LINK_LIBRARY_FILE_FLAG"],
        +	["variable", "CMAKE_LINK_LIBRARY_FLAG"],
        +	["variable", "CMAKE_LINK_LIBRARY_SUFFIX"],
        +	["variable", "CMAKE_LINK_SEARCH_END_STATIC"],
        +	["variable", "CMAKE_LINK_SEARCH_START_STATIC"],
        +	["variable", "CMAKE_LINK_WHAT_YOU_USE"],
        +	["variable", "CMAKE_MACOSX_BUNDLE"],
        +	["variable", "CMAKE_MACOSX_RPATH"],
        +	["variable", "CMAKE_MAJOR_VERSION"],
        +	["variable", "CMAKE_MAKE_PROGRAM"],
        +	["variable", "CMAKE_MAP_IMPORTED_CONFIG_WHATEVER"],
        +	["variable", "CMAKE_MATCH_WHATEVER"],
        +	["variable", "CMAKE_MATCH_COUNT"],
        +	["variable", "CMAKE_MAXIMUM_RECURSION_DEPTH"],
        +	["variable", "CMAKE_MFC_FLAG"],
        +	["variable", "CMAKE_MINIMUM_REQUIRED_VERSION"],
        +	["variable", "CMAKE_MINOR_VERSION"],
        +	["variable", "CMAKE_MODULE_LINKER_FLAGS"],
        +	["variable", "CMAKE_MODULE_LINKER_FLAGS_WHATEVER"],
        +	["variable", "CMAKE_MODULE_LINKER_FLAGS_WHATEVER_INIT"],
        +	["variable", "CMAKE_MODULE_LINKER_FLAGS_INIT"],
        +	["variable", "CMAKE_MODULE_PATH"],
        +	["variable", "CMAKE_MSVCIDE_RUN_PATH"],
        +	["variable", "CMAKE_NETRC"],
        +	["variable", "CMAKE_NETRC_FILE"],
        +	["variable", "CMAKE_NINJA_OUTPUT_PATH_PREFIX"],
        +	["variable", "CMAKE_NOT_USING_CONFIG_FLAGS"],
        +	["variable", "CMAKE_NO_BUILTIN_CHRPATH"],
        +	["variable", "CMAKE_NO_SYSTEM_FROM_IMPORTED"],
        +	["variable", "CMAKE_OBJECT_PATH_MAX"],
        +	["variable", "CMAKE_OSX_ARCHITECTURES"],
        +	["variable", "CMAKE_OSX_DEPLOYMENT_TARGET"],
        +	["variable", "CMAKE_OSX_SYSROOT"],
        +	["variable", "CMAKE_PARENT_LIST_FILE"],
        +	["variable", "CMAKE_PATCH_VERSION"],
        +	["variable", "CMAKE_PDB_OUTPUT_DIRECTORY"],
        +	["variable", "CMAKE_PDB_OUTPUT_DIRECTORY_WHATEVER"],
        +	["variable", "CMAKE_POLICY_DEFAULT_CMPWHATEVER"],
        +	["variable", "CMAKE_POLICY_WARNING_CMPWHATEVER"],
        +	["variable", "CMAKE_POSITION_INDEPENDENT_CODE"],
        +	["variable", "CMAKE_PREFIX_PATH"],
        +	["variable", "CMAKE_PROGRAM_PATH"],
        +	["variable", "CMAKE_PROJECT_WHATEVER_INCLUDE"],
        +	["variable", "CMAKE_PROJECT_DESCRIPTION"],
        +	["variable", "CMAKE_PROJECT_HOMEPAGE_URL"],
        +	["variable", "CMAKE_PROJECT_NAME"],
        +	["variable", "CMAKE_PROJECT_VERSION"],
        +	["variable", "CMAKE_PROJECT_VERSION_MAJOR"],
        +	["variable", "CMAKE_PROJECT_VERSION_MINOR"],
        +	["variable", "CMAKE_PROJECT_VERSION_PATCH"],
        +	["variable", "CMAKE_PROJECT_VERSION_TWEAK"],
        +	["variable", "CMAKE_RANLIB"],
        +	["variable", "CMAKE_ROOT"],
        +	["variable", "CMAKE_RULE_MESSAGES"],
        +	["variable", "CMAKE_RUNTIME_OUTPUT_DIRECTORY"],
        +	["variable", "CMAKE_RUNTIME_OUTPUT_DIRECTORY_WHATEVER"],
        +	["variable", "CMAKE_SCRIPT_MODE_FILE"],
        +	["variable", "CMAKE_SHARED_LIBRARY_PREFIX"],
        +	["variable", "CMAKE_SHARED_LIBRARY_SUFFIX"],
        +	["variable", "CMAKE_SHARED_LINKER_FLAGS"],
        +	["variable", "CMAKE_SHARED_LINKER_FLAGS_WHATEVER"],
        +	["variable", "CMAKE_SHARED_LINKER_FLAGS_WHATEVER_INIT"],
        +	["variable", "CMAKE_SHARED_LINKER_FLAGS_INIT"],
        +	["variable", "CMAKE_SHARED_MODULE_PREFIX"],
        +	["variable", "CMAKE_SHARED_MODULE_SUFFIX"],
        +	["variable", "CMAKE_SIZEOF_VOID_P"],
        +	["variable", "CMAKE_SKIP_BUILD_RPATH"],
        +	["variable", "CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"],
        +	["variable", "CMAKE_SKIP_INSTALL_RPATH"],
        +	["variable", "CMAKE_SKIP_INSTALL_RULES"],
        +	["variable", "CMAKE_SKIP_RPATH"],
        +	["variable", "CMAKE_SOURCE_DIR"],
        +	["variable", "CMAKE_STAGING_PREFIX"],
        +	["variable", "CMAKE_STATIC_LIBRARY_PREFIX"],
        +	["variable", "CMAKE_STATIC_LIBRARY_SUFFIX"],
        +	["variable", "CMAKE_STATIC_LINKER_FLAGS"],
        +	["variable", "CMAKE_STATIC_LINKER_FLAGS_WHATEVER"],
        +	["variable", "CMAKE_STATIC_LINKER_FLAGS_WHATEVER_INIT"],
        +	["variable", "CMAKE_STATIC_LINKER_FLAGS_INIT"],
        +	["variable", "CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS"],
        +	["variable", "CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE"],
        +	["variable", "CMAKE_SUPPRESS_REGENERATION"],
        +	["variable", "CMAKE_SYSROOT"],
        +	["variable", "CMAKE_SYSROOT_COMPILE"],
        +	["variable", "CMAKE_SYSROOT_LINK"],
        +	["variable", "CMAKE_SYSTEM"],
        +	["variable", "CMAKE_SYSTEM_APPBUNDLE_PATH"],
        +	["variable", "CMAKE_SYSTEM_FRAMEWORK_PATH"],
        +	["variable", "CMAKE_SYSTEM_IGNORE_PATH"],
        +	["variable", "CMAKE_SYSTEM_INCLUDE_PATH"],
        +	["variable", "CMAKE_SYSTEM_LIBRARY_PATH"],
        +	["variable", "CMAKE_SYSTEM_NAME"],
        +	["variable", "CMAKE_SYSTEM_PREFIX_PATH"],
        +	["variable", "CMAKE_SYSTEM_PROCESSOR"],
        +	["variable", "CMAKE_SYSTEM_PROGRAM_PATH"],
        +	["variable", "CMAKE_SYSTEM_VERSION"],
        +	["variable", "CMAKE_Swift_LANGUAGE_VERSION"],
        +	["variable", "CMAKE_TOOLCHAIN_FILE"],
        +	["variable", "CMAKE_TRY_COMPILE_CONFIGURATION"],
        +	["variable", "CMAKE_TRY_COMPILE_PLATFORM_VARIABLES"],
        +	["variable", "CMAKE_TRY_COMPILE_TARGET_TYPE"],
        +	["variable", "CMAKE_TWEAK_VERSION"],
        +	["variable", "CMAKE_USER_MAKE_RULES_OVERRIDE"],
        +	["variable", "CMAKE_USER_MAKE_RULES_OVERRIDE_WHATEVER"],
        +	["variable", "CMAKE_USE_RELATIVE_PATHS"],
        +	["variable", "CMAKE_VERBOSE_MAKEFILE"],
        +	["variable", "CMAKE_VERSION"],
        +	["variable", "CMAKE_VISIBILITY_INLINES_HIDDEN"],
        +	["variable", "CMAKE_VS_DEVENV_COMMAND"],
        +	["variable", "CMAKE_VS_GLOBALS"],
        +	["variable", "CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD"],
        +	["variable", "CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD"],
        +	["variable", "CMAKE_VS_INTEL_Fortran_PROJECT_VERSION"],
        +	["variable", "CMAKE_VS_MSBUILD_COMMAND"],
        +	["variable", "CMAKE_VS_NsightTegra_VERSION"],
        +	["variable", "CMAKE_VS_PLATFORM_NAME"],
        +	["variable", "CMAKE_VS_PLATFORM_TOOLSET"],
        +	["variable", "CMAKE_VS_PLATFORM_TOOLSET_CUDA"],
        +	["variable", "CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE"],
        +	["variable", "CMAKE_VS_PLATFORM_TOOLSET_VERSION"],
        +	["variable", "CMAKE_VS_SDK_EXCLUDE_DIRECTORIES"],
        +	["variable", "CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES"],
        +	["variable", "CMAKE_VS_SDK_INCLUDE_DIRECTORIES"],
        +	["variable", "CMAKE_VS_SDK_LIBRARY_DIRECTORIES"],
        +	["variable", "CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES"],
        +	["variable", "CMAKE_VS_SDK_REFERENCE_DIRECTORIES"],
        +	["variable", "CMAKE_VS_SDK_SOURCE_DIRECTORIES"],
        +	["variable", "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION"],
        +	["variable", "CMAKE_VS_WINRT_BY_DEFAULT"],
        +	["variable", "CMAKE_WARN_DEPRECATED"],
        +	["variable", "CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION"],
        +	["variable", "CMAKE_WIN32_EXECUTABLE"],
        +	["variable", "CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS"],
        +	["variable", "CMAKE_XCODE_ATTRIBUTE_WHATEVER"],
        +	["variable", "CMAKE_XCODE_GENERATE_SCHEME"],
        +	["variable", "CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"],
        +	["variable", "CMAKE_XCODE_PLATFORM_TOOLSET"],
        +	["variable", "CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER"],
        +	["variable", "CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN"],
        +	["variable", "CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"],
        +	["variable", "CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"],
        +	["variable", "CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"],
        +	["variable", "CMAKE_XCODE_SCHEME_GUARD_MALLOC"],
        +	["variable", "CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"],
        +	["variable", "CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES"],
        +	["variable", "CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE"],
        +	["variable", "CMAKE_XCODE_SCHEME_MALLOC_STACK"],
        +	["variable", "CMAKE_XCODE_SCHEME_THREAD_SANITIZER"],
        +	["variable", "CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP"],
        +	["variable", "CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"],
        +	["variable", "CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"],
        +	["variable", "CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS"],
        +	["variable", "CPACK_ABSOLUTE_DESTINATION_FILES"],
        +	["variable", "CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY"],
        +	["variable", "CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION"],
        +	["variable", "CPACK_INCLUDE_TOPLEVEL_DIRECTORY"],
        +	["variable", "CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"],
        +	["variable", "CPACK_INSTALL_SCRIPT"],
        +	["variable", "CPACK_PACKAGING_INSTALL_PREFIX"],
        +	["variable", "CPACK_SET_DESTDIR"],
        +	["variable", "CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION"],
        +	["variable", "CTEST_BINARY_DIRECTORY"],
        +	["variable", "CTEST_BUILD_COMMAND"],
        +	["variable", "CTEST_BUILD_NAME"],
        +	["variable", "CTEST_BZR_COMMAND"],
        +	["variable", "CTEST_BZR_UPDATE_OPTIONS"],
        +	["variable", "CTEST_CHANGE_ID"],
        +	["variable", "CTEST_CHECKOUT_COMMAND"],
        +	["variable", "CTEST_CONFIGURATION_TYPE"],
        +	["variable", "CTEST_CONFIGURE_COMMAND"],
        +	["variable", "CTEST_COVERAGE_COMMAND"],
        +	["variable", "CTEST_COVERAGE_EXTRA_FLAGS"],
        +	["variable", "CTEST_CURL_OPTIONS"],
        +	["variable", "CTEST_CUSTOM_COVERAGE_EXCLUDE"],
        +	["variable", "CTEST_CUSTOM_ERROR_EXCEPTION"],
        +	["variable", "CTEST_CUSTOM_ERROR_MATCH"],
        +	["variable", "CTEST_CUSTOM_ERROR_POST_CONTEXT"],
        +	["variable", "CTEST_CUSTOM_ERROR_PRE_CONTEXT"],
        +	["variable", "CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE"],
        +	["variable", "CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS"],
        +	["variable", "CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS"],
        +	["variable", "CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE"],
        +	["variable", "CTEST_CUSTOM_MEMCHECK_IGNORE"],
        +	["variable", "CTEST_CUSTOM_POST_MEMCHECK"],
        +	["variable", "CTEST_CUSTOM_POST_TEST"],
        +	["variable", "CTEST_CUSTOM_PRE_MEMCHECK"],
        +	["variable", "CTEST_CUSTOM_PRE_TEST"],
        +	["variable", "CTEST_CUSTOM_TESTS_IGNORE"],
        +	["variable", "CTEST_CUSTOM_WARNING_EXCEPTION"],
        +	["variable", "CTEST_CUSTOM_WARNING_MATCH"],
        +	["variable", "CTEST_CVS_CHECKOUT"],
        +	["variable", "CTEST_CVS_COMMAND"],
        +	["variable", "CTEST_CVS_UPDATE_OPTIONS"],
        +	["variable", "CTEST_DROP_LOCATION"],
        +	["variable", "CTEST_DROP_METHOD"],
        +	["variable", "CTEST_DROP_SITE"],
        +	["variable", "CTEST_DROP_SITE_CDASH"],
        +	["variable", "CTEST_DROP_SITE_PASSWORD"],
        +	["variable", "CTEST_DROP_SITE_USER"],
        +	["variable", "CTEST_EXTRA_COVERAGE_GLOB"],
        +	["variable", "CTEST_GIT_COMMAND"],
        +	["variable", "CTEST_GIT_INIT_SUBMODULES"],
        +	["variable", "CTEST_GIT_UPDATE_CUSTOM"],
        +	["variable", "CTEST_GIT_UPDATE_OPTIONS"],
        +	["variable", "CTEST_HG_COMMAND"],
        +	["variable", "CTEST_HG_UPDATE_OPTIONS"],
        +	["variable", "CTEST_LABELS_FOR_SUBPROJECTS"],
        +	["variable", "CTEST_MEMORYCHECK_COMMAND"],
        +	["variable", "CTEST_MEMORYCHECK_COMMAND_OPTIONS"],
        +	["variable", "CTEST_MEMORYCHECK_SANITIZER_OPTIONS"],
        +	["variable", "CTEST_MEMORYCHECK_SUPPRESSIONS_FILE"],
        +	["variable", "CTEST_MEMORYCHECK_TYPE"],
        +	["variable", "CTEST_NIGHTLY_START_TIME"],
        +	["variable", "CTEST_P4_CLIENT"],
        +	["variable", "CTEST_P4_COMMAND"],
        +	["variable", "CTEST_P4_OPTIONS"],
        +	["variable", "CTEST_P4_UPDATE_OPTIONS"],
        +	["variable", "CTEST_RUN_CURRENT_SCRIPT"],
        +	["variable", "CTEST_SCP_COMMAND"],
        +	["variable", "CTEST_SITE"],
        +	["variable", "CTEST_SOURCE_DIRECTORY"],
        +	["variable", "CTEST_SUBMIT_URL"],
        +	["variable", "CTEST_SVN_COMMAND"],
        +	["variable", "CTEST_SVN_OPTIONS"],
        +	["variable", "CTEST_SVN_UPDATE_OPTIONS"],
        +	["variable", "CTEST_TEST_LOAD"],
        +	["variable", "CTEST_TEST_TIMEOUT"],
        +	["variable", "CTEST_TRIGGER_SITE"],
        +	["variable", "CTEST_UPDATE_COMMAND"],
        +	["variable", "CTEST_UPDATE_OPTIONS"],
        +	["variable", "CTEST_UPDATE_VERSION_ONLY"],
        +	["variable", "CTEST_USE_LAUNCHERS"],
        +	["variable", "CYGWIN"],
        +	["variable", "ENV"],
        +	["variable", "EXECUTABLE_OUTPUT_PATH"],
        +	["variable", "GHS-MULTI"],
        +	["variable", "IOS"],
        +	["variable", "LIBRARY_OUTPUT_PATH"],
        +	["variable", "MINGW"],
        +	["variable", "MSVC"],
        +	["variable", "MSVC10"],
        +	["variable", "MSVC11"],
        +	["variable", "MSVC12"],
        +	["variable", "MSVC14"],
        +	["variable", "MSVC60"],
        +	["variable", "MSVC70"],
        +	["variable", "MSVC71"],
        +	["variable", "MSVC80"],
        +	["variable", "MSVC90"],
        +	["variable", "MSVC_IDE"],
        +	["variable", "MSVC_TOOLSET_VERSION"],
        +	["variable", "MSVC_VERSION"],
        +	["variable", "MSYS"],
        +	["variable", "PROJECT_BINARY_DIR"],
        +	["variable", "PROJECT_DESCRIPTION"],
        +	["variable", "PROJECT_HOMEPAGE_URL"],
        +	["variable", "PROJECT_NAME"],
        +	["variable", "PROJECT_SOURCE_DIR"],
        +	["variable", "PROJECT_VERSION"],
        +	["variable", "PROJECT_VERSION_MAJOR"],
        +	["variable", "PROJECT_VERSION_MINOR"],
        +	["variable", "PROJECT_VERSION_PATCH"],
        +	["variable", "PROJECT_VERSION_TWEAK"],
        +	["variable", "UNIX"],
        +	["variable", "WIN32"],
        +	["variable", "WINCE"],
        +	["variable", "WINDOWS_PHONE"],
        +	["variable", "WINDOWS_STORE"],
        +	["variable", "XCODE"],
        +	["variable", "XCODE_VERSION"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all variables.
        \ No newline at end of file
        diff --git a/tests/languages/cobol/boolean_feature.test b/tests/languages/cobol/boolean_feature.test
        new file mode 100644
        index 0000000000..fb3632f821
        --- /dev/null
        +++ b/tests/languages/cobol/boolean_feature.test
        @@ -0,0 +1,9 @@
        +false False FALSE
        +true True TRUE
        +
        +----------------------------------------------------
        +
        +[
        +	["boolean", "false"], ["boolean", "False"], ["boolean", "FALSE"],
        +	["boolean", "true"], ["boolean", "True"], ["boolean", "TRUE"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cobol/class-name_feature.test b/tests/languages/cobol/class-name_feature.test
        new file mode 100644
        index 0000000000..31021a4d69
        --- /dev/null
        +++ b/tests/languages/cobol/class-name_feature.test
        @@ -0,0 +1,84 @@
        +PIC 99/99/9999 SOURCE sales-date.
        +PIC $$$$9.99 SOURCE sales-amount.
        +PIC X(34) SOURCE sales-record.
        +
        +pic 9 usage computational value is 5.
        +pic 99 value is 10.
        +
        +pic x(2)
        +pic a(20).
        +
        +greeting pic x(12) value is "Hello World".
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "PIC"],
        +	["class-name", ["99/99/9999"]],
        +	["keyword", "SOURCE"],
        +	" sales-date",
        +	["punctuation", "."],
        +
        +	["keyword", "PIC"],
        +	["class-name", ["$$$$9.99"]],
        +	["keyword", "SOURCE"],
        +	" sales-amount",
        +	["punctuation", "."],
        +
        +	["keyword", "PIC"],
        +	["class-name", [
        +		"X",
        +		["punctuation", "("],
        +		["number", "34"],
        +		["punctuation", ")"]
        +	]],
        +	["keyword", "SOURCE"],
        +	" sales-record",
        +	["punctuation", "."],
        +
        +	["keyword", "pic"],
        +	["class-name", ["9"]],
        +	["keyword", "usage"],
        +	["keyword", "computational"],
        +	["keyword", "value"],
        +	["keyword", "is"],
        +	["number", "5"],
        +	["punctuation", "."],
        +
        +	["keyword", "pic"],
        +	["class-name", ["99"]],
        +	["keyword", "value"],
        +	["keyword", "is"],
        +	["number", "10"],
        +	["punctuation", "."],
        +
        +	["keyword", "pic"],
        +	["class-name", [
        +		"x",
        +		["punctuation", "("],
        +		["number", "2"],
        +		["punctuation", ")"]
        +	]],
        +
        +	["keyword", "pic"],
        +	["class-name", [
        +		"a",
        +		["punctuation", "("],
        +		["number", "20"],
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", "."],
        +
        +	"\r\n\r\ngreeting ",
        +	["keyword", "pic"],
        +	["class-name", [
        +		"x",
        +		["punctuation", "("],
        +		["number", "12"],
        +		["punctuation", ")"]
        +	]],
        +	["keyword", "value"],
        +	["keyword", "is"],
        +	["string", "\"Hello World\""],
        +	["punctuation", "."]
        +]
        diff --git a/tests/languages/cobol/comment_feature.test b/tests/languages/cobol/comment_feature.test
        new file mode 100644
        index 0000000000..5eb1b8d563
        --- /dev/null
        +++ b/tests/languages/cobol/comment_feature.test
        @@ -0,0 +1,11 @@
        +*> comment
        +
        +* temporary variables in computational usage.
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "*> comment"],
        +
        +	["comment", "* temporary variables in computational usage."]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cobol/level_feature.test b/tests/languages/cobol/level_feature.test
        new file mode 100644
        index 0000000000..8e3640f3a9
        --- /dev/null
        +++ b/tests/languages/cobol/level_feature.test
        @@ -0,0 +1,126 @@
        +01 ServiceRecord.
        +   05 SSN                        pic 9(9).
        +   05 Name.
        +      10 GivenName               pic a(20).
        +      10 FamilyName              pic a(20).
        +   05 Rank.
        +      10 RankType                pic a(1)
        +         88 ValidRankType        value 'O' 'E' 'W'.
        +         88 Enlisted             value 'E'.
        +         88 WarrantOfficer       value 'W'.
        +         88 CommissionedOfficer  value 'W'.
        +      10 Grade                   pic x(2)
        +         88 ValidGrade           value '1' '2' '3' '4' '5' '6' '7' '8' '9' '10' '1E' '2E' '3E'.
        +
        +----------------------------------------------------
        +
        +[
        +	["level", "01"],
        +	" ServiceRecord",
        +	["punctuation", "."],
        +
        +	["level", "05"],
        +	" SSN                        ",
        +	["keyword", "pic"],
        +	["class-name", [
        +		"9",
        +		["punctuation", "("],
        +		["number", "9"],
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", "."],
        +
        +	["level", "05"],
        +	" Name",
        +	["punctuation", "."],
        +
        +	["level", "10"],
        +	" GivenName               ",
        +	["keyword", "pic"],
        +	["class-name", [
        +		"a",
        +		["punctuation", "("],
        +		["number", "20"],
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", "."],
        +
        +	["level", "10"],
        +	" FamilyName              ",
        +	["keyword", "pic"],
        +	["class-name", [
        +		"a",
        +		["punctuation", "("],
        +		["number", "20"],
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", "."],
        +
        +	["level", "05"],
        +	" Rank",
        +	["punctuation", "."],
        +
        +	["level", "10"],
        +	" RankType                ",
        +	["keyword", "pic"],
        +	["class-name", [
        +		"a",
        +		["punctuation", "("],
        +		["number", "1"],
        +		["punctuation", ")"]
        +	]],
        +
        +	["level", "88"],
        +	" ValidRankType        ",
        +	["keyword", "value"],
        +	["string", "'O'"],
        +	["string", "'E'"],
        +	["string", "'W'"],
        +	["punctuation", "."],
        +
        +	["level", "88"],
        +	" Enlisted             ",
        +	["keyword", "value"],
        +	["string", "'E'"],
        +	["punctuation", "."],
        +
        +	["level", "88"],
        +	" WarrantOfficer       ",
        +	["keyword", "value"],
        +	["string", "'W'"],
        +	["punctuation", "."],
        +
        +	["level", "88"],
        +	" CommissionedOfficer  ",
        +	["keyword", "value"],
        +	["string", "'W'"],
        +	["punctuation", "."],
        +
        +	["level", "10"],
        +	" Grade                   ",
        +	["keyword", "pic"],
        +	["class-name", [
        +		"x",
        +		["punctuation", "("],
        +		["number", "2"],
        +		["punctuation", ")"]
        +	]],
        +
        +	["level", "88"],
        +	" ValidGrade           ",
        +	["keyword", "value"],
        +	["string", "'1'"],
        +	["string", "'2'"],
        +	["string", "'3'"],
        +	["string", "'4'"],
        +	["string", "'5'"],
        +	["string", "'6'"],
        +	["string", "'7'"],
        +	["string", "'8'"],
        +	["string", "'9'"],
        +	["string", "'10'"],
        +	["string", "'1E'"],
        +	["string", "'2E'"],
        +	["string", "'3E'"],
        +	["punctuation", "."]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cobol/number_feature.test b/tests/languages/cobol/number_feature.test
        new file mode 100644
        index 0000000000..4a73f1e502
        --- /dev/null
        +++ b/tests/languages/cobol/number_feature.test
        @@ -0,0 +1,23 @@
        +zero Zero ZERO
        +
        += 0
        += 123
        += .4e-5
        += +3e5
        += -43
        +
        +x"ff"
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "zero"], ["number", "Zero"], ["number", "ZERO"],
        +
        +	["operator", "="], ["number", "0"],
        +	["operator", "="], ["number", "123"],
        +	["operator", "="], ["number", ".4e-5"],
        +	["operator", "="], ["number", "+3e5"],
        +	["operator", "="], ["number", "-43"],
        +
        +	["string", "x\"ff\""]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cobol/operator_feature.test b/tests/languages/cobol/operator_feature.test
        new file mode 100644
        index 0000000000..872ccc8832
        --- /dev/null
        +++ b/tests/languages/cobol/operator_feature.test
        @@ -0,0 +1,21 @@
        ++ - * /
        += <> < <= > >=
        +&
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +
        +	["operator", "="],
        +	["operator", "<>"],
        +	["operator", "<"],
        +	["operator", "<="],
        +	["operator", ">"],
        +	["operator", ">="],
        +
        +	["operator", "&"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cobol/punctuation_feature.test b/tests/languages/cobol/punctuation_feature.test
        new file mode 100644
        index 0000000000..5d033d5a1c
        --- /dev/null
        +++ b/tests/languages/cobol/punctuation_feature.test
        @@ -0,0 +1,9 @@
        +( )
        +. : ,
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("], ["punctuation", ")"],
        +	["punctuation", "."], ["punctuation", ":"], ["punctuation", ","]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cobol/string_feature.test b/tests/languages/cobol/string_feature.test
        new file mode 100644
        index 0000000000..705f1c4c1f
        --- /dev/null
        +++ b/tests/languages/cobol/string_feature.test
        @@ -0,0 +1,13 @@
        +""
        +''
        +"foo""bar"
        +'foo''bar'
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"\""],
        +	["string", "''"],
        +	["string", "\"foo\"\"bar\""],
        +	["string", "'foo''bar'"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/coffeescript+haml/coffeescript_inclusion.test b/tests/languages/coffeescript+haml/coffeescript_inclusion.test
        index 7a7751692d..866b85faf6 100644
        --- a/tests/languages/coffeescript+haml/coffeescript_inclusion.test
        +++ b/tests/languages/coffeescript+haml/coffeescript_inclusion.test
        @@ -10,15 +10,19 @@
         [
         	["filter-coffee", [
         		["filter-name", ":coffee"],
        -		["string", "'This is coffee script'"]
        +		["text", [
        +			["string", "'This is coffee script'"]
        +		]]
         	]],
         	["punctuation", "~"],
         	["filter-coffee", [
        -        ["filter-name", ":coffee"],
        -        ["string", "'This is coffee script'"]
        -    ]]
        +		["filter-name", ":coffee"],
        +		["text", [
        +			["string", "'This is coffee script'"]
        +		]]
        +	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for CoffeeScript filter in Haml. The tilde serves only as a separator.
        \ No newline at end of file
        +Checks for CoffeeScript filter in Haml. The tilde serves only as a separator.
        diff --git a/tests/languages/coffeescript+pug/coffeescript_inclusion.test b/tests/languages/coffeescript+pug/coffeescript_inclusion.test
        index ccf8963ba1..0ae21dc076 100644
        --- a/tests/languages/coffeescript+pug/coffeescript_inclusion.test
        +++ b/tests/languages/coffeescript+pug/coffeescript_inclusion.test
        @@ -6,14 +6,16 @@
         [
         	["filter-coffee", [
         		["filter-name", ":coffee"],
        -		["string", [
        -			"\"",
        -			["interpolation", "#{foo}"],
        -			"\""
        +		["text", [
        +			["string", [
        +				"\"",
        +				["interpolation", "#{foo}"],
        +				"\""
        +			]]
         		]]
         	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for coffee filter (CoffeeScript) in Jade.
        \ No newline at end of file
        +Checks for coffee filter (CoffeeScript) in pug.
        diff --git a/tests/languages/coffeescript/inline-javascript_feature.test b/tests/languages/coffeescript/inline-javascript_feature.test
        index cf15e26c0a..c6fbd2fcc3 100644
        --- a/tests/languages/coffeescript/inline-javascript_feature.test
        +++ b/tests/languages/coffeescript/inline-javascript_feature.test
        @@ -7,16 +7,20 @@ JS here */`
         [
         	["inline-javascript", [
         		["delimiter", "`"],
        -		["comment", "/* JS here */"],
        +		["script", [
        +			["comment", "/* JS here */"]
        +		]],
         		["delimiter", "`"]
         	]],
         	["inline-javascript", [
        -        ["delimiter", "`"],
        -        ["comment", "/*\r\nJS here */"],
        -        ["delimiter", "`"]
        -    ]]
        +		["delimiter", "`"],
        +		["script", [
        +			["comment", "/*\r\nJS here */"]
        +		]],
        +		["delimiter", "`"]
        +	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for inline JavaScript.
        \ No newline at end of file
        +Checks for inline JavaScript.
        diff --git a/tests/languages/coffeescript/property_feature.test b/tests/languages/coffeescript/property_feature.test
        index 0f25679876..985ce7d7bf 100644
        --- a/tests/languages/coffeescript/property_feature.test
        +++ b/tests/languages/coffeescript/property_feature.test
        @@ -5,11 +5,11 @@ foo_bar :
         
         [
         	["property", "foo"],
        -	["punctuation", ":"],
        +	["operator", ":"],
         	["property", "foo_bar"],
        -	["punctuation", ":"]
        +	["operator", ":"]
         ]
         
         ----------------------------------------------------
         
        -Checks for object properties.
        \ No newline at end of file
        +Checks for object properties.
        diff --git a/tests/languages/concurnas/annotation_feature.test b/tests/languages/concurnas/annotation_feature.test
        new file mode 100644
        index 0000000000..f1792287c3
        --- /dev/null
        +++ b/tests/languages/concurnas/annotation_feature.test
        @@ -0,0 +1,18 @@
        +@Deprecated(SUBSYSTEM_DEPRECATED)
        +@SetUp
        +@Suppress
        +copyMe@
        +
        +----------------------------------------------------
        +
        +[
        +	["annotation", "@Deprecated"], ["punctuation", "("], "SUBSYSTEM_DEPRECATED", ["punctuation", ")"],
        +	["annotation", "@SetUp"],
        +	["annotation", "@Suppress"],
        +	"\r\ncopyMe",
        +	["annotation","@"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for annotations.
        \ No newline at end of file
        diff --git a/tests/languages/concurnas/comment_feature.test b/tests/languages/concurnas/comment_feature.test
        new file mode 100644
        index 0000000000..cbcafa7068
        --- /dev/null
        +++ b/tests/languages/concurnas/comment_feature.test
        @@ -0,0 +1,11 @@
        +// comment
        +/*
        +comment
        +*/
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "// comment"],
        +	["comment", "/*\r\ncomment\r\n*/"]
        +]
        diff --git a/tests/languages/concurnas/function_feature.test b/tests/languages/concurnas/function_feature.test
        new file mode 100644
        index 0000000000..9f9905a4e9
        --- /dev/null
        +++ b/tests/languages/concurnas/function_feature.test
        @@ -0,0 +1,21 @@
        +def myfunc() => 12
        +myfunc()
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "def"],
        +	["function", "myfunc"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +	["number", "12"],
        +
        +	"\r\nmyfunc",
        +	["punctuation", "("],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for functions.
        diff --git a/tests/languages/concurnas/keyword_feature.test b/tests/languages/concurnas/keyword_feature.test
        new file mode 100644
        index 0000000000..45e38f7aaf
        --- /dev/null
        +++ b/tests/languages/concurnas/keyword_feature.test
        @@ -0,0 +1,185 @@
        +abstract
        +actor
        +also
        +annotation
        +assert
        +async
        +await
        +bool
        +boolean
        +break
        +byte
        +case
        +catch
        +changed
        +char
        +class
        +closed
        +constant
        +continue
        +def
        +default
        +del
        +double
        +elif
        +else
        +enum
        +every
        +extends
        +false
        +finally
        +float
        +for
        +from
        +global
        +gpudef
        +gpukernel
        +if
        +import
        +in
        +init
        +inject
        +int
        +lambda
        +local
        +long
        +loop
        +match
        +new
        +nodefault
        +null
        +of
        +onchange
        +open
        +out
        +override
        +package
        +parfor
        +parforsync
        +post
        +pre
        +private
        +protected
        +provide
        +provider
        +public
        +return
        +shared
        +short
        +single
        +size_t
        +sizeof
        +super
        +sync
        +this
        +throw
        +trait
        +trans
        +transient
        +true
        +try
        +typedef
        +unchecked
        +using
        +val
        +var
        +void
        +while
        +with
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "abstract"],
        +	["keyword", "actor"],
        +	["keyword", "also"],
        +	["keyword", "annotation"],
        +	["keyword", "assert"],
        +	["keyword", "async"],
        +	["keyword", "await"],
        +	["keyword", "bool"],
        +	["keyword", "boolean"],
        +	["keyword", "break"],
        +	["keyword", "byte"],
        +	["keyword", "case"],
        +	["keyword", "catch"],
        +	["keyword", "changed"],
        +	["keyword", "char"],
        +	["keyword", "class"],
        +	["keyword", "closed"],
        +	["keyword", "constant"],
        +	["keyword", "continue"],
        +	["keyword", "def"],
        +	["keyword", "default"],
        +	["keyword", "del"],
        +	["keyword", "double"],
        +	["keyword", "elif"],
        +	["keyword", "else"],
        +	["keyword", "enum"],
        +	["keyword", "every"],
        +	["keyword", "extends"],
        +	["keyword", "false"],
        +	["keyword", "finally"],
        +	["keyword", "float"],
        +	["keyword", "for"],
        +	["keyword", "from"],
        +	["keyword", "global"],
        +	["keyword", "gpudef"],
        +	["keyword", "gpukernel"],
        +	["keyword", "if"],
        +	["keyword", "import"],
        +	["keyword", "in"],
        +	["keyword", "init"],
        +	["keyword", "inject"],
        +	["keyword", "int"],
        +	["keyword", "lambda"],
        +	["keyword", "local"],
        +	["keyword", "long"],
        +	["keyword", "loop"],
        +	["keyword", "match"],
        +	["keyword", "new"],
        +	["keyword", "nodefault"],
        +	["keyword", "null"],
        +	["keyword", "of"],
        +	["keyword", "onchange"],
        +	["keyword", "open"],
        +	["keyword", "out"],
        +	["keyword", "override"],
        +	["keyword", "package"],
        +	["keyword", "parfor"],
        +	["keyword", "parforsync"],
        +	["keyword", "post"],
        +	["keyword", "pre"],
        +	["keyword", "private"],
        +	["keyword", "protected"],
        +	["keyword", "provide"],
        +	["keyword", "provider"],
        +	["keyword", "public"],
        +	["keyword", "return"],
        +	["keyword", "shared"],
        +	["keyword", "short"],
        +	["keyword", "single"],
        +	["keyword", "size_t"],
        +	["keyword", "sizeof"],
        +	["keyword", "super"],
        +	["keyword", "sync"],
        +	["keyword", "this"],
        +	["keyword", "throw"],
        +	["keyword", "trait"],
        +	["keyword", "trans"],
        +	["keyword", "transient"],
        +	["keyword", "true"],
        +	["keyword", "try"],
        +	["keyword", "typedef"],
        +	["keyword", "unchecked"],
        +	["keyword", "using"],
        +	["keyword", "val"],
        +	["keyword", "var"],
        +	["keyword", "void"],
        +	["keyword", "while"],
        +	["keyword", "with"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for keywords.
        diff --git a/tests/languages/concurnas/langext_feature.test b/tests/languages/concurnas/langext_feature.test
        new file mode 100644
        index 0000000000..34606886af
        --- /dev/null
        +++ b/tests/languages/concurnas/langext_feature.test
        @@ -0,0 +1,23 @@
        +myAPL || x[⍋x←6?40] ||
        +SimpleLisp||(+ 1 2 (* 3 3 ) )||
        +
        + || invalid ||
        +
        +----------------------------------------------------
        +
        +[
        +	["langext", [
        +		["class-name", "myAPL"],
        +		["punctuation", "||"],
        +		["string", " x[⍋x←6?40] "],
        +		["punctuation", "||"]
        +	]],
        +	["langext", [
        +		["class-name", "SimpleLisp"],
        +		["punctuation", "||"],
        +		["string", "(+ 1 2 (* 3 3 ) )"],
        +		["punctuation", "||"]
        +	]],
        +
        +	"\r\n\r\n || invalid ||"
        +]
        diff --git a/tests/languages/concurnas/number_feature.test b/tests/languages/concurnas/number_feature.test
        new file mode 100644
        index 0000000000..4e52aabcd8
        --- /dev/null
        +++ b/tests/languages/concurnas/number_feature.test
        @@ -0,0 +1,45 @@
        +123
        +123L
        +123l
        +12s
        +12S
        +0x0F
        +0b00001011
        +123.5
        +123.5e10
        +123.5e-10
        +123.5e+10
        +123.5f
        +123.5F
        +123_456
        +123_456L
        +0X01AB_23CD
        +0B1001_1101
        +12E34_56
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "123"],
        +	["number", "123L"],
        +	["number", "123l"],
        +	["number", "12s"],
        +	["number", "12S"],
        +	["number", "0x0F"],
        +	["number", "0b00001011"],
        +	["number", "123.5"],
        +	["number", "123.5e10"],
        +	["number", "123.5e-10"],
        +	["number", "123.5e+10"],
        +	["number", "123.5f"],
        +	["number", "123.5F"],
        +	["number", "123_456"],
        +	["number", "123_456L"],
        +	["number", "0X01AB_23CD"],
        +	["number", "0B1001_1101"],
        +	["number", "12E34_56"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for numbers.
        \ No newline at end of file
        diff --git a/tests/languages/concurnas/operator_feature.test b/tests/languages/concurnas/operator_feature.test
        new file mode 100644
        index 0000000000..f19761e411
        --- /dev/null
        +++ b/tests/languages/concurnas/operator_feature.test
        @@ -0,0 +1,66 @@
        ++ ++ +=
        +- -- -=
        += == <>
        +&== &<>
        +isnot
        +is as
        +comp
        +/ /= * *=
        +mod mod=
        +< <== > >==
        +and or
        +band bor bxor
        +^ ~
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "++"],
        +	["operator", "+="],
        +
        +	["operator", "-"],
        +	["operator", "--"],
        +	["operator", "-="],
        +
        +	["operator", "="],
        +	["operator", "=="],
        +	["operator", "<>"],
        +
        +	["operator", "&=="],
        +	["operator", "&<>"],
        +
        +	["operator", "isnot"],
        +
        +	["operator", "is"],
        +	["operator", "as"],
        +
        +	["operator", "comp"],
        +
        +	["operator", "/"],
        +	["operator", "/="],
        +	["operator", "*"],
        +	["operator", "*="],
        +
        +	["operator", "mod"],
        +	["operator", "mod="],
        +
        +	["operator", "<"],
        +	["operator", "<=="],
        +	["operator", ">"],
        +	["operator", ">=="],
        +
        +	["operator", "and"],
        +	["operator", "or"],
        +
        +	["operator", "band"],
        +	["operator", "bor"],
        +	["operator", "bxor"],
        +
        +	["operator", "^"],
        +	["operator", "~"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for operators.
        diff --git a/tests/languages/concurnas/regex_feature.test b/tests/languages/concurnas/regex_feature.test
        new file mode 100644
        index 0000000000..5615bdc7d8
        --- /dev/null
        +++ b/tests/languages/concurnas/regex_feature.test
        @@ -0,0 +1,13 @@
        +r'say'
        +r"hello"
        +
        +----------------------------------------------------
        +
        +[
        +	["regex-literal", [
        +		["regex", "r'say'"]
        +	]],
        +	["regex-literal", [
        +		["regex", "r\"hello\""]
        +	]]
        +]
        diff --git a/tests/languages/concurnas/string_feature.test b/tests/languages/concurnas/string_feature.test
        new file mode 100644
        index 0000000000..ee0c237b29
        --- /dev/null
        +++ b/tests/languages/concurnas/string_feature.test
        @@ -0,0 +1,33 @@
        +"hi"
        +"addition result: {1+2}"
        +'hi'
        +'contains: "'
        +
        +----------------------------------------------------
        +
        +[
        +	["string-literal", [
        +		["string", "\"hi\""]
        +	]],
        +	["string-literal", [
        +		["string", "\"addition result: "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["number", "1"],
        +			["operator", "+"],
        +			["number", "2"],
        +			["punctuation", "}"]
        +		]],
        +		["string", "\""]
        +	]],
        +	["string-literal", [
        +		["string", "'hi'"]
        +	]],
        +	["string-literal", [
        +		["string", "'contains: \"'"]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for raw strings.
        diff --git a/tests/languages/coq/attribute_feature.test b/tests/languages/coq/attribute_feature.test
        new file mode 100644
        index 0000000000..7d727fc1a0
        --- /dev/null
        +++ b/tests/languages/coq/attribute_feature.test
        @@ -0,0 +1,93 @@
        +#[program]
        +#[program=yes]
        +#[deprecated(since="8.9.0")]
        +#[local, universes(polymorphic)]
        +#[universes(polymorphic(foo,bar))]
        +#[canonical=yes, canonical=no]
        +#[ export ]
        +
        +(* legacy *)
        +Cumulative
        +Global
        +Local
        +Monomorphic
        +NonCumulative
        +Polymorphic
        +Private
        +Program
        +
        +----------------------------------------------------
        +
        +[
        +	["attribute", [
        +		["punctuation", "#["],
        +		"program",
        +		["punctuation", "]"]
        +	]],
        +	["attribute", [
        +		["punctuation", "#["],
        +		"program",
        +		["operator", "="],
        +		"yes",
        +		["punctuation", "]"]
        +	]],
        +	["attribute", [
        +		["punctuation", "#["],
        +		"deprecated",
        +		["punctuation", "("],
        +		"since",
        +		["operator", "="],
        +		["string", "\"8.9.0\""],
        +		["punctuation", ")"],
        +		["punctuation", "]"]
        +	]],
        +	["attribute", [
        +		["punctuation", "#["],
        +		"local",
        +		["punctuation", ","],
        +		" universes",
        +		["punctuation", "("],
        +		"polymorphic",
        +		["punctuation", ")"],
        +		["punctuation", "]"]
        +	]],
        +	["attribute", [
        +		["punctuation", "#["],
        +		"universes",
        +		["punctuation", "("],
        +		"polymorphic",
        +		["punctuation", "("],
        +		"foo",
        +		["punctuation", ","],
        +		"bar",
        +		["punctuation", ")"],
        +		["punctuation", ")"],
        +		["punctuation", "]"]
        +	]],
        +	["attribute", [
        +		["punctuation", "#["],
        +		"canonical",
        +		["operator", "="],
        +		"yes",
        +		["punctuation", ","],
        +		" canonical",
        +		["operator", "="],
        +		"no",
        +		["punctuation", "]"]
        +	]],
        +	["attribute", [
        +		["punctuation", "#["],
        +		" export ",
        +		["punctuation", "]"]
        +	]],
        +
        +	["comment", "(* legacy *)"],
        +	["attribute", "Cumulative"],
        +	["attribute", "Global"],
        +	["attribute", "Local"],
        +	["attribute", "Monomorphic"],
        +	["attribute", "NonCumulative"],
        +	["attribute", "Polymorphic"],
        +	["attribute", "Private"],
        +	["attribute", "Program"]
        +]
        diff --git a/tests/languages/coq/comment_feature.test b/tests/languages/coq/comment_feature.test
        new file mode 100644
        index 0000000000..9564560a59
        --- /dev/null
        +++ b/tests/languages/coq/comment_feature.test
        @@ -0,0 +1,17 @@
        +(**)
        +(* comment *)
        +(*
        + comment
        + *)
        +
        +(* comments (* can be (* nested *) *) *)
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "(**)"],
        +	["comment", "(* comment *)"],
        +	["comment", "(*\r\n comment\r\n *)"],
        +
        +	["comment", "(* comments (* can be (* nested *) *) *)"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/coq/keyword_feature.test b/tests/languages/coq/keyword_feature.test
        new file mode 100644
        index 0000000000..8e17324efe
        --- /dev/null
        +++ b/tests/languages/coq/keyword_feature.test
        @@ -0,0 +1,547 @@
        +_
        +Abort
        +About
        +Add
        +Admit
        +Admitted
        +All
        +apply
        +Arguments
        +as
        +As
        +Assumptions
        +at
        +Axiom
        +Axioms
        +Back
        +BackTo
        +Backtrace
        +Bind
        +BinOp
        +BinOpSpec
        +BinRel
        +Blacklist
        +by
        +Canonical
        +Case
        +Cd
        +Check
        +Class
        +Classes
        +Close
        +Coercion
        +Coercions
        +cofix
        +CoFixpoint
        +CoInductive
        +Collection
        +Combined
        +Compute
        +Conjecture
        +Conjectures
        +Constant
        +Constants
        +Constraint
        +Constructors
        +Context
        +Corollary
        +Create
        +CstOp
        +Custom
        +Cut
        +Debug
        +Declare
        +Defined
        +Definition
        +Delimit
        +Dependencies
        +Dependent
        +Derive
        +Diffs
        +Drop
        +Elimination
        +else
        +end
        +End
        +Entry
        +Equality
        +Eval
        +Example
        +Existential
        +Existentials
        +Existing
        +exists
        +exists2
        +Export
        +Extern
        +Extraction
        +Fact
        +Fail
        +Field
        +File
        +Firstorder
        +fix
        +Fixpoint
        +Flags
        +Focus
        +for
        +forall
        +From
        +fun
        +Funclass
        +Function
        +Functional
        +GC
        +Generalizable
        +Goal
        +Grab
        +Grammar
        +Graph
        +Guarded
        +Haskell
        +Heap
        +Hide
        +Hint
        +HintDb
        +Hints
        +Hypotheses
        +Hypothesis
        +Identity
        +if
        +IF
        +Immediate
        +Implicit
        +Implicits
        +Import
        +in
        +Include
        +Induction
        +Inductive
        +Infix
        +Info
        +Initial
        +InjTyp
        +Inline
        +Inspect
        +Instance
        +Instances
        +Intro
        +Intros
        +Inversion
        +Inversion_clear
        +JSON
        +Language
        +Left
        +Lemma
        +let
        +Let
        +Lia
        +Libraries
        +Library
        +Load
        +LoadPath
        +Locate
        +Ltac
        +Ltac2
        +match
        +Match
        +measure
        +Method
        +Minimality
        +ML
        +Module
        +Modules
        +Morphism
        +move
        +Next
        +NoInline
        +Notation
        +Number
        +Obligation
        +Obligations
        +OCaml
        +Opaque
        +Open
        +Optimize
        +Parameter
        +Parameters
        +Parametric
        +Path
        +Paths
        +Prenex
        +Preterm
        +Primitive
        +Print
        +Profile
        +Projections
        +Proof
        +Prop
        +PropBinOp
        +Property
        +PropOp
        +Proposition
        +PropUOp
        +Pwd
        +Qed
        +Quit
        +Rec
        +Record
        +Recursive
        +Redirect
        +Reduction
        +Register
        +Relation
        +Remark
        +Remove
        +removed
        +Require
        +Reserved
        +Reset
        +Resolve
        +Restart
        +return
        +Rewrite
        +Right
        +Ring
        +Rings
        +Saturate
        +Save
        +Scheme
        +Scope
        +Scopes
        +Search
        +SearchHead
        +SearchPattern
        +SearchRewrite
        +Section
        +Separate
        +Set
        +Setoid
        +Show
        +Signatures
        +Solve
        +Solver
        +Sort
        +Sortclass
        +Sorted
        +Spec
        +SProp
        +Step
        +Strategies
        +Strategy
        +String
        +struct
        +Structure
        +SubClass
        +Subgraph
        +SuchThat
        +Tactic
        +Term
        +TestCompile
        +then
        +Theorem
        +Time
        +Timeout
        +To
        +Transparent
        +Type
        +Typeclasses
        +Types
        +Typing
        +Undelimit
        +Undo
        +Unfocus
        +Unfocused
        +Unfold
        +Universe
        +Universes
        +UnOp
        +UnOpSpec
        +Unshelve
        +using
        +Variable
        +Variables
        +Variant
        +Verbose
        +View
        +Visibility
        +wf
        +where
        +with
        +Zify
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "_"],
        +	["keyword", "Abort"],
        +	["keyword", "About"],
        +	["keyword", "Add"],
        +	["keyword", "Admit"],
        +	["keyword", "Admitted"],
        +	["keyword", "All"],
        +	["keyword", "apply"],
        +	["keyword", "Arguments"],
        +	["keyword", "as"],
        +	["keyword", "As"],
        +	["keyword", "Assumptions"],
        +	["keyword", "at"],
        +	["keyword", "Axiom"],
        +	["keyword", "Axioms"],
        +	["keyword", "Back"],
        +	["keyword", "BackTo"],
        +	["keyword", "Backtrace"],
        +	["keyword", "Bind"],
        +	["keyword", "BinOp"],
        +	["keyword", "BinOpSpec"],
        +	["keyword", "BinRel"],
        +	["keyword", "Blacklist"],
        +	["keyword", "by"],
        +	["keyword", "Canonical"],
        +	["keyword", "Case"],
        +	["keyword", "Cd"],
        +	["keyword", "Check"],
        +	["keyword", "Class"],
        +	["keyword", "Classes"],
        +	["keyword", "Close"],
        +	["keyword", "Coercion"],
        +	["keyword", "Coercions"],
        +	["keyword", "cofix"],
        +	["keyword", "CoFixpoint"],
        +	["keyword", "CoInductive"],
        +	["keyword", "Collection"],
        +	["keyword", "Combined"],
        +	["keyword", "Compute"],
        +	["keyword", "Conjecture"],
        +	["keyword", "Conjectures"],
        +	["keyword", "Constant"],
        +	["keyword", "Constants"],
        +	["keyword", "Constraint"],
        +	["keyword", "Constructors"],
        +	["keyword", "Context"],
        +	["keyword", "Corollary"],
        +	["keyword", "Create"],
        +	["keyword", "CstOp"],
        +	["keyword", "Custom"],
        +	["keyword", "Cut"],
        +	["keyword", "Debug"],
        +	["keyword", "Declare"],
        +	["keyword", "Defined"],
        +	["keyword", "Definition"],
        +	["keyword", "Delimit"],
        +	["keyword", "Dependencies"],
        +	["keyword", "Dependent"],
        +	["keyword", "Derive"],
        +	["keyword", "Diffs"],
        +	["keyword", "Drop"],
        +	["keyword", "Elimination"],
        +	["keyword", "else"],
        +	["keyword", "end"],
        +	["keyword", "End"],
        +	["keyword", "Entry"],
        +	["keyword", "Equality"],
        +	["keyword", "Eval"],
        +	["keyword", "Example"],
        +	["keyword", "Existential"],
        +	["keyword", "Existentials"],
        +	["keyword", "Existing"],
        +	["keyword", "exists"],
        +	["keyword", "exists2"],
        +	["keyword", "Export"],
        +	["keyword", "Extern"],
        +	["keyword", "Extraction"],
        +	["keyword", "Fact"],
        +	["keyword", "Fail"],
        +	["keyword", "Field"],
        +	["keyword", "File"],
        +	["keyword", "Firstorder"],
        +	["keyword", "fix"],
        +	["keyword", "Fixpoint"],
        +	["keyword", "Flags"],
        +	["keyword", "Focus"],
        +	["keyword", "for"],
        +	["keyword", "forall"],
        +	["keyword", "From"],
        +	["keyword", "fun"],
        +	["keyword", "Funclass"],
        +	["keyword", "Function"],
        +	["keyword", "Functional"],
        +	["keyword", "GC"],
        +	["keyword", "Generalizable"],
        +	["keyword", "Goal"],
        +	["keyword", "Grab"],
        +	["keyword", "Grammar"],
        +	["keyword", "Graph"],
        +	["keyword", "Guarded"],
        +	["keyword", "Haskell"],
        +	["keyword", "Heap"],
        +	["keyword", "Hide"],
        +	["keyword", "Hint"],
        +	["keyword", "HintDb"],
        +	["keyword", "Hints"],
        +	["keyword", "Hypotheses"],
        +	["keyword", "Hypothesis"],
        +	["keyword", "Identity"],
        +	["keyword", "if"],
        +	["keyword", "IF"],
        +	["keyword", "Immediate"],
        +	["keyword", "Implicit"],
        +	["keyword", "Implicits"],
        +	["keyword", "Import"],
        +	["keyword", "in"],
        +	["keyword", "Include"],
        +	["keyword", "Induction"],
        +	["keyword", "Inductive"],
        +	["keyword", "Infix"],
        +	["keyword", "Info"],
        +	["keyword", "Initial"],
        +	["keyword", "InjTyp"],
        +	["keyword", "Inline"],
        +	["keyword", "Inspect"],
        +	["keyword", "Instance"],
        +	["keyword", "Instances"],
        +	["keyword", "Intro"],
        +	["keyword", "Intros"],
        +	["keyword", "Inversion"],
        +	["keyword", "Inversion_clear"],
        +	["keyword", "JSON"],
        +	["keyword", "Language"],
        +	["keyword", "Left"],
        +	["keyword", "Lemma"],
        +	["keyword", "let"],
        +	["keyword", "Let"],
        +	["keyword", "Lia"],
        +	["keyword", "Libraries"],
        +	["keyword", "Library"],
        +	["keyword", "Load"],
        +	["keyword", "LoadPath"],
        +	["keyword", "Locate"],
        +	["keyword", "Ltac"],
        +	["keyword", "Ltac2"],
        +	["keyword", "match"],
        +	["keyword", "Match"],
        +	["keyword", "measure"],
        +	["keyword", "Method"],
        +	["keyword", "Minimality"],
        +	["keyword", "ML"],
        +	["keyword", "Module"],
        +	["keyword", "Modules"],
        +	["keyword", "Morphism"],
        +	["keyword", "move"],
        +	["keyword", "Next"],
        +	["keyword", "NoInline"],
        +	["keyword", "Notation"],
        +	["keyword", "Number"],
        +	["keyword", "Obligation"],
        +	["keyword", "Obligations"],
        +	["keyword", "OCaml"],
        +	["keyword", "Opaque"],
        +	["keyword", "Open"],
        +	["keyword", "Optimize"],
        +	["keyword", "Parameter"],
        +	["keyword", "Parameters"],
        +	["keyword", "Parametric"],
        +	["keyword", "Path"],
        +	["keyword", "Paths"],
        +	["keyword", "Prenex"],
        +	["keyword", "Preterm"],
        +	["keyword", "Primitive"],
        +	["keyword", "Print"],
        +	["keyword", "Profile"],
        +	["keyword", "Projections"],
        +	["keyword", "Proof"],
        +	["keyword", "Prop"],
        +	["keyword", "PropBinOp"],
        +	["keyword", "Property"],
        +	["keyword", "PropOp"],
        +	["keyword", "Proposition"],
        +	["keyword", "PropUOp"],
        +	["keyword", "Pwd"],
        +	["keyword", "Qed"],
        +	["keyword", "Quit"],
        +	["keyword", "Rec"],
        +	["keyword", "Record"],
        +	["keyword", "Recursive"],
        +	["keyword", "Redirect"],
        +	["keyword", "Reduction"],
        +	["keyword", "Register"],
        +	["keyword", "Relation"],
        +	["keyword", "Remark"],
        +	["keyword", "Remove"],
        +	["keyword", "removed"],
        +	["keyword", "Require"],
        +	["keyword", "Reserved"],
        +	["keyword", "Reset"],
        +	["keyword", "Resolve"],
        +	["keyword", "Restart"],
        +	["keyword", "return"],
        +	["keyword", "Rewrite"],
        +	["keyword", "Right"],
        +	["keyword", "Ring"],
        +	["keyword", "Rings"],
        +	["keyword", "Saturate"],
        +	["keyword", "Save"],
        +	["keyword", "Scheme"],
        +	["keyword", "Scope"],
        +	["keyword", "Scopes"],
        +	["keyword", "Search"],
        +	["keyword", "SearchHead"],
        +	["keyword", "SearchPattern"],
        +	["keyword", "SearchRewrite"],
        +	["keyword", "Section"],
        +	["keyword", "Separate"],
        +	["keyword", "Set"],
        +	["keyword", "Setoid"],
        +	["keyword", "Show"],
        +	["keyword", "Signatures"],
        +	["keyword", "Solve"],
        +	["keyword", "Solver"],
        +	["keyword", "Sort"],
        +	["keyword", "Sortclass"],
        +	["keyword", "Sorted"],
        +	["keyword", "Spec"],
        +	["keyword", "SProp"],
        +	["keyword", "Step"],
        +	["keyword", "Strategies"],
        +	["keyword", "Strategy"],
        +	["keyword", "String"],
        +	["keyword", "struct"],
        +	["keyword", "Structure"],
        +	["keyword", "SubClass"],
        +	["keyword", "Subgraph"],
        +	["keyword", "SuchThat"],
        +	["keyword", "Tactic"],
        +	["keyword", "Term"],
        +	["keyword", "TestCompile"],
        +	["keyword", "then"],
        +	["keyword", "Theorem"],
        +	["keyword", "Time"],
        +	["keyword", "Timeout"],
        +	["keyword", "To"],
        +	["keyword", "Transparent"],
        +	["keyword", "Type"],
        +	["keyword", "Typeclasses"],
        +	["keyword", "Types"],
        +	["keyword", "Typing"],
        +	["keyword", "Undelimit"],
        +	["keyword", "Undo"],
        +	["keyword", "Unfocus"],
        +	["keyword", "Unfocused"],
        +	["keyword", "Unfold"],
        +	["keyword", "Universe"],
        +	["keyword", "Universes"],
        +	["keyword", "UnOp"],
        +	["keyword", "UnOpSpec"],
        +	["keyword", "Unshelve"],
        +	["keyword", "using"],
        +	["keyword", "Variable"],
        +	["keyword", "Variables"],
        +	["keyword", "Variant"],
        +	["keyword", "Verbose"],
        +	["keyword", "View"],
        +	["keyword", "Visibility"],
        +	["keyword", "wf"],
        +	["keyword", "where"],
        +	["keyword", "with"],
        +	["keyword", "Zify"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/coq/number_feature.test b/tests/languages/coq/number_feature.test
        new file mode 100644
        index 0000000000..3027ea8b35
        --- /dev/null
        +++ b/tests/languages/coq/number_feature.test
        @@ -0,0 +1,33 @@
        +0
        +123
        +123.456
        +123.456e65
        +123.456e+65
        +1_2_3.4_5_6e-6_5
        +1_2_3e-6_5
        +
        +0x0
        +0X0
        +0xbad.345e
        +0xbad.345ep54
        +0xbad.345ep+54
        +0xb_a_d.3_4_5_ep-5_4
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "0"],
        +	["number", "123"],
        +	["number", "123.456"],
        +	["number", "123.456e65"],
        +	["number", "123.456e+65"],
        +	["number", "1_2_3.4_5_6e-6_5"],
        +	["number", "1_2_3e-6_5"],
        +
        +	["number", "0x0"],
        +	["number", "0X0"],
        +	["number", "0xbad.345e"],
        +	["number", "0xbad.345ep54"],
        +	["number", "0xbad.345ep+54"],
        +	["number", "0xb_a_d.3_4_5_ep-5_4"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/coq/operator_feature.test b/tests/languages/coq/operator_feature.test
        new file mode 100644
        index 0000000000..227cf1943a
        --- /dev/null
        +++ b/tests/languages/coq/operator_feature.test
        @@ -0,0 +1,83 @@
        +->
        ++
        +<
        +<-
        +<->
        +<:
        +<+
        +<<:
        +<=
        +=
        +=>
        +>
        +>->
        +>=
        +|
        +|-
        +||
        +@
        +*
        +**
        +/
        +/\
        +\/
        +&
        +%
        +-
        +!
        +?
        +^
        +~
        +
        +..
        +...
        +
        +::=
        +:=
        +=
        +
        +'
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "->"],
        +	["operator", "+"],
        +	["operator", "<"],
        +	["operator", "<-"],
        +	["operator", "<->"],
        +	["operator", "<:"],
        +	["operator", "<+"],
        +	["operator", "<<:"],
        +	["operator", "<="],
        +	["operator", "="],
        +	["operator", "=>"],
        +	["operator", ">"],
        +	["operator", ">->"],
        +	["operator", ">="],
        +	["operator", "|"],
        +	["operator", "|-"],
        +	["operator", "||"],
        +	["operator", "@"],
        +	["operator", "*"],
        +	["operator", "**"],
        +	["operator", "/"],
        +	["operator", "/\\"],
        +	["operator", "\\/"],
        +	["operator", "&"],
        +	["operator", "%"],
        +	["operator", "-"],
        +	["operator", "!"],
        +	["operator", "?"],
        +	["operator", "^"],
        +	["operator", "~"],
        +
        +	["operator", ".."],
        +	["operator", "..."],
        +
        +	["operator", "::="],
        +	["operator", ":="],
        +	["operator", "="],
        +
        +	["operator", "'"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/coq/punctuation_feature.test b/tests/languages/coq/punctuation_feature.test
        new file mode 100644
        index 0000000000..6d4579d9cb
        --- /dev/null
        +++ b/tests/languages/coq/punctuation_feature.test
        @@ -0,0 +1,35 @@
        +, ; .
        +( ) .( `(
        +{ } @{ } `{ } {| }
        +[ ] [= ]
        +
        +: :>
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", ","],
        +	["punctuation", ";"],
        +	["punctuation", "."],
        +
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ".("],
        +	["punctuation", "`("],
        +
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punct", "@{"],
        +	["punctuation", "}"],
        +	["punctuation", "`{"],
        +	["punctuation", "}"],
        +	["punct", "{|"],
        +	["punctuation", "}"],
        +
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punct", "[="],
        +	["punctuation", "]"],
        +
        +	["punctuation", ":"], ["punct", ":>"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/coq/string_feature.test b/tests/languages/coq/string_feature.test
        new file mode 100644
        index 0000000000..c03f3f51cf
        --- /dev/null
        +++ b/tests/languages/coq/string_feature.test
        @@ -0,0 +1,9 @@
        +""
        +"foo""bar"
        +
        +----------------------------------------------------
        +
        +[
        +	["string", "\"\""],
        +	["string", "\"foo\"\"bar\""]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cpp/base-clause_feature.test b/tests/languages/cpp/base-clause_feature.test
        new file mode 100644
        index 0000000000..260a7099e3
        --- /dev/null
        +++ b/tests/languages/cpp/base-clause_feature.test
        @@ -0,0 +1,126 @@
        +struct Base {};
        +struct Derived : Base {};
        +struct Derived : private Base;
        +class X : public virtual B {};
        +class Y : virtual public B {};
        +class Y : virtual baz::B {};
        +class Z : public B;
        +struct AA : X, Y, foo::bar::Z {};
        +
        +class service : private Transport // comment
        +{};
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "struct"],
        +	["class-name", "Base"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "struct"],
        +	["class-name", "Derived"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["class-name", "Base"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "struct"],
        +	["class-name", "Derived"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["keyword", "private"],
        +		["class-name", "Base"]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "class"],
        +	["class-name", "X"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["keyword", "public"],
        +		["keyword", "virtual"],
        +		["class-name", "B"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "class"],
        +	["class-name", "Y"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["keyword", "virtual"],
        +		["keyword", "public"],
        +		["class-name", "B"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "class"],
        +	["class-name", "Y"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["keyword", "virtual"],
        +		" baz",
        +		["double-colon", "::"],
        +		["class-name", "B"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "class"],
        +	["class-name", "Z"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["keyword", "public"],
        +		["class-name", "B"],
        +		["operator", "<"],
        +		"foo",
        +		["double-colon", "::"],
        +		["class-name", "T"],
        +		["operator", ">"]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "struct"],
        +	["class-name", "AA"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["class-name", "X"],
        +		["punctuation", ","],
        +		["class-name", "Y"],
        +		["punctuation", ","],
        +		" foo",
        +		["double-colon", "::"],
        +		"bar",
        +		["double-colon", "::"],
        +		["class-name", "Z"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "class"],
        +	["class-name", "service"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["keyword", "private"],
        +		["class-name", "Transport"],
        +		["comment", "// comment"]
        +	]],
        +
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for the base clauses of classes and structs.
        diff --git a/tests/languages/cpp/class-name_feature.test b/tests/languages/cpp/class-name_feature.test
        index f3d5df5f63..086f6af2af 100644
        --- a/tests/languages/cpp/class-name_feature.test
        +++ b/tests/languages/cpp/class-name_feature.test
        @@ -1,13 +1,63 @@
         class Foo
         class Foo_bar
        +concept Foo_bar
        +struct foo
        +enum bar
        +enum class FooBar
        +
        +template
        +
        +void Foo::bar() {}
        +Foo::~Foo() {}
        +void Foo::bar() {}
         
         ----------------------------------------------------
         
         [
         	["keyword", "class"], ["class-name", "Foo"],
        -	["keyword", "class"], ["class-name", "Foo_bar"]
        +	["keyword", "class"], ["class-name", "Foo_bar"],
        +	["keyword", "concept"], ["class-name", "Foo_bar"],
        +	["keyword", "struct"], ["class-name", "foo"],
        +	["keyword", "enum"], ["class-name", "bar"],
        +	["keyword", "enum"], ["keyword", "class"], ["class-name", "FooBar"],
        +
        +	["keyword", "template"],
        +	["operator", "<"],
        +	["keyword", "typename"],
        +	["class-name", "FooBar"],
        +	["operator", ">"],
        +
        +	["keyword", "void"],
        +	["class-name", "Foo"],
        +	["double-colon", "::"],
        +	["function", "bar"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["class-name", "Foo"],
        +	["double-colon", "::"],
        +	["operator", "~"],
        +	["function", "Foo"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "void"],
        +	["class-name", "Foo"],
        +	["operator", "<"],
        +	["keyword", "int"],
        +	["operator", ">"],
        +	["double-colon", "::"],
        +	["function", "bar"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
         ]
         
         ----------------------------------------------------
         
        -Checks for class names.
        \ No newline at end of file
        +Checks for class names.
        diff --git a/tests/languages/cpp/comment_feature.test b/tests/languages/cpp/comment_feature.test
        new file mode 100644
        index 0000000000..6370e5daba
        --- /dev/null
        +++ b/tests/languages/cpp/comment_feature.test
        @@ -0,0 +1,26 @@
        +//
        +// comment
        +// the comment \
        +   continues!
        +
        +/**/
        +/*
        + * comment
        + */
        +
        +/* open-ended comment
        +
        +----------------------------------------------------
        +
        +[
        +	["comment", "//"],
        +	["comment", "// comment"],
        +	["comment", "// the comment \\\r\n   continues!"],
        +	["comment", "/**/"],
        +	["comment", "/*\r\n * comment\r\n */"],
        +	["comment", "/* open-ended comment"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for comments.
        diff --git a/tests/languages/cpp/function_feature.test b/tests/languages/cpp/function_feature.test
        new file mode 100644
        index 0000000000..2968199382
        --- /dev/null
        +++ b/tests/languages/cpp/function_feature.test
        @@ -0,0 +1,93 @@
        +foo();
        +line.substr(0, separator_index);
        +boost::trim(key);
        +bpo::value()
        +bpo::value>()->multitoken()
        +std::make_unique(std::move(entries));
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "foo"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	"\r\nline",
        +	["punctuation", "."],
        +	["function", "substr"],
        +	["punctuation", "("],
        +	["number", "0"],
        +	["punctuation", ","],
        +	" separator_index",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	"\r\nboost",
        +	["double-colon", "::"],
        +	["function", "trim"],
        +	["punctuation", "("],
        +	"key",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	"\r\nbpo",
        +	["double-colon", "::"],
        +	["generic-function", [
        +		["function", "value"],
        +		["generic", [
        +			["operator", "<"],
        +			"std",
        +			["double-colon", "::"],
        +			"string",
        +			["operator", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	"\r\nbpo",
        +	["double-colon", "::"],
        +	["generic-function", [
        +		["function", "value"],
        +		["generic", [
        +			["operator", "<"],
        +			"std",
        +			["double-colon", "::"],
        +			"vector",
        +			["operator", "<"],
        +			"std",
        +			["double-colon", "::"],
        +			"string",
        +			["operator", ">>"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["operator", "->"],
        +	["function", "multitoken"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	"\r\nstd",
        +	["double-colon", "::"],
        +	["generic-function", [
        +		["function", "make_unique"],
        +		["generic", [
        +			["operator", "<"],
        +			"service",
        +			["double-colon", "::"],
        +			"UniqueMap",
        +			["operator", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	"std",
        +	["double-colon", "::"],
        +	["function", "move"],
        +	["punctuation", "("],
        +	"entries",
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +	["punctuation", ";"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cpp/issue2347.test b/tests/languages/cpp/issue2347.test
        new file mode 100644
        index 0000000000..83afac78ef
        --- /dev/null
        +++ b/tests/languages/cpp/issue2347.test
        @@ -0,0 +1,70 @@
        +class MainWindow : public QMainWindow
        +{
        +  Q_OBJECT
        +
        + private slots:
        +  void changeWindowTitle();
        +};
        +void MainWindow::changeWindowTitle()
        +{
        +  setWindowTitle(plainTextEdit->currentFile.split("/").last() + " - Notepanda");
        +}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "class"],
        +	["class-name", "MainWindow"],
        +	["operator", ":"],
        +	["base-clause", [
        +		["keyword", "public"],
        +		["class-name", "QMainWindow"]
        +	]],
        +
        +	["punctuation", "{"],
        +
        +	"\r\n  Q_OBJECT\r\n\r\n ",
        +
        +	["keyword", "private"],
        +	" slots",
        +	["operator", ":"],
        +
        +	["keyword", "void"],
        +	["function", "changeWindowTitle"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "void"],
        +	["class-name", "MainWindow"],
        +	["double-colon", "::"],
        +	["function", "changeWindowTitle"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	["punctuation", "{"],
        +
        +	["function", "setWindowTitle"],
        +	["punctuation", "("],
        +	"plainTextEdit",
        +	["operator", "->"],
        +	"currentFile",
        +	["punctuation", "."],
        +	["function", "split"],
        +	["punctuation", "("],
        +	["string", "\"/\""],
        +	["punctuation", ")"],
        +	["punctuation", "."],
        +	["function", "last"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["operator", "+"],
        +	["string", "\" - Notepanda\""],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"]
        +]
        diff --git a/tests/languages/cpp/issue3042.test b/tests/languages/cpp/issue3042.test
        new file mode 100644
        index 0000000000..ab5c47b4df
        --- /dev/null
        +++ b/tests/languages/cpp/issue3042.test
        @@ -0,0 +1,126 @@
        +class Foo
        +{
        +public:
        +
        +	friend bool operator== (const Foo& f1, const Foo& f2);
        +	friend bool operator!= (const Foo& f1, const Foo& f2);
        +
        +	friend bool operator< (const Foo& f1, const Foo& f2);
        +	friend bool operator> (const Foo& f1, const Foo& f2);
        +
        +	friend bool operator<= (const Foo& f1, const Foo& f2);
        +	friend bool operator>= (const Foo& f1, const Foo& f2);
        +};
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "class"], ["class-name", "Foo"],
        +	["punctuation", "{"],
        +	["keyword", "public"], ["operator", ":"],
        +
        +	["keyword", "friend"],
        +	["keyword", "bool"],
        +	["keyword", "operator"],
        +	["operator", "=="],
        +	["punctuation", "("],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f1",
        +	["punctuation", ","],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f2",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "friend"],
        +	["keyword", "bool"],
        +	["keyword", "operator"],
        +	["operator", "!="],
        +	["punctuation", "("],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f1",
        +	["punctuation", ","],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f2",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "friend"],
        +	["keyword", "bool"],
        +	["keyword", "operator"],
        +	["operator", "<"],
        +	["punctuation", "("],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f1",
        +	["punctuation", ","],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f2",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "friend"],
        +	["keyword", "bool"],
        +	["keyword", "operator"],
        +	["operator", ">"],
        +	["punctuation", "("],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f1",
        +	["punctuation", ","],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f2",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "friend"],
        +	["keyword", "bool"],
        +	["keyword", "operator"],
        +	["operator", "<="],
        +	["punctuation", "("],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f1",
        +	["punctuation", ","],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f2",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "friend"],
        +	["keyword", "bool"],
        +	["keyword", "operator"],
        +	["operator", ">="],
        +	["punctuation", "("],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f1",
        +	["punctuation", ","],
        +	["keyword", "const"],
        +	" Foo",
        +	["operator", "&"],
        +	" f2",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +	["punctuation", ";"]
        +]
        diff --git a/tests/languages/cpp/keyword_feature.test b/tests/languages/cpp/keyword_feature.test
        index 180f68ef09..69c90b55df 100644
        --- a/tests/languages/cpp/keyword_feature.test
        +++ b/tests/languages/cpp/keyword_feature.test
        @@ -1,49 +1,193 @@
        -alignas alignof asm auto bool
        -break case catch char char16_t char32_t
        +alignas
        +alignof
        +asm
        +auto
        +bool
        +break
        +case
        +catch
        +char
        +char8_t
        +char16_t
        +char32_t
         class;
        -compl const constexpr
        -const_cast continue decltype default
        -delete do double dynamic_cast
        -else enum explicit export extern
        -float for friend goto if
        -inline int long mutable namespace
        -new noexcept nullptr operator
        -private protected public register
        -reinterpret_cast return short
        -signed sizeof static static_assert
        -static_cast struct switch template
        -this thread_local throw try
        -typedef typeid typename union
        -unsigned using virtual void
        -volatile wchar_t while
        -int8_t int16_t int32_t int64_t
        -uint8_t uint16_t uint32_t uint64_t
        +compl
        +concept
        +const
        +consteval
        +constexpr
        +constinit
        +const_cast
        +continue
        +co_await
        +co_return
        +co_yield
        +decltype
        +default
        +delete
        +do
        +double
        +dynamic_cast
        +else
        +enum;
        +explicit
        +export
        +extern
        +final
        +float
        +for
        +friend
        +goto
        +if
        +import;
        +inline
        +int
        +long
        +module;
        +mutable
        +namespace
        +new
        +noexcept
        +nullptr
        +operator
        +override
        +private
        +protected
        +public
        +register
        +reinterpret_cast
        +requires
        +return
        +short
        +signed
        +sizeof
        +static
        +static_assert
        +static_cast
        +struct;
        +switch
        +template
        +this
        +thread_local
        +throw
        +try
        +typedef
        +typeid
        +typename
        +union
        +unsigned
        +using
        +virtual
        +void
        +volatile
        +wchar_t
        +while
        +int8_t
        +int16_t
        +int32_t
        +int64_t
        +uint8_t
        +uint16_t
        +uint32_t
        +uint64_t
         
         ----------------------------------------------------
         
         [
        -	["keyword", "alignas"], ["keyword", "alignof"], ["keyword", "asm"], ["keyword", "auto"], ["keyword", "bool"],
        -	["keyword", "break"], ["keyword", "case"], ["keyword", "catch"], ["keyword", "char"], ["keyword", "char16_t"], ["keyword", "char32_t"],
        +	["keyword", "alignas"],
        +	["keyword", "alignof"],
        +	["keyword", "asm"],
        +	["keyword", "auto"],
        +	["keyword", "bool"],
        +	["keyword", "break"],
        +	["keyword", "case"],
        +	["keyword", "catch"],
        +	["keyword", "char"],
        +	["keyword", "char8_t"],
        +	["keyword", "char16_t"],
        +	["keyword", "char32_t"],
         	["keyword", "class"], ["punctuation", ";"],
        -	["keyword", "compl"], ["keyword", "const"], ["keyword", "constexpr"],
        -	["keyword", "const_cast"], ["keyword", "continue"], ["keyword", "decltype"], ["keyword", "default"],
        -	["keyword", "delete"], ["keyword", "do"], ["keyword", "double"], ["keyword", "dynamic_cast"],
        -	["keyword", "else"], ["keyword", "enum"], ["keyword", "explicit"], ["keyword", "export"], ["keyword", "extern"],
        -	["keyword", "float"], ["keyword", "for"], ["keyword", "friend"], ["keyword", "goto"], ["keyword", "if"],
        -	["keyword", "inline"], ["keyword", "int"], ["keyword", "long"], ["keyword", "mutable"], ["keyword", "namespace"],
        -	["keyword", "new"], ["keyword", "noexcept"], ["keyword", "nullptr"], ["keyword", "operator"],
        -	["keyword", "private"], ["keyword", "protected"], ["keyword", "public"], ["keyword", "register"],
        -	["keyword", "reinterpret_cast"], ["keyword", "return"], ["keyword", "short"],
        -	["keyword", "signed"], ["keyword", "sizeof"], ["keyword", "static"], ["keyword", "static_assert"],
        -	["keyword", "static_cast"], ["keyword", "struct"], ["keyword", "switch"], ["keyword", "template"],
        -	["keyword", "this"], ["keyword", "thread_local"], ["keyword", "throw"], ["keyword", "try"],
        -	["keyword", "typedef"], ["keyword", "typeid"], ["keyword", "typename"], ["keyword", "union"],
        -	["keyword", "unsigned"], ["keyword", "using"], ["keyword", "virtual"], ["keyword", "void"],
        -	["keyword", "volatile"], ["keyword", "wchar_t"], ["keyword", "while"],
        -	["keyword", "int8_t"], ["keyword", "int16_t"], ["keyword", "int32_t"], ["keyword", "int64_t"],
        -	["keyword", "uint8_t"], ["keyword", "uint16_t"], ["keyword", "uint32_t"], ["keyword", "uint64_t"]
        +	["keyword", "compl"],
        +	["keyword", "concept"],
        +	["keyword", "const"],
        +	["keyword", "consteval"],
        +	["keyword", "constexpr"],
        +	["keyword", "constinit"],
        +	["keyword", "const_cast"],
        +	["keyword", "continue"],
        +	["keyword", "co_await"],
        +	["keyword", "co_return"],
        +	["keyword", "co_yield"],
        +	["keyword", "decltype"],
        +	["keyword", "default"],
        +	["keyword", "delete"],
        +	["keyword", "do"],
        +	["keyword", "double"],
        +	["keyword", "dynamic_cast"],
        +	["keyword", "else"],
        +	["keyword", "enum"], ["punctuation", ";"],
        +	["keyword", "explicit"],
        +	["keyword", "export"],
        +	["keyword", "extern"],
        +	["keyword", "final"],
        +	["keyword", "float"],
        +	["keyword", "for"],
        +	["keyword", "friend"],
        +	["keyword", "goto"],
        +	["keyword", "if"],
        +	["keyword", "import"], ["punctuation", ";"],
        +	["keyword", "inline"],
        +	["keyword", "int"],
        +	["keyword", "long"],
        +	["keyword", "module"], ["punctuation", ";"],
        +	["keyword", "mutable"],
        +	["keyword", "namespace"],
        +	["keyword", "new"],
        +	["keyword", "noexcept"],
        +	["keyword", "nullptr"],
        +	["keyword", "operator"],
        +	["keyword", "override"],
        +	["keyword", "private"],
        +	["keyword", "protected"],
        +	["keyword", "public"],
        +	["keyword", "register"],
        +	["keyword", "reinterpret_cast"],
        +	["keyword", "requires"],
        +	["keyword", "return"],
        +	["keyword", "short"],
        +	["keyword", "signed"],
        +	["keyword", "sizeof"],
        +	["keyword", "static"],
        +	["keyword", "static_assert"],
        +	["keyword", "static_cast"],
        +	["keyword", "struct"], ["punctuation", ";"],
        +	["keyword", "switch"],
        +	["keyword", "template"],
        +	["keyword", "this"],
        +	["keyword", "thread_local"],
        +	["keyword", "throw"],
        +	["keyword", "try"],
        +	["keyword", "typedef"],
        +	["keyword", "typeid"],
        +	["keyword", "typename"],
        +	["keyword", "union"],
        +	["keyword", "unsigned"],
        +	["keyword", "using"],
        +	["keyword", "virtual"],
        +	["keyword", "void"],
        +	["keyword", "volatile"],
        +	["keyword", "wchar_t"],
        +	["keyword", "while"],
        +	["keyword", "int8_t"],
        +	["keyword", "int16_t"],
        +	["keyword", "int32_t"],
        +	["keyword", "int64_t"],
        +	["keyword", "uint8_t"],
        +	["keyword", "uint16_t"],
        +	["keyword", "uint32_t"],
        +	["keyword", "uint64_t"]
         ]
         
         ----------------------------------------------------
         
        -Checks for all keywords
        \ No newline at end of file
        +Checks for all keywords.
        diff --git a/tests/languages/cpp/module_feature.test b/tests/languages/cpp/module_feature.test
        new file mode 100644
        index 0000000000..b6675c3d4e
        --- /dev/null
        +++ b/tests/languages/cpp/module_feature.test
        @@ -0,0 +1,116 @@
        +export module speech;
        +
        +export const char* get_phrase_en() {
        +    return "Hello, world!";
        +}
        +
        +export module speech;
        +
        +export import :english;
        +export import :spanish;
        +
        +export module speech:english;
        +
        +import speech;
        +import :PrivWidget;
        +
        +import ;
        +import ;
        +import "foo.h";
        +import ;
        +
        +module : private;
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "export"],
        +	["keyword", "module"],
        +	["module", ["speech"]],
        +	["punctuation", ";"],
        +
        +	["keyword", "export"],
        +	["keyword", "const"],
        +	["keyword", "char"],
        +	["operator", "*"],
        +	["function", "get_phrase_en"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +
        +	["keyword", "return"],
        +	["string", "\"Hello, world!\""],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "export"],
        +	["keyword", "module"],
        +	["module", ["speech"]],
        +	["punctuation", ";"],
        +
        +	["keyword", "export"],
        +	["keyword", "import"],
        +	["module", [
        +		["operator", ":"],
        +		"english"
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "export"],
        +	["keyword", "import"],
        +	["module", [
        +		["operator", ":"],
        +		"spanish"
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "export"],
        +	["keyword", "module"],
        +	["module", [
        +		"speech",
        +		["operator", ":"],
        +		"english"
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "import"],
        +	["module", ["speech"]],
        +	["punctuation", ";"],
        +
        +	["keyword", "import"],
        +	["module", [
        +		["operator", ":"],
        +		"PrivWidget"
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "import"],
        +	["module", [
        +		["string", ""]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "import"],
        +	["module", [
        +		["string", ""]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "import"],
        +	["module", [
        +		["string", "\"foo.h\""]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "import"],
        +	["module", [
        +		["string", ""]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "module"],
        +	["operator", ":"],
        +	["keyword", "private"],
        +	["punctuation", ";"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/cpp/number_feature.test b/tests/languages/cpp/number_feature.test
        new file mode 100644
        index 0000000000..47d15d9a61
        --- /dev/null
        +++ b/tests/languages/cpp/number_feature.test
        @@ -0,0 +1,64 @@
        +42
        +3.14159
        +4e10
        +2.1e-10
        +0.4e+2
        +0xbabe
        +0xBABE
        +0x1.2
        +0x0.3p-3
        +0x0.3p4L
        +42f
        +42F
        +42u
        +42U
        +42l
        +42L
        +0b0101
        +0B0101
        +
        +18446744073709550592ull
        +18'446'744'073'709'550'592llu
        +1844'6744'0737'0955'0592uLL
        +184467'440737'0'95505'92LLU
        +1'048'576
        +0x10'0000
        +0'004'000'000
        +1.602'176'565e-19
        +0b010'01010
        +
        +----------------------------------------------------
        +
        +[
        +	["number", "42"],
        +	["number", "3.14159"],
        +	["number", "4e10"],
        +	["number", "2.1e-10"],
        +	["number", "0.4e+2"],
        +	["number", "0xbabe"],
        +	["number", "0xBABE"],
        +	["number", "0x1.2"],
        +	["number", "0x0.3p-3"],
        +	["number", "0x0.3p4L"],
        +	["number", "42f"],
        +	["number", "42F"],
        +	["number", "42u"],
        +	["number", "42U"],
        +	["number", "42l"],
        +	["number", "42L"],
        +	["number", "0b0101"],
        +	["number", "0B0101"],
        +	["number", "18446744073709550592ull"],
        +	["number", "18'446'744'073'709'550'592llu"],
        +	["number", "1844'6744'0737'0955'0592uLL"],
        +	["number", "184467'440737'0'95505'92LLU"],
        +	["number", "1'048'576"],
        +	["number", "0x10'0000"],
        +	["number", "0'004'000'000"],
        +	["number", "1.602'176'565e-19"],
        +	["number", "0b010'01010"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for binary, decimal, and hexadecimal numbers.
        diff --git a/tests/languages/cpp/operator_feature.test b/tests/languages/cpp/operator_feature.test
        new file mode 100644
        index 0000000000..c619b3aac3
        --- /dev/null
        +++ b/tests/languages/cpp/operator_feature.test
        @@ -0,0 +1,73 @@
        ++ - * / % -- ++
        +>> <<
        +~ & | ^
        ++= -= *= /= %= >>= <<= &= |= ^=
        +! && ||
        +->
        +? :
        += == != < > <= >= <=>
        +and and_eq bitand bitor not not_eq or or_eq xor xor_eq
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "%"],
        +	["operator", "--"],
        +	["operator", "++"],
        +
        +	["operator", ">>"],
        +	["operator", "<<"],
        +
        +	["operator", "~"],
        +	["operator", "&"],
        +	["operator", "|"],
        +	["operator", "^"],
        +
        +	["operator", "+="],
        +	["operator", "-="],
        +	["operator", "*="],
        +	["operator", "/="],
        +	["operator", "%="],
        +	["operator", ">>="],
        +	["operator", "<<="],
        +	["operator", "&="],
        +	["operator", "|="],
        +	["operator", "^="],
        +
        +	["operator", "!"],
        +	["operator", "&&"],
        +	["operator", "||"],
        +
        +	["operator", "->"],
        +
        +	["operator", "?"],
        +	["operator", ":"],
        +
        +	["operator", "="],
        +	["operator", "=="],
        +	["operator", "!="],
        +	["operator", "<"],
        +	["operator", ">"],
        +	["operator", "<="],
        +	["operator", ">="],
        +	["operator", "<=>"],
        +
        +	["operator", "and"],
        +	["operator", "and_eq"],
        +	["operator", "bitand"],
        +	["operator", "bitor"],
        +	["operator", "not"],
        +	["operator", "not_eq"],
        +	["operator", "or"],
        +	["operator", "or_eq"],
        +	["operator", "xor"],
        +	["operator", "xor_eq"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all operators.
        diff --git a/tests/languages/cpp/punctuation_feature.test b/tests/languages/cpp/punctuation_feature.test
        new file mode 100644
        index 0000000000..5ea8918234
        --- /dev/null
        +++ b/tests/languages/cpp/punctuation_feature.test
        @@ -0,0 +1,18 @@
        +( ) [ ] { }
        +, ; . ::
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["punctuation", ","],
        +	["punctuation", ";"],
        +	["punctuation", "."],
        +	["double-colon", "::"]
        +]
        \ No newline at end of file
        diff --git a/tests/languages/crystal/attribute_feature.test b/tests/languages/crystal/attribute_feature.test
        index 02d07afd7a..726049b028 100644
        --- a/tests/languages/crystal/attribute_feature.test
        +++ b/tests/languages/crystal/attribute_feature.test
        @@ -1,17 +1,60 @@
         @[AlwaysInline]
         @[CallConvention("X86_StdCall")]
        +@[MyAnnotation(key: "value", value: 123)]
        +@[MyAnnotation("foo", 123, false)]
         
         ----------------------------------------------------
         
         [
         	["attribute", [
         		["delimiter", "@["],
        -		["constant", "AlwaysInline"],
        +		["attribute", "AlwaysInline"],
         		["delimiter", "]"]
         	]],
         	["attribute", [
         		["delimiter", "@["],
        -		["function", "CallConvention"], ["punctuation", "("], ["string", [ "\"X86_StdCall\"" ]], ["punctuation", ")"],
        +		["attribute", "CallConvention"],
        +		["args", [
        +			["punctuation", "("],
        +			["string-literal", [
        +				["string", "\"X86_StdCall\""]
        +			]],
        +			["punctuation", ")"]
        +		]],
        +		["delimiter", "]"]
        +	]],
        +	["attribute", [
        +		["delimiter", "@["],
        +		["attribute", "MyAnnotation"],
        +		["args", [
        +			["punctuation", "("],
        +			["symbol", "key"],
        +			["operator", ":"],
        +			["string-literal", [
        +				["string", "\"value\""]
        +			]],
        +			["punctuation", ","],
        +			["symbol", "value"],
        +			["operator", ":"],
        +			["number", "123"],
        +			["punctuation", ")"]
        +		]],
        +		["delimiter", "]"]
        +	]],
        +	["attribute", [
        +		["delimiter", "@["],
        +		["attribute", "MyAnnotation"],
        +		["args", [
        +			["punctuation", "("],
        +			["string-literal", [
        +				["string", "\"foo\""]
        +			]],
        +			["punctuation", ","],
        +			["number", "123"],
        +			["punctuation", ","],
        +			["boolean", "false"],
        +			["punctuation", ")"]
        +		]],
         		["delimiter", "]"]
         	]]
         ]
        diff --git a/tests/languages/crystal/char_feature.test b/tests/languages/crystal/char_feature.test
        new file mode 100644
        index 0000000000..6734edc97b
        --- /dev/null
        +++ b/tests/languages/crystal/char_feature.test
        @@ -0,0 +1,41 @@
        +'a'
        +'z'
        +'0'
        +'_'
        +'あ'
        +'\''         # single quote
        +'\\'         # backslash
        +'\a'         # alert
        +'\b'         # backspace
        +'\e'         # escape
        +'\f'         # form feed
        +'\n'         # newline
        +'\r'         # carriage return
        +'\t'         # tab
        +'\v'         # vertical tab
        +'\0'         # null character
        +'\uFFFF'     # hexadecimal unicode character
        +'\u{10FFFF}' # hexadecimal unicode character
        +
        +----------------------------------------------------
        +
        +[
        +	["char", "'a'"],
        +	["char", "'z'"],
        +	["char", "'0'"],
        +	["char", "'_'"],
        +	["char", "'あ'"],
        +	["char", "'\\''"], ["comment", "# single quote"],
        +	["char", "'\\\\'"], ["comment", "# backslash"],
        +	["char", "'\\a'"], ["comment", "# alert"],
        +	["char", "'\\b'"], ["comment", "# backspace"],
        +	["char", "'\\e'"], ["comment", "# escape"],
        +	["char", "'\\f'"], ["comment", "# form feed"],
        +	["char", "'\\n'"], ["comment", "# newline"],
        +	["char", "'\\r'"], ["comment", "# carriage return"],
        +	["char", "'\\t'"], ["comment", "# tab"],
        +	["char", "'\\v'"], ["comment", "# vertical tab"],
        +	["char", "'\\0'"], ["comment", "# null character"],
        +	["char", "'\\uFFFF'"], ["comment", "# hexadecimal unicode character"],
        +	["char", "'\\u{10FFFF}'"], ["comment", "# hexadecimal unicode character"]
        +]
        diff --git a/tests/languages/crystal/expansion_feature.test b/tests/languages/crystal/expansion_feature.test
        index b40bd1f51f..b11bcc4ab1 100644
        --- a/tests/languages/crystal/expansion_feature.test
        +++ b/tests/languages/crystal/expansion_feature.test
        @@ -8,26 +8,34 @@
         [
         	["expansion", [
         		["delimiter", "{{"],
        -		["number", "1_u32"],
        +		["content", [
        +			["number", "1_u32"]
        +		]],
         		["delimiter", "}}"]
         	]],
         	["expansion", [
         		["delimiter", "{%"],
        -		["number", "2_u32"],
        +		["content", [
        +			["number", "2_u32"]
        +		]],
         		["delimiter", "%}"]
         	]],
         	["expansion", [
         		["delimiter", "{{"],
        -		["punctuation", "{"],
        -		["number", "3_u32"],
        -		["punctuation", "}"],
        +		["content", [
        +			["punctuation", "{"],
        +			["number", "3_u32"],
        +			["punctuation", "}"]
        +		]],
         		["delimiter", "}}"]
         	]],
         	["expansion", [
         		["delimiter", "{%"],
        -		["operator", "%"],
        -		["number", "4_u32"],
        -		["operator", "%"],
        +		["content", [
        +			["operator", "%"],
        +			["number", "4_u32"],
        +			["operator", "%"]
        +		]],
         		["delimiter", "%}"]
         	]]
         ]
        diff --git a/tests/languages/crystal/keyword_feature.test b/tests/languages/crystal/keyword_feature.test
        index ea15473e98..5b61e97ae3 100644
        --- a/tests/languages/crystal/keyword_feature.test
        +++ b/tests/languages/crystal/keyword_feature.test
        @@ -1,33 +1,127 @@
        -abstract alias as asm begin break case
        -class;
        -def do else elsif
        -end ensure enum extend for fun
        -if include instance_sizeof
         .is_a?
        -lib macro module next of out pointerof
        -private protected rescue
         .responds_to?
        -return require select self sizeof struct super
        -then type typeof uninitialized union unless
        -until when while with yield __DIR__ __END_LINE__
        -__FILE__ __LINE__
        +abstract
        +alias
        +annotation;
        +as
        +asm
        +begin
        +break
        +case
        +class;
        +def;
        +do
        +else
        +elsif
        +end
        +ensure
        +enum
        +extend
        +for
        +fun
        +if
        +ifdef
        +include
        +instance_sizeof
        +lib
        +macro
        +module;
        +next
        +of
        +out
        +pointerof
        +private
        +protected
        +ptr
        +require
        +rescue
        +return
        +select
        +self
        +sizeof
        +struct
        +super
        +then
        +type
        +typeof
        +undef
        +uninitialized
        +union
        +unless
        +until
        +when
        +while
        +with
        +yield
        +
        +__DIR__
        +__END_LINE__
        +__FILE__
        +__LINE__
         
         ----------------------------------------------------
         
         [
        -	["keyword", "abstract"], ["keyword", "alias"], ["keyword", "as"], ["keyword", "asm"], ["keyword", "begin"], ["keyword", "break"], ["keyword", "case"],
        -	["keyword", "class"], ["punctuation", ";"],
        -	["keyword", "def"], ["keyword", "do"], ["keyword", "else"], ["keyword", "elsif"],
        -	["keyword", "end"], ["keyword", "ensure"], ["keyword", "enum"], ["keyword", "extend"], ["keyword", "for"], ["keyword", "fun"],
        -	["keyword", "if"], ["keyword", "include"], ["keyword", "instance_sizeof"],
         	["punctuation", "."], ["keyword", "is_a?"],
        -	["keyword", "lib"], ["keyword", "macro"], ["keyword", "module"], ["keyword", "next"], ["keyword", "of"], ["keyword", "out"], ["keyword", "pointerof"],
        -	["keyword", "private"], ["keyword", "protected"], ["keyword", "rescue"],
         	["punctuation", "."], ["keyword", "responds_to?"],
        -	["keyword", "return"], ["keyword", "require"], ["keyword", "select"], ["keyword", "self"], ["keyword", "sizeof"], ["keyword", "struct"], ["keyword", "super"],
        -	["keyword", "then"], ["keyword", "type"], ["keyword", "typeof"], ["keyword", "uninitialized"], ["keyword", "union"], ["keyword", "unless"],
        -	["keyword", "until"], ["keyword", "when"], ["keyword", "while"], ["keyword", "with"], ["keyword", "yield"], ["keyword", "__DIR__"], ["keyword", "__END_LINE__"],
        -	["keyword", "__FILE__"], ["keyword", "__LINE__"]
        +	["keyword", "abstract"],
        +	["keyword", "alias"],
        +	["keyword", "annotation"], ["punctuation", ";"],
        +	["keyword", "as"],
        +	["keyword", "asm"],
        +	["keyword", "begin"],
        +	["keyword", "break"],
        +	["keyword", "case"],
        +	["keyword", "class"], ["punctuation", ";"],
        +	["keyword", "def"], ["punctuation", ";"],
        +	["keyword", "do"],
        +	["keyword", "else"],
        +	["keyword", "elsif"],
        +	["keyword", "end"],
        +	["keyword", "ensure"],
        +	["keyword", "enum"],
        +	["keyword", "extend"],
        +	["keyword", "for"],
        +	["keyword", "fun"],
        +	["keyword", "if"],
        +	["keyword", "ifdef"],
        +	["keyword", "include"],
        +	["keyword", "instance_sizeof"],
        +	["keyword", "lib"],
        +	["keyword", "macro"],
        +	["keyword", "module"], ["punctuation", ";"],
        +	["keyword", "next"],
        +	["keyword", "of"],
        +	["keyword", "out"],
        +	["keyword", "pointerof"],
        +	["keyword", "private"],
        +	["keyword", "protected"],
        +	["keyword", "ptr"],
        +	["keyword", "require"],
        +	["keyword", "rescue"],
        +	["keyword", "return"],
        +	["keyword", "select"],
        +	["keyword", "self"],
        +	["keyword", "sizeof"],
        +	["keyword", "struct"],
        +	["keyword", "super"],
        +	["keyword", "then"],
        +	["keyword", "type"],
        +	["keyword", "typeof"],
        +	["keyword", "undef"],
        +	["keyword", "uninitialized"],
        +	["keyword", "union"],
        +	["keyword", "unless"],
        +	["keyword", "until"],
        +	["keyword", "when"],
        +	["keyword", "while"],
        +	["keyword", "with"],
        +	["keyword", "yield"],
        +
        +	["keyword", "__DIR__"],
        +	["keyword", "__END_LINE__"],
        +	["keyword", "__FILE__"],
        +	["keyword", "__LINE__"]
         ]
         
         ----------------------------------------------------
        diff --git a/tests/languages/crystal/operator_feature.test b/tests/languages/crystal/operator_feature.test
        new file mode 100644
        index 0000000000..43c7205933
        --- /dev/null
        +++ b/tests/languages/crystal/operator_feature.test
        @@ -0,0 +1,82 @@
        ++ - * / % **
        ++= -= *= /= %= **=
        +
        +== != < > <= >= <=> ===
        +!~ =~
        +=
        +& | ^ ~ << >>
        +&= |= ^= <<= >>=
        +&& || !
        +&&= ||=
        +
        +=>
        +->
        +
        +&.
        +
        +? :
        +.. ...
        +
        +and or not
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "%"],
        +	["operator", "**"],
        +
        +	["operator", "+="],
        +	["operator", "-="],
        +	["operator", "*="],
        +	["operator", "/="],
        +	["operator", "%="],
        +	["operator", "**="],
        +
        +	["operator", "=="],
        +	["operator", "!="],
        +	["operator", "<"],
        +	["operator", ">"],
        +	["operator", "<="],
        +	["operator", ">="],
        +	["operator", "<=>"],
        +	["operator", "==="],
        +
        +	["operator", "!~"],
        +	["operator", "=~"],
        +
        +	["operator", "="],
        +
        +	["operator", "&"],
        +	["operator", "|"],
        +	["operator", "^"],
        +	["operator", "~"],
        +	["operator", "<<"],
        +	["operator", ">>"],
        +
        +	["operator", "&="],
        +	["operator", "|="],
        +	["operator", "^="],
        +	["operator", "<<="],
        +	["operator", ">>="],
        +
        +	["operator", "&&"],
        +	["operator", "||"],
        +	["operator", "!"],
        +
        +	["operator", "&&="],
        +	["operator", "||="],
        +
        +	["operator", "=>"],
        +	["operator", "->"],
        +
        +	["operator", "&."],
        +
        +	["operator", "?"], ["operator", ":"],
        +	["operator", ".."], ["operator", "..."],
        +
        +	"\r\n\r\nand or not"
        +]
        diff --git a/tests/languages/crystal/punctuation_feature.test b/tests/languages/crystal/punctuation_feature.test
        new file mode 100644
        index 0000000000..affcf8f11b
        --- /dev/null
        +++ b/tests/languages/crystal/punctuation_feature.test
        @@ -0,0 +1,20 @@
        +( ) [ ] { }
        +, .
        +:: \
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["punctuation", ","],
        +	["punctuation", "."],
        +
        +	["double-colon", "::"],
        +	["punctuation", "\\"]
        +]
        diff --git a/tests/languages/crystal/regex_feature.test b/tests/languages/crystal/regex_feature.test
        new file mode 100644
        index 0000000000..7f075142ee
        --- /dev/null
        +++ b/tests/languages/crystal/regex_feature.test
        @@ -0,0 +1,184 @@
        +/foo|bar/
        +/h(e+)llo/
        +/\d+/
        +/あ/
        +
        +/\//         # slash
        +/\\/         # backslash
        +/\b/         # backspace
        +/\e/         # escape
        +/\f/         # form feed
        +/\n/         # newline
        +/\r/         # carriage return
        +/\t/         # tab
        +/\v/         # vertical tab
        +/\NNN/       # octal ASCII character
        +/\xNN/       # hexadecimal ASCII character
        +/\x{FFFF}/   # hexadecimal unicode character
        +/\x{10FFFF}/ # hexadecimal unicode character
        +
        +/foo/i.match("FOO")         # => #
        +/foo/m.match("bar\nfoo")    # => #
        +/foo /x.match("foo")        # => #
        +/foo /imx.match("bar\nFOO") # => #
        +
        +%r((/)) # => /(\/)/
        +%r[[/]] # => /[\/]/
        +%r{{/}} # => /{\/}/
        +%r<> # => /<\/>/
        +%r|/|   # => /\//
        +
        +----------------------------------------------------
        +
        +[
        +	["regex-literal", [
        +		["regex", "/foo|bar/"]
        +	]],
        +	["regex-literal", [
        +		["regex", "/h(e+)llo/"]
        +	]],
        +	["regex-literal", [
        +		["regex", "/\\d+/"]
        +	]],
        +	["regex-literal", [
        +		["regex", "/あ/"]
        +	]],
        +
        +	["regex-literal", [
        +		["regex", "/\\//"]
        +	]],
        +	["comment", "# slash"],
        +
        +	["regex-literal", [
        +		["regex", "/\\\\/"]
        +	]],
        +	["comment", "# backslash"],
        +
        +	["regex-literal", [
        +		["regex", "/\\b/"]
        +	]],
        +	["comment", "# backspace"],
        +
        +	["regex-literal", [
        +		["regex", "/\\e/"]
        +	]],
        +	["comment", "# escape"],
        +
        +	["regex-literal", [
        +		["regex", "/\\f/"]
        +	]],
        +	["comment", "# form feed"],
        +
        +	["regex-literal", [
        +		["regex", "/\\n/"]
        +	]],
        +	["comment", "# newline"],
        +
        +	["regex-literal", [
        +		["regex", "/\\r/"]
        +	]],
        +	["comment", "# carriage return"],
        +
        +	["regex-literal", [
        +		["regex", "/\\t/"]
        +	]],
        +	["comment", "# tab"],
        +
        +	["regex-literal", [
        +		["regex", "/\\v/"]
        +	]],
        +	["comment", "# vertical tab"],
        +
        +	["regex-literal", [
        +		["regex", "/\\NNN/"]
        +	]],
        +	["comment", "# octal ASCII character"],
        +
        +	["regex-literal", [
        +		["regex", "/\\xNN/"]
        +	]],
        +	["comment", "# hexadecimal ASCII character"],
        +
        +	["regex-literal", [
        +		["regex", "/\\x{FFFF}/"]
        +	]],
        +	["comment", "# hexadecimal unicode character"],
        +
        +	["regex-literal", [
        +		["regex", "/\\x{10FFFF}/"]
        +	]],
        +	["comment", "# hexadecimal unicode character"],
        +
        +	["regex-literal", [
        +		["regex", "/foo/i"]
        +	]],
        +	["punctuation", "."],
        +	"match",
        +	["punctuation", "("],
        +	["string-literal", [
        +		["string", "\"FOO\""]
        +	]],
        +	["punctuation", ")"],
        +	["comment", "# => #"],
        +
        +	["regex-literal", [
        +		["regex", "/foo/m"]
        +	]],
        +	["punctuation", "."],
        +	"match",
        +	["punctuation", "("],
        +	["string-literal", [
        +		["string", "\"bar\\nfoo\""]
        +	]],
        +	["punctuation", ")"],
        +	["comment", "# => #"],
        +
        +	["regex-literal", [
        +		["regex", "/foo /x"]
        +	]],
        +	["punctuation", "."],
        +	"match",
        +	["punctuation", "("],
        +	["string-literal", [
        +		["string", "\"foo\""]
        +	]],
        +	["punctuation", ")"],
        +	["comment", "# => #"],
        +
        +	["regex-literal", [
        +		["regex", "/foo /imx"]
        +	]],
        +	["punctuation", "."],
        +	"match",
        +	["punctuation", "("],
        +	["string-literal", [
        +		["string", "\"bar\\nFOO\""]
        +	]],
        +	["punctuation", ")"],
        +	["comment", "# => #"],
        +
        +	["regex-literal", [
        +		["regex", "%r((/))"]
        +	]],
        +	["comment", "# => /(\\/)/"],
        +
        +	["regex-literal", [
        +		["regex", "%r[[/]]"]
        +	]],
        +	["comment", "# => /[\\/]/"],
        +
        +	["regex-literal", [
        +		["regex", "%r{{/}}"]
        +	]],
        +	["comment", "# => /{\\/}/"],
        +
        +	["regex-literal", [
        +		["regex", "%r<>"]
        +	]],
        +	["comment", "# => /<\\/>/"],
        +
        +	["regex-literal", [
        +		["regex", "%r|/|"]
        +	]],
        +	["comment", "# => /\\//"]
        +]
        diff --git a/tests/languages/crystal/string_feature.test b/tests/languages/crystal/string_feature.test
        new file mode 100644
        index 0000000000..04a8ebded6
        --- /dev/null
        +++ b/tests/languages/crystal/string_feature.test
        @@ -0,0 +1,321 @@
        +"hello world"
        +
        +"\""                  # double quote
        +"\\"                  # backslash
        +"\#"                  # hash character (to escape interpolation)
        +"\a"                  # alert
        +"\b"                  # backspace
        +"\e"                  # escape
        +"\f"                  # form feed
        +"\n"                  # newline
        +"\r"                  # carriage return
        +"\t"                  # tab
        +"\v"                  # vertical tab
        +"\377"                # octal ASCII character
        +"\xFF"                # hexadecimal ASCII character
        +"\uFFFF"              # hexadecimal unicode character
        +"\u{0}".."\u{10FFFF}" # hexadecimal unicode character
        +
        +"\101" # => "A"
        +"\123" # => "S"
        +"\12"  # => "\n"
        +"\1"   # string with one character with code point 1
        +
        +"\u{48 45 4C 4C 4F}" # => "HELLO"
        +
        +"sum: #{a} + #{b} = #{a + b}"
        +
        +"\#{a + b}"  # => "#{a + b}"
        +%q(#{a + b}) # => "#{a + b}"
        +
        +%(hello ("world")) # => "hello (\"world\")"
        +%[hello ["world"]] # => "hello [\"world\"]"
        +%{hello {"world"}} # => "hello {\"world\"}"
        +%> # => "hello <\"world\">"
        +%|hello "world"|   # => "hello \"world\""
        +
        +name = "world"
        +%q(hello \n #{name}) # => "hello \\n \#{name}"
        +%Q(hello \n #{name}) # => "hello \n world"
        +
        +%w(foo bar baz)  # => ["foo", "bar", "baz"]
        +%w(foo\nbar baz) # => ["foo\\nbar", "baz"]
        +%w(foo(bar) baz) # => ["foo(bar)", "baz"]
        +
        +%w(foo\ bar baz) # => ["foo bar", "baz"]
        +
        +"hello " \
        +"world, " \
        +"no newlines" # same as "hello world, no newlines"
        +
        +"hello \
        +     world, \
        +     no newlines" # same as "hello world, no newlines"
        +
        +<<-XML
        +
        +  
        +
        +XML
        +
        +----------------------------------------------------
        +
        +[
        +	["string-literal", [
        +		["string", "\"hello world\""]
        +	]],
        +
        +	["string-literal", [
        +		["string", "\"\\\"\""]
        +	]],
        +	["comment", "# double quote"],
        +
        +	["string-literal", [
        +		["string", "\"\\\\\""]
        +	]],
        +	["comment", "# backslash"],
        +
        +	["string-literal", [
        +		["string", "\"\\#\""]
        +	]],
        +	["comment", "# hash character (to escape interpolation)"],
        +
        +	["string-literal", [
        +		["string", "\"\\a\""]
        +	]],
        +	["comment", "# alert"],
        +
        +	["string-literal", [
        +		["string", "\"\\b\""]
        +	]],
        +	["comment", "# backspace"],
        +
        +	["string-literal", [
        +		["string", "\"\\e\""]
        +	]],
        +	["comment", "# escape"],
        +
        +	["string-literal", [
        +		["string", "\"\\f\""]
        +	]],
        +	["comment", "# form feed"],
        +
        +	["string-literal", [
        +		["string", "\"\\n\""]
        +	]],
        +	["comment", "# newline"],
        +
        +	["string-literal", [
        +		["string", "\"\\r\""]
        +	]],
        +	["comment", "# carriage return"],
        +
        +	["string-literal", [
        +		["string", "\"\\t\""]
        +	]],
        +	["comment", "# tab"],
        +
        +	["string-literal", [
        +		["string", "\"\\v\""]
        +	]],
        +	["comment", "# vertical tab"],
        +
        +	["string-literal", [
        +		["string", "\"\\377\""]
        +	]],
        +	["comment", "# octal ASCII character"],
        +
        +	["string-literal", [
        +		["string", "\"\\xFF\""]
        +	]],
        +	["comment", "# hexadecimal ASCII character"],
        +
        +	["string-literal", [
        +		["string", "\"\\uFFFF\""]
        +	]],
        +	["comment", "# hexadecimal unicode character"],
        +
        +	["string-literal", [
        +		["string", "\"\\u{0}\""]
        +	]],
        +	["operator", ".."],
        +	["string-literal", [
        +		["string", "\"\\u{10FFFF}\""]
        +	]],
        +	["comment", "# hexadecimal unicode character"],
        +
        +	["string-literal", [
        +		["string", "\"\\101\""]
        +	]],
        +	["comment", "# => \"A\""],
        +
        +	["string-literal", [
        +		["string", "\"\\123\""]
        +	]],
        +	["comment", "# => \"S\""],
        +
        +	["string-literal", [
        +		["string", "\"\\12\""]
        +	]],
        +	["comment", "# => \"\\n\""],
        +
        +	["string-literal", [
        +		["string", "\"\\1\""]
        +	]],
        +	["comment", "# string with one character with code point 1"],
        +
        +	["string-literal", [
        +		["string", "\"\\u{48 45 4C 4C 4F}\""]
        +	]],
        +	["comment", "# => \"HELLO\""],
        +
        +	["string-literal", [
        +		["string", "\"sum: "],
        +		["interpolation", [
        +			["delimiter", "#{"],
        +			["content", ["a"]],
        +			["delimiter", "}"]
        +		]],
        +		["string", " + "],
        +		["interpolation", [
        +			["delimiter", "#{"],
        +			["content", ["b"]],
        +			["delimiter", "}"]
        +		]],
        +		["string", " = "],
        +		["interpolation", [
        +			["delimiter", "#{"],
        +			["content", [
        +				"a ",
        +				["operator", "+"],
        +				" b"
        +			]],
        +			["delimiter", "}"]
        +		]],
        +		["string", "\""]
        +	]],
        +
        +	["string-literal", [
        +		["string", "\"\\#{a + b}\""]
        +	]],
        +	["comment", "# => \"#{a + b}\""],
        +
        +	["string-literal", [
        +		["string", "%q("],
        +		["interpolation", [
        +			["delimiter", "#{"],
        +			["content", [
        +				"a ",
        +				["operator", "+"],
        +				" b"
        +			]],
        +			["delimiter", "}"]
        +		]],
        +		["string", ")"]
        +	]],
        +	["comment", "# => \"#{a + b}\""],
        +
        +	["string-literal", [
        +		["string", "%(hello (\"world\"))"]
        +	]],
        +	["comment", "# => \"hello (\\\"world\\\")\""],
        +
        +	["string-literal", [
        +		["string", "%[hello [\"world\"]]"]
        +	]],
        +	["comment", "# => \"hello [\\\"world\\\"]\""],
        +
        +	["string-literal", [
        +		["string", "%{hello {\"world\"}}"]
        +	]],
        +	["comment", "# => \"hello {\\\"world\\\"}\""],
        +
        +	["string-literal", [
        +		["string", "%>"]
        +	]],
        +	["comment", "# => \"hello <\\\"world\\\">\""],
        +
        +	["string-literal", [
        +		["string", "%|hello \"world\"|"]
        +	]],
        +	["comment", "# => \"hello \\\"world\\\"\""],
        +
        +	"\r\n\r\nname ",
        +	["operator", "="],
        +	["string-literal", [
        +		["string", "\"world\""]
        +	]],
        +
        +	["string-literal", [
        +		["string", "%q(hello \\n "],
        +		["interpolation", [
        +			["delimiter", "#{"],
        +			["content", ["name"]],
        +			["delimiter", "}"]
        +		]],
        +		["string", ")"]
        +	]],
        +	["comment", "# => \"hello \\\\n \\#{name}\""],
        +
        +	["string-literal", [
        +		["string", "%Q(hello \\n "],
        +		["interpolation", [
        +			["delimiter", "#{"],
        +			["content", ["name"]],
        +			["delimiter", "}"]
        +		]],
        +		["string", ")"]
        +	]],
        +	["comment", "# => \"hello \\n world\""],
        +
        +	["string-literal", [
        +		["string", "%w(foo bar baz)"]
        +	]],
        +	["comment", "# => [\"foo\", \"bar\", \"baz\"]"],
        +
        +	["string-literal", [
        +		["string", "%w(foo\\nbar baz)"]
        +	]],
        +	["comment", "# => [\"foo\\\\nbar\", \"baz\"]"],
        +
        +	["string-literal", [
        +		["string", "%w(foo(bar) baz)"]
        +	]],
        +	["comment", "# => [\"foo(bar)\", \"baz\"]"],
        +
        +	["string-literal", [
        +		["string", "%w(foo\\ bar baz)"]
        +	]],
        +	["comment", "# => [\"foo bar\", \"baz\"]"],
        +
        +	["string-literal", [
        +		["string", "\"hello \""]
        +	]],
        +	["punctuation", "\\"],
        +
        +	["string-literal", [
        +		["string", "\"world, \""]
        +	]],
        +	["punctuation", "\\"],
        +
        +	["string-literal", [
        +		["string", "\"no newlines\""]
        +	]],
        +	["comment", "# same as \"hello world, no newlines\""],
        +
        +	["string-literal", [
        +		["string", "\"hello \\\r\n     world, \\\r\n     no newlines\""]
        +	]],
        +	["comment", "# same as \"hello world, no newlines\""],
        +
        +	["string-literal", [
        +		["delimiter", [
        +			["punctuation", "<<-"],
        +			["symbol", "XML"]
        +		]],
        +		["string", "\r\n\r\n  \r\n\r\n"],
        +		["delimiter", [
        +			["symbol", "XML"]
        +		]]
        +	]]
        +]
        diff --git a/tests/languages/crystal/symbol_feature.test b/tests/languages/crystal/symbol_feature.test
        new file mode 100644
        index 0000000000..d585682131
        --- /dev/null
        +++ b/tests/languages/crystal/symbol_feature.test
        @@ -0,0 +1,17 @@
        +:unquoted_symbol
        +:"quoted symbol"
        +:"a" # identical to :a
        +:あ
        +:question?
        +:exclamation!
        +
        +----------------------------------------------------
        +
        +[
        +	["symbol", ":unquoted_symbol"],
        +	["symbol", ":\"quoted symbol\""],
        +	["symbol", ":\"a\""], ["comment", "# identical to :a"],
        +	["symbol", ":あ"],
        +	["symbol", ":question?"],
        +	["symbol", ":exclamation!"]
        +]
        diff --git a/tests/languages/csharp!+xml-doc/inclusion.test b/tests/languages/csharp!+xml-doc/inclusion.test
        new file mode 100644
        index 0000000000..828c9f5b69
        --- /dev/null
        +++ b/tests/languages/csharp!+xml-doc/inclusion.test
        @@ -0,0 +1,65 @@
        +/// 
        +/// Class level summary documentation goes here.
        +/// 
        +/// 
        +/// Longer comments can be associated with a type or member through
        +/// the remarks tag.
        +/// 
        +
        +----------------------------------------------------
        +
        +[
        +	["doc-comment", [
        +		"/// ",
        +		["tag", [
        +			["tag", [
        +				["punctuation", "<"],
        +				"summary"
        +			]],
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["doc-comment", [
        +		"/// Class level summary documentation goes here."
        +	]],
        +	["doc-comment", [
        +		"/// ",
        +		["tag", [
        +			["tag", [
        +				["punctuation", ""]
        +		]]
        +	]],
        +	["doc-comment", [
        +		"/// ",
        +		["tag", [
        +			["tag", [
        +				["punctuation", "<"],
        +				"remarks"
        +			]],
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["doc-comment", [
        +		"/// Longer comments can be associated with a type or member through"
        +	]],
        +	["doc-comment", [
        +		"/// the remarks tag."
        +	]],
        +	["doc-comment", [
        +		"/// ",
        +		["tag", [
        +			["tag", [
        +				["punctuation", ""]
        +		]]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for XML documentation comments.
        diff --git a/tests/languages/csharp+aspnet/directive_feature.test b/tests/languages/csharp+aspnet/directive_feature.test
        index f19c2a82c2..aadd833503 100644
        --- a/tests/languages/csharp+aspnet/directive_feature.test
        +++ b/tests/languages/csharp+aspnet/directive_feature.test
        @@ -8,63 +8,63 @@
         ----------------------------------------------------
         
         [
        -	["directive tag", [
        -		["directive tag", "<%:"],
        +	["directive", [
        +		["directive", "<%:"],
         		" Page",
         		["punctuation", "."],
         		"Title ",
        -		["directive tag", "%>"]
        +		["directive", "%>"]
         	]],
         
        -	["directive tag", [
        -        ["directive tag", "<%#:"],
        -        "Item",
        -        ["punctuation", "."],
        -        "ProductID",
        -        ["directive tag", "%>"]
        -    ]],
        +	["directive", [
        +		["directive", "<%#:"],
        +		"Item",
        +		["punctuation", "."],
        +		"ProductID",
        +		["directive", "%>"]
        +	]],
         
        -    ["tag", [
        -        ["tag", [
        -            ["punctuation", "<"],
        -            "a"
        -        ]],
        -        ["attr-name", [
        -            "href"
        -        ]],
        -        ["attr-value", [
        -            ["punctuation", "="],
        -            ["punctuation", "\""],
        -            "ProductDetails.aspx?productID=",
        -            ["directive tag", [
        -                ["directive tag", "<%#:"],
        -                "Item",
        -		        ["punctuation", "."],
        -		        "ProductID",
        -		        ["directive tag", "%>"]
        -            ]],
        -            ["punctuation", "\""]
        -        ]],
        -        ["punctuation", ">"]
        -    ]],
        +	["tag", [
        +		["tag", [
        +			["punctuation", "<"],
        +			"a"
        +		]],
        +		["attr-name", [
        +			"href"
        +		]],
        +		["attr-value", [
        +			["punctuation", "="],
        +			["punctuation", "\""],
        +			"ProductDetails.aspx?productID=",
        +			["directive", [
        +				["directive", "<%#:"],
        +				"Item",
        +				["punctuation", "."],
        +				"ProductID",
        +				["directive", "%>"]
        +			]],
        +			["punctuation", "\""]
        +		]],
        +		["punctuation", ">"]
        +	]],
         
        -    ["directive tag", [
        -        ["directive tag", "<%"],
        -        ["keyword", "if"],
        -        ["punctuation", "("],
        -        "foo",
        -        ["punctuation", ")"],
        -        ["punctuation", "{"],
        -        ["directive tag", "%>"]
        -    ]],
        -    "\r\n\tfoobar\r\n",
        -    ["directive tag", [
        -        ["directive tag", "<%"],
        -        ["punctuation", "}"],
        -        ["directive tag", "%>"]
        -    ]]
        +	["directive", [
        +		["directive", "<%"],
        +		["keyword", "if"],
        +		["punctuation", "("],
        +		"foo",
        +		["punctuation", ")"],
        +		["punctuation", "{"],
        +		["directive", "%>"]
        +	]],
        +	"\r\n\tfoobar\r\n",
        +	["directive", [
        +		["directive", "<%"],
        +		["punctuation", "}"],
        +		["directive", "%>"]
        +	]]
         ]
         
         ----------------------------------------------------
         
        -Checks for directives.
        \ No newline at end of file
        +Checks for directives.
        diff --git a/tests/languages/csharp/attribute_feature.test b/tests/languages/csharp/attribute_feature.test
        new file mode 100644
        index 0000000000..fbc54fbc05
        --- /dev/null
        +++ b/tests/languages/csharp/attribute_feature.test
        @@ -0,0 +1,240 @@
        +[Foo]
        +[Foo(1, 2)]
        +[Foo(1, 2, Name = "bar")]
        +[Foo, Bar]
        +[Foo("()"), Bar("[]"), Baz]
        +
        +[return: MaybeNull]
        +[assembly: InternalsVisibleTo("Tests")]
        +
        +[assembly: Foo]
        +[module: Foo]
        +[field: Foo]
        +[event: Foo]
        +[method: Foo]
        +[param: Foo]
        +[property: Foo]
        +[return: Foo]
        +[type: Foo]
        +
        +// not attributes
        +
        +var a = d
        +[Foo];
        +var b = new Foo?[Count];
        +var c = new (int, int)[Count];
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "["],
        +	["attribute", [
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["class-name", ["Foo"]],
        +		["attribute-arguments", [
        +			["punctuation", "("],
        +			["number", "1"],
        +			["punctuation", ","],
        +			["number", "2"],
        +			["punctuation", ")"]
        +		]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["class-name", ["Foo"]],
        +		["attribute-arguments", [
        +			["punctuation", "("],
        +			["number", "1"],
        +			["punctuation", ","],
        +			["number", "2"],
        +			["punctuation", ","],
        +			" Name ",
        +			["operator", "="],
        +			["string", "\"bar\""],
        +			["punctuation", ")"]
        +		]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["class-name", ["Foo"]],
        +		["punctuation", ","],
        +		["class-name", ["Bar"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["class-name", ["Foo"]],
        +		["attribute-arguments", [
        +			["punctuation", "("],
        +			["string", "\"()\""],
        +			["punctuation", ")"]
        +		]],
        +		["punctuation", ","],
        +		["class-name", ["Bar"]],
        +		["attribute-arguments", [
        +			["punctuation", "("],
        +			["string", "\"[]\""],
        +			["punctuation", ")"]
        +		]],
        +		["punctuation", ","],
        +		["class-name", ["Baz"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "return"],
        +		["punctuation", ":"],
        +		["class-name", ["MaybeNull"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "assembly"],
        +		["punctuation", ":"],
        +		["class-name", ["InternalsVisibleTo"]],
        +		["attribute-arguments", [
        +			["punctuation", "("],
        +			["string", "\"Tests\""],
        +			["punctuation", ")"]
        +		]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "assembly"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "module"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "field"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "event"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "method"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "param"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "property"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "return"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["punctuation", "["],
        +	["attribute", [
        +		["target", "type"],
        +		["punctuation", ":"],
        +		["class-name", ["Foo"]]
        +	]],
        +	["punctuation", "]"],
        +
        +	["comment", "// not attributes"],
        +
        +	["class-name", [
        +		["keyword", "var"]
        +	]],
        +	" a ",
        +	["operator", "="],
        +	" d\r\n",
        +
        +	["punctuation", "["],
        +	"Foo",
        +	["punctuation", "]"],
        +	["punctuation", ";"],
        +
        +	["class-name", [
        +		["keyword", "var"]
        +	]],
        +	" b ",
        +	["operator", "="],
        +	["keyword", "new"],
        +	["constructor-invocation", [
        +		"Foo",
        +		["punctuation", "<"],
        +		["keyword", "int"],
        +		["punctuation", ">"],
        +		["punctuation", "?"]
        +	]],
        +	["punctuation", "["],
        +	"Count",
        +	["punctuation", "]"],
        +	["punctuation", ";"],
        +
        +	["class-name", [
        +		["keyword", "var"]
        +	]],
        +	" c ",
        +	["operator", "="],
        +	["keyword", "new"],
        +	["constructor-invocation", [
        +		["punctuation", "("],
        +		["keyword", "int"],
        +		["punctuation", ","],
        +		["keyword", "int"],
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", "["],
        +	"Count",
        +	["punctuation", "]"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for class names of attributes.
        diff --git a/tests/languages/csharp/char_feature.test b/tests/languages/csharp/char_feature.test
        new file mode 100644
        index 0000000000..184ed6b581
        --- /dev/null
        +++ b/tests/languages/csharp/char_feature.test
        @@ -0,0 +1,11 @@
        +'a'
        +'\''
        +'\\'
        +
        +----------------------------------------------------
        +
        +[
        +	["char", "'a'"],
        +	["char", "'\\''"],
        +	["char", "'\\\\'"]
        +]
        diff --git a/tests/languages/csharp/class-name-declaration_feature.test b/tests/languages/csharp/class-name-declaration_feature.test
        new file mode 100644
        index 0000000000..0d347ed4f5
        --- /dev/null
        +++ b/tests/languages/csharp/class-name-declaration_feature.test
        @@ -0,0 +1,147 @@
        +class Foo
        +interface BarBaz
        +struct Foo
        +enum Foo
        +record Foo
        +class Foo
        +interface Bar
        +record Foo
        +
        +record TestData(string Name);
        +
        +// not variables
        +public static RGBColor FromRainbow(Rainbow colorBand) =>
        +	colorBand switch
        +	{
        +		Rainbow.Red => new RGBColor(0xFF, 0x00, 0x00),
        +		_           => throw new ArgumentException(message: "invalid enum value", paramName: nameof(colorBand)),
        +	};
        +
        +try {} catch (ArgumentException e) {}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "class"],
        +	["class-name", ["Foo"]],
        +
        +	["keyword", "interface"],
        +	["class-name", ["BarBaz"]],
        +
        +	["keyword", "struct"],
        +	["class-name", ["Foo"]],
        +
        +	["keyword", "enum"],
        +	["class-name", ["Foo"]],
        +
        +	["keyword", "record"],
        +	["class-name", ["Foo"]],
        +
        +	["keyword", "class"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"A",
        +		["punctuation", ","],
        +		" B",
        +		["punctuation", ">"]
        +	]],
        +
        +	["keyword", "interface"],
        +	["class-name", [
        +		"Bar",
        +		["punctuation", "<"],
        +		["keyword", "out"],
        +		" T",
        +		["punctuation", ">"]
        +	]],
        +
        +	["keyword", "record"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"A",
        +		["punctuation", ","],
        +		" B",
        +		["punctuation", ">"]
        +	]],
        +
        +	["keyword", "record"],
        +	["class-name", ["TestData"]],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
        +	" Name",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["comment", "// not variables"],
        +
        +	["keyword", "public"],
        +	["keyword", "static"],
        +	["return-type", ["RGBColor"]],
        +	["function", "FromRainbow"],
        +	["punctuation", "("],
        +	["class-name", ["Rainbow"]],
        +	" colorBand",
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +
        +	"\r\n\tcolorBand ",
        +	["keyword", "switch"],
        +
        +	["punctuation", "{"],
        +
        +	"\r\n\t\tRainbow",
        +	["punctuation", "."],
        +	"Red ",
        +	["operator", "=>"],
        +	["keyword", "new"],
        +	["constructor-invocation", ["RGBColor"]],
        +	["punctuation", "("],
        +	["number", "0xFF"],
        +	["punctuation", ","],
        +	["number", "0x00"],
        +	["punctuation", ","],
        +	["number", "0x00"],
        +	["punctuation", ")"],
        +	["punctuation", ","],
        +
        +	"\r\n\t\t_           ",
        +	["operator", "=>"],
        +	["keyword", "throw"],
        +	["keyword", "new"],
        +	["constructor-invocation", ["ArgumentException"]],
        +	["punctuation", "("],
        +	["named-parameter", "message"],
        +	["punctuation", ":"],
        +	["string", "\"invalid enum value\""],
        +	["punctuation", ","],
        +	["named-parameter", "paramName"],
        +	["punctuation", ":"],
        +	["keyword", "nameof"],
        +	["punctuation", "("],
        +	"colorBand",
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +	["punctuation", ","],
        +
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "try"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["keyword", "catch"],
        +	["punctuation", "("],
        +	["class-name", ["ArgumentException"]],
        +	" e",
        +	["punctuation", ")"],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for class names at the class declaration.
        diff --git a/tests/languages/csharp/class-name-variables-parameters_feature.test b/tests/languages/csharp/class-name-variables-parameters_feature.test
        new file mode 100644
        index 0000000000..53b93c85ca
        --- /dev/null
        +++ b/tests/languages/csharp/class-name-variables-parameters_feature.test
        @@ -0,0 +1,207 @@
        +int a;
        +Foo b;
        +Foo @new_var;
        +Foo c = null;
        +static Foo<(Bar, int)>[,,] d;
        +void Foo(Foo a, Bar b, Bar[, ] c, Foo<(int, int)> d);
        +Bar Abc => 0;
        +Bar.FooBar Abc;
        +
        +if (foo is Bar)
        +if (foo is not Bar)
        +if (foo is null)
        +if (foo is not null)
        +if (t is (int, string))
        +if ((e1, e2) is (0, int i) or (int i, 0))
        +var baz = foo as Bar;
        +
        +----------------------------------------------------
        +
        +[
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" a",
        +	["punctuation", ";"],
        +	["class-name", [
        +		"Foo"
        +	]],
        +	" b",
        +	["punctuation", ";"],
        +	["class-name", [
        +		"Foo"
        +	]],
        +	" @new_var",
        +	["punctuation", ";"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"Bar",
        +		["punctuation", ">"]
        +	]],
        +	" c ",
        +	["operator", "="],
        +	["keyword", "null"],
        +	["punctuation", ";"],
        +	["keyword", "static"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		["punctuation", "("],
        +		"Bar",
        +		["punctuation", ","],
        +		["keyword", "int"],
        +		["punctuation", ")"],
        +		["punctuation", ">"],
        +		["punctuation", "["],
        +		["punctuation", ","],
        +		["punctuation", ","],
        +		["punctuation", "]"]
        +	]],
        +	" d",
        +	["punctuation", ";"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
        +	["function", "Foo"],
        +	["punctuation", "("],
        +	["class-name", [
        +		"Foo"
        +	]],
        +	" a",
        +	["punctuation", ","],
        +	["class-name", [
        +		"Bar",
        +		["punctuation", "<"],
        +		"Foo",
        +		["punctuation", ">"]
        +	]],
        +	" b",
        +	["punctuation", ","],
        +	["class-name", [
        +		"Bar",
        +		["punctuation", "["],
        +		["punctuation", ","],
        +		["punctuation", "]"]
        +	]],
        +	" c",
        +	["punctuation", ","],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		["punctuation", "("],
        +		["keyword", "int"],
        +		["punctuation", ","],
        +		["keyword", "int"],
        +		["punctuation", ")"],
        +		["punctuation", ">"]
        +	]],
        +	" d",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		"Bar",
        +		["punctuation", "<"],
        +		"Foo",
        +		["punctuation", ">"]
        +	]],
        +	" Abc ",
        +	["operator", "=>"],
        +	["number", "0"],
        +	["punctuation", ";"],
        +	["class-name", [
        +		"Bar",
        +		["punctuation", "<"],
        +		"Foo",
        +		["punctuation", ">"],
        +		["punctuation", "."],
        +		"FooBar",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"]
        +	]],
        +	" Abc",
        +	["punctuation", ";"],
        +
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	"foo ",
        +	["keyword", "is"],
        +	["class-name", [
        +		"Bar"
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	"foo ",
        +	["keyword", "is"],
        +	["keyword", "not"],
        +	["class-name", [
        +		"Bar"
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	"foo ",
        +	["keyword", "is"],
        +	["keyword", "null"],
        +	["punctuation", ")"],
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	"foo ",
        +	["keyword", "is"],
        +	["keyword", "not"],
        +	["keyword", "null"],
        +	["punctuation", ")"],
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	"t ",
        +	["keyword", "is"],
        +	["punctuation", "("],
        +	["keyword", "int"],
        +	["punctuation", ","],
        +	["keyword", "string"],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +	["keyword", "if"],
        +	["punctuation", "("],
        +	["punctuation", "("],
        +	"e1",
        +	["punctuation", ","],
        +	" e2",
        +	["punctuation", ")"],
        +	["keyword", "is"],
        +	["punctuation", "("],
        +	["number", "0"],
        +	["punctuation", ","],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" i",
        +	["punctuation", ")"],
        +	["keyword", "or"],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" i",
        +	["punctuation", ","],
        +	["number", "0"],
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +	["class-name", [
        +		["keyword", "var"]
        +	]],
        +	" baz ",
        +	["operator", "="],
        +	" foo ",
        +	["keyword", "as"],
        +	["class-name", [
        +		"Bar"
        +	]],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for class names in variables and parameters.
        diff --git a/tests/languages/csharp/constructor-invocation_feature.test b/tests/languages/csharp/constructor-invocation_feature.test
        new file mode 100644
        index 0000000000..eb29e46d07
        --- /dev/null
        +++ b/tests/languages/csharp/constructor-invocation_feature.test
        @@ -0,0 +1,86 @@
        +new Foo();
        +new Foo>();
        +new Foo>[0];
        +new Foo>[] {};
        +new Foo> {};
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "new"],
        +	["constructor-invocation", ["Foo"]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "new"],
        +	["constructor-invocation", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"A",
        +		["punctuation", ","],
        +		" B",
        +		["punctuation", "<"],
        +		"C",
        +		["punctuation", ">"],
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "new"],
        +	["constructor-invocation", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"A",
        +		["punctuation", ","],
        +		" B",
        +		["punctuation", "<"],
        +		"C",
        +		["punctuation", ">"],
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", "["],
        +	["number", "0"],
        +	["punctuation", "]"],
        +	["punctuation", ";"],
        +
        +	["keyword", "new"],
        +	["constructor-invocation", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"A",
        +		["punctuation", ","],
        +		" B",
        +		["punctuation", "<"],
        +		"C",
        +		["punctuation", ">"],
        +		["punctuation", ">"],
        +		["punctuation", "["],
        +		["punctuation", "]"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["keyword", "new"],
        +	["constructor-invocation", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"A",
        +		["punctuation", ","],
        +		" B",
        +		["punctuation", "<"],
        +		"C",
        +		["punctuation", ">"],
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for different constructor invocations styles.
        diff --git a/tests/languages/csharp/for_feature.test b/tests/languages/csharp/for_feature.test
        new file mode 100644
        index 0000000000..4cbc40b3b6
        --- /dev/null
        +++ b/tests/languages/csharp/for_feature.test
        @@ -0,0 +1,33 @@
        +for (Int32 i = 0; i < count; i++)
        +foreach (Foo e in Elements)
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "for"],
        +	["punctuation", "("],
        +	["class-name", ["Int32"]],
        +	" i ",
        +	["operator", "="],
        +	["number", "0"],
        +	["punctuation", ";"],
        +	" i ",
        +	["operator", "<"],
        +	" count",
        +	["punctuation", ";"],
        +	" i",
        +	["operator", "++"],
        +	["punctuation", ")"],
        +	["keyword", "foreach"],
        +	["punctuation", "("],
        +	["class-name", ["Foo"]],
        +	" e ",
        +	["keyword", "in"],
        +	" Elements",
        +	["punctuation", ")"]
        +]
        +
        +
        +----------------------------------------------------
        +
        +Checks for `for` and `foreach` loops.
        diff --git a/tests/languages/csharp/generic-constraint_feature.test b/tests/languages/csharp/generic-constraint_feature.test
        new file mode 100644
        index 0000000000..124104b7a4
        --- /dev/null
        +++ b/tests/languages/csharp/generic-constraint_feature.test
        @@ -0,0 +1,122 @@
        +void abc() where U : struct, IFoo where V : IFoo {}
        +delegate void F(U u) where U : class, IFoo;
        +class Foo where T : IFoo {}
        +readonly struct Foo where T : unmanaged {}
        +
        +----------------------------------------------------
        +
        +[
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
        +	["generic-method", [
        +		["function", "abc"],
        +		["generic", [
        +			["punctuation", "<"],
        +			"U",
        +			["punctuation", ","],
        +			" V",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["keyword", "where"],
        +	["class-name", "U"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "struct"],
        +		["punctuation", ","],
        +		["class-name", [
        +			"IFoo"
        +		]]
        +	]],
        +	["keyword", "where"],
        +	["class-name", "V"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["class-name", [
        +			"IFoo",
        +			["punctuation", "<"],
        +			"U",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "delegate"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
        +	["generic-method", [
        +		["function", "F"],
        +		["generic", [
        +			["punctuation", "<"],
        +			"U",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["class-name", [
        +		"U"
        +	]],
        +	" u",
        +	["punctuation", ")"],
        +	["keyword", "where"],
        +	["class-name", "U"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "class"],
        +		["punctuation", ","],
        +		["class-name", [
        +			"IFoo",
        +			["punctuation", "<"],
        +			"Bar",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "class"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"T",
        +		["punctuation", ">"]
        +	]],
        +	["keyword", "where"],
        +	["class-name", "T"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["class-name", [
        +			"IFoo",
        +			["punctuation", "<"],
        +			["keyword", "int"],
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "readonly"],
        +	["keyword", "struct"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"T",
        +		["punctuation", ">"]
        +	]],
        +	["keyword", "where"],
        +	["class-name", "T"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "unmanaged"]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for class names and keywords in generic constraints.
        diff --git a/tests/languages/csharp/generic_feature.test b/tests/languages/csharp/generic_feature.test
        index 05d3f589a9..32a69dcd87 100644
        --- a/tests/languages/csharp/generic_feature.test
        +++ b/tests/languages/csharp/generic_feature.test
        @@ -4,25 +4,31 @@ method();
         ----------------------------------------------------
         
         [
        -	["keyword", "void"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
         	["generic-method", [
         		["function", "method"],
        -		["punctuation", "<"],
        -		["class-name", ["T"]],
        -		["punctuation", ","],
        -		["class-name", ["U"]],
        -		["punctuation", ">"]
        +		["generic", [
        +			["punctuation", "<"],
        +			"T",
        +			["punctuation", ","],
        +			" U",
        +			["punctuation", ">"]
        +		]]
         	]],
         	["punctuation", "("],
         	["punctuation", ")"],
         	["punctuation", ";"],
         	["generic-method", [
         		["function", "method"],
        -		["punctuation", "<"],
        -		["keyword", "int"],
        -		["punctuation", ","],
        -		["keyword", "char"],
        -		["punctuation", ">"]
        +		["generic", [
        +			["punctuation", "<"],
        +			["keyword", "int"],
        +			["punctuation", ","],
        +			["keyword", "char"],
        +			["punctuation", ">"]
        +		]]
         	]],
         	["punctuation", "("],
         	["punctuation", ")"],
        @@ -31,4 +37,4 @@ method();
         
         ----------------------------------------------------
         
        -Checks for generic methods
        \ No newline at end of file
        +Checks for generic methods
        diff --git a/tests/languages/csharp/interpolation-string_feature.test b/tests/languages/csharp/interpolation-string_feature.test
        new file mode 100644
        index 0000000000..fba1721ffe
        --- /dev/null
        +++ b/tests/languages/csharp/interpolation-string_feature.test
        @@ -0,0 +1,168 @@
        +$"Hello, {{ {name} }}! Today is {date.DayOfWeek}, it's {date:HH:mm} now."
        +@$"Hello, {{ {name} }}! Today is {date.DayOfWeek}, it's {date:HH:mm} now."
        +$"{a,5} and {b + "" /* foo ":} */:format} {h(a, b)}"
        +$"{1}{2}{3}"
        +
        +@$"
        +"
        +$@"
        +"
        +
        +$@"{
        +	1 + 2 // some comment ":}{}
        +}"
        +
        +----------------------------------------------------
        +
        +[
        +	["interpolation-string", [
        +		["string", "$\"Hello, {{ "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", ["name"]],
        +			["punctuation", "}"]
        +		]],
        +		["string", " }}! Today is "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				"date",
        +				["punctuation", "."],
        +				"DayOfWeek"
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", ", it's "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", ["date"]],
        +			["format-string", [
        +				["punctuation", ":"],
        +				"HH:mm"
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", " now.\""]
        +	]],
        +	["interpolation-string", [
        +		["string", "@$\"Hello, {{ "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", ["name"]],
        +			["punctuation", "}"]
        +		]],
        +		["string", " }}! Today is "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				"date",
        +				["punctuation", "."],
        +				"DayOfWeek"
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", ", it's "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", ["date"]],
        +			["format-string", [
        +				["punctuation", ":"],
        +				"HH:mm"
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", " now.\""]
        +	]],
        +	["interpolation-string", [
        +		["string", "$\""],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				"a",
        +				["punctuation", ","],
        +				["number", "5"]
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", " and "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				"b ",
        +				["operator", "+"],
        +				["string", "\"\""],
        +				["comment", "/* foo \":} */"]
        +			]],
        +			["format-string", [
        +				["punctuation", ":"],
        +				"format"
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", " "],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				["function", "h"],
        +				["punctuation", "("],
        +				"a",
        +				["punctuation", ","],
        +				" b",
        +				["punctuation", ")"]
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", "\""]
        +	]],
        +	["interpolation-string", [
        +		["string", "$\""],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				["number", "1"]
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				["number", "2"]
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				["number", "3"]
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", "\""]
        +	]],
        +
        +	["interpolation-string", [
        +		["string", "@$\"\r\n\""]
        +	]],
        +	["interpolation-string", [
        +		["string", "$@\"\r\n\""]
        +	]],
        +
        +	["interpolation-string", [
        +		["string", "$@\""],
        +		["interpolation", [
        +			["punctuation", "{"],
        +			["expression", [
        +				["number", "1"],
        +				["operator", "+"],
        +				["number", "2"],
        +				["comment", "// some comment \":}{}"]
        +			]],
        +			["punctuation", "}"]
        +		]],
        +		["string", "\""]
        +	]]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for string interpolation.
        diff --git a/tests/languages/csharp/issue1365.test b/tests/languages/csharp/issue1365.test
        index 6aaf3c7169..7829c78002 100644
        --- a/tests/languages/csharp/issue1365.test
        +++ b/tests/languages/csharp/issue1365.test
        @@ -1,5 +1,5 @@
         interface ILogger {
        -    void Init(SomeClass file);
        +	void Init(SomeClass file);
         	void LogInfo(string message);
         }
         public class SomeClass : BaseClass {}
        @@ -8,32 +8,48 @@ public class SomeClass : BaseClass {}
         
         [
         	["keyword", "interface"],
        -	["class-name", ["ILogger"]],
        +	["class-name", [
        +		"ILogger"
        +	]],
         	["punctuation", "{"],
        -	["keyword", "void"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
         	["function", "Init"],
         	["punctuation", "("],
        -	["class-name", ["SomeClass"]],
        +	["class-name", [
        +		"SomeClass"
        +	]],
         	" file",
         	["punctuation", ")"],
         	["punctuation", ";"],
        -	["keyword", "void"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
         	["function", "LogInfo"],
         	["punctuation", "("],
        -	["keyword", "string"],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
         	" message",
         	["punctuation", ")"],
         	["punctuation", ";"],
         	["punctuation", "}"],
         	["keyword", "public"],
         	["keyword", "class"],
        -	["class-name", ["SomeClass"]],
        +	["class-name", [
        +		"SomeClass"
        +	]],
         	["punctuation", ":"],
        -	["class-name", ["BaseClass"]],
        +	["type-list", [
        +		["class-name", [
        +			"BaseClass"
        +		]]
        +	]],
         	["punctuation", "{"],
         	["punctuation", "}"]
         ]
         
         ----------------------------------------------------
         
        -Checks for class names. See #1365
        \ No newline at end of file
        +Checks for class names. See #1365
        diff --git a/tests/languages/csharp/issue1371.test b/tests/languages/csharp/issue1371.test
        index 1b2cb7be99..ddee898406 100644
        --- a/tests/languages/csharp/issue1371.test
        +++ b/tests/languages/csharp/issue1371.test
        @@ -2,14 +2,14 @@ container.Register();
         container.Register();
         var container = new Container(f =>
         {
        -    f.For().Use();
        +	f.For().Use();
         });
         class LandAnimal {
        -    public void Move() => Run(); }
        +	public void Move() => Run(); }
         class Dog : LandAnimal {
        -    public new void Move() => Run(); }
        +	public new void Move() => Run(); }
         class Works : LandAnimal {
        -    public override void Move() => Run(); }
        +	public override void Move() => Run(); }
         [Required]
         [RequiredAttribute()]
         [Range(1, 10)]
        @@ -21,9 +21,11 @@ class Works : LandAnimal {
         	["punctuation", "."],
         	["generic-method", [
         		["function", "Register"],
        -		["punctuation", "<"],
        -		["class-name", ["Car"]],
        -		["punctuation", ">"]
        +		["generic", [
        +			["punctuation", "<"],
        +			"Car",
        +			["punctuation", ">"]
        +		]]
         	]],
         	["punctuation", "("],
         	["punctuation", ")"],
        @@ -32,41 +34,50 @@ class Works : LandAnimal {
         	["punctuation", "."],
         	["generic-method", [
         		["function", "Register"],
        -		["punctuation", "<"],
        -		["class-name", ["IJuice"]],
        -		["punctuation", ","],
        -		["class-name", ["Juice"]],
        -		["punctuation", ">"]
        +		["generic", [
        +			["punctuation", "<"],
        +			"IJuice",
        +			["punctuation", ","],
        +			" Juice",
        +			["punctuation", ">"]
        +		]]
         	]],
         	["punctuation", "("],
         	["punctuation", ")"],
         	["punctuation", ";"],
        -	["keyword", "var"],
        +	["class-name", [
        +		["keyword", "var"]
        +	]],
         	" container ",
         	["operator", "="],
         	["keyword", "new"],
        -	["class-name", ["Container"]],
        +	["constructor-invocation", [
        +		"Container"
        +	]],
         	["punctuation", "("],
         	"f ",
        -	["operator", "="],
        -	["operator", ">"],
        +	["operator", "=>"],
         	["punctuation", "{"],
        -	"\r\n    f",
        +	"\r\n\tf",
         	["punctuation", "."],
         	["generic-method", [
         		["function", "For"],
        -		["punctuation", "<"],
        -		["class-name", ["IFoo"]],
        -		["punctuation", ">"]
        +		["generic", [
        +			["punctuation", "<"],
        +			"IFoo",
        +			["punctuation", ">"]
        +		]]
         	]],
         	["punctuation", "("],
         	["punctuation", ")"],
         	["punctuation", "."],
         	["generic-method", [
         		["function", "Use"],
        -		["punctuation", "<"],
        -		["class-name", ["Foo"]],
        -		["punctuation", ">"]
        +		["generic", [
        +			["punctuation", "<"],
        +			"Foo",
        +			["punctuation", ">"]
        +		]]
         	]],
         	["punctuation", "("],
         	["punctuation", ")"],
        @@ -75,74 +86,107 @@ class Works : LandAnimal {
         	["punctuation", ")"],
         	["punctuation", ";"],
         	["keyword", "class"],
        -	["class-name", ["LandAnimal"]],
        +	["class-name", [
        +		"LandAnimal"
        +	]],
         	["punctuation", "{"],
         	["keyword", "public"],
        -	["keyword", "void"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
         	["function", "Move"],
         	["punctuation", "("],
         	["punctuation", ")"],
        -	["operator", "="],
        -	["operator", ">"],
        +	["operator", "=>"],
         	["function", "Run"],
         	["punctuation", "("],
         	["punctuation", ")"],
         	["punctuation", ";"],
         	["punctuation", "}"],
         	["keyword", "class"],
        -	["class-name", ["Dog"]],
        +	["class-name", [
        +		"Dog"
        +	]],
         	["punctuation", ":"],
        -	["class-name", ["LandAnimal"]],
        +	["type-list", [
        +		["class-name", [
        +			"LandAnimal"
        +		]]
        +	]],
         	["punctuation", "{"],
         	["keyword", "public"],
         	["keyword", "new"],
        -	["keyword", "void"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
         	["function", "Move"],
         	["punctuation", "("],
         	["punctuation", ")"],
        -	["operator", "="],
        -	["operator", ">"],
        +	["operator", "=>"],
         	["function", "Run"],
         	["punctuation", "("],
         	["punctuation", ")"],
         	["punctuation", ";"],
         	["punctuation", "}"],
         	["keyword", "class"],
        -	["class-name", ["Works"]],
        +	["class-name", [
        +		"Works"
        +	]],
         	["punctuation", ":"],
        -	["class-name", ["LandAnimal"]],
        +	["type-list", [
        +		["class-name", [
        +			"LandAnimal"
        +		]]
        +	]],
         	["punctuation", "{"],
         	["keyword", "public"],
         	["keyword", "override"],
        -	["keyword", "void"],
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
         	["function", "Move"],
         	["punctuation", "("],
         	["punctuation", ")"],
        -	["operator", "="],
        -	["operator", ">"],
        +	["operator", "=>"],
         	["function", "Run"],
         	["punctuation", "("],
         	["punctuation", ")"],
         	["punctuation", ";"],
         	["punctuation", "}"],
         	["punctuation", "["],
        -	["class-name", ["Required"]],
        +	["attribute", [
        +		["class-name", [
        +			"Required"
        +		]]
        +	]],
         	["punctuation", "]"],
         	["punctuation", "["],
        -	["class-name", ["RequiredAttribute"]],
        -	["punctuation", "("],
        -	["punctuation", ")"],
        +	["attribute", [
        +		["class-name", [
        +			"RequiredAttribute"
        +		]],
        +		["attribute-arguments", [
        +			["punctuation", "("],
        +			["punctuation", ")"]
        +		]]
        +	]],
         	["punctuation", "]"],
         	["punctuation", "["],
        -	["class-name", ["Range"]],
        -	["punctuation", "("],
        -	["number", "1"],
        -	["punctuation", ","],
        -	["number", "10"],
        -	["punctuation", ")"],
        +	["attribute", [
        +		["class-name", [
        +			"Range"
        +		]],
        +		["attribute-arguments", [
        +			["punctuation", "("],
        +			["number", "1"],
        +			["punctuation", ","],
        +			["number", "10"],
        +			["punctuation", ")"]
        +		]]
        +	]],
         	["punctuation", "]"]
         ]
         
         ----------------------------------------------------
         
        -Checks for various cases of class names. See #1371
        \ No newline at end of file
        +Checks for various cases of class names. See #1371
        diff --git a/tests/languages/csharp/issue2968.test b/tests/languages/csharp/issue2968.test
        new file mode 100644
        index 0000000000..c825e4f65b
        --- /dev/null
        +++ b/tests/languages/csharp/issue2968.test
        @@ -0,0 +1,27 @@
        +func(from: "America", to: "Asia"); // Prism incorrectly highlights "from" as a keyword
        +
        +from element in list; // no issues here
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "func"],
        +	["punctuation", "("],
        +	["named-parameter", "from"],
        +	["punctuation", ":"],
        +	["string", "\"America\""],
        +	["punctuation", ","],
        +	["named-parameter", "to"],
        +	["punctuation", ":"],
        +	["string", "\"Asia\""],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["comment", "// Prism incorrectly highlights \"from\" as a keyword"],
        +
        +	["keyword", "from"],
        +	" element ",
        +	["keyword", "in"],
        +	" list",
        +	["punctuation", ";"],
        +	["comment", "// no issues here"]
        +]
        diff --git a/tests/languages/csharp/keyword_feature.test b/tests/languages/csharp/keyword_feature.test
        index e1c37f0a08..3d42242aa8 100644
        --- a/tests/languages/csharp/keyword_feature.test
        +++ b/tests/languages/csharp/keyword_feature.test
        @@ -1,6 +1,7 @@
         abstract
         add
         alias
        +and
         as
         ascending
         async
        @@ -8,6 +9,7 @@ await
         base
         bool
         break
        +by
         byte
         case
         catch
        @@ -24,17 +26,16 @@ do
         double
         dynamic
         else
        -enum
        +enum;
         event
         explicit
         extern
        -false
         finally
         fixed
         float
         for
         foreach
        -from
        +from foo;
         get
         global
         goto
        @@ -42,7 +43,8 @@ group
         if
         implicit
         in
        -int
        +init;
        +int;
         interface;
         internal
         into
        @@ -51,11 +53,16 @@ join
         let
         lock
         long
        -namespace
        +nameof
        +namespace;
         new;
        +not
        +notnull
         null
         object
        +on
         operator
        +or
         orderby
         out
         override
        @@ -65,6 +72,7 @@ private
         protected
         public
         readonly
        +record;
         ref
         remove
         return
        @@ -76,17 +84,17 @@ short
         sizeof
         stackalloc
         static
        -string
        -struct
        +string;
        +struct;
         switch
         this
         throw
        -true
         try
         typeof
         uint
         ulong
         unchecked
        +unmanaged
         unsafe
         ushort
         using
        @@ -95,16 +103,21 @@ var
         virtual
         void
         volatile
        -where
        +when
        +where;
         while
         yield
         
        +// very contextual keywords:
        +Person person2 = person1 with { FirstName = "John" };
        +
         ----------------------------------------------------
         
         [
         	["keyword", "abstract"],
         	["keyword", "add"],
         	["keyword", "alias"],
        +	["keyword", "and"],
         	["keyword", "as"],
         	["keyword", "ascending"],
         	["keyword", "async"],
        @@ -112,6 +125,7 @@ yield
         	["keyword", "base"],
         	["keyword", "bool"],
         	["keyword", "break"],
        +	["keyword", "by"],
         	["keyword", "byte"],
         	["keyword", "case"],
         	["keyword", "catch"],
        @@ -128,17 +142,16 @@ yield
         	["keyword", "double"],
         	["keyword", "dynamic"],
         	["keyword", "else"],
        -	["keyword", "enum"],
        +	["keyword", "enum"], ["punctuation", ";"],
         	["keyword", "event"],
         	["keyword", "explicit"],
         	["keyword", "extern"],
        -	["keyword", "false"],
         	["keyword", "finally"],
         	["keyword", "fixed"],
         	["keyword", "float"],
         	["keyword", "for"],
         	["keyword", "foreach"],
        -	["keyword", "from"],
        +	["keyword", "from"], " foo", ["punctuation", ";"],
         	["keyword", "get"],
         	["keyword", "global"],
         	["keyword", "goto"],
        @@ -146,7 +159,8 @@ yield
         	["keyword", "if"],
         	["keyword", "implicit"],
         	["keyword", "in"],
        -	["keyword", "int"],
        +	["keyword", "init"], ["punctuation", ";"],
        +	["keyword", "int"], ["punctuation", ";"],
         	["keyword", "interface"], ["punctuation", ";"],
         	["keyword", "internal"],
         	["keyword", "into"],
        @@ -155,11 +169,16 @@ yield
         	["keyword", "let"],
         	["keyword", "lock"],
         	["keyword", "long"],
        -	["keyword", "namespace"],
        +	["keyword", "nameof"],
        +	["keyword", "namespace"], ["punctuation", ";"],
         	["keyword", "new"], ["punctuation", ";"],
        +	["keyword", "not"],
        +	["keyword", "notnull"],
         	["keyword", "null"],
         	["keyword", "object"],
        +	["keyword", "on"],
         	["keyword", "operator"],
        +	["keyword", "or"],
         	["keyword", "orderby"],
         	["keyword", "out"],
         	["keyword", "override"],
        @@ -169,6 +188,7 @@ yield
         	["keyword", "protected"],
         	["keyword", "public"],
         	["keyword", "readonly"],
        +	["keyword", "record"], ["punctuation", ";"],
         	["keyword", "ref"],
         	["keyword", "remove"],
         	["keyword", "return"],
        @@ -180,17 +200,17 @@ yield
         	["keyword", "sizeof"],
         	["keyword", "stackalloc"],
         	["keyword", "static"],
        -	["keyword", "string"],
        -	["keyword", "struct"],
        +	["keyword", "string"], ["punctuation", ";"],
        +	["keyword", "struct"], ["punctuation", ";"],
         	["keyword", "switch"],
         	["keyword", "this"],
         	["keyword", "throw"],
        -	["keyword", "true"],
         	["keyword", "try"],
         	["keyword", "typeof"],
         	["keyword", "uint"],
         	["keyword", "ulong"],
         	["keyword", "unchecked"],
        +	["keyword", "unmanaged"],
         	["keyword", "unsafe"],
         	["keyword", "ushort"],
         	["keyword", "using"],
        @@ -199,11 +219,26 @@ yield
         	["keyword", "virtual"],
         	["keyword", "void"],
         	["keyword", "volatile"],
        -	["keyword", "where"],
        +	["keyword", "when"],
        +	["keyword", "where"], ["punctuation", ";"],
         	["keyword", "while"],
        -	["keyword", "yield"]
        +	["keyword", "yield"],
        +
        +	["comment", "// very contextual keywords:"],
        +
        +	["class-name", ["Person"]],
        +	" person2 ",
        +	["operator", "="],
        +	" person1 ",
        +	["keyword", "with"],
        +	["punctuation", "{"],
        +	" FirstName ",
        +	["operator", "="],
        +	["string", "\"John\""],
        +	["punctuation", "}"],
        +	["punctuation", ";"]
         ]
         
         ----------------------------------------------------
         
        -Checks for all keywords.
        \ No newline at end of file
        +Checks for all keywords.
        diff --git a/tests/languages/csharp/named-parameter_feature.test b/tests/languages/csharp/named-parameter_feature.test
        new file mode 100644
        index 0000000000..7e7560b90f
        --- /dev/null
        +++ b/tests/languages/csharp/named-parameter_feature.test
        @@ -0,0 +1,21 @@
        +Foo(abc: 4, xyz: 6);
        +
        +----------------------------------------------------
        +
        +[
        +	["function", "Foo"],
        +	["punctuation", "("],
        +	["named-parameter", "abc"],
        +	["punctuation", ":"],
        +	["number", "4"],
        +	["punctuation", ","],
        +	["named-parameter", "xyz"],
        +	["punctuation", ":"],
        +	["number", "6"],
        +	["punctuation", ")"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for named method parameters.
        diff --git a/tests/languages/csharp/namespace_feature.test b/tests/languages/csharp/namespace_feature.test
        new file mode 100644
        index 0000000000..d4c4906756
        --- /dev/null
        +++ b/tests/languages/csharp/namespace_feature.test
        @@ -0,0 +1,25 @@
        +namespace Foo {}
        +namespace Foo.Bar {}
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "namespace"],
        +	["namespace", ["Foo"]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "namespace"],
        +	["namespace", [
        +		"Foo",
        +		["punctuation", "."],
        +		"Bar"
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"]
        +]
        +
        +
        +----------------------------------------------------
        +
        +Checks for namespace declarations.
        diff --git a/tests/languages/csharp/number_feature.test b/tests/languages/csharp/number_feature.test
        index 126808037b..4f4d262a4d 100644
        --- a/tests/languages/csharp/number_feature.test
        +++ b/tests/languages/csharp/number_feature.test
        @@ -1,17 +1,55 @@
         42
         3.14159
        +3.14159f
        +3.14159e-23
        +.1f
        +1234L
        +1234u
        +700000000000ul
        +700000000000Lu
        +0xFFFFFFFFFFFFFFFFul
         0xbabe
         0XBABE
        +1_000_000
        +1_2_3_4.5_6e-7_8
        +0X_BA_BE
        +0b_1_0000_0000_0000_0000_0000_0000_0000_0000
        +
        +0.06m
        +0.06M
        +0.06f
        +0.06F
        +0.06d
        +0.06D
         
         ----------------------------------------------------
         
         [
         	["number", "42"],
         	["number", "3.14159"],
        +	["number", "3.14159f"],
        +	["number", "3.14159e-23"],
        +	["number", ".1f"],
        +	["number", "1234L"],
        +	["number", "1234u"],
        +	["number", "700000000000ul"],
        +	["number", "700000000000Lu"],
        +	["number", "0xFFFFFFFFFFFFFFFFul"],
         	["number", "0xbabe"],
        -	["number", "0XBABE"]
        +	["number", "0XBABE"],
        +	["number", "1_000_000"],
        +	["number", "1_2_3_4.5_6e-7_8"],
        +	["number", "0X_BA_BE"],
        +	["number", "0b_1_0000_0000_0000_0000_0000_0000_0000_0000"],
        +
        +	["number", "0.06m"],
        +	["number", "0.06M"],
        +	["number", "0.06f"],
        +	["number", "0.06F"],
        +	["number", "0.06d"],
        +	["number", "0.06D"]
         ]
         
         ----------------------------------------------------
         
        -Checks for decimal and hexadecimal numbers.
        \ No newline at end of file
        +Checks for decimal and hexadecimal numbers.
        diff --git a/tests/languages/csharp/operator_feature.test b/tests/languages/csharp/operator_feature.test
        new file mode 100644
        index 0000000000..7e74ca4571
        --- /dev/null
        +++ b/tests/languages/csharp/operator_feature.test
        @@ -0,0 +1,61 @@
        ++ - * / % -- ++
        +>> <<
        +~ & | ^
        ++= -= *= /= %= >>= <<= &= |= ^=
        +! && ||
        +-> =>
        += == != < > <= >=
        +?? ??=
        +
        +----------------------------------------------------
        +
        +[
        +	["operator", "+"],
        +	["operator", "-"],
        +	["operator", "*"],
        +	["operator", "/"],
        +	["operator", "%"],
        +	["operator", "--"],
        +	["operator", "++"],
        +
        +	["operator", ">>"],
        +	["operator", "<<"],
        +
        +	["operator", "~"],
        +	["operator", "&"],
        +	["operator", "|"],
        +	["operator", "^"],
        +
        +	["operator", "+="],
        +	["operator", "-="],
        +	["operator", "*="],
        +	["operator", "/="],
        +	["operator", "%="],
        +	["operator", ">>="],
        +	["operator", "<<="],
        +	["operator", "&="],
        +	["operator", "|="],
        +	["operator", "^="],
        +
        +	["operator", "!"],
        +	["operator", "&&"],
        +	["operator", "||"],
        +
        +	["operator", "->"],
        +	["operator", "=>"],
        +
        +	["operator", "="],
        +	["operator", "=="],
        +	["operator", "!="],
        +	["operator", "<"],
        +	["operator", ">"],
        +	["operator", "<="],
        +	["operator", ">="],
        +
        +	["operator", "??"],
        +	["operator", "??="]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for all operators.
        diff --git a/tests/languages/csharp/preprocessor_feature.test b/tests/languages/csharp/preprocessor_feature.test
        index 93ad4903ab..8f03332608 100644
        --- a/tests/languages/csharp/preprocessor_feature.test
        +++ b/tests/languages/csharp/preprocessor_feature.test
        @@ -7,6 +7,7 @@
         #endregion
         #error
         #line
        +#nullable
         #pragma
         #region
         #undef
        @@ -18,18 +19,19 @@
         	["preprocessor", ["#", ["directive", "define"], " DEBUG"]],
         	["preprocessor", ["#", ["directive", "if"], " DEBUG"]],
         	["preprocessor", ["#", ["directive", "endif"]]],
        -	
        +
         	["preprocessor", ["#", ["directive", "elif"]]],
        -    ["preprocessor", ["#", ["directive", "else"]]],
        -    ["preprocessor", ["#", ["directive", "endregion"]]],
        -    ["preprocessor", ["#", ["directive", "error"]]],
        -    ["preprocessor", ["#", ["directive", "line"]]],
        -    ["preprocessor", ["#", ["directive", "pragma"]]],
        -    ["preprocessor", ["#", ["directive", "region"]]],
        -    ["preprocessor", ["#", ["directive", "undef"]]],
        -    ["preprocessor", ["#", ["directive", "warning"]]]
        +	["preprocessor", ["#", ["directive", "else"]]],
        +	["preprocessor", ["#", ["directive", "endregion"]]],
        +	["preprocessor", ["#", ["directive", "error"]]],
        +	["preprocessor", ["#", ["directive", "line"]]],
        +	["preprocessor", ["#", ["directive", "nullable"]]],
        +	["preprocessor", ["#", ["directive", "pragma"]]],
        +	["preprocessor", ["#", ["directive", "region"]]],
        +	["preprocessor", ["#", ["directive", "undef"]]],
        +	["preprocessor", ["#", ["directive", "warning"]]]
         ]
         
         ----------------------------------------------------
         
        -Checks for preprocessor directives.
        \ No newline at end of file
        +Checks for preprocessor directives.
        diff --git a/tests/languages/csharp/punctuation_feature.test b/tests/languages/csharp/punctuation_feature.test
        new file mode 100644
        index 0000000000..b9a7bf1499
        --- /dev/null
        +++ b/tests/languages/csharp/punctuation_feature.test
        @@ -0,0 +1,27 @@
        +. , ; : ::
        +? ?.
        +[ ] { } ( )
        +
        +----------------------------------------------------
        +
        +[
        +	["punctuation", "."],
        +	["punctuation", ","],
        +	["punctuation", ";"],
        +	["punctuation", ":"],
        +	["punctuation", "::"],
        +
        +	["punctuation", "?"],
        +	["punctuation", "?."],
        +
        +	["punctuation", "["],
        +	["punctuation", "]"],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +	["punctuation", "("],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for punctuation.
        diff --git a/tests/languages/csharp/range_feature.test b/tests/languages/csharp/range_feature.test
        new file mode 100644
        index 0000000000..42010fa0d7
        --- /dev/null
        +++ b/tests/languages/csharp/range_feature.test
        @@ -0,0 +1,42 @@
        +list[2..^3];
        +list[..^3];
        +list[2..];
        +list[..];
        +
        +----------------------------------------------------
        +
        +[
        +	"list",
        +	["punctuation", "["],
        +	["number", "2"],
        +	["range", ".."],
        +	["operator", "^"],
        +	["number", "3"],
        +	["punctuation", "]"],
        +	["punctuation", ";"],
        +
        +	"\r\nlist",
        +	["punctuation", "["],
        +	["range", ".."],
        +	["operator", "^"],
        +	["number", "3"],
        +	["punctuation", "]"],
        +	["punctuation", ";"],
        +
        +	"\r\nlist",
        +	["punctuation", "["],
        +	["number", "2"],
        +	["range", ".."],
        +	["punctuation", "]"],
        +	["punctuation", ";"],
        +
        +	"\r\nlist",
        +	["punctuation", "["],
        +	["range", ".."],
        +	["punctuation", "]"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for ranges.
        diff --git a/tests/languages/csharp/return-type_feature.test b/tests/languages/csharp/return-type_feature.test
        new file mode 100644
        index 0000000000..9742e85159
        --- /dev/null
        +++ b/tests/languages/csharp/return-type_feature.test
        @@ -0,0 +1,166 @@
        +Foo Bar();
        +Foo Bar();
        +Foo[,] Bar();
        +new Foo[,] Bar();
        +(int, long)? Foo();
        +(int, long)? Foo => null;
        +Baz?[,]? Foo { get; set } = null;
        +int[]? this[int index] => null;
        +int[]? IInterface.this[int index] => null;
        +
        +----------------------------------------------------
        +
        +[
        +	["return-type", [
        +		"Foo"
        +	]],
        +	["function", "Bar"],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"]
        +	]],
        +	["generic-method", [
        +		["function", "Bar"],
        +		["generic", [
        +			["punctuation", "<"],
        +			"A",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"],
        +		["punctuation", "["],
        +		["punctuation", ","],
        +		["punctuation", "]"]
        +	]],
        +	["generic-method", [
        +		["function", "Bar"],
        +		["generic", [
        +			["punctuation", "<"],
        +			"A",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["keyword", "new"],
        +	["return-type", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"],
        +		["punctuation", "["],
        +		["punctuation", ","],
        +		["punctuation", "]"]
        +	]],
        +	["generic-method", [
        +		["function", "Bar"],
        +		["generic", [
        +			["punctuation", "<"],
        +			"A",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		["punctuation", "("],
        +		["keyword", "int"],
        +		["punctuation", ","],
        +		["keyword", "long"],
        +		["punctuation", ")"],
        +		["punctuation", "?"]
        +	]],
        +	["generic-method", [
        +		["function", "Foo"],
        +		["generic", [
        +			["punctuation", "<"],
        +			["keyword", "int"],
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		["punctuation", "("],
        +		["keyword", "int"],
        +		["punctuation", ","],
        +		["keyword", "long"],
        +		["punctuation", ")"],
        +		["punctuation", "?"]
        +	]],
        +	" Foo ",
        +	["operator", "=>"],
        +	["keyword", "null"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		"Baz",
        +		["punctuation", "?"],
        +		["punctuation", "["],
        +		["punctuation", ","],
        +		["punctuation", "]"],
        +		["punctuation", "?"]
        +	]],
        +	" Foo ",
        +	["punctuation", "{"],
        +	["keyword", "get"],
        +	["punctuation", ";"],
        +	["keyword", "set"],
        +	["punctuation", "}"],
        +	["operator", "="],
        +	["keyword", "null"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		["keyword", "int"],
        +		["punctuation", "["],
        +		["punctuation", "]"],
        +		["punctuation", "?"]
        +	]],
        +	["keyword", "this"],
        +	["punctuation", "["],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" index",
        +	["punctuation", "]"],
        +	["operator", "=>"],
        +	["keyword", "null"],
        +	["punctuation", ";"],
        +	["return-type", [
        +		["keyword", "int"],
        +		["punctuation", "["],
        +		["punctuation", "]"],
        +		["punctuation", "?"]
        +	]],
        +	" IInterface",
        +	["punctuation", "."],
        +	["keyword", "this"],
        +	["punctuation", "["],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" index",
        +	["punctuation", "]"],
        +	["operator", "=>"],
        +	["keyword", "null"],
        +	["punctuation", ";"]
        +]
        +
        +
        +----------------------------------------------------
        +
        +Checks for the return type.
        diff --git a/tests/languages/csharp/string_feature.test b/tests/languages/csharp/string_feature.test
        index 2814cb561c..83bc61389e 100644
        --- a/tests/languages/csharp/string_feature.test
        +++ b/tests/languages/csharp/string_feature.test
        @@ -7,10 +7,6 @@
         @"foo
         bar"
         
        -'a'
        -'\''
        -'\\'
        -
         ----------------------------------------------------
         
         [
        @@ -20,13 +16,9 @@ bar"
         	["string", "@\"\""],
         	["string", "@\"foo\""],
         	["string", "@\"fo\"\"o\""],
        -	["string", "@\"foo\r\nbar\""],
        -	["string", "'a'"],
        -	["string", "'\\''"],
        -	["string", "'\\\\'"]
        +	["string", "@\"foo\r\nbar\""]
         ]
         
         ----------------------------------------------------
         
         Checks for normal and verbatim strings.
        -Also checks for single quoted characters.
        \ No newline at end of file
        diff --git a/tests/languages/csharp/switch_feature.test b/tests/languages/csharp/switch_feature.test
        new file mode 100644
        index 0000000000..1b77188088
        --- /dev/null
        +++ b/tests/languages/csharp/switch_feature.test
        @@ -0,0 +1,651 @@
        +public static decimal CalculateToll(object vehicle) =>
        +	vehicle switch
        +	{
        +		DeliveryTruck t when t.GrossWeightClass > 5000 => 10.00m + 5.00m,
        +		DeliveryTruck t when t.GrossWeightClass < 3000 => 10.00m - 2.00m,
        +		DeliveryTruck _ => 10.00m,
        +		_ => throw new ArgumentException("Not a known vehicle type", nameof(vehicle))
        +	};
        +
        +DeliveryTruck t when t.GrossWeightClass switch
        +{
        +	> 5000 => 10.00m + 5.00m,
        +	< 3000 => 10.00m - 2.00m,
        +	_ => 10.00m,
        +},
        +DeliveryTruck t when t.GrossWeightClass switch
        +{
        +	< 3000 => 10.00m - 2.00m,
        +	>= 3000 and <= 5000 => 10.00m,
        +	> 5000 => 10.00m + 5.00m,
        +},
        +
        +switch (DateTime.Now.DayOfWeek)
        +{
        +	case DayOfWeek.Sunday:
        +	case DayOfWeek.Saturday:
        +		Console.WriteLine("The weekend");
        +		break;
        +	case DayOfWeek.Monday:
        +		Console.WriteLine("The first day of the work week.");
        +		break;
        +	case DayOfWeek.Friday:
        +		Console.WriteLine("The last day of the work week.");
        +		break;
        +	default:
        +		Console.WriteLine("The middle of the work week.");
        +		break;
        +}
        +
        +switch (str)
        +{
        +	case "1":
        +	case "small":
        +		cost += 25;
        +		break;
        +	case "2":
        +	case "medium":
        +		cost += 25;
        +		goto case "1";
        +	case "3":
        +	case "large":
        +		cost += 50;
        +		goto case "1";
        +	default:
        +		Console.WriteLine("Invalid selection. Please select 1, 2, or 3.");
        +		break;
        +}
        +
        +switch (sh)
        +{
        +	// Note that this code never evaluates to true.
        +	case Shape shape when shape == null:
        +		break;
        +	case null:
        +		break;
        +	case Rectangle r when r.Length == r.Width && r.Area > 0:
        +		break;
        +	default:
        +		break;
        +}
        +
        +switch (coll)
        +{
        +	case Array arr:
        +		break;
        +	case IEnumerable ieInt:
        +		break;
        +	case object o:
        +		break;
        +	default:
        +		break;
        +}
        +
        +bool IsValidPercentage(object x) => x is
        +	>= 0 and <= 100 or    // integer tests
        +	>= 0F and <= 100F or  // float tests
        +	>= 0D and <= 100D;    // double tests
        +
        +bool isSmallByte(object o) => o is byte and < 100;
        +
        +case (0, int x):
        +case (int x, 0):
        +	Console.WriteLine(x);
        +
        +case < 2: break;
        +case 0 or 1 or 2 or 3 or 4 or 5: break;
        +
        +int x = b switch { <100 => 0, 100 => 1, 101 => 2, >101 => 3 };
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "public"],
        +	["keyword", "static"],
        +	["return-type", [
        +		["keyword", "decimal"]
        +	]],
        +	["function", "CalculateToll"],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "object"]
        +	]],
        +	" vehicle",
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +
        +	"\r\n\tvehicle ",
        +	["keyword", "switch"],
        +
        +	["punctuation", "{"],
        +
        +	["class-name", ["DeliveryTruck"]],
        +	" t ",
        +	["keyword", "when"],
        +	" t",
        +	["punctuation", "."],
        +	"GrossWeightClass ",
        +	["operator", ">"],
        +	["number", "5000"],
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["operator", "+"],
        +	["number", "5.00m"],
        +	["punctuation", ","],
        +
        +	["class-name", ["DeliveryTruck"]],
        +	" t ",
        +	["keyword", "when"],
        +	" t",
        +	["punctuation", "."],
        +	"GrossWeightClass ",
        +	["operator", "<"],
        +	["number", "3000"],
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["operator", "-"],
        +	["number", "2.00m"],
        +	["punctuation", ","],
        +
        +	["return-type", ["DeliveryTruck"]],
        +	" _ ",
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["punctuation", ","],
        +
        +	"\r\n\t\t_ ",
        +	["operator", "=>"],
        +	["keyword", "throw"],
        +	["keyword", "new"],
        +	["constructor-invocation", ["ArgumentException"]],
        +	["punctuation", "("],
        +	["string", "\"Not a known vehicle type\""],
        +	["punctuation", ","],
        +	["keyword", "nameof"],
        +	["punctuation", "("],
        +	"vehicle",
        +	["punctuation", ")"],
        +	["punctuation", ")"],
        +
        +	["punctuation", "}"],
        +	["punctuation", ";"],
        +
        +	["class-name", ["DeliveryTruck"]],
        +	" t ",
        +	["keyword", "when"],
        +	" t",
        +	["punctuation", "."],
        +	"GrossWeightClass ",
        +	["keyword", "switch"],
        +
        +	["punctuation", "{"],
        +
        +	["operator", ">"],
        +	["number", "5000"],
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["operator", "+"],
        +	["number", "5.00m"],
        +	["punctuation", ","],
        +
        +	["operator", "<"],
        +	["number", "3000"],
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["operator", "-"],
        +	["number", "2.00m"],
        +	["punctuation", ","],
        +
        +	"\r\n\t_ ",
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["punctuation", ","],
        +
        +	["punctuation", "}"],
        +	["punctuation", ","],
        +
        +	["class-name", ["DeliveryTruck"]],
        +	" t ",
        +	["keyword", "when"],
        +	" t",
        +	["punctuation", "."],
        +	"GrossWeightClass ",
        +	["keyword", "switch"],
        +
        +	["punctuation", "{"],
        +
        +	["operator", "<"],
        +	["number", "3000"],
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["operator", "-"],
        +	["number", "2.00m"],
        +	["punctuation", ","],
        +
        +	["operator", ">="],
        +	["number", "3000"],
        +	["keyword", "and"],
        +	["operator", "<="],
        +	["number", "5000"],
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["punctuation", ","],
        +
        +	["operator", ">"],
        +	["number", "5000"],
        +	["operator", "=>"],
        +	["number", "10.00m"],
        +	["operator", "+"],
        +	["number", "5.00m"],
        +	["punctuation", ","],
        +
        +	["punctuation", "}"],
        +	["punctuation", ","],
        +
        +	["keyword", "switch"],
        +	["punctuation", "("],
        +	"DateTime",
        +	["punctuation", "."],
        +	"Now",
        +	["punctuation", "."],
        +	"DayOfWeek",
        +	["punctuation", ")"],
        +
        +	["punctuation", "{"],
        +
        +	["keyword", "case"],
        +	" DayOfWeek",
        +	["punctuation", "."],
        +	"Sunday",
        +	["punctuation", ":"],
        +
        +	["keyword", "case"],
        +	" DayOfWeek",
        +	["punctuation", "."],
        +	"Saturday",
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tConsole",
        +	["punctuation", "."],
        +	["function", "WriteLine"],
        +	["punctuation", "("],
        +	["string", "\"The weekend\""],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	" DayOfWeek",
        +	["punctuation", "."],
        +	"Monday",
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tConsole",
        +	["punctuation", "."],
        +	["function", "WriteLine"],
        +	["punctuation", "("],
        +	["string", "\"The first day of the work week.\""],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	" DayOfWeek",
        +	["punctuation", "."],
        +	"Friday",
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tConsole",
        +	["punctuation", "."],
        +	["function", "WriteLine"],
        +	["punctuation", "("],
        +	["string", "\"The last day of the work week.\""],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "default"],
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tConsole",
        +	["punctuation", "."],
        +	["function", "WriteLine"],
        +	["punctuation", "("],
        +	["string", "\"The middle of the work week.\""],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "switch"],
        +	["punctuation", "("],
        +	"str",
        +	["punctuation", ")"],
        +
        +	["punctuation", "{"],
        +
        +	["keyword", "case"],
        +	["string", "\"1\""],
        +	["punctuation", ":"],
        +
        +	["keyword", "case"],
        +	["string", "\"small\""],
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tcost ",
        +	["operator", "+="],
        +	["number", "25"],
        +	["punctuation", ";"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["string", "\"2\""],
        +	["punctuation", ":"],
        +
        +	["keyword", "case"],
        +	["string", "\"medium\""],
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tcost ",
        +	["operator", "+="],
        +	["number", "25"],
        +	["punctuation", ";"],
        +
        +	["keyword", "goto"],
        +	["keyword", "case"],
        +	["string", "\"1\""],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["string", "\"3\""],
        +	["punctuation", ":"],
        +
        +	["keyword", "case"],
        +	["string", "\"large\""],
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tcost ",
        +	["operator", "+="],
        +	["number", "50"],
        +	["punctuation", ";"],
        +
        +	["keyword", "goto"],
        +	["keyword", "case"],
        +	["string", "\"1\""],
        +	["punctuation", ";"],
        +
        +	["keyword", "default"],
        +	["punctuation", ":"],
        +
        +	"\r\n\t\tConsole",
        +	["punctuation", "."],
        +	["function", "WriteLine"],
        +	["punctuation", "("],
        +	["string", "\"Invalid selection. Please select 1, 2, or 3.\""],
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "switch"],
        +	["punctuation", "("],
        +	"sh",
        +	["punctuation", ")"],
        +
        +	["punctuation", "{"],
        +
        +	["comment", "// Note that this code never evaluates to true."],
        +
        +	["keyword", "case"],
        +	["class-name", ["Shape"]],
        +	" shape ",
        +	["keyword", "when"],
        +	" shape ",
        +	["operator", "=="],
        +	["keyword", "null"],
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["keyword", "null"],
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["class-name", ["Rectangle"]],
        +	" r ",
        +	["keyword", "when"],
        +	" r",
        +	["punctuation", "."],
        +	"Length ",
        +	["operator", "=="],
        +	" r",
        +	["punctuation", "."],
        +	"Width ",
        +	["operator", "&&"],
        +	" r",
        +	["punctuation", "."],
        +	"Area ",
        +	["operator", ">"],
        +	["number", "0"],
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "default"],
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +
        +	["keyword", "switch"],
        +	["punctuation", "("],
        +	"coll",
        +	["punctuation", ")"],
        +
        +	["punctuation", "{"],
        +
        +	["keyword", "case"],
        +	["class-name", ["Array"]],
        +	" arr",
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["class-name", [
        +		"IEnumerable",
        +		["punctuation", "<"],
        +		["keyword", "int"],
        +		["punctuation", ">"]
        +	]],
        +	" ieInt",
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["class-name", [
        +		["keyword", "object"]
        +	]],
        +	" o",
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "default"],
        +	["punctuation", ":"],
        +
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["punctuation", "}"],
        +
        +	["return-type", [
        +		["keyword", "bool"]
        +	]],
        +	["function", "IsValidPercentage"],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "object"]
        +	]],
        +	" x",
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +	" x ",
        +	["keyword", "is"],
        +
        +	["operator", ">="],
        +	["number", "0"],
        +	["keyword", "and"],
        +	["operator", "<="],
        +	["number", "100"],
        +	["keyword", "or"],
        +	["comment", "// integer tests"],
        +
        +	["operator", ">="],
        +	["number", "0F"],
        +	["keyword", "and"],
        +	["operator", "<="],
        +	["number", "100F"],
        +	["keyword", "or"],
        +	["comment", "// float tests"],
        +
        +	["operator", ">="],
        +	["number", "0D"],
        +	["keyword", "and"],
        +	["operator", "<="],
        +	["number", "100D"],
        +	["punctuation", ";"],
        +	["comment", "// double tests"],
        +
        +	["return-type", [
        +		["keyword", "bool"]
        +	]],
        +	["function", "isSmallByte"],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "object"]
        +	]],
        +	" o",
        +	["punctuation", ")"],
        +	["operator", "=>"],
        +	" o ",
        +	["keyword", "is"],
        +	["class-name", [
        +		["keyword", "byte"]
        +	]],
        +	["keyword", "and"],
        +	["operator", "<"],
        +	["number", "100"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["punctuation", "("],
        +	["number", "0"],
        +	["punctuation", ","],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" x",
        +	["punctuation", ")"],
        +	["punctuation", ":"],
        +
        +	["keyword", "case"],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" x",
        +	["punctuation", ","],
        +	["number", "0"],
        +	["punctuation", ")"],
        +	["punctuation", ":"],
        +
        +	"\r\n\tConsole",
        +	["punctuation", "."],
        +	["function", "WriteLine"],
        +	["punctuation", "("],
        +	"x",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["operator", "<"],
        +	["number", "2"],
        +	["punctuation", ":"],
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["keyword", "case"],
        +	["number", "0"],
        +	["keyword", "or"],
        +	["number", "1"],
        +	["keyword", "or"],
        +	["number", "2"],
        +	["keyword", "or"],
        +	["number", "3"],
        +	["keyword", "or"],
        +	["number", "4"],
        +	["keyword", "or"],
        +	["number", "5"],
        +	["punctuation", ":"],
        +	["keyword", "break"],
        +	["punctuation", ";"],
        +
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" x ",
        +	["operator", "="],
        +	" b ",
        +	["keyword", "switch"],
        +	["punctuation", "{"],
        +	["operator", "<"],
        +	["number", "100"],
        +	["operator", "=>"],
        +	["number", "0"],
        +	["punctuation", ","],
        +	["number", "100"],
        +	["operator", "=>"],
        +	["number", "1"],
        +	["punctuation", ","],
        +	["number", "101"],
        +	["operator", "=>"],
        +	["number", "2"],
        +	["punctuation", ","],
        +	["operator", ">"],
        +	["number", "101"],
        +	["operator", "=>"],
        +	["number", "3"],
        +	["punctuation", "}"],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for switch statements and expressions.
        diff --git a/tests/languages/csharp/type-expression_feature.test b/tests/languages/csharp/type-expression_feature.test
        new file mode 100644
        index 0000000000..1ef9e28e74
        --- /dev/null
        +++ b/tests/languages/csharp/type-expression_feature.test
        @@ -0,0 +1,63 @@
        +default(int)
        +default(Foo)
        +typeof(Foo)
        +typeof((int, long))
        +default(Foo>)
        +sizeof(int)
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "default"],
        +	["punctuation", "("],
        +	["type-expression", [
        +		["keyword", "int"]
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "default"],
        +	["punctuation", "("],
        +	["type-expression", [
        +		"Foo"
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "typeof"],
        +	["punctuation", "("],
        +	["type-expression", [
        +		"Foo"
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "typeof"],
        +	["punctuation", "("],
        +	["type-expression", [
        +		["punctuation", "("],
        +		["keyword", "int"],
        +		["punctuation", ","],
        +		["keyword", "long"],
        +		["punctuation", ")"]
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "default"],
        +	["punctuation", "("],
        +	["type-expression", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"Bar",
        +		["punctuation", ","],
        +		" IFoo",
        +		["punctuation", "<"],
        +		"Bar",
        +		["punctuation", ">"],
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", ")"],
        +	["keyword", "sizeof"],
        +	["punctuation", "("],
        +	["type-expression", [
        +		["keyword", "int"]
        +	]],
        +	["punctuation", ")"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for class names of type expressions.
        diff --git a/tests/languages/csharp/type-list_feature.test b/tests/languages/csharp/type-list_feature.test
        new file mode 100644
        index 0000000000..bd01217e05
        --- /dev/null
        +++ b/tests/languages/csharp/type-list_feature.test
        @@ -0,0 +1,300 @@
        +class Foo : Bar, T>, IBar, IFoo
        +	where T : class, IBar, IFoo {}
        +
        +public class Foo : IBar {}
        +
        +public delegate ErrorCode GetInfoMethod(H handle, A value, I paramName,
        +	Size_t paramValueSize, IntPtr paramValue, out Size_t paramValueSizeRet)
        +	where H : unmanaged, IInfoHandle where A : unmanaged where I : unmanaged, Enum;
        +
        +// the "new()" constraint
        +void Foo()
        +	where A : IFoo, new()
        +	where B : new(), IFoo;
        +
        +// records are kinda difficult to handle
        +public abstract record Person(string FirstName, string LastName);
        +public record Teacher(string FirstName, string LastName, int Grade)
        +	: Person(FirstName, LastName), IFoo;
        +public record Student(string FirstName, string LastName, int Grade)
        +	: Person(FirstName, LastName);
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "class"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "<"],
        +		"T",
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["class-name", [
        +			"Bar",
        +			["punctuation", "<"],
        +			"IList",
        +			["punctuation", "<"],
        +			"Bar",
        +			["punctuation", ">"],
        +			["punctuation", ","],
        +			" T",
        +			["punctuation", ">"]
        +		]],
        +		["punctuation", ","],
        +		["class-name", [
        +			"IBar",
        +			["punctuation", "<"],
        +			"Bar",
        +			["punctuation", ","],
        +			" T",
        +			["punctuation", ">"]
        +		]],
        +		["punctuation", ","],
        +		["class-name", ["IFoo"]]
        +	]],
        +
        +	["keyword", "where"],
        +	["class-name", "T"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "class"],
        +		["punctuation", ","],
        +		["class-name", [
        +			"IBar",
        +			["punctuation", "<"],
        +			"IFoo",
        +			["punctuation", ">"]
        +		]],
        +		["punctuation", ","],
        +		["class-name", [
        +			"IFoo",
        +			["punctuation", "<"],
        +			"Bar",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "public"],
        +	["keyword", "class"],
        +	["class-name", ["Foo"]],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["class-name", [
        +			"IBar",
        +			["punctuation", "<"],
        +			["keyword", "int"],
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "{"],
        +	["punctuation", "}"],
        +
        +	["keyword", "public"],
        +	["keyword", "delegate"],
        +	["return-type", ["ErrorCode"]],
        +	["generic-method", [
        +		["function", "GetInfoMethod"],
        +		["generic", [
        +			["punctuation", "<"],
        +			"H",
        +			["punctuation", ","],
        +			" A",
        +			["punctuation", ","],
        +			" I",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["class-name", ["H"]],
        +	" handle",
        +	["punctuation", ","],
        +	["class-name", ["A"]],
        +	["keyword", "value"],
        +	["punctuation", ","],
        +	["class-name", ["I"]],
        +	" paramName",
        +	["punctuation", ","],
        +
        +	["class-name", ["Size_t"]],
        +	" paramValueSize",
        +	["punctuation", ","],
        +	["class-name", ["IntPtr"]],
        +	" paramValue",
        +	["punctuation", ","],
        +	["keyword", "out"],
        +	["class-name", ["Size_t"]],
        +	" paramValueSizeRet",
        +	["punctuation", ")"],
        +
        +	["keyword", "where"],
        +	["class-name", "H"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "unmanaged"],
        +		["punctuation", ","],
        +		["class-name", [
        +			"IInfoHandle",
        +			["punctuation", "<"],
        +			"A",
        +			["punctuation", ","],
        +			" I",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["keyword", "where"],
        +	["class-name", "A"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "unmanaged"]
        +	]],
        +	["keyword", "where"],
        +	["class-name", "I"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "unmanaged"],
        +		["punctuation", ","],
        +		["class-name", ["Enum"]]
        +	]],
        +	["punctuation", ";"],
        +
        +	["comment", "// the \"new()\" constraint"],
        +
        +	["return-type", [
        +		["keyword", "void"]
        +	]],
        +	["generic-method", [
        +		["function", "Foo"],
        +		["generic", [
        +			["punctuation", "<"],
        +			"A",
        +			["punctuation", ","],
        +			" B",
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", "("],
        +	["punctuation", ")"],
        +
        +	["keyword", "where"],
        +	["class-name", "A"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["class-name", ["IFoo"]],
        +		["punctuation", ","],
        +		["keyword", "new"],
        +		["punctuation", "("],
        +		["punctuation", ")"]
        +	]],
        +
        +	["keyword", "where"],
        +	["class-name", "B"],
        +	["punctuation", ":"],
        +	["type-list", [
        +		["keyword", "new"],
        +		["punctuation", "("],
        +		["punctuation", ")"],
        +		["punctuation", ","],
        +		["class-name", ["IFoo"]]
        +	]],
        +	["punctuation", ";"],
        +
        +	["comment", "// records are kinda difficult to handle"],
        +
        +	["keyword", "public"],
        +	["keyword", "abstract"],
        +	["keyword", "record"],
        +	["class-name", ["Person"]],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
        +	" FirstName",
        +	["punctuation", ","],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
        +	" LastName",
        +	["punctuation", ")"],
        +	["punctuation", ";"],
        +
        +	["keyword", "public"],
        +	["keyword", "record"],
        +	["class-name", ["Teacher"]],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
        +	" FirstName",
        +	["punctuation", ","],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
        +	" LastName",
        +	["punctuation", ","],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" Grade",
        +	["punctuation", ")"],
        +
        +	["punctuation", ":"],
        +	["type-list", [
        +		["class-name", ["Person"]],
        +		["record-arguments", [
        +			["punctuation", "("],
        +			"FirstName",
        +			["punctuation", ","],
        +			" LastName",
        +			["punctuation", ")"]
        +		]],
        +		["punctuation", ","],
        +		["class-name", [
        +			"IFoo",
        +			["punctuation", "<"],
        +			["keyword", "int"],
        +			["punctuation", ">"]
        +		]]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "public"],
        +	["keyword", "record"],
        +	["class-name", ["Student"]],
        +	["punctuation", "("],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
        +	" FirstName",
        +	["punctuation", ","],
        +	["class-name", [
        +		["keyword", "string"]
        +	]],
        +	" LastName",
        +	["punctuation", ","],
        +	["class-name", [
        +		["keyword", "int"]
        +	]],
        +	" Grade",
        +	["punctuation", ")"],
        +
        +	["punctuation", ":"],
        +	["type-list", [
        +		["class-name", ["Person"]],
        +		["record-arguments", [
        +			["punctuation", "("],
        +			"FirstName",
        +			["punctuation", ","],
        +			" LastName",
        +			["punctuation", ")"]
        +		]]
        +	]],
        +	["punctuation", ";"]
        +]
        +
        +----------------------------------------------------
        +
        +Checks for type lists of inheritance or generic constraints.
        diff --git a/tests/languages/csharp/using-directive_feature.test b/tests/languages/csharp/using-directive_feature.test
        new file mode 100644
        index 0000000000..aa0723e828
        --- /dev/null
        +++ b/tests/languages/csharp/using-directive_feature.test
        @@ -0,0 +1,81 @@
        +using System;
        +using System.IO;
        +using static System.Math;
        +using static Foo.Bar.FooBar;
        +using FooBar = Foo.Bar;
        +using FooBar = Foo.Bar.FooBar;
        +
        +----------------------------------------------------
        +
        +[
        +	["keyword", "using"],
        +	["namespace", ["System"]],
        +	["punctuation", ";"],
        +
        +	["keyword", "using"],
        +	["namespace", [
        +		"System",
        +		["punctuation", "."],
        +		"IO"
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "using"],
        +	["keyword", "static"],
        +	["class-name", [
        +		"System",
        +		["punctuation", "."],
        +		"Math"
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "using"],
        +	["keyword", "static"],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "."],
        +		"Bar",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"],
        +		["punctuation", "."],
        +		"FooBar",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "using"],
        +	["class-name", "FooBar"],
        +	["operator", "="],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "."],
        +		"Bar"
        +	]],
        +	["punctuation", ";"],
        +
        +	["keyword", "using"],
        +	["class-name", "FooBar"],
        +	["operator", "="],
        +	["class-name", [
        +		"Foo",
        +		["punctuation", "."],
        +		"Bar",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"],
        +		["punctuation", "."],
        +		"FooBar",
        +		["punctuation", "<"],
        +		"IFoo",
        +		["punctuation", ">"]
        +	]],
        +	["punctuation", ";"]
        +]
        +
        +
        +----------------------------------------------------
        +
        +Checks for using directives.
        diff --git a/tests/languages/cshtml/block_feature.test b/tests/languages/cshtml/block_feature.test
        new file mode 100644
        index 0000000000..59bd8b05de
        --- /dev/null
        +++ b/tests/languages/cshtml/block_feature.test
        @@ -0,0 +1,899 @@
        +@for (var i = 0; i < people.Length; i++)
        +{
        +    var person = people[i];
        +    Name: @person.Name
        +}
        +
        +@if (value % 2 == 0)
        +{
        +    

        The value was even.

        +} + +@if (value % 2 == 0) +{ +

        The value was even.

        +} +else if (value >= 1337) +{ +

        The value is large.

        +} +else +{ +

        The value is odd and small.

        +} + +@switch (value) +{ + case 1: +

        The value is 1!

        + break; + case 1337: +

        Your number is 1337!

        + break; + default: +

        Your number wasn't 1 or 1337.

        + break; +} + +@for (var i = 0; i < people.Length; i++) +{ + var person = people[i]; +

        Name: @person.Name

        +

        Age: @person.Age

        +} + +@foreach (var person in people) +{ +

        Name: @person.Name

        +

        Age: @person.Age

        +} + +@{ var i = 0; } +@while (i < people.Length) +{ + var person = people[i]; +

        Name: @person.Name

        +

        Age: @person.Age

        + + i++; +} + +@{ var i = 0; } +@do +{ + var person = people[i]; +

        Name: @person.Name

        +

        Age: @person.Age

        + + i++; +} while (i < people.Length); + +@using (Html.BeginForm()) +{ +
        + Email: + +
        +} + +@try +{ + throw new InvalidOperationException("You did something invalid."); +} +catch (Exception ex) +{ +

        The exception message: @ex.Message

        +} +finally +{ +

        The finally statement.

        +} + +@lock (SomeLock) +{ + // Do critical section work +} + +---------------------------------------------------- + +[ + ["block", [ + ["keyword", "@for"], + ["csharp", [ + ["punctuation", "("], + ["class-name", [ + ["keyword", "var"] + ]], + " i ", + ["operator", "="], + ["number", "0"], + ["punctuation", ";"], + " i ", + ["operator", "<"], + " people", + ["punctuation", "."], + "Length", + ["punctuation", ";"], + " i", + ["operator", "++"], + ["punctuation", ")"], + + ["punctuation", "{"], + + ["class-name", [ + ["keyword", "var"] + ]], + " person ", + ["operator", "="], + " people", + ["punctuation", "["], + "i", + ["punctuation", "]"], + ["punctuation", ";"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "text" + ]], + ["punctuation", ">"] + ]], + "Name: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Name" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@if"], + ["csharp", [ + ["punctuation", "("], + ["keyword", "value"], + ["operator", "%"], + ["number", "2"], + ["operator", "=="], + ["number", "0"], + ["punctuation", ")"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "The value was even.", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@if"], + ["csharp", [ + ["punctuation", "("], + ["keyword", "value"], + ["operator", "%"], + ["number", "2"], + ["operator", "=="], + ["number", "0"], + ["punctuation", ")"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "The value was even.", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"], + + ["keyword", "else"], + ["keyword", "if"], + ["punctuation", "("], + ["keyword", "value"], + ["operator", ">="], + ["number", "1337"], + ["punctuation", ")"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "The value is large.", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"], + + ["keyword", "else"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "The value is odd and small.", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@switch"], + ["csharp", [ + ["punctuation", "("], + ["keyword", "value"], + ["punctuation", ")"], + + ["punctuation", "{"], + + ["keyword", "case"], + ["number", "1"], + ["punctuation", ":"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "The value is 1!", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["keyword", "break"], + ["punctuation", ";"], + + ["keyword", "case"], + ["number", "1337"], + ["punctuation", ":"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Your number is 1337!", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["keyword", "break"], + ["punctuation", ";"], + + ["keyword", "default"], + ["punctuation", ":"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Your number wasn't 1 or 1337.", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["keyword", "break"], + ["punctuation", ";"], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@for"], + ["csharp", [ + ["punctuation", "("], + ["class-name", [ + ["keyword", "var"] + ]], + " i ", + ["operator", "="], + ["number", "0"], + ["punctuation", ";"], + " i ", + ["operator", "<"], + " people", + ["punctuation", "."], + "Length", + ["punctuation", ";"], + " i", + ["operator", "++"], + ["punctuation", ")"], + + ["punctuation", "{"], + + ["class-name", [ + ["keyword", "var"] + ]], + " person ", + ["operator", "="], + " people", + ["punctuation", "["], + "i", + ["punctuation", "]"], + ["punctuation", ";"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Name: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Name" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Age: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Age" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@foreach"], + ["csharp", [ + ["punctuation", "("], + ["class-name", [ + ["keyword", "var"] + ]], + " person ", + ["keyword", "in"], + " people", + ["punctuation", ")"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Name: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Name" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Age: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Age" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + ["class-name", [ + ["keyword", "var"] + ]], + " i ", + ["operator", "="], + ["number", "0"], + ["punctuation", ";"], + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@while"], + ["csharp", [ + ["punctuation", "("], + "i ", + ["operator", "<"], + " people", + ["punctuation", "."], + "Length", + ["punctuation", ")"], + + ["punctuation", "{"], + + ["class-name", [ + ["keyword", "var"] + ]], + " person ", + ["operator", "="], + " people", + ["punctuation", "["], + "i", + ["punctuation", "]"], + ["punctuation", ";"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Name: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Name" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Age: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Age" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + "\r\n\r\n i", ["operator", "++"], ["punctuation", ";"], + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + ["class-name", [ + ["keyword", "var"] + ]], + " i ", + ["operator", "="], + ["number", "0"], + ["punctuation", ";"], + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@do"], + + ["csharp", [ + ["punctuation", "{"], + + ["class-name", [ + ["keyword", "var"] + ]], + " person ", + ["operator", "="], + " people", + ["punctuation", "["], + "i", + ["punctuation", "]"], + ["punctuation", ";"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Name: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Name" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Age: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "person", + ["punctuation", "."], + "Age" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + "\r\n\r\n i", + ["operator", "++"], + ["punctuation", ";"], + + ["punctuation", "}"], + ["keyword", "while"], + ["punctuation", "("], + "i ", + ["operator", "<"], + " people", + ["punctuation", "."], + "Length", + ["punctuation", ")"], + ["punctuation", ";"] + ]] + ]], + + ["block", [ + ["keyword", "@using"], + ["csharp", [ + ["punctuation", "("], + "Html", + ["punctuation", "."], + ["function", "BeginForm"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ")"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "div" + ]], + ["punctuation", ">"] + ]], + + "\r\n Email: ", + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "input" + ]], + ["attr-name", ["type"]], + ["attr-value", [ + ["punctuation", "="], + ["punctuation", "\""], + "email", + ["punctuation", "\""] + ]], + ["attr-name", ["id"]], + ["attr-value", [ + ["punctuation", "="], + ["punctuation", "\""], + "Email", + ["punctuation", "\""] + ]], + ["attr-name", ["value"]], + ["attr-value", [ + ["punctuation", "="], + ["punctuation", "\""], + ["punctuation", "\""] + ]], + ["punctuation", ">"] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "button" + ]], + ["punctuation", ">"] + ]], + "Register", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@try"], + + ["csharp", [ + ["punctuation", "{"], + + ["keyword", "throw"], + ["keyword", "new"], + ["constructor-invocation", ["InvalidOperationException"]], + ["punctuation", "("], + ["string", "\"You did something invalid.\""], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["keyword", "catch"], + ["punctuation", "("], + ["class-name", ["Exception"]], + " ex", + ["punctuation", ")"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "The exception message: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "ex", + ["punctuation", "."], + "Message" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"], + + ["keyword", "finally"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "The finally statement.", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@lock"], + ["csharp", [ + ["punctuation", "("], "SomeLock", ["punctuation", ")"], + ["punctuation", "{"], + ["comment", "// Do critical section work"], + ["punctuation", "}"] + ]] + ]] +] diff --git a/tests/languages/cshtml/code-block_feature.test b/tests/languages/cshtml/code-block_feature.test new file mode 100644 index 0000000000..469d79c616 --- /dev/null +++ b/tests/languages/cshtml/code-block_feature.test @@ -0,0 +1,327 @@ +@{ + var quote = "The future depends on what you do today. - Mahatma Gandhi"; +} + +

        @quote

        + +@{ + quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr."; +} + +

        @quote

        + +@{ + void RenderName(string name) + { +

        Name: @name

        + } + + RenderName("Mahatma Gandhi"); + RenderName("Martin Luther King, Jr."); +} + +@{ + var inCSharp = true; +

        Now in HTML, was in C# @inCSharp

        +} + +@{ + Func petTemplate = @

        You have a pet named @item.Name.

        ; + + var pets = new List + { + new Pet { Name = "Rin Tin Tin" }, + new Pet { Name = "Mr. Bigglesworth" }, + new Pet { Name = "K-9" } + }; +} + +---------------------------------------------------- + +[ + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + + ["class-name", [ + ["keyword", "var"] + ]], + " quote ", + ["operator", "="], + ["string", "\"The future depends on what you do today. - Mahatma Gandhi\""], + ["punctuation", ";"], + + ["punctuation", "}"] + ]] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", ["quote"]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + + "\r\n quote ", + ["operator", "="], + ["string", "\"Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.\""], + ["punctuation", ";"], + + ["punctuation", "}"] + ]] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", ["quote"]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + + ["return-type", [ + ["keyword", "void"] + ]], + ["function", "RenderName"], + ["punctuation", "("], + ["class-name", [ + ["keyword", "string"] + ]], + " name", + ["punctuation", ")"], + + ["punctuation", "{"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Name: ", + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "strong" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", ["name"]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"], + + ["function", "RenderName"], + ["punctuation", "("], + ["string", "\"Mahatma Gandhi\""], + ["punctuation", ")"], + ["punctuation", ";"], + + ["function", "RenderName"], + ["punctuation", "("], + ["string", "\"Martin Luther King, Jr.\""], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + + ["class-name", [ + ["keyword", "var"] + ]], + " inCSharp ", + ["operator", "="], + ["boolean", "true"], + ["punctuation", ";"], + + ["html", [ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Now in HTML, was in C# ", + ["value", [ + ["keyword", "@"], + ["csharp", ["inCSharp"]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + + ["punctuation", "}"] + ]] + ]], + + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + + ["class-name", [ + "Func", + ["punctuation", "<"], + ["keyword", "dynamic"], + ["punctuation", ","], + ["keyword", "object"], + ["punctuation", ">"] + ]], + " petTemplate ", + ["operator", "="], + ["html", [ + ["delegate-operator", "@"], + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "You have a pet named ", + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "strong" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", [ + "item", + ["punctuation", "."], + "Name" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + ".", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] + ]], + ["punctuation", ";"], + + ["class-name", [ + ["keyword", "var"] + ]], + " pets ", + ["operator", "="], + ["keyword", "new"], + ["constructor-invocation", [ + "List", + ["punctuation", "<"], + "Pet", + ["punctuation", ">"] + ]], + + ["punctuation", "{"], + + ["keyword", "new"], + ["constructor-invocation", ["Pet"]], + ["punctuation", "{"], + " Name ", + ["operator", "="], + ["string", "\"Rin Tin Tin\""], + ["punctuation", "}"], + ["punctuation", ","], + + ["keyword", "new"], + ["constructor-invocation", ["Pet"]], + ["punctuation", "{"], + " Name ", + ["operator", "="], + ["string", "\"Mr. Bigglesworth\""], + ["punctuation", "}"], + ["punctuation", ","], + + ["keyword", "new"], + ["constructor-invocation", ["Pet"]], + ["punctuation", "{"], + " Name ", + ["operator", "="], + ["string", "\"K-9\""], + ["punctuation", "}"], + + ["punctuation", "}"], + ["punctuation", ";"], + + ["punctuation", "}"] + ]] + ]] +] diff --git a/tests/languages/cshtml/comment_feature.test b/tests/languages/cshtml/comment_feature.test new file mode 100644 index 0000000000..a3eb706dc7 --- /dev/null +++ b/tests/languages/cshtml/comment_feature.test @@ -0,0 +1,30 @@ +@{ + /* C# comment */ + // Another C# comment +} + + +@* + @{ + /* C# comment */ + // Another C# comment + } + +*@ + +---------------------------------------------------- + +[ + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + ["comment", "/* C# comment */"], + ["comment", "// Another C# comment"], + ["punctuation", "}"] + ]] + ]], + ["comment", ""], + + ["razor-comment", "@*\r\n @{\r\n /* C# comment */\r\n // Another C# comment\r\n }\r\n \r\n*@"] +] diff --git a/tests/languages/cshtml/value_feature.test b/tests/languages/cshtml/value_feature.test new file mode 100644 index 0000000000..4e5848295f --- /dev/null +++ b/tests/languages/cshtml/value_feature.test @@ -0,0 +1,346 @@ +

        @@Username

        +

        @Username

        + +

        @DateTime.Now

        +

        @DateTime.IsLeapYear(2016)

        + +

        @await DoSomething("hello", "world")

        + +

        @GenericMethod()

        + +

        Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))

        +

        Last week: @DateTime.Now - TimeSpan.FromDays(7)

        +

        Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)

        + +@{ + var joe = new Person("Joe", 33); +} + +

        Age@(joe.Age)

        + +

        @(GenericMethod())

        + +@("Hello World") + +@Html.Raw("Hello World") + +---------------------------------------------------- + +[ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "@@Username", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", ["Username"]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", [ + "DateTime", + ["punctuation", "."], + "Now" + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", [ + "DateTime", + ["punctuation", "."], + ["function", "IsLeapYear"], + ["punctuation", "("], + ["number", "2016"], + ["punctuation", ")"] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", [ + ["keyword", "await"], + ["function", "DoSomething"], + ["punctuation", "("], + ["string", "\"hello\""], + ["punctuation", ","], + ["string", "\"world\""], + ["punctuation", ")"] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", [ + ["generic-method", [ + ["function", "GenericMethod"], + ["generic", [ + ["punctuation", "<"], + ["keyword", "int"], + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Last week this time: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "("], + "DateTime", + ["punctuation", "."], + "Now ", + ["operator", "-"], + " TimeSpan", + ["punctuation", "."], + ["function", "FromDays"], + ["punctuation", "("], + ["number", "7"], + ["punctuation", ")"], + ["punctuation", ")"] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Last week: ", + ["value", [ + ["keyword", "@"], + ["csharp", [ + "DateTime", + ["punctuation", "."], + "Now" + ]] + ]], + " - TimeSpan.FromDays(7)", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)", + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["block", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "{"], + + ["class-name", [ + ["keyword", "var"] + ]], + " joe ", + ["operator", "="], + ["keyword", "new"], + ["constructor-invocation", ["Person"]], + ["punctuation", "("], + ["string", "\"Joe\""], + ["punctuation", ","], + ["number", "33"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"] + ]] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + "Age", + ["value", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "("], + "joe", + ["punctuation", "."], + "Age", + ["punctuation", ")"] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "p" + ]], + ["punctuation", ">"] + ]], + ["value", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "("], + ["generic-method", [ + ["function", "GenericMethod"], + ["generic", [ + ["punctuation", "<"], + ["keyword", "int"], + ["punctuation", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ")"] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["value", [ + ["keyword", "@"], + ["csharp", [ + ["punctuation", "("], + ["string", "\"Hello World\""], + ["punctuation", ")"] + ]] + ]], + + ["value", [ + ["keyword", "@"], + ["csharp", [ + "Html", + ["punctuation", "."], + ["function", "Raw"], + ["punctuation", "("], + ["string", "\"Hello World\""], + ["punctuation", ")"] + ]] + ]] +] diff --git a/tests/languages/csp/directive_no_value_feature.test b/tests/languages/csp/directive_no_value_feature.test index 5ae927df77..a9fce90009 100644 --- a/tests/languages/csp/directive_no_value_feature.test +++ b/tests/languages/csp/directive_no_value_feature.test @@ -3,7 +3,8 @@ upgrade-insecure-requests; ---------------------------------------------------- [ - ["directive", "upgrade-insecure-requests;"] + ["directive", "upgrade-insecure-requests"], + ["punctuation", ";"] ] ---------------------------------------------------- diff --git a/tests/languages/csp/directive_with_source_expression_feature.test b/tests/languages/csp/directive_with_source_expression_feature.test index fc059f4246..747dcc6a3b 100644 --- a/tests/languages/csp/directive_with_source_expression_feature.test +++ b/tests/languages/csp/directive_with_source_expression_feature.test @@ -1,10 +1,29 @@ -script-src example.com; +input-protection tolerance=50; input-protection-clip before=60; input-protection-selectors div; policy-uri https://example.com; script-src example.com; script-src-attr 'none'; style-src-elem 'none'; ---------------------------------------------------- [ - ["directive", "script-src "], - "example.com;" + ["directive", "input-protection"], + " tolerance=50", + ["punctuation", ";"], + ["directive", "input-protection-clip"], + " before=60", + ["punctuation", ";"], + ["directive", "input-protection-selectors"], + " div", + ["punctuation", ";"], + ["directive", "policy-uri"], + ["host", ["https://example.com"]], + ["punctuation", ";"], + ["directive", "script-src"], + ["host", ["example.com"]], + ["punctuation", ";"], + ["directive", "script-src-attr"], + ["none", "'none'"], + ["punctuation", ";"], + ["directive", "style-src-elem"], + ["none", "'none'"], + ["punctuation", ";"] ] ---------------------------------------------------- diff --git a/tests/languages/csp/hash_feature.test b/tests/languages/csp/hash_feature.test new file mode 100644 index 0000000000..fd3b130cd2 --- /dev/null +++ b/tests/languages/csp/hash_feature.test @@ -0,0 +1,8 @@ +style-src 'sha256-EpOpN/ahUF6jhWShDUdy+NvvtaGcu5F7qM6+x2mfkh4=' + +---------------------------------------------------- + +[ + ["directive", "style-src"], + ["hash", "'sha256-EpOpN/ahUF6jhWShDUdy+NvvtaGcu5F7qM6+x2mfkh4='"] +] diff --git a/tests/languages/csp/host_feature.test b/tests/languages/csp/host_feature.test new file mode 100644 index 0000000000..9bc19e5c12 --- /dev/null +++ b/tests/languages/csp/host_feature.test @@ -0,0 +1,46 @@ +default-src trusted.com *.trusted.com; +img-src *; +media-src media1.com media2.com; +script-src userscripts.example.com; +frame-ancestors https://alice https://bob; +frame-ancestors https://example.com/; + +sandbox allow-scripts; + +---------------------------------------------------- + +[ + ["directive", "default-src"], + ["host", ["trusted.com"]], + ["host", [ + ["important", "*"], + ".trusted.com" + ]], + ["punctuation", ";"], + + ["directive", "img-src"], + ["host", [ + ["important", "*"] + ]], + ["punctuation", ";"], + + ["directive", "media-src"], + ["host", ["media1.com"]], + ["host", ["media2.com"]], + ["punctuation", ";"], + + ["directive", "script-src"], + ["host", ["userscripts.example.com"]], + ["punctuation", ";"], + + ["directive", "frame-ancestors"], + ["host", ["https://alice"]], + ["host", ["https://bob"]], + ["punctuation", ";"], + + ["directive", "frame-ancestors"], + ["host", ["https://example.com/"]], + ["punctuation", ";"], + + ["directive", "sandbox"], " allow-scripts", ["punctuation", ";"] +] diff --git a/tests/languages/csp/issue2661.test b/tests/languages/csp/issue2661.test new file mode 100644 index 0000000000..6eb7c5f519 --- /dev/null +++ b/tests/languages/csp/issue2661.test @@ -0,0 +1,14 @@ +default-src-is-a-fake; fake-default-src; + +---------------------------------------------------- + +[ + "default-src-is-a-fake", + ["punctuation", ";"], + " fake-default-src", + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for directive names with adjacent hyphens. diff --git a/tests/languages/csp/keyword_safe_feature.html.test b/tests/languages/csp/keyword_safe_feature.html.test new file mode 100644 index 0000000000..db3f36f6b2 --- /dev/null +++ b/tests/languages/csp/keyword_safe_feature.html.test @@ -0,0 +1,16 @@ +default-src 'report-sample'; +style-src 'self' 'strict-dynamic'; + +---------------------------------------------------- + +default-src +'report-sample' +; +style-src +'self' +'strict-dynamic' +; + +---------------------------------------------------- + +Checks for source expressions classified as safe. diff --git a/tests/languages/csp/keyword_unsafe_feature.html.test b/tests/languages/csp/keyword_unsafe_feature.html.test new file mode 100644 index 0000000000..227bec6b5e --- /dev/null +++ b/tests/languages/csp/keyword_unsafe_feature.html.test @@ -0,0 +1,20 @@ +navigate-to 'unsafe-allow-redirects'; +script-src 'unsafe-dynamic' 'unsafe-eval' 'unsafe-hash-attributes' 'unsafe-hashed-attributes' 'unsafe-hashes' 'unsafe-inline'; + +---------------------------------------------------- + +navigate-to +'unsafe-allow-redirects' +; +script-src +'unsafe-dynamic' +'unsafe-eval' +'unsafe-hash-attributes' +'unsafe-hashed-attributes' +'unsafe-hashes' +'unsafe-inline' +; + +---------------------------------------------------- + +Checks for source expressions classified as unsafe. diff --git a/tests/languages/csp/nonce_feature.test b/tests/languages/csp/nonce_feature.test new file mode 100644 index 0000000000..dc0e4a33ee --- /dev/null +++ b/tests/languages/csp/nonce_feature.test @@ -0,0 +1,9 @@ +style-src 'nonce-yeah'; + +---------------------------------------------------- + +[ + ["directive", "style-src"], + ["nonce", "'nonce-yeah'"], + ["punctuation", ";"] +] diff --git a/tests/languages/csp/none_feature.test b/tests/languages/csp/none_feature.test new file mode 100644 index 0000000000..7b4e837d31 --- /dev/null +++ b/tests/languages/csp/none_feature.test @@ -0,0 +1,8 @@ +sandbox 'none' + +---------------------------------------------------- + +[ + ["directive", "sandbox"], + ["none", "'none'"] +] diff --git a/tests/languages/csp/safe_feature.test b/tests/languages/csp/safe_feature.test deleted file mode 100644 index af31d1ac4d..0000000000 --- a/tests/languages/csp/safe_feature.test +++ /dev/null @@ -1,19 +0,0 @@ -default-src 'none'; style-src 'self' 'strict-dynamic' 'nonce-yeah' 'sha256-EpOpN/ahUF6jhWShDUdy+NvvtaGcu5F7qM6+x2mfkh4='; - ----------------------------------------------------- - -[ - ["directive", "default-src "], - ["safe", "'none'"], - "; ", - ["directive", "style-src "], - ["safe", "'self'"], - ["safe", "'strict-dynamic'"], - ["safe", "'nonce-yeah'"], - ["safe", "'sha256-EpOpN/ahUF6jhWShDUdy+NvvtaGcu5F7qM6+x2mfkh4='"], - ";" -] - ----------------------------------------------------- - -Checks for source expressions classified as safe. diff --git a/tests/languages/csp/scheme_feature.test b/tests/languages/csp/scheme_feature.test new file mode 100644 index 0000000000..5807a8c5dd --- /dev/null +++ b/tests/languages/csp/scheme_feature.test @@ -0,0 +1,10 @@ +default-src https: 'unsafe-inline' 'unsafe-eval' + +---------------------------------------------------- + +[ + ["directive", "default-src"], + ["scheme", "https:"], + ["keyword", "'unsafe-inline'"], + ["keyword", "'unsafe-eval'"] +] diff --git a/tests/languages/csp/unsafe_feature.test b/tests/languages/csp/unsafe_feature.test deleted file mode 100644 index 1fe7e478e3..0000000000 --- a/tests/languages/csp/unsafe_feature.test +++ /dev/null @@ -1,15 +0,0 @@ -script-src 'unsafe-inline' 'unsafe-eval' 'unsafe-hashed-attributes'; - ----------------------------------------------------- - -[ - ["directive", "script-src "], - ["unsafe", "'unsafe-inline'"], - ["unsafe", "'unsafe-eval'"], - ["unsafe", "'unsafe-hashed-attributes'"], - ";" -] - ----------------------------------------------------- - -Checks for source expressions classified as unsafe. diff --git a/tests/languages/css!+css-extras/atrule_selector-function-argument_feature.test b/tests/languages/css!+css-extras/atrule_selector-function-argument_feature.test new file mode 100644 index 0000000000..e361b23a64 --- /dev/null +++ b/tests/languages/css!+css-extras/atrule_selector-function-argument_feature.test @@ -0,0 +1,26 @@ +@supports selector(::-webkit-foo) { + /* style to apply when the `::-webkit-foo` selector is actually supported, + * instead of just being parsed as matching nothing because of Selectors 4 + * § Appendix B: https://drafts.csswg.org/selectors-4/#compat */ +} + +---------------------------------------------------- + +[ + ["atrule", [ + ["rule", "@supports"], + ["function", "selector"], + ["punctuation", "("], + ["selector-function-argument", [ + ["pseudo-element", "::-webkit-foo"] + ]], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["comment", "/* style to apply when the `::-webkit-foo` selector is actually supported,\r\n\t * instead of just being parsed as matching nothing because of Selectors 4\r\n\t * § Appendix B: https://drafts.csswg.org/selectors-4/#compat */"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks for the selector function in @supports rules. diff --git a/tests/languages/css!+css-extras/color_feature.test b/tests/languages/css!+css-extras/color_feature.test new file mode 100644 index 0000000000..261b6690e0 --- /dev/null +++ b/tests/languages/css!+css-extras/color_feature.test @@ -0,0 +1,341 @@ +AliceBlue +AntiqueWhite +Aqua +Aquamarine +Azure +Beige +Bisque +Black +BlanchedAlmond +Blue +BlueViolet +Brown +BurlyWood +CadetBlue +Chartreuse +Chocolate +Coral +CornflowerBlue +Cornsilk +Crimson +Cyan +DarkBlue +DarkCyan +DarkGoldenRod +DarkGrey +DarkGreen +DarkKhaki +DarkMagenta +DarkOliveGreen +DarkOrange +DarkOrchid +DarkRed +DarkSalmon +DarkSeaGreen +DarkSlateBlue +DarkSlateGrey +DarkTurquoise +DarkViolet +DeepPink +DeepSkyBlue +DimGrey +DodgerBlue +FireBrick +FloralWhite +ForestGreen +Fuchsia +Gainsboro +GhostWhite +Gold +GoldenRod +Grey +Green +GreenYellow +HoneyDew +HotPink +IndianRed +Indigo +Ivory +Khaki +Lavender +LavenderBlush +LawnGreen +LemonChiffon +LightBlue +LightCoral +LightCyan +LightGoldenRodYellow +LightGrey +LightGreen +LightPink +LightSalmon +LightSeaGreen +LightSkyBlue +LightSlateGrey +LightSteelBlue +LightYellow +Lime +LimeGreen +Linen +Magenta +Maroon +MediumAquaMarine +MediumBlue +MediumOrchid +MediumPurple +MediumSeaGreen +MediumSlateBlue +MediumSpringGreen +MediumTurquoise +MediumVioletRed +MidnightBlue +MintCream +MistyRose +Moccasin +NavajoWhite +Navy +OldLace +Olive +OliveDrab +Orange +OrangeRed +Orchid +PaleGoldenRod +PaleGreen +PaleTurquoise +PaleVioletRed +PapayaWhip +PeachPuff +Peru +Pink +Plum +PowderBlue +Purple +Red +RosyBrown +RoyalBlue +SaddleBrown +Salmon +SandyBrown +SeaGreen +SeaShell +Sienna +Silver +SkyBlue +SlateBlue +SlateGrey +Snow +SpringGreen +SteelBlue +Tan +Teal +Thistle +Tomato +Transparent +Turquoise +Violet +Wheat +White +WhiteSmoke +Yellow +YellowGreen + +rgb(0,0,0) +rgba(0 , 255 , 0, 0.123) +hsl(170, 50%, 45%) +hsla(120,100%,50%,0.3) + +---------------------------------------------------- + +[ + ["color", "AliceBlue"], + ["color", "AntiqueWhite"], + ["color", "Aqua"], + ["color", "Aquamarine"], + ["color", "Azure"], + ["color", "Beige"], + ["color", "Bisque"], + ["color", "Black"], + ["color", "BlanchedAlmond"], + ["color", "Blue"], + ["color", "BlueViolet"], + ["color", "Brown"], + ["color", "BurlyWood"], + ["color", "CadetBlue"], + ["color", "Chartreuse"], + ["color", "Chocolate"], + ["color", "Coral"], + ["color", "CornflowerBlue"], + ["color", "Cornsilk"], + ["color", "Crimson"], + ["color", "Cyan"], + ["color", "DarkBlue"], + ["color", "DarkCyan"], + ["color", "DarkGoldenRod"], + ["color", "DarkGrey"], + ["color", "DarkGreen"], + ["color", "DarkKhaki"], + ["color", "DarkMagenta"], + ["color", "DarkOliveGreen"], + ["color", "DarkOrange"], + ["color", "DarkOrchid"], + ["color", "DarkRed"], + ["color", "DarkSalmon"], + ["color", "DarkSeaGreen"], + ["color", "DarkSlateBlue"], + ["color", "DarkSlateGrey"], + ["color", "DarkTurquoise"], + ["color", "DarkViolet"], + ["color", "DeepPink"], + ["color", "DeepSkyBlue"], + ["color", "DimGrey"], + ["color", "DodgerBlue"], + ["color", "FireBrick"], + ["color", "FloralWhite"], + ["color", "ForestGreen"], + ["color", "Fuchsia"], + ["color", "Gainsboro"], + ["color", "GhostWhite"], + ["color", "Gold"], + ["color", "GoldenRod"], + ["color", "Grey"], + ["color", "Green"], + ["color", "GreenYellow"], + ["color", "HoneyDew"], + ["color", "HotPink"], + ["color", "IndianRed"], + ["color", "Indigo"], + ["color", "Ivory"], + ["color", "Khaki"], + ["color", "Lavender"], + ["color", "LavenderBlush"], + ["color", "LawnGreen"], + ["color", "LemonChiffon"], + ["color", "LightBlue"], + ["color", "LightCoral"], + ["color", "LightCyan"], + ["color", "LightGoldenRodYellow"], + ["color", "LightGrey"], + ["color", "LightGreen"], + ["color", "LightPink"], + ["color", "LightSalmon"], + ["color", "LightSeaGreen"], + ["color", "LightSkyBlue"], + ["color", "LightSlateGrey"], + ["color", "LightSteelBlue"], + ["color", "LightYellow"], + ["color", "Lime"], + ["color", "LimeGreen"], + ["color", "Linen"], + ["color", "Magenta"], + ["color", "Maroon"], + ["color", "MediumAquaMarine"], + ["color", "MediumBlue"], + ["color", "MediumOrchid"], + ["color", "MediumPurple"], + ["color", "MediumSeaGreen"], + ["color", "MediumSlateBlue"], + ["color", "MediumSpringGreen"], + ["color", "MediumTurquoise"], + ["color", "MediumVioletRed"], + ["color", "MidnightBlue"], + ["color", "MintCream"], + ["color", "MistyRose"], + ["color", "Moccasin"], + ["color", "NavajoWhite"], + ["color", "Navy"], + ["color", "OldLace"], + ["color", "Olive"], + ["color", "OliveDrab"], + ["color", "Orange"], + ["color", "OrangeRed"], + ["color", "Orchid"], + ["color", "PaleGoldenRod"], + ["color", "PaleGreen"], + ["color", "PaleTurquoise"], + ["color", "PaleVioletRed"], + ["color", "PapayaWhip"], + ["color", "PeachPuff"], + ["color", "Peru"], + ["color", "Pink"], + ["color", "Plum"], + ["color", "PowderBlue"], + ["color", "Purple"], + ["color", "Red"], + ["color", "RosyBrown"], + ["color", "RoyalBlue"], + ["color", "SaddleBrown"], + ["color", "Salmon"], + ["color", "SandyBrown"], + ["color", "SeaGreen"], + ["color", "SeaShell"], + ["color", "Sienna"], + ["color", "Silver"], + ["color", "SkyBlue"], + ["color", "SlateBlue"], + ["color", "SlateGrey"], + ["color", "Snow"], + ["color", "SpringGreen"], + ["color", "SteelBlue"], + ["color", "Tan"], + ["color", "Teal"], + ["color", "Thistle"], + ["color", "Tomato"], + ["color", "Transparent"], + ["color", "Turquoise"], + ["color", "Violet"], + ["color", "Wheat"], + ["color", "White"], + ["color", "WhiteSmoke"], + ["color", "Yellow"], + ["color", "YellowGreen"], + + ["color", [ + ["function", "rgb"], + ["punctuation", "("], + ["number", "0"], + ["punctuation", ","], + ["number", "0"], + ["punctuation", ","], + ["number", "0"], + ["punctuation", ")"] + ]], + ["color", [ + ["function", "rgba"], + ["punctuation", "("], + ["number", "0"], + ["punctuation", ","], + ["number", "255"], + ["punctuation", ","], + ["number", "0"], + ["punctuation", ","], + ["number", "0.123"], + ["punctuation", ")"] + ]], + ["color", [ + ["function", "hsl"], + ["punctuation", "("], + ["number", "170"], + ["punctuation", ","], + ["number", "50"], + ["unit", "%"], + ["punctuation", ","], + ["number", "45"], + ["unit", "%"], + ["punctuation", ")"] + ]], + ["color", [ + ["function", "hsla"], + ["punctuation", "("], + ["number", "120"], + ["punctuation", ","], + ["number", "100"], + ["unit", "%"], + ["punctuation", ","], + ["number", "50"], + ["unit", "%"], + ["punctuation", ","], + ["number", "0.3"], + ["punctuation", ")"] + ]] +] diff --git a/tests/languages/css!+css-extras/number_feature.test b/tests/languages/css!+css-extras/number_feature.test index 24ed5305e2..1ac34b99ca 100644 --- a/tests/languages/css!+css-extras/number_feature.test +++ b/tests/languages/css!+css-extras/number_feature.test @@ -1,15 +1,66 @@ 42 3.14159 -42% -3.14% +-42 +-3.14159 +.5 +-.5 + +/* complex example */ +foo { + foo: 0 1em 2ch; + bar:-0px 3px; + baz:calc(100% - 5px - -4em); +} ---------------------------------------------------- [ ["number", "42"], ["number", "3.14159"], - ["number", "42%"], - ["number", "3.14%"] + ["number", "-42"], + ["number", "-3.14159"], + ["number", ".5"], + ["number", "-.5"], + + ["comment", "/* complex example */"], + ["selector", [ + "foo" + ]], + ["punctuation", "{"], + + ["property", "foo"], + ["punctuation", ":"], + ["number", "0"], + ["number", "1"], + ["unit", "em"], + ["number", "2"], + ["unit", "ch"], + ["punctuation", ";"], + + ["property", "bar"], + ["punctuation", ":"], + ["number", "-0"], + ["unit", "px"], + ["number", "3"], + ["unit", "px"], + ["punctuation", ";"], + + ["property", "baz"], + ["punctuation", ":"], + ["function", "calc"], + ["punctuation", "("], + ["number", "100"], + ["unit", "%"], + ["operator", "-"], + ["number", "5"], + ["unit", "px"], + ["operator", "-"], + ["number", "-4"], + ["unit", "em"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"] ] ---------------------------------------------------- diff --git a/tests/languages/css!+css-extras/operator_feature.test b/tests/languages/css!+css-extras/operator_feature.test new file mode 100644 index 0000000000..0df7612b38 --- /dev/null +++ b/tests/languages/css!+css-extras/operator_feature.test @@ -0,0 +1,71 @@ +width: calc(100% + 20px); +width: calc(100% - 20px); +width: calc(5px * 2); +width: calc(10px / 2); +height: -20px; +content: 'this - is not an operator'; + +---------------------------------------------------- + +[ + ["property", "width"], + ["punctuation", ":"], + ["function", "calc"], + ["punctuation", "("], + ["number", "100"], + ["unit", "%"], + ["operator", "+"], + ["number", "20"], + ["unit", "px"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["property", "width"], + ["punctuation", ":"], + ["function", "calc"], + ["punctuation", "("], + ["number", "100"], + ["unit", "%"], + ["operator", "-"], + ["number", "20"], + ["unit", "px"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["property", "width"], + ["punctuation", ":"], + ["function", "calc"], + ["punctuation", "("], + ["number", "5"], + ["unit", "px"], + ["operator", "*"], + ["number", "2"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["property", "width"], + ["punctuation", ":"], + ["function", "calc"], + ["punctuation", "("], + ["number", "10"], + ["unit", "px"], + ["operator", "/"], + ["number", "2"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["property", "height"], + ["punctuation", ":"], + ["number", "-20"], + ["unit", "px"], + ["punctuation", ";"], + + ["property", "content"], + ["punctuation", ":"], + ["string", "'this - is not an operator'"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for operators. diff --git a/tests/languages/css!+css-extras/selector_attribute_feature.test b/tests/languages/css!+css-extras/selector_attribute_feature.test new file mode 100644 index 0000000000..fe2587b7a6 --- /dev/null +++ b/tests/languages/css!+css-extras/selector_attribute_feature.test @@ -0,0 +1,269 @@ +[attr] {} + +[attr=val] {} +[attr="val"] {} +[attr='val'] {} +[attr|=val] {} +[attr~=val] {} +[attr|=val] {} +[attr^=val] {} +[attr$=val] {} +[attr*=val] {} + +[foo|attr][*|attr][|attr] {} +[foo|attr|=val] {} + +[attr=val i] {} +[attr="val" S] {} + +[ attr ] {} +[ attr = val ] {} +[ attr = val i] {} + +[attr="i#m :not(a.class)"] {} + +---------------------------------------------------- + +[ + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "\"val\""], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "'val'"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "|="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "~="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "|="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "^="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "$="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "*="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + "foo", + ["punctuation", "|"] + ]], + ["attr-name", "attr"], + ["punctuation", "]"] + ]], + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + "*", + ["punctuation", "|"] + ]], + ["attr-name", "attr"], + ["punctuation", "]"] + ]], + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + ["punctuation", "|"] + ]], + ["attr-name", "attr"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["namespace", [ + "foo", + ["punctuation", "|"] + ]], + ["attr-name", "attr"], + ["operator", "|="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "val"], + ["case-sensitivity", "i"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "\"val\""], + ["case-sensitivity", "S"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "val"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "val"], + ["case-sensitivity", "i"], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["attribute", [ + ["punctuation", "["], + ["attr-name", "attr"], + ["operator", "="], + ["attr-value", "\"i#m :not(a.class)\""], + ["punctuation", "]"] + ]] + ]], + ["punctuation", "{"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks for attributes inside selectors. \ No newline at end of file diff --git a/tests/languages/css!+css-extras/selector_feature.test b/tests/languages/css!+css-extras/selector_feature.test index 3931a66334..6521dc44b7 100644 --- a/tests/languages/css!+css-extras/selector_feature.test +++ b/tests/languages/css!+css-extras/selector_feature.test @@ -1,15 +1,11 @@ foo:after { foo::first-letter { -foo:nth-child(2n+1) { +foo.bar.baz { -foo.bar { +foo#bar.baz { -foo#bar { - -#foo > .bar:not(baz):after { - -div[foo="bar"] { +#foo > .bar:hover:after { ---------------------------------------------------- @@ -26,33 +22,25 @@ div[foo="bar"] { ["selector", [ "foo", - ["pseudo-class", ":nth-child(2n+1)"] - ]], ["punctuation", "{"], - - ["selector", [ - "foo", - ["class", ".bar"] + ["class", ".bar"], + ["class", ".baz"] ]], ["punctuation", "{"], ["selector", [ "foo", - ["id", "#bar"] + ["id", "#bar"], + ["class", ".baz"] ]], ["punctuation", "{"], ["selector", [ ["id", "#foo"], - " > ", + ["combinator", ">"], ["class", ".bar"], - ["pseudo-class", ":not(baz)"], + ["pseudo-class", ":hover"], ["pseudo-element", ":after"] - ]], ["punctuation", "{"], - - ["selector", [ - "div", - ["attribute", "[foo=\"bar\"]"] ]], ["punctuation", "{"] ] ---------------------------------------------------- -Checks for pseudo-elements, pseudo-classes, classes and ids inside selectors. \ No newline at end of file +Checks for pseudo-elements, pseudo-classes, classes and ids inside selectors. diff --git a/tests/languages/css!+css-extras/selector_n-th_feature.test b/tests/languages/css!+css-extras/selector_n-th_feature.test new file mode 100644 index 0000000000..0b7bcb8e9a --- /dev/null +++ b/tests/languages/css!+css-extras/selector_n-th_feature.test @@ -0,0 +1,82 @@ +:nth-child(2n+1) {} +:nth-child(+2n - 1) {} +:nth-child(2n) {} +:nth-child(+5) {} +:nth-child(even) {} +:nth-child(odd) {} + +---------------------------------------------------- + +[ + ["selector", [ + ["pseudo-class", ":nth-child"], + ["punctuation", "("], + ["n-th", [ + ["number", "2n"], + ["operator", "+"], + ["number", "1"] + ]], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["pseudo-class", ":nth-child"], + ["punctuation", "("], + ["n-th", [ + ["operator", "+"], + ["number", "2n"], + ["operator", "-"], + ["number", "1"] + ]], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["pseudo-class", ":nth-child"], + ["punctuation", "("], + ["n-th", [ + ["number", "2n"] + ]], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["pseudo-class", ":nth-child"], + ["punctuation", "("], + ["n-th", [ + ["operator", "+"], + ["number", "5"] + ]], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["pseudo-class", ":nth-child"], + ["punctuation", "("], + ["n-th", "even"], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["pseudo-class", ":nth-child"], + ["punctuation", "("], + ["n-th", "odd"], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks for n-th expressions. diff --git a/tests/languages/css!+css-extras/selector_pseudo-class_feature.test b/tests/languages/css!+css-extras/selector_pseudo-class_feature.test new file mode 100644 index 0000000000..bf2cea6217 --- /dev/null +++ b/tests/languages/css!+css-extras/selector_pseudo-class_feature.test @@ -0,0 +1,59 @@ +foo:hover {} + +:lang(en) {} + +.bar:not(baz:hover):not(.foo) {} + +:where(p:not(.class)) {} + +---------------------------------------------------- + +[ + ["selector", [ + "foo", + ["pseudo-class", ":hover"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["pseudo-class", ":lang"], + ["punctuation", "("], + "en", + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["class", ".bar"], + ["pseudo-class", ":not"], + ["punctuation", "("], + "baz", + ["pseudo-class", ":hover"], + ["punctuation", ")"], + ["pseudo-class", ":not"], + ["punctuation", "("], + ["class", ".foo"], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], + + ["selector", [ + ["pseudo-class", ":where"], + ["punctuation", "("], + "p", + ["pseudo-class", ":not"], + ["punctuation", "("], + ["class", ".class"], + ["punctuation", ")"], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks for pseudo-classes inside selectors. diff --git a/tests/languages/css!+css-extras/unit_feature.test b/tests/languages/css!+css-extras/unit_feature.test new file mode 100644 index 0000000000..6d5c15c8e6 --- /dev/null +++ b/tests/languages/css!+css-extras/unit_feature.test @@ -0,0 +1,21 @@ +100% +1rem +500ms +.5s +-3px +-0.618vw + +---------------------------------------------------- + +[ + ["number", "100"], ["unit", "%"], + ["number", "1"], ["unit", "rem"], + ["number", "500"], ["unit", "ms"], + ["number", ".5"], ["unit", "s"], + ["number", "-3"], ["unit", "px"], + ["number", "-0.618"], ["unit", "vw"] +] + +---------------------------------------------------- + +Checks for units. diff --git a/tests/languages/css!+css-extras/variable_feature.test b/tests/languages/css!+css-extras/variable_feature.test new file mode 100644 index 0000000000..657688fcd1 --- /dev/null +++ b/tests/languages/css!+css-extras/variable_feature.test @@ -0,0 +1,54 @@ +element { + --foo: green; +} + +var(--color-primary) +var(--level-3) +var(--foo, red) +calc(100% - var(--margin-size) * 2) + +---------------------------------------------------- + +[ + ["selector", ["element"]], + ["punctuation", "{"], + ["variable", "--foo"], + ["punctuation", ":"], + ["color", "green"], + ["punctuation", ";"], + ["punctuation", "}"], + + ["function", "var"], + ["punctuation", "("], + ["variable", "--color-primary"], + ["punctuation", ")"], + + ["function", "var"], + ["punctuation", "("], + ["variable", "--level-3"], + ["punctuation", ")"], + + ["function", "var"], + ["punctuation", "("], + ["variable", "--foo"], + ["punctuation", ","], + ["color", "red"], + ["punctuation", ")"], + + ["function", "calc"], + ["punctuation", "("], + ["number", "100"], + ["unit", "%"], + ["operator", "-"], + ["function", "var"], + ["punctuation", "("], + ["variable", "--margin-size"], + ["punctuation", ")"], + ["operator", "*"], + ["number", "2"], + ["punctuation", ")"] +] + +---------------------------------------------------- + +Checks for variables. diff --git a/tests/languages/css+css-extras+sass/issue2992.test b/tests/languages/css+css-extras+sass/issue2992.test new file mode 100644 index 0000000000..7300a2ec96 --- /dev/null +++ b/tests/languages/css+css-extras+sass/issue2992.test @@ -0,0 +1,31 @@ +.lucidagrande-normal-black-14px + color: var(--black) + font-family: var(--font-family-lucidagrande) + font-size: var(--font-size-m) + --foo: black + +---------------------------------------------------- + +[ + ["selector", ".lucidagrande-normal-black-14px"], + ["property-line", [ + ["property", "color"], + ["punctuation", ":"], + " var(--black)" + ]], + ["property-line", [ + ["property", "font-family"], + ["punctuation", ":"], + " var(--font-family-lucidagrande)" + ]], + ["property-line", [ + ["property", "font-size"], + ["punctuation", ":"], + " var(--font-size-m)" + ]], + ["property-line", [ + ["property", "--foo"], + ["punctuation", ":"], + " black" + ]] +] diff --git a/tests/languages/css+haml/css+haml_usage.test b/tests/languages/css+haml/css+haml_usage.test index c90047f28f..61638eac43 100644 --- a/tests/languages/css+haml/css+haml_usage.test +++ b/tests/languages/css+haml/css+haml_usage.test @@ -10,19 +10,23 @@ [ ["filter-css", [ ["filter-name", ":css"], - ["selector", ".test"], - ["punctuation", "{"], - ["punctuation", "}"] + ["text", [ + ["selector", ".test"], + ["punctuation", "{"], + ["punctuation", "}"] + ]] ]], ["punctuation", "~"], ["filter-css", [ - ["filter-name", ":css"], - ["selector", ".test"], - ["punctuation", "{"], - ["punctuation", "}"] - ]] + ["filter-name", ":css"], + ["text", [ + ["selector", ".test"], + ["punctuation", "{"], + ["punctuation", "}"] + ]] + ]] ] ---------------------------------------------------- -Checks for CSS filter in Haml. The tilde serves only as a separator. \ No newline at end of file +Checks for CSS filter in Haml. The tilde serves only as a separator. diff --git a/tests/languages/css+http/css_inclusion.test b/tests/languages/css+http/css_inclusion.test new file mode 100644 index 0000000000..5c3a24f884 --- /dev/null +++ b/tests/languages/css+http/css_inclusion.test @@ -0,0 +1,31 @@ +Content-type: text/css + +a.link:hover { + color: red; +} + +---------------------------------------------------- + +[ + ["header", [ + ["header-name", "Content-type"], + ["punctuation", ":"], + ["header-value", "text/css"] + ]], + + ["text-css", [ + ["selector", "a.link:hover"], + ["punctuation", "{"], + + ["property", "color"], + ["punctuation", ":"], + " red", + ["punctuation", ";"], + + ["punctuation", "}"] + ]] +] + +---------------------------------------------------- + +Checks for JavaScript content in HTTP. diff --git a/tests/languages/css/atrule_feature.test b/tests/languages/css/atrule_feature.test index abc75def35..adb84ab093 100644 --- a/tests/languages/css/atrule_feature.test +++ b/tests/languages/css/atrule_feature.test @@ -1,6 +1,8 @@ @import url(foo.css); @media print {} @media (min-width: 640px) and (min-height: 1000px) {} +@supports (top: 50vmax) + or (top: 50vw) {} @main-color: red; ---------------------------------------------------- @@ -8,7 +10,12 @@ [ ["atrule", [ ["rule", "@import"], - ["url", "url(foo.css)"], + ["url", [ + ["function", "url"], + ["punctuation", "("], + "foo.css", + ["punctuation", ")"] + ]], ["punctuation", ";"] ]], ["atrule", [ @@ -24,15 +31,31 @@ ["punctuation", ":"], " 640px", ["punctuation", ")"], - " and ", + ["keyword", "and"], ["punctuation", "("], - ["property", "min-height"], - ["punctuation", ":"], - " 1000px", - ["punctuation", ")"] + ["property", "min-height"], + ["punctuation", ":"], + " 1000px", + ["punctuation", ")"] ]], ["punctuation", "{"], - ["punctuation", "}"], + ["punctuation", "}"], + ["atrule", [ + ["rule", "@supports"], + ["punctuation", "("], + ["property", "top"], + ["punctuation", ":"], + " 50vmax", + ["punctuation", ")"], + ["keyword", "or"], + ["punctuation", "("], + ["property", "top"], + ["punctuation", ":"], + " 50vw", + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["punctuation", "}"], ["atrule", [ ["rule", "@main-color"], ["punctuation", ":"], @@ -44,4 +67,4 @@ ---------------------------------------------------- Checks for at-rules. -Also checks for LESS variables. \ No newline at end of file +Also checks for LESS variables. diff --git a/tests/languages/css/atrule_selector-function-argument_feature.test b/tests/languages/css/atrule_selector-function-argument_feature.test new file mode 100644 index 0000000000..41b3480b65 --- /dev/null +++ b/tests/languages/css/atrule_selector-function-argument_feature.test @@ -0,0 +1,24 @@ +@supports selector(::-webkit-foo) { + /* style to apply when the `::-webkit-foo` selector is actually supported, + * instead of just being parsed as matching nothing because of Selectors 4 + * § Appendix B: https://drafts.csswg.org/selectors-4/#compat */ +} + +---------------------------------------------------- + +[ + ["atrule", [ + ["rule", "@supports"], + ["function", "selector"], + ["punctuation", "("], + ["selector-function-argument", "::-webkit-foo"], + ["punctuation", ")"] + ]], + ["punctuation", "{"], + ["comment", "/* style to apply when the `::-webkit-foo` selector is actually supported,\r\n\t * instead of just being parsed as matching nothing because of Selectors 4\r\n\t * § Appendix B: https://drafts.csswg.org/selectors-4/#compat */"], + ["punctuation", "}"] +] + +---------------------------------------------------- + +Checks for the selector function in @supports rules. diff --git a/tests/languages/css/function_feature.test b/tests/languages/css/function_feature.test index 0ed4f12bfc..0af02a0c55 100644 --- a/tests/languages/css/function_feature.test +++ b/tests/languages/css/function_feature.test @@ -17,7 +17,13 @@ filter: opacity(alpha=0); ["punctuation", ":"], ["function", "rgba"], ["punctuation", "("], - "0, 0, 0, 0.2", + "0", + ["punctuation", ","], + " 0", + ["punctuation", ","], + " 0", + ["punctuation", ","], + " 0.2", ["punctuation", ")"], ["punctuation", ";"], diff --git a/tests/languages/css/important_feature.test b/tests/languages/css/important_feature.test index ad69c39a43..0f5c1409e9 100644 --- a/tests/languages/css/important_feature.test +++ b/tests/languages/css/important_feature.test @@ -1,5 +1,6 @@ color: red !important; padding: 10px 20px 30px !important; +position:absolute!important; ---------------------------------------------------- @@ -10,12 +11,17 @@ padding: 10px 20px 30px !important; ["important", "!important"], ["punctuation", ";"], ["property", "padding"], - ["punctuation", ":"], - " 10px 20px 30px ", - ["important", "!important"], - ["punctuation", ";"] + ["punctuation", ":"], + " 10px 20px 30px ", + ["important", "!important"], + ["punctuation", ";"], + ["property", "position"], + ["punctuation", ":"], + "absolute", + ["important", "!important"], + ["punctuation", ";"] ] ---------------------------------------------------- -Checks for !important rule. \ No newline at end of file +Checks for !important rule. diff --git a/tests/languages/css/selector_feature.test b/tests/languages/css/selector_feature.test index 5a59720135..227ac755a6 100644 --- a/tests/languages/css/selector_feature.test +++ b/tests/languages/css/selector_feature.test @@ -1,25 +1,38 @@ foo{ + foo + bar { + foo:first-child:hover { + * { + foo, bar{ +[foo="{\"}"] { + ---------------------------------------------------- [ ["selector", "foo"], ["punctuation", "{"], + ["selector", "foo + bar"], ["punctuation", "{"], + ["selector", "foo:first-child:hover"], ["punctuation", "{"], + ["selector", "*"], ["punctuation", "{"], + ["selector", "foo,\r\nbar"], + ["punctuation", "{"], + + ["selector", "[foo=\"{\\\"}\"]"], ["punctuation", "{"] ] ---------------------------------------------------- -Checks for single-line and multi-line selectors. \ No newline at end of file +Checks for single-line and multi-line selectors. diff --git a/tests/languages/css/url_feature.test b/tests/languages/css/url_feature.test index 05ce8f9f74..6acaf0f074 100644 --- a/tests/languages/css/url_feature.test +++ b/tests/languages/css/url_feature.test @@ -1,4 +1,5 @@ url(foo.png) +url(close\)parens) url('foo.png') url("foo.png") url('foo\ @@ -6,16 +7,70 @@ bar.png') url("foo\ bar.png") +@import url("https://cdn.jsdelivr.net/npm/prismj1.19.0/themes/prism-dark.css"); +@import url("https://cdn.jsdelivr.net/npm/prismjs/themes/prism-dark.css"); + ---------------------------------------------------- [ - ["url", "url(foo.png)"], - ["url", "url('foo.png')"], - ["url", "url(\"foo.png\")"], - ["url", "url('foo\\\r\nbar.png')"], - ["url", "url(\"foo\\\r\nbar.png\")"] + ["url", [ + ["function", "url"], + ["punctuation", "("], + "foo.png", + ["punctuation", ")"] + ]], + ["url", [ + ["function", "url"], + ["punctuation", "("], + "close\\)parens", + ["punctuation", ")"] + ]], + ["url", [ + ["function", "url"], + ["punctuation", "("], + ["string", "'foo.png'"], + ["punctuation", ")"] + ]], + ["url", [ + ["function", "url"], + ["punctuation", "("], + ["string", "\"foo.png\""], + ["punctuation", ")"] + ]], + ["url", [ + ["function", "url"], + ["punctuation", "("], + ["string", "'foo\\\r\nbar.png'"], + ["punctuation", ")"] + ]], + ["url", [ + ["function", "url"], + ["punctuation", "("], + ["string", "\"foo\\\r\nbar.png\""], + ["punctuation", ")"] + ]], + ["atrule", [ + ["rule", "@import"], + ["url", [ + ["function", "url"], + ["punctuation", "("], + ["string", "\"https://cdn.jsdelivr.net/npm/prismj1.19.0/themes/prism-dark.css\""], + ["punctuation", ")"] + ]], + ["punctuation", ";"] + ]], + ["atrule", [ + ["rule", "@import"], + ["url", [ + ["function", "url"], + ["punctuation", "("], + ["string", "\"https://cdn.jsdelivr.net/npm/prismjs/themes/prism-dark.css\""], + ["punctuation", ")"] + ]], + ["punctuation", ";"] + ]] ] ---------------------------------------------------- -Checks for url(), unquoted, single-quoted and double-quoted. \ No newline at end of file +Checks for url(), unquoted, single-quoted and double-quoted. diff --git a/tests/languages/csv/value.test b/tests/languages/csv/value.test new file mode 100644 index 0000000000..230d655ab2 --- /dev/null +++ b/tests/languages/csv/value.test @@ -0,0 +1,99 @@ +aaa,bbb,ccc +zzz,yyy,xxx + +"aaa","bbb","ccc" + +"aaa","b +bb","ccc" + +"aaa","b""bb","ccc" + +Year,Make,Model,Description,Price +1997,Ford,E350,"ac, abs, moon",3000.00 +1999,Chevy,"Venture ""Extended Edition""","",4900.00 +1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00 +1996,Jeep,Grand Cherokee,"MUST SELL! +air, moon roof, loaded",4799.00 + +---------------------------------------------------- + +[ + ["value", "aaa"], + ["punctuation", ","], + ["value", "bbb"], + ["punctuation", ","], + ["value", "ccc"], + + ["value", "zzz"], + ["punctuation", ","], + ["value", "yyy"], + ["punctuation", ","], + ["value", "xxx"], + + ["value", "\"aaa\""], + ["punctuation", ","], + ["value", "\"bbb\""], + ["punctuation", ","], + ["value", "\"ccc\""], + + ["value", "\"aaa\""], + ["punctuation", ","], + ["value", "\"b\r\nbb\""], + ["punctuation", ","], + ["value", "\"ccc\""], + + ["value", "\"aaa\""], + ["punctuation", ","], + ["value", "\"b\"\"bb\""], + ["punctuation", ","], + ["value", "\"ccc\""], + + ["value", "Year"], + ["punctuation", ","], + ["value", "Make"], + ["punctuation", ","], + ["value", "Model"], + ["punctuation", ","], + ["value", "Description"], + ["punctuation", ","], + ["value", "Price"], + + ["value", "1997"], + ["punctuation", ","], + ["value", "Ford"], + ["punctuation", ","], + ["value", "E350"], + ["punctuation", ","], + ["value", "\"ac, abs, moon\""], + ["punctuation", ","], + ["value", "3000.00"], + + ["value", "1999"], + ["punctuation", ","], + ["value", "Chevy"], + ["punctuation", ","], + ["value", "\"Venture \"\"Extended Edition\"\"\""], + ["punctuation", ","], + ["value", "\"\""], + ["punctuation", ","], + ["value", "4900.00"], + + ["value", "1999"], + ["punctuation", ","], + ["value", "Chevy"], + ["punctuation", ","], + ["value", "\"Venture \"\"Extended Edition, Very Large\"\"\""], + ["punctuation", ","], + ["punctuation", ","], + ["value", "5000.00"], + + ["value", "1996"], + ["punctuation", ","], + ["value", "Jeep"], + ["punctuation", ","], + ["value", "Grand Cherokee"], + ["punctuation", ","], + ["value", "\"MUST SELL!\r\nair, moon roof, loaded\""], + ["punctuation", ","], + ["value", "4799.00"] +] \ No newline at end of file diff --git a/tests/languages/cypher/boolean_feature.test b/tests/languages/cypher/boolean_feature.test new file mode 100644 index 0000000000..1e007c8291 --- /dev/null +++ b/tests/languages/cypher/boolean_feature.test @@ -0,0 +1,17 @@ +true TRUE +false FALSE +null + +---------------------------------------------------- + +[ + ["boolean", "true"], + ["boolean", "TRUE"], + ["boolean", "false"], + ["boolean", "FALSE"], + ["boolean", "null"] +] + +---------------------------------------------------- + +Checks for booleans and null. diff --git a/tests/languages/cypher/class-name_feature.test b/tests/languages/cypher/class-name_feature.test new file mode 100644 index 0000000000..c9acf49e08 --- /dev/null +++ b/tests/languages/cypher/class-name_feature.test @@ -0,0 +1,114 @@ +(p:Student) +(p:Student { name: "John" }) +(:`Student`) +(:`Student` { name: "John"}) + +(p:Student:Teacher) +(p:Student { name: "John" }:Teacher) +(:`Student`:`Teacher`) +(:`Student` { name: "John"}:`Teacher` { classes: "..." }) + +// no class names but still interesting cases + +(p { name: "John" }) +({ name: "John" }) +() + +---------------------------------------------------- + +[ + ["punctuation", "("], + "p", + ["operator", ":"], + ["class-name", "Student"], + ["punctuation", ")"], + ["punctuation", "("], + "p", + ["operator", ":"], + ["class-name", "Student"], + ["punctuation", "{"], + " name", + ["operator", ":"], + ["string", "\"John\""], + ["punctuation", "}"], + ["punctuation", ")"], + ["punctuation", "("], + ["operator", ":"], + ["class-name", "`Student`"], + ["punctuation", ")"], + ["punctuation", "("], + ["operator", ":"], + ["class-name", "`Student`"], + ["punctuation", "{"], + " name", + ["operator", ":"], + ["string", "\"John\""], + ["punctuation", "}"], + ["punctuation", ")"], + + ["punctuation", "("], + "p", + ["operator", ":"], + ["class-name", "Student"], + ["operator", ":"], + ["class-name", "Teacher"], + ["punctuation", ")"], + ["punctuation", "("], + "p", + ["operator", ":"], + ["class-name", "Student"], + ["punctuation", "{"], + " name", + ["operator", ":"], + ["string", "\"John\""], + ["punctuation", "}"], + ["operator", ":"], + ["class-name", "Teacher"], + ["punctuation", ")"], + ["punctuation", "("], + ["operator", ":"], + ["class-name", "`Student`"], + ["operator", ":"], + ["class-name", "`Teacher`"], + ["punctuation", ")"], + ["punctuation", "("], + ["operator", ":"], + ["class-name", "`Student`"], + ["punctuation", "{"], + " name", + ["operator", ":"], + ["string", "\"John\""], + ["punctuation", "}"], + ["operator", ":"], + ["class-name", "`Teacher`"], + ["punctuation", "{"], + " classes", + ["operator", ":"], + ["string", "\"...\""], + ["punctuation", "}"], + ["punctuation", ")"], + + ["comment", "// no class names but still interesting cases"], + + ["punctuation", "("], + "p ", + ["punctuation", "{"], + " name", + ["operator", ":"], + ["string", "\"John\""], + ["punctuation", "}"], + ["punctuation", ")"], + ["punctuation", "("], + ["punctuation", "{"], + " name", + ["operator", ":"], + ["string", "\"John\""], + ["punctuation", "}"], + ["punctuation", ")"], + ["punctuation", "("], + ["punctuation", ")"] +] + +---------------------------------------------------- + +Checks for class names. diff --git a/tests/languages/cypher/comment_feature.test b/tests/languages/cypher/comment_feature.test new file mode 100644 index 0000000000..68f6d9d9b9 --- /dev/null +++ b/tests/languages/cypher/comment_feature.test @@ -0,0 +1,11 @@ +//comment + +---------------------------------------------------- + +[ + ["comment", "//comment"] +] + +---------------------------------------------------- + +Checks for comments. diff --git a/tests/languages/cypher/function_feature.test b/tests/languages/cypher/function_feature.test new file mode 100644 index 0000000000..45938868f5 --- /dev/null +++ b/tests/languages/cypher/function_feature.test @@ -0,0 +1,13 @@ +foo() + +---------------------------------------------------- + +[ + ["function", "foo"], + ["punctuation", "("], + ["punctuation", ")"] +] + +---------------------------------------------------- + +Checks for function names. diff --git a/tests/languages/cypher/keyword_feature.test b/tests/languages/cypher/keyword_feature.test new file mode 100644 index 0000000000..69053c80e7 --- /dev/null +++ b/tests/languages/cypher/keyword_feature.test @@ -0,0 +1,138 @@ +ADD +ALL +AND +AS +ASC +ASCENDING +ASSERT +CALL +CASE +COMMIT +CONSTRAINT +CONTAINS +CREATE +CSV +DELETE +DESC +DESCENDING +DETACH +DISTINCT +DO +DROP +ELSE +END +ENDS +EXISTS +FOR +FOREACH +IN +INDEX +IS +JOIN +KEY +LIMIT +LOAD +MANDATORY +MATCH +MERGE +NODE +NOT +OF +ON +OPTIONAL +OR +ORDER BY +PERIODIC +REMOVE +REQUIRE +RETURN +SCALAR +SCAN +SET +SKIP +START +STARTS +THEN +UNION +UNIQUE +UNWIND +USING +WHEN +WHERE +WITH +XOR +YIELD + +---------------------------------------------------- + +[ + ["keyword", "ADD"], + ["keyword", "ALL"], + ["keyword", "AND"], + ["keyword", "AS"], + ["keyword", "ASC"], + ["keyword", "ASCENDING"], + ["keyword", "ASSERT"], + ["keyword", "CALL"], + ["keyword", "CASE"], + ["keyword", "COMMIT"], + ["keyword", "CONSTRAINT"], + ["keyword", "CONTAINS"], + ["keyword", "CREATE"], + ["keyword", "CSV"], + ["keyword", "DELETE"], + ["keyword", "DESC"], + ["keyword", "DESCENDING"], + ["keyword", "DETACH"], + ["keyword", "DISTINCT"], + ["keyword", "DO"], + ["keyword", "DROP"], + ["keyword", "ELSE"], + ["keyword", "END"], + ["keyword", "ENDS"], + ["keyword", "EXISTS"], + ["keyword", "FOR"], + ["keyword", "FOREACH"], + ["keyword", "IN"], + ["keyword", "INDEX"], + ["keyword", "IS"], + ["keyword", "JOIN"], + ["keyword", "KEY"], + ["keyword", "LIMIT"], + ["keyword", "LOAD"], + ["keyword", "MANDATORY"], + ["keyword", "MATCH"], + ["keyword", "MERGE"], + ["keyword", "NODE"], + ["keyword", "NOT"], + ["keyword", "OF"], + ["keyword", "ON"], + ["keyword", "OPTIONAL"], + ["keyword", "OR"], + ["keyword", "ORDER"], + ["keyword", "BY"], + ["keyword", "PERIODIC"], + ["keyword", "REMOVE"], + ["keyword", "REQUIRE"], + ["keyword", "RETURN"], + ["keyword", "SCALAR"], + ["keyword", "SCAN"], + ["keyword", "SET"], + ["keyword", "SKIP"], + ["keyword", "START"], + ["keyword", "STARTS"], + ["keyword", "THEN"], + ["keyword", "UNION"], + ["keyword", "UNIQUE"], + ["keyword", "UNWIND"], + ["keyword", "USING"], + ["keyword", "WHEN"], + ["keyword", "WHERE"], + ["keyword", "WITH"], + ["keyword", "XOR"], + ["keyword", "YIELD"] +] + +---------------------------------------------------- + +Checks for keywords. diff --git a/tests/languages/cypher/number_feature.test b/tests/languages/cypher/number_feature.test new file mode 100644 index 0000000000..4134b30a5c --- /dev/null +++ b/tests/languages/cypher/number_feature.test @@ -0,0 +1,35 @@ +123 +123E45 + +3.14 +6.022E23 + +0x13af +0xFC3A9 +0x66eff + +01372 +02127 +05671 + +---------------------------------------------------- + +[ + ["number", "123"], + ["number", "123E45"], + + ["number", "3.14"], + ["number", "6.022E23"], + + ["number", "0x13af"], + ["number", "0xFC3A9"], + ["number", "0x66eff"], + + ["number", "01372"], + ["number", "02127"], + ["number", "05671"] +] + +---------------------------------------------------- + +Checks for numbers. diff --git a/tests/languages/cypher/operator_feature.test b/tests/languages/cypher/operator_feature.test new file mode 100644 index 0000000000..fe9b82b4d3 --- /dev/null +++ b/tests/languages/cypher/operator_feature.test @@ -0,0 +1,49 @@ ++ - * / % ^ + += <> > >= < <= + +=~ | : .. + +- -> +<- - +- - +-- +<-- +--> + +---------------------------------------------------- + +[ + ["operator", "+"], + ["operator", "-"], + ["operator", "*"], + ["operator", "/"], + ["operator", "%"], + ["operator", "^"], + + ["operator", "="], + ["operator", "<>"], + ["operator", ">"], + ["operator", ">="], + ["operator", "<"], + ["operator", "<="], + + ["operator", "=~"], + ["operator", "|"], + ["operator", ":"], + ["operator", ".."], + + ["operator", "-"], + ["operator", "->"], + ["operator", "<-"], + ["operator", "-"], + ["operator", "-"], + ["operator", "-"], + ["operator", "--"], + ["operator", "<--"], + ["operator", "-->"] +] + +---------------------------------------------------- + +Checks for operators. diff --git a/tests/languages/cypher/punctuation_feature.test b/tests/languages/cypher/punctuation_feature.test new file mode 100644 index 0000000000..eeee234df9 --- /dev/null +++ b/tests/languages/cypher/punctuation_feature.test @@ -0,0 +1,19 @@ +( ) [ ] { } ; , . + +---------------------------------------------------- + +[ + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "["], + ["punctuation", "]"], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", ";"], + ["punctuation", ","], + ["punctuation", "."] +] + +---------------------------------------------------- + +Checks for punctuation. diff --git a/tests/languages/cypher/relationship_feature.test b/tests/languages/cypher/relationship_feature.test new file mode 100644 index 0000000000..ca5cbb7e0a --- /dev/null +++ b/tests/languages/cypher/relationship_feature.test @@ -0,0 +1,79 @@ +-[r:REL_TYPE]-> + +-[:REL_TYPE]-> + +<-[:LIKES]- + +-[{blocked: false}]-> + +-[:KNOWS*1..2]- + +-[*]-> + +-[*3..5]-> + +---------------------------------------------------- + +[ + ["operator", "-"], + ["punctuation", "["], + "r", + ["operator", ":"], + ["relationship", "REL_TYPE"], + ["punctuation", "]"], + ["operator", "->"], + + ["operator", "-"], + ["punctuation", "["], + ["operator", ":"], + ["relationship", "REL_TYPE"], + ["punctuation", "]"], + ["operator", "->"], + + ["operator", "<-"], + ["punctuation", "["], + ["operator", ":"], + ["relationship", "LIKES"], + ["punctuation", "]"], + ["operator", "-"], + + ["operator", "-"], + ["punctuation", "["], + ["punctuation", "{"], + "blocked", + ["operator", ":"], + ["boolean", "false"], + ["punctuation", "}"], + ["punctuation", "]"], + ["operator", "->"], + + ["operator", "-"], + ["punctuation", "["], + ["operator", ":"], + ["relationship", "KNOWS"], + ["operator", "*"], + ["number", "1"], + ["operator", ".."], + ["number", "2"], + ["punctuation", "]"], + ["operator", "-"], + + ["operator", "-"], + ["punctuation", "["], + ["operator", "*"], + ["punctuation", "]"], + ["operator", "->"], + + ["operator", "-"], + ["punctuation", "["], + ["operator", "*"], + ["number", "3"], + ["operator", ".."], + ["number", "5"], + ["punctuation", "]"], + ["operator", "->"] +] + +---------------------------------------------------- + +Checks for relationships. diff --git a/tests/languages/cypher/string_feature.test b/tests/languages/cypher/string_feature.test new file mode 100644 index 0000000000..00a64b2932 --- /dev/null +++ b/tests/languages/cypher/string_feature.test @@ -0,0 +1,19 @@ +"" +"foo" +'' +'foo' +"\foo//'\bar" + +---------------------------------------------------- + +[ + ["string", "\"\""], + ["string", "\"foo\""], + ["string", "''"], + ["string", "'foo'"], + ["string", "\"\\foo//'\\bar\""] +] + +---------------------------------------------------- + +Checks for strings. diff --git a/tests/languages/cypher/variable_feature.test b/tests/languages/cypher/variable_feature.test new file mode 100644 index 0000000000..73038b3b6c --- /dev/null +++ b/tests/languages/cypher/variable_feature.test @@ -0,0 +1,13 @@ +$name +a.$name + +---------------------------------------------------- + +[ + ["variable", "$name"], + "\r\na", ["punctuation", "."], ["variable", "$name"] +] + +---------------------------------------------------- + +Checks for variables. diff --git a/tests/languages/d/char_feature.test b/tests/languages/d/char_feature.test new file mode 100644 index 0000000000..8d62d47523 --- /dev/null +++ b/tests/languages/d/char_feature.test @@ -0,0 +1,23 @@ +'a' +'\'' +'\\' +'\n' +'\xFF' +'\377' +'\uFFFF' +'\U0010FFFF' +'\quot' + +---------------------------------------------------- + +[ + ["char", "'a'"], + ["char", "'\\''"], + ["char", "'\\\\'"], + ["char", "'\\n'"], + ["char", "'\\xFF'"], + ["char", "'\\377'"], + ["char", "'\\uFFFF'"], + ["char", "'\\U0010FFFF'"], + ["char", "'\\quot'"] +] diff --git a/tests/languages/d/comment_feature.test b/tests/languages/d/comment_feature.test index ed1f86036b..06e3074ea6 100644 --- a/tests/languages/d/comment_feature.test +++ b/tests/languages/d/comment_feature.test @@ -9,6 +9,9 @@ bar +/ baz +/ // This q{is} a comment // This /* is a */ comment +/* +comment +*/ ---------------------------------------------------- @@ -18,10 +21,11 @@ baz +/ ["comment", "/+ foo\r\nbar +/"], ["comment", "/+ foo\r\n\t/+\r\n\tbar +/\r\nbaz +/"], ["comment", "// This q{is} a comment"], - ["comment", "// This /* is a */ comment"] + ["comment", "// This /* is a */ comment"], + ["comment", "/*\r\ncomment\r\n*/"] ] ---------------------------------------------------- Checks for shebang and nestable multi-line comments. -Other comments are tested in clike. \ No newline at end of file +Other comments are tested in clike. diff --git a/tests/languages/d/issue2027.test b/tests/languages/d/issue2027.test new file mode 100644 index 0000000000..4f3cc7448a --- /dev/null +++ b/tests/languages/d/issue2027.test @@ -0,0 +1,47 @@ +string foo = "It's"; +foo = "It's"; +foo = "It's"; + +string bar = `It's`; +bar = `It's`; +bar = `It's`; +bar = `It's`; + +---------------------------------------------------- + +[ + ["keyword", "string"], + " foo ", + ["operator", "="], + ["string", "\"It's\""], + ["punctuation", ";"], + "\r\nfoo ", + ["operator", "="], + ["string", "\"It's\""], + ["punctuation", ";"], + "\r\nfoo ", + ["operator", "="], + ["string", "\"It's\""], + ["punctuation", ";"], + ["keyword", "string"], + " bar ", + ["operator", "="], + ["string", "`It's`"], + ["punctuation", ";"], + "\r\nbar ", + ["operator", "="], + ["string", "`It's`"], + ["punctuation", ";"], + "\r\nbar ", + ["operator", "="], + ["string", "`It's`"], + ["punctuation", ";"], + "\r\nbar ", + ["operator", "="], + ["string", "`It's`"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks for issue #2027 which was about strings not being matched correctly. diff --git a/tests/languages/d/string_feature.test b/tests/languages/d/string_feature.test index fc501b11d4..5eddabb335 100644 --- a/tests/languages/d/string_feature.test +++ b/tests/languages/d/string_feature.test @@ -19,19 +19,24 @@ bar/" q"|fo"o bar|" -'a' '\'' '\u000A' - "" "foo"c "bar"w "baz"d "fo\"o bar" `foo` +q{foo} +q{ q{bar} } + ---------------------------------------------------- [ - ["string", "r\"\""], ["string", "x\"\""], - ["string", "r\"fo\\\"o\"c"], ["string", "x\"00 FBCD\"w"], ["string", "r\"baz\"d"], + ["string", "r\"\""], + ["string", "x\"\""], + + ["string", "r\"fo\\\"o\"c"], + ["string", "x\"00 FBCD\"w"], + ["string", "r\"baz\"d"], ["string", "q\"[fo\"o\r\nbar]\""], ["string", "q\"(fo\"o\r\nbar)\""], @@ -43,14 +48,15 @@ bar" ["string", "q\"/fo\"o\r\nbar/\""], ["string", "q\"|fo\"o\r\nbar|\""], - ["string", "'a'"], ["string", "'\\''"], ["string", "'\\u000A'"], - ["string", "\"\""], ["string", "\"foo\"c"], ["string", "\"bar\"w"], ["string", "\"baz\"d"], ["string", "\"fo\\\"o\r\nbar\""], - ["string", "`foo`"] + ["string", "`foo`"], + + ["string", "q{foo}"], + ["string", "q{ q{bar} }"] ] ---------------------------------------------------- -Checks for strings. \ No newline at end of file +Checks for strings and token strings. diff --git a/tests/languages/d/token-string_feature.test b/tests/languages/d/token-string_feature.test deleted file mode 100644 index 01627c4a85..0000000000 --- a/tests/languages/d/token-string_feature.test +++ /dev/null @@ -1,13 +0,0 @@ -q{foo} -q{ q{bar} } - ----------------------------------------------------- - -[ - ["token-string", "q{foo}"], - ["token-string", "q{ q{bar} }"] -] - ----------------------------------------------------- - -Checks for token strings. \ No newline at end of file diff --git a/tests/languages/dart/class-name_feature.test b/tests/languages/dart/class-name_feature.test new file mode 100644 index 0000000000..f97d9ab6f6 --- /dev/null +++ b/tests/languages/dart/class-name_feature.test @@ -0,0 +1,174 @@ +class Foo with ns.Bar { + const Foo(this.bar); + + final Bar bar; + + Baz baz(ns.Bat bat) { + return Baz(bat); + } + +} + +class MyWidget extends SingleChildStatelessWidget { + MyWidget({Key key, Widget child}): super(key: key, child: child); + + @override + Widget buildWithChild(BuildContext context, Widget child) { + return SomethingWidget(child: child); + } +} + +var copy = Foo.Bar.from(foo); +ID foo = something(); + +---------------------------------------------------- + +[ + ["keyword", "class"], + ["class-name", ["Foo"]], + ["keyword", "with"], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bar" + ]], + ["punctuation", "{"], + + ["keyword", "const"], + ["class-name", ["Foo"]], + ["punctuation", "("], + ["keyword", "this"], + ["punctuation", "."], + "bar", + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "final"], ["class-name", ["Bar"]], " bar", ["punctuation", ";"], + + ["class-name", ["Baz"]], + ["generics", [ + ["punctuation", "<"], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bat" + ]], + ["punctuation", ">"] + ]], + ["function", "baz"], + ["punctuation", "("], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bat" + ]], + " bat", + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "return"], + ["class-name", ["Baz"]], + ["generics", [ + ["punctuation", "<"], + ["class-name", [ + ["namespace", [ + "ns", + ["punctuation", "."] + ]], + "Bat" + ]], + ["punctuation", ">"] + ]], + ["punctuation", "("], + "bat", + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["punctuation", "}"], + + ["keyword", "class"], + ["class-name", ["MyWidget"]], + ["keyword", "extends"], + ["class-name", ["SingleChildStatelessWidget"]], + ["punctuation", "{"], + + ["class-name", ["MyWidget"]], + ["punctuation", "("], + ["punctuation", "{"], + ["class-name", ["Key"]], + " key", + ["punctuation", ","], + ["class-name", ["Widget"]], + " child", + ["punctuation", "}"], + ["punctuation", ")"], + ["punctuation", ":"], + ["keyword", "super"], + ["punctuation", "("], + "key", + ["punctuation", ":"], + " key", + ["punctuation", ","], + " child", + ["punctuation", ":"], + " child", + ["punctuation", ")"], + ["punctuation", ";"], + + ["metadata", "@override"], + + ["class-name", ["Widget"]], + ["function", "buildWithChild"], + ["punctuation", "("], + ["class-name", ["BuildContext"]], + " context", + ["punctuation", ","], + ["class-name", ["Widget"]], + " child", + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "return"], + ["class-name", ["SomethingWidget"]], + ["punctuation", "("], + "child", + ["punctuation", ":"], + " child", + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["punctuation", "}"], + + ["keyword", "var"], + " copy ", + ["operator", "="], + ["class-name", ["Foo.Bar"]], + ["punctuation", "."], + ["function", "from"], + ["punctuation", "("], + "foo", + ["punctuation", ")"], + ["punctuation", ";"], + + ["class-name", ["ID"]], + " foo ", + ["operator", "="], + ["function", "something"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"] +] + +---------------------------------------------------- + +Checks class names and generics diff --git a/tests/languages/dart/keyword_feature.test b/tests/languages/dart/keyword_feature.test index a5e3c6c2da..745f75e9e8 100644 --- a/tests/languages/dart/keyword_feature.test +++ b/tests/languages/dart/keyword_feature.test @@ -3,19 +3,22 @@ abstract assert async await break case catch class; const -continue default deferred +continue covariant default deferred do dynamic else enum -export external +export extension external extends; factory final finally for -get if +get hide if implements; +interface; import -in library +in +library +mixin new; null -operator part rethrow return -set static super switch this +on operator part rethrow return +set show static super switch sync this throw try typedef var void while with yield @@ -27,23 +30,25 @@ void while with yield ["keyword", "break"], ["keyword", "case"], ["keyword", "catch"], ["keyword", "class"], ["punctuation", ";"], ["keyword", "const"], - ["keyword", "continue"], ["keyword", "default"], ["keyword", "deferred"], + ["keyword", "continue"], ["keyword", "covariant"], ["keyword", "default"], ["keyword", "deferred"], ["keyword", "do"], ["keyword", "dynamic"], ["keyword", "else"], ["keyword", "enum"], - ["keyword", "export"], ["keyword", "external"], + ["keyword", "export"], ["keyword", "extension"], ["keyword", "external"], ["keyword", "extends"], ["punctuation", ";"], ["keyword", "factory"], ["keyword", "final"], ["keyword", "finally"], ["keyword", "for"], - ["keyword", "get"], ["keyword", "if"], + ["keyword", "get"], ["keyword", "hide"], ["keyword", "if"], ["keyword", "implements"], ["punctuation", ";"], + ["keyword", "interface"], ["punctuation", ";"], ["keyword", "import"], ["keyword", "in"], ["keyword", "library"], + ["keyword", "mixin"], ["keyword", "new"], ["punctuation", ";"], ["keyword", "null"], - ["keyword", "operator"], ["keyword", "part"], ["keyword", "rethrow"], ["keyword", "return"], - ["keyword", "set"], ["keyword", "static"], ["keyword", "super"], ["keyword", "switch"], ["keyword", "this"], + ["keyword", "on"], ["keyword", "operator"], ["keyword", "part"], ["keyword", "rethrow"], ["keyword", "return"], + ["keyword", "set"], ["keyword", "show"], ["keyword", "static"], ["keyword", "super"], ["keyword", "switch"], ["keyword", "sync"], ["keyword", "this"], ["keyword", "throw"], ["keyword", "try"], ["keyword", "typedef"], ["keyword", "var"], ["keyword", "void"], ["keyword", "while"], ["keyword", "with"], ["keyword", "yield"] ] ---------------------------------------------------- -Checks for all keywords. \ No newline at end of file +Checks for all keywords. diff --git a/tests/languages/dart/metadata_feature.test b/tests/languages/dart/metadata_feature.test index e88e7ba126..2eecbac80a 100644 --- a/tests/languages/dart/metadata_feature.test +++ b/tests/languages/dart/metadata_feature.test @@ -1,20 +1,148 @@ @deprecated @override -@todo('seth', 'make this do something') +@ToDo('seth', 'make this do something') + +@DataTable("sale_orders") +class SaleOrder { + @DataColumn("sale_order_date") + DateTime date; +} + +@table +class Product { + @column + String name; +} + +const DataColumn column = const DataColumn(); + +const DataTable table = const DataTable(); + +class DataTable { + final String name; + + const DataTable([this.name]); +} + +class DataColumn { + final String name; + + const DataColumn([this.name]); +} ---------------------------------------------------- [ ["metadata", "@deprecated"], + ["metadata", "@override"], - ["metadata", "@todo"], + + ["metadata", "@ToDo"], ["punctuation", "("], - ["string", "'seth'"], + ["string-literal", [ + ["string", "'seth'"] + ]], ["punctuation", ","], - ["string", "'make this do something'"], - ["punctuation", ")"] + ["string-literal", [ + ["string", "'make this do something'"] + ]], + ["punctuation", ")"], + + ["metadata", "@DataTable"], + ["punctuation", "("], + ["string-literal", [ + ["string", "\"sale_orders\""] + ]], + ["punctuation", ")"], + + ["keyword", "class"], + ["class-name", ["SaleOrder"]], + ["punctuation", "{"], + + ["metadata", "@DataColumn"], + ["punctuation", "("], + ["string-literal", [ + ["string", "\"sale_order_date\""] + ]], + ["punctuation", ")"], + + ["class-name", ["DateTime"]], + " date", + ["punctuation", ";"], + + ["punctuation", "}"], + + ["metadata", "@table"], + ["keyword", "class"], ["class-name", ["Product"]], ["punctuation", "{"], + ["metadata", "@column"], + ["class-name", ["String"]], " name", ["punctuation", ";"], + ["punctuation", "}"], + + ["keyword", "const"], + ["class-name", ["DataColumn"]], + " column ", + ["operator", "="], + ["keyword", "const"], + ["class-name", ["DataColumn"]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "const"], + ["class-name", ["DataTable"]], + " table ", + ["operator", "="], + ["keyword", "const"], + ["class-name", ["DataTable"]], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + ["keyword", "class"], + ["class-name", ["DataTable"]], + ["punctuation", "{"], + + ["keyword", "final"], + ["class-name", ["String"]], + " name", + ["punctuation", ";"], + + ["keyword", "const"], + ["class-name", ["DataTable"]], + ["punctuation", "("], + ["punctuation", "["], + ["keyword", "this"], + ["punctuation", "."], + "name", + ["punctuation", "]"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["keyword", "class"], + ["class-name", ["DataColumn"]], + ["punctuation", "{"], + + ["keyword", "final"], + ["class-name", ["String"]], + " name", + ["punctuation", ";"], + + ["keyword", "const"], + ["class-name", ["DataColumn"]], + ["punctuation", "("], + ["punctuation", "["], + ["keyword", "this"], + ["punctuation", "."], + "name", + ["punctuation", "]"], + ["punctuation", ")"], + ["punctuation", ";"], + + ["punctuation", "}"] ] ---------------------------------------------------- -Checks for metadata. \ No newline at end of file +Checks for metadata. diff --git a/tests/languages/dart/operator_feature.test b/tests/languages/dart/operator_feature.test index 5d631fd0bb..01993d9ed4 100644 --- a/tests/languages/dart/operator_feature.test +++ b/tests/languages/dart/operator_feature.test @@ -1,14 +1,13 @@ ++ -- * / % ~/ + - ! ~ -<< >> ? -& ^ | ->= > <= < +< << <= <<= +> >> >= >>= +& ^ | ? as is is! == != && || = *= /= ~/= %= += -= -<<= >>= &= ^= |= ---------------------------------------------------- @@ -17,17 +16,16 @@ as is is! ["operator", "++"], ["operator", "--"], ["operator", "*"], ["operator", "/"], ["operator", "%"], ["operator", "~/"], ["operator", "+"], ["operator", "-"], ["operator", "!"], ["operator", "~"], - ["operator", "<<"], ["operator", ">>"], ["operator", "?"], - ["operator", "&"], ["operator", "^"], ["operator", "|"], - ["operator", ">="], ["operator", ">"], ["operator", "<="], ["operator", "<"], + ["operator", "<"], ["operator", "<<"], ["operator", "<="], ["operator", "<<="], + ["operator", ">"], ["operator", ">>"], ["operator", ">="], ["operator", ">>="], + ["operator", "&"], ["operator", "^"], ["operator", "|"], ["operator", "?"], ["operator", "as"], ["operator", "is"], ["operator", "is!"], ["operator", "=="], ["operator", "!="], ["operator", "&&"], ["operator", "||"], ["operator", "="], ["operator", "*="], ["operator", "/="], ["operator", "~/="], ["operator", "%="], ["operator", "+="], ["operator", "-="], - ["operator", "<<="], ["operator", ">>="], ["operator", "&="], ["operator", "^="], ["operator", "|="] ] ---------------------------------------------------- -Checks for all operators. \ No newline at end of file +Checks for all operators. diff --git a/tests/languages/dart/string_feature.test b/tests/languages/dart/string_feature.test index feffdbce44..951d9fe223 100644 --- a/tests/languages/dart/string_feature.test +++ b/tests/languages/dart/string_feature.test @@ -8,18 +8,89 @@ bar""" '''foo bar''' +'$string has ${string.length} letters' +"cookie has ${cookie.number_of_chips} chips" + ---------------------------------------------------- [ - ["string", "\"\""], ["string", "''"], - ["string", "r\"\""], ["string", "r''"], - ["string", "\"\"\"\"\"\""], ["string", "''''''"], - ["string", "r\"\"\"\"\"\""], ["string", "r''''''"], - ["string", "\"fo\\\"o\""], ["string", "'fo\\'o'"], - ["string", "\"\"\"foo\r\nbar\"\"\""], ["string", "'''foo\r\nbar'''"] + ["string-literal", [ + ["string", "\"\""] + ]], + ["string-literal", [ + ["string", "''"] + ]], + + ["string-literal", [ + ["string", "r\"\""] + ]], + ["string-literal", [ + ["string", "r''"] + ]], + + ["string-literal", [ + ["string", "\"\"\"\"\"\""] + ]], + ["string-literal", [ + ["string", "''''''"] + ]], + + ["string-literal", [ + ["string", "r\"\"\"\"\"\""] + ]], + ["string-literal", [ + ["string", "r''''''"] + ]], + + ["string-literal", [ + ["string", "\"fo\\\"o\""] + ]], + ["string-literal", [ + ["string", "'fo\\'o'"] + ]], + + ["string-literal", [ + ["string", "\"\"\"foo\r\nbar\"\"\""] + ]], + + ["string-literal", [ + ["string", "'''foo\r\nbar'''"] + ]], + + ["string-literal", [ + ["string", "'"], + ["interpolation", [ + ["punctuation", "$"], + ["expression", ["string"]] + ]], + ["string", " has "], + ["interpolation", [ + ["punctuation", "${"], + ["expression", [ + "string", + ["punctuation", "."], + "length" + ]], + ["punctuation", "}"] + ]], + ["string", " letters'"] + ]], + ["string-literal", [ + ["string", "\"cookie has "], + ["interpolation", [ + ["punctuation", "${"], + ["expression", [ + "cookie", + ["punctuation", "."], + "number_of_chips" + ]], + ["punctuation", "}"] + ]], + ["string", " chips\""] + ]] ] ---------------------------------------------------- Checks for single quoted and double quoted strings, -multi-line strings and "raw" strings. \ No newline at end of file +multi-line strings and "raw" strings. diff --git a/tests/languages/dataweave/boolean_feature.test b/tests/languages/dataweave/boolean_feature.test new file mode 100644 index 0000000000..6d1903d869 --- /dev/null +++ b/tests/languages/dataweave/boolean_feature.test @@ -0,0 +1,12 @@ +true +false + +---------------------------------------------------- + +[ + ["boolean", "true"], + ["boolean", "false"] +] + +---------------------------------------------------- +Check for boolean \ No newline at end of file diff --git a/tests/languages/dataweave/comment_feature.test b/tests/languages/dataweave/comment_feature.test new file mode 100644 index 0000000000..6791431849 --- /dev/null +++ b/tests/languages/dataweave/comment_feature.test @@ -0,0 +1,17 @@ +// Line comment "" + /* Block comment */ + /** + * MultiLine Comment + **/ +/* "" */ + +---------------------------------------------------- + +[ + ["comment", "// Line comment \"\"\t"], + ["comment", "/* Block comment */"], + ["comment", "/**\r\n\t* MultiLine Comment\r\n\t**/"], + ["comment", "/* \"\" */"] +] +---------------------------------------------------- +Check for comments \ No newline at end of file diff --git a/tests/languages/dataweave/dates_feature.test b/tests/languages/dataweave/dates_feature.test new file mode 100644 index 0000000000..fb0644e7fc --- /dev/null +++ b/tests/languages/dataweave/dates_feature.test @@ -0,0 +1,27 @@ +|12-12-2001-T12:00:00| +|12-12-2001-T12:00:00+03:00| +|12-12-2001-T12:00:00Z| +|12-12-2001| +|12:00:00| +|12:00:00Z| +|12:00:00-03:00| +|P1D| +|P1Y1D| +|P1Y1D2H3M5S| + +---------------------------------------------------- + +[ + ["date", "|12-12-2001-T12:00:00|"], + ["date", "|12-12-2001-T12:00:00+03:00|"], + ["date", "|12-12-2001-T12:00:00Z|"], + ["date", "|12-12-2001|"], + ["date", "|12:00:00|"], + ["date", "|12:00:00Z|"], + ["date", "|12:00:00-03:00|"], + ["date", "|P1D|"], + ["date", "|P1Y1D|"], + ["date", "|P1Y1D2H3M5S|"] +] +---------------------------------------------------- +Check for date \ No newline at end of file diff --git a/tests/languages/dataweave/functions_feature.test b/tests/languages/dataweave/functions_feature.test new file mode 100644 index 0000000000..84285da4a8 --- /dev/null +++ b/tests/languages/dataweave/functions_feature.test @@ -0,0 +1,30 @@ +myfunction(a, b,123) +payload.myFunction(1,2,3) + +---------------------------------------------------- + +[ + ["function", "myfunction"], + ["punctuation", "("], + "a", + ["punctuation", ","], + " b", + ["punctuation", ","], + ["number", "123"], + ["punctuation", ")"], + + "\r\npayload", + ["punctuation", "."], + ["function", "myFunction"], + ["punctuation", "("], + ["number", "1"], + ["punctuation", ","], + ["number", "2"], + ["punctuation", ","], + ["number", "3"], + ["punctuation", ")"] +] + +---------------------------------------------------- + +Check for functions diff --git a/tests/languages/dataweave/keywords_feature.test b/tests/languages/dataweave/keywords_feature.test new file mode 100644 index 0000000000..73d4e58bf0 --- /dev/null +++ b/tests/languages/dataweave/keywords_feature.test @@ -0,0 +1,134 @@ +%dw 2.0 +input payalod application/json +ns ns0 http://localhost.com +var a = 123 +type T = String +fun test(a: Number) = a + 123 +output application/json +--- +{} match { + case a is String -> x as String +} +update { + case a at .name -> +} +if(true or false and not true) do { + +} +else +payload match { + case a is String -> x as String +} + +null +unless +using + +---------------------------------------------------- + +[ + "%dw ", + ["number", "2.0"], + + ["keyword", "input"], + " payalod ", + ["mime-type", "application/json"], + + ["keyword", "ns"], + " ns0 ", + ["url", "http://localhost.com"], + + ["keyword", "var"], + " a ", + ["operator", "="], + ["number", "123"], + + ["keyword", "type"], + " T ", + ["operator", "="], + " String\r\n", + + ["keyword", "fun"], + ["function", "test"], + ["punctuation", "("], + ["property", "a"], + ["punctuation", ":"], + " Number", + ["punctuation", ")"], + ["operator", "="], + " a ", + ["operator", "+"], + ["number", "123"], + + ["keyword", "output"], + ["mime-type", "application/json"], + + ["operator", "---"], + + ["punctuation", "{"], + ["punctuation", "}"], + ["keyword", "match"], + ["punctuation", "{"], + + ["keyword", "case"], + " a ", + ["keyword", "is"], + " String ", + ["operator", "->"], + " x ", + ["keyword", "as"], + " String\r\n", + + ["punctuation", "}"], + + ["keyword", "update"], + ["punctuation", "{"], + + ["keyword", "case"], + " a ", + ["keyword", "at"], + ["punctuation", "."], + "name ", + ["operator", "->"], + + ["punctuation", "}"], + + ["keyword", "if"], + ["punctuation", "("], + ["boolean", "true"], + ["keyword", "or"], + ["boolean", "false"], + ["keyword", "and"], + ["keyword", "not"], + ["boolean", "true"], + ["punctuation", ")"], + ["keyword", "do"], + ["punctuation", "{"], + + ["punctuation", "}"], + + ["keyword", "else"], + + "\r\npayload ", + ["keyword", "match"], + ["punctuation", "{"], + + ["keyword", "case"], + " a ", + ["keyword", "is"], + " String ", + ["operator", "->"], + " x ", + ["keyword", "as"], + " String\r\n", + + ["punctuation", "}"], + + ["keyword", "null"], + ["keyword", "unless"], + ["keyword", "using"] +] + +---------------------------------------------------- + +Check for keywords diff --git a/tests/languages/dataweave/null_feature.test b/tests/languages/dataweave/null_feature.test new file mode 100644 index 0000000000..862eca5daa --- /dev/null +++ b/tests/languages/dataweave/null_feature.test @@ -0,0 +1,9 @@ +null + +---------------------------------------------------- + +[ + ["keyword", "null"] +] +---------------------------------------------------- +Check for null \ No newline at end of file diff --git a/tests/languages/dataweave/number_feature.test b/tests/languages/dataweave/number_feature.test new file mode 100644 index 0000000000..a902c641df --- /dev/null +++ b/tests/languages/dataweave/number_feature.test @@ -0,0 +1,25 @@ +0 +123 +3.14159 +5.0e8 +0.2E+2 +47e-5 +-1.23 +-2.34E33 +-4.34E-33 + +---------------------------------------------------- + +[ + ["number", "0"], + ["number", "123"], + ["number", "3.14159"], + ["number", "5.0e8"], + ["number", "0.2E+2"], + ["number", "47e-5"], + ["number", "-1.23"], + ["number", "-2.34E33"], + ["number", "-4.34E-33"] +] +---------------------------------------------------- +Check for number \ No newline at end of file diff --git a/tests/languages/dataweave/operators_feature.test b/tests/languages/dataweave/operators_feature.test new file mode 100644 index 0000000000..f2ea0cac01 --- /dev/null +++ b/tests/languages/dataweave/operators_feature.test @@ -0,0 +1,79 @@ +a > b +c < d +a = 1 +a << 1 +b >> 2 +d <= 2 +e >= 3 +f != 4 +g ~= 4 +h == 1 +(a) -> 1 +a ++ b +c -- d +payload.name! +payload.name? + +---------------------------------------------------- + +[ + "a ", + ["operator", ">"], + " b\r\nc ", + ["operator", "<"], + " d\r\na ", + ["operator", "="], + ["number", "1"], + + "\r\na ", + ["operator", "<<"], + ["number", "1"], + + "\r\nb ", + ["operator", ">>"], + ["number", "2"], + + "\r\nd ", + ["operator", "<="], + ["number", "2"], + + "\r\ne ", + ["operator", ">="], + ["number", "3"], + + "\r\nf ", + ["operator", "!="], + ["number", "4"], + + "\r\ng ", + ["operator", "~="], + ["number", "4"], + + "\r\nh ", + ["operator", "=="], + ["number", "1"], + + ["punctuation", "("], + "a", + ["punctuation", ")"], + ["operator", "->"], + ["number", "1"], + + "\r\na ", + ["operator", "++"], + " b\r\nc ", + ["operator", "--"], + " d\r\npayload", + ["punctuation", "."], + "name", + ["operator", "!"], + + "\r\npayload", + ["punctuation", "."], + "name", + ["operator", "?"] +] + +---------------------------------------------------- + +Check for operators diff --git a/tests/languages/dataweave/property_feature.test b/tests/languages/dataweave/property_feature.test new file mode 100644 index 0000000000..ee3148ebc3 --- /dev/null +++ b/tests/languages/dataweave/property_feature.test @@ -0,0 +1,53 @@ +{ + a: 123, + "My Name": true, + t#test : true, + "test" @(a: true): 2, + test#"test" @(a: true): 3 +} + +---------------------------------------------------- + +[ + ["punctuation", "{"], + + ["property", "a"], + ["punctuation", ":"], + ["number", "123"], + ["punctuation", ","], + + ["property", "\"My Name\""], + ["punctuation", ":"], + ["boolean", "true"], + ["punctuation", ","], + + ["property", "t#test"], + ["punctuation", ":"], + ["boolean", "true"], + ["punctuation", ","], + + ["property", "\"test\""], + ["punctuation", "@"], + ["punctuation", "("], + ["property", "a"], + ["punctuation", ":"], + ["boolean", "true"], + ["punctuation", ")"], + ["punctuation", ":"], + ["number", "2"], + ["punctuation", ","], + + ["property", "test#\"test\""], + ["punctuation", "@"], + ["punctuation", "("], + ["property", "a"], + ["punctuation", ":"], + ["boolean", "true"], + ["punctuation", ")"], + ["punctuation", ":"], + ["number", "3"], + + ["punctuation", "}"] +] +---------------------------------------------------- +Check for properties \ No newline at end of file diff --git a/tests/languages/dataweave/regex_feature.test b/tests/languages/dataweave/regex_feature.test new file mode 100644 index 0000000000..2ff1190c87 --- /dev/null +++ b/tests/languages/dataweave/regex_feature.test @@ -0,0 +1,15 @@ +/(asd)+?[a-Z]/ +/ / +/\w+\/\s*/ +/([0-1]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])/ + +---------------------------------------------------- + +[ + ["regex", "/(asd)+?[a-Z]/"], + ["regex", "/ /"], + ["regex", "/\\w+\\/\\s*/"], + ["regex", "/([0-1]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])/"] +] +---------------------------------------------------- +Check for regex \ No newline at end of file diff --git a/tests/languages/dataweave/string_feature.test b/tests/languages/dataweave/string_feature.test new file mode 100644 index 0000000000..854b3ca8d7 --- /dev/null +++ b/tests/languages/dataweave/string_feature.test @@ -0,0 +1,27 @@ +"" +"foo" +"foo\"bar\"baz" +"\u2642\\" +`hello` +'test' +"this is a multiline +test +that +can +be long" +"This string \r\n Should also \\ \t" + +---------------------------------------------------- + +[ + ["string", "\"\""], + ["string", "\"foo\""], + ["string", "\"foo\\\"bar\\\"baz\""], + ["string", "\"\\u2642\\\\\""], + ["string", "`hello`"], + ["string", "'test'"], + ["string", "\"this is a multiline\r\ntest\r\nthat \r\ncan \r\nbe long\""], + ["string", "\"This string \\r\\n Should also \\\\ \\t\""] +] +---------------------------------------------------- +Check for strings \ No newline at end of file diff --git a/tests/languages/dax/boolean_feature.test b/tests/languages/dax/boolean_feature.test new file mode 100644 index 0000000000..cc6bb4fdd6 --- /dev/null +++ b/tests/languages/dax/boolean_feature.test @@ -0,0 +1,15 @@ +TRUE +FALSE +NULL + +---------------------------------------------------- + +[ + ["boolean", "TRUE"], + ["boolean", "FALSE"], + ["boolean", "NULL"] +] + +---------------------------------------------------- + +Checks for booleans. \ No newline at end of file diff --git a/tests/languages/dax/comment_feature.test b/tests/languages/dax/comment_feature.test new file mode 100644 index 0000000000..b43dfcb853 --- /dev/null +++ b/tests/languages/dax/comment_feature.test @@ -0,0 +1,21 @@ +/**/ +/* foo +bar */ +// +// foo +-- +-- foo +---------------------------------------------------- + +[ + ["comment", "/**/"], + ["comment", "/* foo\r\nbar */"], + ["comment", "//"], + ["comment", "// foo"], + ["comment", "--"], + ["comment", "-- foo"] +] + +---------------------------------------------------- + +Checks for comments. \ No newline at end of file diff --git a/tests/languages/dax/datafield_feature.test b/tests/languages/dax/datafield_feature.test new file mode 100644 index 0000000000..c5fbb8b541 --- /dev/null +++ b/tests/languages/dax/datafield_feature.test @@ -0,0 +1,29 @@ +'table'[field] +'table name'[field] +'ta""ble'[field] +'ta''ble'[field] +'table'[field name] +'table name'[field name] +table[field] +table[field name] +'table' +'こんにちは' + +---------------------------------------------------- + +[ + ["data-field", "'table'[field]"], + ["data-field", "'table name'[field]"], + ["data-field", "'ta\"\"ble'[field]"], + ["data-field", "'ta''ble'[field]"], + ["data-field", "'table'[field name]"], + ["data-field", "'table name'[field name]"], + ["data-field", "table[field]"], + ["data-field", "table[field name]"], + ["data-field", "'table'"], + ["data-field", "'こんにちは'"] +] + +---------------------------------------------------- + +Checks for datafield tokens. \ No newline at end of file diff --git a/tests/languages/dax/function_feature.test b/tests/languages/dax/function_feature.test new file mode 100644 index 0000000000..618ca41ef0 --- /dev/null +++ b/tests/languages/dax/function_feature.test @@ -0,0 +1,596 @@ +ABS ( +ABS( +ACOS( +ACOSH( +ACOT( +ACOTH( +ADDCOLUMNS( +ADDMISSINGITEMS( +ALL( +ALLCROSSFILTERED( +ALLEXCEPT( +ALLNOBLANKROW( +ALLSELECTED( +AND( +APPROXIMATEDISTINCTCOUNT( +ASIN( +ASINH( +ATAN( +ATANH( +AVERAGE( +AVERAGEA( +AVERAGEX( +BETA.DIST( +BETA.INV( +BLANK( +CALCULATE( +CALCULATETABLE( +CALENDAR( +CALENDARAUTO( +CEILING( +CHISQ.DIST( +CHISQ.DIST.RT( +CHISQ.INV( +CHISQ.INV.RT( +CLOSINGBALANCEMONTH( +CLOSINGBALANCEQUARTER( +CLOSINGBALANCEYEAR( +COALESCE( +COMBIN( +COMBINA( +COMBINEVALUES( +CONCATENATE( +CONCATENATEX( +CONFIDENCE.NORM( +CONFIDENCE.T( +CONTAINS( +CONTAINSROW( +CONTAINSSTRING( +CONTAINSSTRINGEXACT( +CONVERT( +COS( +COSH( +COT( +COTH( +COUNT( +COUNTA( +COUNTAX( +COUNTBLANK( +COUNTROWS( +COUNTX( +CROSSFILTER( +CROSSJOIN( +CURRENCY( +CURRENTGROUP( +CUSTOMDATA( +DATATABLE( +DATE( +DATEADD( +DATEDIFF( +DATESBETWEEN( +DATESINPERIOD( +DATESMTD( +DATESQTD( +DATESYTD( +DATEVALUE( +DAY( +DEGREES( +DETAILROWS( +DISTINCT( +DISTINCTCOUNT( +DISTINCTCOUNTNOBLANK( +DIVIDE( +EARLIER( +EARLIEST( +EDATE( +ENDOFMONTH( +ENDOFQUARTER( +ENDOFYEAR( +EOMONTH( +ERROR( +EVEN( +EXACT( +EXCEPT( +EXP( +EXPON.DIST( +FACT( +FALSE( +FILTER( +FILTERS( +FIND( +FIRSTDATE( +FIRSTNONBLANK( +FIRSTNONBLANKVALUE( +FIXED( +FLOOR( +FORMAT( +GCD( +GENERATE( +GENERATEALL( +GENERATESERIES( +GEOMEAN( +GEOMEANX( +GROUPBY( +HASONEFILTER( +HASONEVALUE( +HOUR( +IF( +IF.EAGER( +IFERROR( +IGNORE( +INT( +INTERSECT( +ISBLANK( +ISCROSSFILTERED( +ISEMPTY( +ISERROR( +ISEVEN( +ISFILTERED( +ISINSCOPE( +ISLOGICAL( +ISNONTEXT( +ISNUMBER( +ISO.CEILING( +ISODD( +ISONORAFTER( +ISSELECTEDMEASURE( +ISSUBTOTAL( +ISTEXT( +KEEPFILTERS( +KEYWORDMATCH( +LASTDATE( +LASTNONBLANK( +LASTNONBLANKVALUE( +LCM( +LEFT( +LEN( +LN( +LOG( +LOG10( +LOOKUPVALUE( +LOWER( +MAX( +MAXA( +MAXX( +MEDIAN( +MEDIANX( +MID( +MIN( +MINA( +MINUTE( +MINX( +MOD( +MONTH( +MROUND( +NATURALINNERJOIN( +NATURALLEFTOUTERJOIN( +NEXTDAY( +NEXTMONTH( +NEXTQUARTER( +NEXTYEAR( +NONVISUAL( +NORM.DIST( +NORM.INV( +NORM.S.DIST( +NORM.S.INV( +NOT( +NOW( +ODD( +OPENINGBALANCEMONTH( +OPENINGBALANCEQUARTER( +OPENINGBALANCEYEAR( +OR( +PARALLELPERIOD( +PATH( +PATHCONTAINS( +PATHITEM( +PATHITEMREVERSE( +PATHLENGTH( +PERCENTILE.EXC( +PERCENTILE.INC( +PERCENTILEX.EXC( +PERCENTILEX.INC( +PERMUT( +PI( +POISSON.DIST( +POWER( +PREVIOUSDAY( +PREVIOUSMONTH( +PREVIOUSQUARTER( +PREVIOUSYEAR( +PRODUCT( +PRODUCTX( +QUARTER( +QUOTIENT( +RADIANS( +RAND( +RANDBETWEEN( +RANK.EQ( +RANKX( +RELATED( +RELATEDTABLE( +REMOVEFILTERS( +REPLACE( +REPT( +RIGHT( +ROLLUP( +ROLLUPADDISSUBTOTAL( +ROLLUPGROUP( +ROLLUPISSUBTOTAL( +ROUND( +ROUNDDOWN( +ROUNDUP( +ROW( +SAMEPERIODLASTYEAR( +SAMPLE( +SEARCH( +SECOND( +SELECTCOLUMNS( +SELECTEDMEASURE( +SELECTEDMEASUREFORMATSTRING( +SELECTEDMEASURENAME( +SELECTEDVALUE( +SIGN( +SIN( +SINH( +SQRT( +SQRTPI( +STARTOFMONTH( +STARTOFQUARTER( +STARTOFYEAR( +STDEV.P( +STDEV.S( +STDEVX.P( +STDEVX.S( +SUBSTITUTE( +SUBSTITUTEWITHINDEX( +SUM( +SUMMARIZE( +SUMMARIZECOLUMNS( +SUMX( +SWITCH( +T.DIST( +T.DIST.2T( +T.DIST.RT( +T.INV( +T.INV.2T( +TAN( +TANH( +TIME( +TIMEVALUE( +TODAY( +TOPN( +TOPNPERLEVEL( +TOPNSKIP( +TOTALMTD( +TOTALQTD( +TOTALYTD( +TREATAS( +TRIM( +TRUE( +TRUNC( +UNICHAR( +UNICODE( +UNION( +UPPER( +USERELATIONSHIP( +USERNAME( +USEROBJECTID( +USERPRINCIPALNAME( +UTCNOW( +UTCTODAY( +VALUE( +VALUES( +VAR.P( +VAR.S( +VARX.P( +VARX.S( +WEEKDAY( +WEEKNUM( +XIRR( +XNPV( +YEAR( +YEARFRAC( + + +---------------------------------------------------- + +[ + ["function", "ABS"], ["punctuation", "("], + ["function", "ABS"], ["punctuation","("], + ["function", "ACOS"], ["punctuation","("], + ["function", "ACOSH"], ["punctuation","("], + ["function", "ACOT"], ["punctuation","("], + ["function", "ACOTH"], ["punctuation","("], + ["function", "ADDCOLUMNS"], ["punctuation","("], + ["function", "ADDMISSINGITEMS"], ["punctuation","("], + ["function", "ALL"], ["punctuation","("], + ["function", "ALLCROSSFILTERED"], ["punctuation","("], + ["function", "ALLEXCEPT"], ["punctuation","("], + ["function", "ALLNOBLANKROW"], ["punctuation","("], + ["function", "ALLSELECTED"], ["punctuation","("], + ["function", "AND"], ["punctuation","("], + ["function", "APPROXIMATEDISTINCTCOUNT"], ["punctuation","("], + ["function", "ASIN"], ["punctuation","("], + ["function", "ASINH"], ["punctuation","("], + ["function", "ATAN"], ["punctuation","("], + ["function", "ATANH"], ["punctuation","("], + ["function", "AVERAGE"], ["punctuation","("], + ["function", "AVERAGEA"], ["punctuation","("], + ["function", "AVERAGEX"], ["punctuation","("], + ["function", "BETA.DIST"], ["punctuation","("], + ["function", "BETA.INV"], ["punctuation","("], + ["function", "BLANK"], ["punctuation","("], + ["function", "CALCULATE"], ["punctuation","("], + ["function", "CALCULATETABLE"], ["punctuation","("], + ["function", "CALENDAR"], ["punctuation","("], + ["function", "CALENDARAUTO"], ["punctuation","("], + ["function", "CEILING"], ["punctuation","("], + ["function", "CHISQ.DIST"], ["punctuation","("], + ["function", "CHISQ.DIST.RT"], ["punctuation","("], + ["function", "CHISQ.INV"], ["punctuation","("], + ["function", "CHISQ.INV.RT"], ["punctuation","("], + ["function", "CLOSINGBALANCEMONTH"], ["punctuation","("], + ["function", "CLOSINGBALANCEQUARTER"], ["punctuation","("], + ["function", "CLOSINGBALANCEYEAR"], ["punctuation","("], + ["function", "COALESCE"], ["punctuation","("], + ["function", "COMBIN"], ["punctuation","("], + ["function", "COMBINA"], ["punctuation","("], + ["function", "COMBINEVALUES"], ["punctuation","("], + ["function", "CONCATENATE"], ["punctuation","("], + ["function", "CONCATENATEX"], ["punctuation","("], + ["function", "CONFIDENCE.NORM"], ["punctuation","("], + ["function", "CONFIDENCE.T"], ["punctuation","("], + ["function", "CONTAINS"], ["punctuation","("], + ["function", "CONTAINSROW"], ["punctuation","("], + ["function", "CONTAINSSTRING"], ["punctuation","("], + ["function", "CONTAINSSTRINGEXACT"], ["punctuation","("], + ["function", "CONVERT"], ["punctuation","("], + ["function", "COS"], ["punctuation","("], + ["function", "COSH"], ["punctuation","("], + ["function", "COT"], ["punctuation","("], + ["function", "COTH"], ["punctuation","("], + ["function", "COUNT"], ["punctuation","("], + ["function", "COUNTA"], ["punctuation","("], + ["function", "COUNTAX"], ["punctuation","("], + ["function", "COUNTBLANK"], ["punctuation","("], + ["function", "COUNTROWS"], ["punctuation","("], + ["function", "COUNTX"], ["punctuation","("], + ["function", "CROSSFILTER"], ["punctuation","("], + ["function", "CROSSJOIN"], ["punctuation","("], + ["function", "CURRENCY"], ["punctuation","("], + ["function", "CURRENTGROUP"], ["punctuation","("], + ["function", "CUSTOMDATA"], ["punctuation","("], + ["function", "DATATABLE"], ["punctuation","("], + ["function", "DATE"], ["punctuation","("], + ["function", "DATEADD"], ["punctuation","("], + ["function", "DATEDIFF"], ["punctuation","("], + ["function", "DATESBETWEEN"], ["punctuation","("], + ["function", "DATESINPERIOD"], ["punctuation","("], + ["function", "DATESMTD"], ["punctuation","("], + ["function", "DATESQTD"], ["punctuation","("], + ["function", "DATESYTD"], ["punctuation","("], + ["function", "DATEVALUE"], ["punctuation","("], + ["function", "DAY"], ["punctuation","("], + ["function", "DEGREES"], ["punctuation","("], + ["function", "DETAILROWS"], ["punctuation","("], + ["function", "DISTINCT"], ["punctuation","("], + ["function", "DISTINCTCOUNT"], ["punctuation","("], + ["function", "DISTINCTCOUNTNOBLANK"], ["punctuation","("], + ["function", "DIVIDE"], ["punctuation","("], + ["function", "EARLIER"], ["punctuation","("], + ["function", "EARLIEST"], ["punctuation","("], + ["function", "EDATE"], ["punctuation","("], + ["function", "ENDOFMONTH"], ["punctuation","("], + ["function", "ENDOFQUARTER"], ["punctuation","("], + ["function", "ENDOFYEAR"], ["punctuation","("], + ["function", "EOMONTH"], ["punctuation","("], + ["function", "ERROR"], ["punctuation","("], + ["function", "EVEN"], ["punctuation","("], + ["function", "EXACT"], ["punctuation","("], + ["function", "EXCEPT"], ["punctuation","("], + ["function", "EXP"], ["punctuation","("], + ["function", "EXPON.DIST"], ["punctuation","("], + ["function", "FACT"], ["punctuation","("], + ["function", "FALSE"], ["punctuation","("], + ["function", "FILTER"], ["punctuation","("], + ["function", "FILTERS"], ["punctuation","("], + ["function", "FIND"], ["punctuation","("], + ["function", "FIRSTDATE"], ["punctuation","("], + ["function", "FIRSTNONBLANK"], ["punctuation","("], + ["function", "FIRSTNONBLANKVALUE"], ["punctuation","("], + ["function", "FIXED"], ["punctuation","("], + ["function", "FLOOR"], ["punctuation","("], + ["function", "FORMAT"], ["punctuation","("], + ["function", "GCD"], ["punctuation","("], + ["function", "GENERATE"], ["punctuation","("], + ["function", "GENERATEALL"], ["punctuation","("], + ["function", "GENERATESERIES"], ["punctuation","("], + ["function", "GEOMEAN"], ["punctuation","("], + ["function", "GEOMEANX"], ["punctuation","("], + ["function", "GROUPBY"], ["punctuation","("], + ["function", "HASONEFILTER"], ["punctuation","("], + ["function", "HASONEVALUE"], ["punctuation","("], + ["function", "HOUR"], ["punctuation","("], + ["function", "IF"], ["punctuation","("], + ["function", "IF.EAGER"], ["punctuation","("], + ["function", "IFERROR"], ["punctuation","("], + ["function", "IGNORE"], ["punctuation","("], + ["function", "INT"], ["punctuation","("], + ["function", "INTERSECT"], ["punctuation","("], + ["function", "ISBLANK"], ["punctuation","("], + ["function", "ISCROSSFILTERED"], ["punctuation","("], + ["function", "ISEMPTY"], ["punctuation","("], + ["function", "ISERROR"], ["punctuation","("], + ["function", "ISEVEN"], ["punctuation","("], + ["function", "ISFILTERED"], ["punctuation","("], + ["function", "ISINSCOPE"], ["punctuation","("], + ["function", "ISLOGICAL"], ["punctuation","("], + ["function", "ISNONTEXT"], ["punctuation","("], + ["function", "ISNUMBER"], ["punctuation","("], + ["function", "ISO.CEILING"], ["punctuation","("], + ["function", "ISODD"], ["punctuation","("], + ["function", "ISONORAFTER"], ["punctuation","("], + ["function", "ISSELECTEDMEASURE"], ["punctuation","("], + ["function", "ISSUBTOTAL"], ["punctuation","("], + ["function", "ISTEXT"], ["punctuation","("], + ["function", "KEEPFILTERS"], ["punctuation","("], + ["function", "KEYWORDMATCH"], ["punctuation","("], + ["function", "LASTDATE"], ["punctuation","("], + ["function", "LASTNONBLANK"], ["punctuation","("], + ["function", "LASTNONBLANKVALUE"], ["punctuation","("], + ["function", "LCM"], ["punctuation","("], + ["function", "LEFT"], ["punctuation","("], + ["function", "LEN"], ["punctuation","("], + ["function", "LN"], ["punctuation","("], + ["function", "LOG"], ["punctuation","("], + ["function", "LOG10"], ["punctuation","("], + ["function", "LOOKUPVALUE"], ["punctuation","("], + ["function", "LOWER"], ["punctuation","("], + ["function", "MAX"], ["punctuation","("], + ["function", "MAXA"], ["punctuation","("], + ["function", "MAXX"], ["punctuation","("], + ["function", "MEDIAN"], ["punctuation","("], + ["function", "MEDIANX"], ["punctuation","("], + ["function", "MID"], ["punctuation","("], + ["function", "MIN"], ["punctuation","("], + ["function", "MINA"], ["punctuation","("], + ["function", "MINUTE"], ["punctuation","("], + ["function", "MINX"], ["punctuation","("], + ["function", "MOD"], ["punctuation","("], + ["function", "MONTH"], ["punctuation","("], + ["function", "MROUND"], ["punctuation","("], + ["function", "NATURALINNERJOIN"], ["punctuation","("], + ["function", "NATURALLEFTOUTERJOIN"], ["punctuation","("], + ["function", "NEXTDAY"], ["punctuation","("], + ["function", "NEXTMONTH"], ["punctuation","("], + ["function", "NEXTQUARTER"], ["punctuation","("], + ["function", "NEXTYEAR"], ["punctuation","("], + ["function", "NONVISUAL"], ["punctuation","("], + ["function", "NORM.DIST"], ["punctuation","("], + ["function", "NORM.INV"], ["punctuation","("], + ["function", "NORM.S.DIST"], ["punctuation","("], + ["function", "NORM.S.INV"], ["punctuation","("], + ["function", "NOT"], ["punctuation","("], + ["function", "NOW"], ["punctuation","("], + ["function", "ODD"], ["punctuation","("], + ["function", "OPENINGBALANCEMONTH"], ["punctuation","("], + ["function", "OPENINGBALANCEQUARTER"], ["punctuation","("], + ["function", "OPENINGBALANCEYEAR"], ["punctuation","("], + ["function", "OR"], ["punctuation","("], + ["function", "PARALLELPERIOD"], ["punctuation","("], + ["function", "PATH"], ["punctuation","("], + ["function", "PATHCONTAINS"], ["punctuation","("], + ["function", "PATHITEM"], ["punctuation","("], + ["function", "PATHITEMREVERSE"], ["punctuation","("], + ["function", "PATHLENGTH"], ["punctuation","("], + ["function", "PERCENTILE.EXC"], ["punctuation","("], + ["function", "PERCENTILE.INC"], ["punctuation","("], + ["function", "PERCENTILEX.EXC"], ["punctuation","("], + ["function", "PERCENTILEX.INC"], ["punctuation","("], + ["function", "PERMUT"], ["punctuation","("], + ["function", "PI"], ["punctuation","("], + ["function", "POISSON.DIST"], ["punctuation","("], + ["function", "POWER"], ["punctuation","("], + ["function", "PREVIOUSDAY"], ["punctuation","("], + ["function", "PREVIOUSMONTH"], ["punctuation","("], + ["function", "PREVIOUSQUARTER"], ["punctuation","("], + ["function", "PREVIOUSYEAR"], ["punctuation","("], + ["function", "PRODUCT"], ["punctuation","("], + ["function", "PRODUCTX"], ["punctuation","("], + ["function", "QUARTER"], ["punctuation","("], + ["function", "QUOTIENT"], ["punctuation","("], + ["function", "RADIANS"], ["punctuation","("], + ["function", "RAND"], ["punctuation","("], + ["function", "RANDBETWEEN"], ["punctuation","("], + ["function", "RANK.EQ"], ["punctuation","("], + ["function", "RANKX"], ["punctuation","("], + ["function", "RELATED"], ["punctuation","("], + ["function", "RELATEDTABLE"], ["punctuation","("], + ["function", "REMOVEFILTERS"], ["punctuation","("], + ["function", "REPLACE"], ["punctuation","("], + ["function", "REPT"], ["punctuation","("], + ["function", "RIGHT"], ["punctuation","("], + ["function", "ROLLUP"], ["punctuation","("], + ["function", "ROLLUPADDISSUBTOTAL"], ["punctuation","("], + ["function", "ROLLUPGROUP"], ["punctuation","("], + ["function", "ROLLUPISSUBTOTAL"], ["punctuation","("], + ["function", "ROUND"], ["punctuation","("], + ["function", "ROUNDDOWN"], ["punctuation","("], + ["function", "ROUNDUP"], ["punctuation","("], + ["function", "ROW"], ["punctuation","("], + ["function", "SAMEPERIODLASTYEAR"], ["punctuation","("], + ["function", "SAMPLE"], ["punctuation","("], + ["function", "SEARCH"], ["punctuation","("], + ["function", "SECOND"], ["punctuation","("], + ["function", "SELECTCOLUMNS"], ["punctuation","("], + ["function", "SELECTEDMEASURE"], ["punctuation","("], + ["function", "SELECTEDMEASUREFORMATSTRING"], ["punctuation","("], + ["function", "SELECTEDMEASURENAME"], ["punctuation","("], + ["function", "SELECTEDVALUE"], ["punctuation","("], + ["function", "SIGN"], ["punctuation","("], + ["function", "SIN"], ["punctuation","("], + ["function", "SINH"], ["punctuation","("], + ["function", "SQRT"], ["punctuation","("], + ["function", "SQRTPI"], ["punctuation","("], + ["function", "STARTOFMONTH"], ["punctuation","("], + ["function", "STARTOFQUARTER"], ["punctuation","("], + ["function", "STARTOFYEAR"], ["punctuation","("], + ["function", "STDEV.P"], ["punctuation","("], + ["function", "STDEV.S"], ["punctuation","("], + ["function", "STDEVX.P"], ["punctuation","("], + ["function", "STDEVX.S"], ["punctuation","("], + ["function", "SUBSTITUTE"], ["punctuation","("], + ["function", "SUBSTITUTEWITHINDEX"], ["punctuation","("], + ["function", "SUM"], ["punctuation","("], + ["function", "SUMMARIZE"], ["punctuation","("], + ["function", "SUMMARIZECOLUMNS"], ["punctuation","("], + ["function", "SUMX"], ["punctuation","("], + ["function", "SWITCH"], ["punctuation","("], + ["function", "T.DIST"], ["punctuation","("], + ["function", "T.DIST.2T"], ["punctuation","("], + ["function", "T.DIST.RT"], ["punctuation","("], + ["function", "T.INV"], ["punctuation","("], + ["function", "T.INV.2T"], ["punctuation","("], + ["function", "TAN"], ["punctuation","("], + ["function", "TANH"], ["punctuation","("], + ["function", "TIME"], ["punctuation","("], + ["function", "TIMEVALUE"], ["punctuation","("], + ["function", "TODAY"], ["punctuation","("], + ["function", "TOPN"], ["punctuation","("], + ["function", "TOPNPERLEVEL"], ["punctuation","("], + ["function", "TOPNSKIP"], ["punctuation","("], + ["function", "TOTALMTD"], ["punctuation","("], + ["function", "TOTALQTD"], ["punctuation","("], + ["function", "TOTALYTD"], ["punctuation","("], + ["function", "TREATAS"], ["punctuation","("], + ["function", "TRIM"], ["punctuation","("], + ["function", "TRUE"], ["punctuation","("], + ["function", "TRUNC"], ["punctuation","("], + ["function", "UNICHAR"], ["punctuation","("], + ["function", "UNICODE"], ["punctuation","("], + ["function", "UNION"], ["punctuation","("], + ["function", "UPPER"], ["punctuation","("], + ["function", "USERELATIONSHIP"], ["punctuation","("], + ["function", "USERNAME"], ["punctuation","("], + ["function", "USEROBJECTID"], ["punctuation","("], + ["function", "USERPRINCIPALNAME"], ["punctuation","("], + ["function", "UTCNOW"], ["punctuation","("], + ["function", "UTCTODAY"], ["punctuation","("], + ["function", "VALUE"], ["punctuation","("], + ["function", "VALUES"], ["punctuation","("], + ["function", "VAR.P"], ["punctuation","("], + ["function", "VAR.S"], ["punctuation","("], + ["function", "VARX.P"], ["punctuation","("], + ["function", "VARX.S"], ["punctuation","("], + ["function", "WEEKDAY"], ["punctuation","("], + ["function", "WEEKNUM"], ["punctuation","("], + ["function", "XIRR"], ["punctuation","("], + ["function", "XNPV"], ["punctuation","("], + ["function", "YEAR"], ["punctuation","("], + ["function", "YEARFRAC"], ["punctuation","("] +] + +---------------------------------------------------- + +Checks for functions. \ No newline at end of file diff --git a/tests/languages/dax/keyword_feature.test b/tests/languages/dax/keyword_feature.test new file mode 100644 index 0000000000..568511bce5 --- /dev/null +++ b/tests/languages/dax/keyword_feature.test @@ -0,0 +1,37 @@ +DEFINE +MEASURE +EVALUATE +ORDER BY +ORDER BY +ORDER +BY +RETURN +VAR +START AT +START AT +START +AT +ASC +DESC + +---------------------------------------------------- + +[ + ["keyword", "DEFINE"], + ["keyword", "MEASURE"], + ["keyword", "EVALUATE"], + ["keyword", "ORDER BY"], + ["keyword", "ORDER\tBY"], + ["keyword", "ORDER\r\nBY"], + ["keyword", "RETURN"], + ["keyword", "VAR"], + ["keyword", "START AT"], + ["keyword", "START\tAT"], + ["keyword", "START\r\nAT"], + ["keyword", "ASC"], + ["keyword", "DESC"] +] + +---------------------------------------------------- + +Checks for all keywords. \ No newline at end of file diff --git a/tests/languages/dax/measure_feature.test b/tests/languages/dax/measure_feature.test new file mode 100644 index 0000000000..a7a694cb9d --- /dev/null +++ b/tests/languages/dax/measure_feature.test @@ -0,0 +1,15 @@ +[measure] +[measure name] +[こんにちは] + +---------------------------------------------------- + +[ + ["measure", "[measure]"], + ["measure", "[measure name]"], + ["measure", "[こんにちは]"] +] + +---------------------------------------------------- + +Checks for measure tokens. \ No newline at end of file diff --git a/tests/languages/dax/number_feature.test b/tests/languages/dax/number_feature.test new file mode 100644 index 0000000000..fe81803e39 --- /dev/null +++ b/tests/languages/dax/number_feature.test @@ -0,0 +1,15 @@ +42 +0.154 +.123 + +---------------------------------------------------- + +[ + ["number", "42"], + ["number", "0.154"], + ["number", ".123"] +] + +---------------------------------------------------- + +Checks for decimal numbers. \ No newline at end of file diff --git a/tests/languages/dax/operator_feature.test b/tests/languages/dax/operator_feature.test new file mode 100644 index 0000000000..97c4016e96 --- /dev/null +++ b/tests/languages/dax/operator_feature.test @@ -0,0 +1,23 @@ ++ - * / ^ += > >= < <= <> +& && || +:= + +IN +NOT + +---------------------------------------------------- + +[ + ["operator", "+"], ["operator", "-"], ["operator", "*"], ["operator", "/"], ["operator", "^"], + ["operator", "="], ["operator", ">"], ["operator", ">="], ["operator", "<"], ["operator", "<="], ["operator", "<>"], + ["operator", "&"], ["operator", "&&"], ["operator", "||"], + ["operator", ":="], + + ["operator", "IN"], + ["operator", "NOT"] +] + +---------------------------------------------------- + +Checks for all operators. \ No newline at end of file diff --git a/tests/languages/dax/string_feature.test b/tests/languages/dax/string_feature.test new file mode 100644 index 0000000000..381c95b8f4 --- /dev/null +++ b/tests/languages/dax/string_feature.test @@ -0,0 +1,18 @@ +"" +"foo" +"foo +bar" +"foo""bar" + +---------------------------------------------------- + +[ + ["string", "\"\""], + ["string", "\"foo\""], + ["string", "\"foo\r\nbar\""], + ["string", "\"foo\"\"bar\""] +] + +---------------------------------------------------- + +Checks for strings. diff --git a/tests/languages/dhall/boolean_feature.test b/tests/languages/dhall/boolean_feature.test new file mode 100644 index 0000000000..55c2410481 --- /dev/null +++ b/tests/languages/dhall/boolean_feature.test @@ -0,0 +1,13 @@ +False +True + +---------------------------------------------------- + +[ + ["boolean", "False"], + ["boolean", "True"] +] + +---------------------------------------------------- + +Checks for Bool literals. diff --git a/tests/languages/dhall/builtin_feature.test b/tests/languages/dhall/builtin_feature.test new file mode 100644 index 0000000000..8ec35a04ec --- /dev/null +++ b/tests/languages/dhall/builtin_feature.test @@ -0,0 +1,9 @@ +Some +None + +---------------------------------------------------- + +[ + ["builtin", "Some"], + ["builtin", "None"] +] diff --git a/tests/languages/dhall/comment_feature.test b/tests/languages/dhall/comment_feature.test new file mode 100644 index 0000000000..86a35a4e08 --- /dev/null +++ b/tests/languages/dhall/comment_feature.test @@ -0,0 +1,20 @@ +-- comment + +{- + comment + {- + nested comment + -} +-} + +---------------------------------------------------- + +[ + ["comment", "-- comment"], + + ["comment", "{-\r\n\tcomment\r\n\t{-\r\n\t\tnested comment\r\n\t-}\r\n-}"] +] + +---------------------------------------------------- + +Checks for comments. diff --git a/tests/languages/dhall/env_feature.test b/tests/languages/dhall/env_feature.test new file mode 100644 index 0000000000..68a3827e09 --- /dev/null +++ b/tests/languages/dhall/env_feature.test @@ -0,0 +1,21 @@ +env:DHALL_PRELUDE +env:"Quotes variable" + +---------------------------------------------------- + +[ + ["env", [ + ["function", "env"], + ["operator", ":"], + ["variable", "DHALL_PRELUDE"] + ]], + ["env", [ + ["function", "env"], + ["operator", ":"], + ["variable", "\"Quotes variable\""] + ]] +] + +---------------------------------------------------- + +Checks for environment variables. diff --git a/tests/languages/dhall/hash_feature.test b/tests/languages/dhall/hash_feature.test new file mode 100644 index 0000000000..934a4ecf1d --- /dev/null +++ b/tests/languages/dhall/hash_feature.test @@ -0,0 +1,15 @@ +sha256:33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037 + +---------------------------------------------------- + +[ + ["hash", [ + ["function", "sha256"], + ["operator", ":"], + ["number", "33f7f4c3aff62e5ecf4848f964363133452d420dcde045784518fb59fa970037"] + ]] +] + +---------------------------------------------------- + +Checks for sha256 hashes. diff --git a/tests/languages/dhall/keyword_feature.test b/tests/languages/dhall/keyword_feature.test new file mode 100644 index 0000000000..91a227e0f6 --- /dev/null +++ b/tests/languages/dhall/keyword_feature.test @@ -0,0 +1,39 @@ +as +assert +else +forall +if +in +let +merge +missing +then +toMap +using +with + +∀ + +---------------------------------------------------- + +[ + ["keyword", "as"], + ["keyword", "assert"], + ["keyword", "else"], + ["keyword", "forall"], + ["keyword", "if"], + ["keyword", "in"], + ["keyword", "let"], + ["keyword", "merge"], + ["keyword", "missing"], + ["keyword", "then"], + ["keyword", "toMap"], + ["keyword", "using"], + ["keyword", "with"], + + ["keyword", "∀"] +] + +---------------------------------------------------- + +Checks for keywords. diff --git a/tests/languages/dhall/label_feature.test b/tests/languages/dhall/label_feature.test new file mode 100644 index 0000000000..16255a2dce --- /dev/null +++ b/tests/languages/dhall/label_feature.test @@ -0,0 +1,11 @@ +`"foo"'s 123` + +---------------------------------------------------- + +[ + ["label", "`\"foo\"'s 123`"] +] + +---------------------------------------------------- + +Checks for escaped labels. diff --git a/tests/languages/dhall/number_feature.test b/tests/languages/dhall/number_feature.test new file mode 100644 index 0000000000..3cc8a50b1d --- /dev/null +++ b/tests/languages/dhall/number_feature.test @@ -0,0 +1,35 @@ +0 +123 +123e-5 +-123e+2 +123.456 ++123.456e-7 +0xFF +-0xFF ++0xFF + +Infinity +-Infinity +NaN + +---------------------------------------------------- + +[ + ["number", "0"], + ["number", "123"], + ["number", "123e-5"], + ["number", "-123e+2"], + ["number", "123.456"], + ["number", "+123.456e-7"], + ["number", "0xFF"], + ["number", "-0xFF"], + ["number", "+0xFF"], + + ["number", "Infinity"], + ["number", "-Infinity"], + ["number", "NaN"] +] + +---------------------------------------------------- + +Checks for numeric literals. diff --git a/tests/languages/dhall/operator_feature.test b/tests/languages/dhall/operator_feature.test new file mode 100644 index 0000000000..5f49f3eeb7 --- /dev/null +++ b/tests/languages/dhall/operator_feature.test @@ -0,0 +1,44 @@ +/\ //\\ && || != == == // -> ++ :: + ++ * # | = : ? < > | \ + +∧ ⩓ ≡ ⫽ λ → + +---------------------------------------------------- + +[ + ["operator", "/\\"], + ["operator", "//\\\\"], + ["operator", "&&"], + ["operator", "||"], + ["operator", "!="], + ["operator", "=="], + ["operator", "=="], + ["operator", "//"], + ["operator", "->"], + ["operator", "++"], + ["operator", "::"], + + ["operator", "+"], + ["operator", "*"], + ["operator", "#"], + ["operator", "|"], + ["operator", "="], + ["operator", ":"], + ["operator", "?"], + ["operator", "<"], + ["operator", ">"], + ["operator", "|"], + ["operator", "\\"], + + ["operator", "∧"], + ["operator", "⩓"], + ["operator", "≡"], + ["operator", "⫽"], + ["operator", "λ"], + ["operator", "→"] +] + +---------------------------------------------------- + +Checks for operators. diff --git a/tests/languages/dhall/punctuation_feature.test b/tests/languages/dhall/punctuation_feature.test new file mode 100644 index 0000000000..c18547e170 --- /dev/null +++ b/tests/languages/dhall/punctuation_feature.test @@ -0,0 +1,23 @@ +. .. / + +{ } [ ] ( ) , + +---------------------------------------------------- + +[ + ["punctuation", "."], + ["punctuation", ".."], + ["punctuation", "/"], + + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", "["], + ["punctuation", "]"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ","] +] + +---------------------------------------------------- + +Checks for punctuation. diff --git a/tests/languages/dhall/string_feature.test b/tests/languages/dhall/string_feature.test new file mode 100644 index 0000000000..215aa23ab9 --- /dev/null +++ b/tests/languages/dhall/string_feature.test @@ -0,0 +1,48 @@ +"" +"foo" +"\"" + +"foo/${bar}" + +''foo'' +''bar'''baz'' + +'' +foo/${bar} +'' + +---------------------------------------------------- + +[ + ["string", ["\"\""]], + ["string", ["\"foo\""]], + ["string", ["\"\\\"\""]], + + ["string", [ + "\"foo/", + ["interpolation", [ + ["punctuation", "${"], + ["expression", ["bar"]], + ["punctuation", "}"] + ]], + "\"" + ]], + + ["string", ["''foo''"]], + ["string", ["''bar'''baz''"]], + + ["string", [ + "''\r\nfoo/", + ["interpolation", [ + ["punctuation", "${"], + ["expression", ["bar"]], + ["punctuation", "}"] + ]], + + "\r\n''" + ]] +] + +---------------------------------------------------- + +Checks for strings. diff --git a/tests/languages/dhall/url_feature.test b/tests/languages/dhall/url_feature.test new file mode 100644 index 0000000000..adea9f26f6 --- /dev/null +++ b/tests/languages/dhall/url_feature.test @@ -0,0 +1,11 @@ +https://prelude.dhall-lang.org/Natural/sum + +---------------------------------------------------- + +[ + ["url", "https://prelude.dhall-lang.org/Natural/sum"] +] + +---------------------------------------------------- + +Checks for URL literals. diff --git a/tests/languages/diff/diff_feature.test b/tests/languages/diff/diff_feature.test index 0e53490016..2dbba25c82 100644 --- a/tests/languages/diff/diff_feature.test +++ b/tests/languages/diff/diff_feature.test @@ -1,5 +1,7 @@ ! qt: core + unchanged + - qt: core + qt: core gui @@ -9,13 +11,14 @@ ---------------------------------------------------- [ - ["diff", "! qt: core"], - ["deleted", "- qt: core"], - ["inserted", "+ qt: core gui"], - ["deleted", "< qt: core"], - ["inserted", "> qt: core quick"] + ["diff", [["prefix", "!"], ["line", " qt: core\r\n"]]], + ["unchanged", [["prefix", " "], ["line", " unchanged\r\n"]]], + ["deleted-sign", [["prefix", "-"], ["line", " qt: core\r\n"]]], + ["inserted-sign", [["prefix", "+"], ["line", " qt: core gui\r\n"]]], + ["deleted-arrow", [["prefix", "<"], ["line", " qt: core\r\n"]]], + ["inserted-arrow", [["prefix", ">"], ["line", " qt: core quick"]]] ] ---------------------------------------------------- -Checks for deleted, inserted and different lines. \ No newline at end of file +Checks for deleted, inserted and different lines. diff --git a/tests/languages/django!+css/inclusion.test b/tests/languages/django!+css/inclusion.test new file mode 100644 index 0000000000..ef4bb9c74e --- /dev/null +++ b/tests/languages/django!+css/inclusion.test @@ -0,0 +1,56 @@ + + +---------------------------------------------------- + +[ + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "style" + ]], + ["punctuation", ">"] + ]], + ["style", [ + ["language-css", [ + ["selector", "a"], + ["punctuation", "{"], + ["django", [ + ["delimiter", "{%"], + ["tag", "if"], + ["variable", "setColor"], + ["delimiter", "%}"] + ]], + ["property", "color"], + ["punctuation", ":"], + ["django", [ + ["delimiter", "{{"], + ["variable", "bar"], + ["delimiter", "}}"] + ]], + ["punctuation", ";"], + ["django", [ + ["delimiter", "{%"], + ["tag", "endif"], + ["delimiter", "%}"] + ]], + ["punctuation", "}"] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]] +] + +---------------------------------------------------- + +Checks for Django/Jinja2 code inside \r\n\t`"]]], - ["punctuation", ";"] + ["language-javascript", [ + ["keyword", "let"], + " str ", + ["operator", "="], + ["template-string", [ + ["template-punctuation", "`"], + ["string", "\r\n\t\t\r\n\t"], + ["template-punctuation", "`"] + ]], + ["punctuation", ";"] + ]] ]], ["tag", [ ["tag", [ @@ -35,4 +40,4 @@ ---------------------------------------------------- -Checks for Javascript usage inside Markup, using + +'; +]]> +"foo" + + + + + ---------------------------------------------------- [ - ["tag", [ ["tag", [ ["punctuation", "<"], "script" ]], - ["attr-name", [ - "type" - ]], + ["attr-name", ["type"]], ["attr-value", [ ["punctuation", "="], ["punctuation", "\""], @@ -24,9 +33,11 @@ ["punctuation", ">"] ]], ["script", [ - ["function", "foo"], - ["punctuation", "("], - ["punctuation", ")"] + ["language-javascript", [ + ["function", "foo"], + ["punctuation", "("], + ["punctuation", ")"] + ]] ]], ["tag", [ ["tag", [ @@ -44,7 +55,9 @@ ["punctuation", ">"] ]], ["script", [ - ["string", "\"foo bar\""] + ["language-javascript", [ + ["string", "\"foo bar\""] + ]] ]], ["tag", [ ["tag", [ @@ -52,9 +65,94 @@ "script" ]], ["punctuation", ">"] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "script" + ]], + ["attr-name", ["type"]], + ["attr-value", [ + ["punctuation", "="], + ["punctuation", "\""], + "application/javascript", + ["punctuation", "\""] + ]], + ["punctuation", ">"] + ]], + ["script", [ + ["language-javascript", [ + ["keyword", "var"], + " a ", + ["operator", "="], + ["number", "0"], + ["punctuation", ";"] + ]], + ["included-cdata", [ + ["cdata", "'"], + ["punctuation", ";"] + ]], + ["cdata", "]]>"] + ]], + ["language-javascript", [ + ["string", "\"foo\""] + ]] + ]], + ["tag", [ + ["tag", [ + ["punctuation", ""] + ]], + + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "foo" + ]], + ["special-attr", [ + ["attr-name", "onclick"], + ["attr-value", [ + ["punctuation", "="], + ["punctuation", "\""], + ["value", [ + ["keyword", "this"], + ["punctuation", "."], + "textContent", + ["operator", "="], + ["string", "'Clicked!'"] + ]], + ["punctuation", "\""] + ]] + ]], + ["punctuation", ">"] + ]], + ["tag", [ + ["tag", [ + ["punctuation", "<"], + "foo" + ]], + ["attr-name", ["mouseover"]], + ["attr-value", [ + ["punctuation", "="], + ["punctuation", "\""], + "this.textContent=", + ["punctuation", "'"], + "Over!", + ["punctuation", "'"], + ["punctuation", "\""] + ]], + ["punctuation", ">"] ]] ] ---------------------------------------------------- -Checks for Javascript usage inside Markup, using `); + + // inherit language + test('

        Example 2

        ', `
        `); + }); + +}); diff --git a/tests/run.js b/tests/run.js index 46366cca3c..390d771d33 100644 --- a/tests/run.js +++ b/tests/run.js @@ -1,45 +1,30 @@ -"use strict"; +// @ts-check +'use strict'; -var TestDiscovery = require("./helper/test-discovery"); -var TestCase = require("./helper/test-case"); -var path = require("path"); -var argv = require("yargs").argv; +const TestDiscovery = require('./helper/test-discovery'); +const TestCase = require('./helper/test-case'); +const path = require('path'); +const { argv } = require('yargs'); -var testSuite; -if (argv.language) { - testSuite = TestDiscovery.loadSomeTests(__dirname + "/languages", argv.language); -} else { - // load complete test suite - testSuite = TestDiscovery.loadAllTests(__dirname + "/languages"); -} - -// define tests for all tests in all languages in the test suite -for (var language in testSuite) { - if (!testSuite.hasOwnProperty(language)) { - continue; - } - - (function (language, testFiles) { - describe("Testing language '" + language + "'", function () { - this.timeout(10000); +const testSuite = + (argv.language) + ? TestDiscovery.loadSomeTests(argv.language) + // load complete test suite + : TestDiscovery.loadAllTests(); - testFiles.forEach( - function (filePath) { - var fileName = path.basename(filePath, path.extname(filePath)); +const update = !!argv.update; - it("– should pass test case '" + fileName + "'", - function () { - - if (path.extname(filePath) === '.test') { - TestCase.runTestCase(language, filePath); - } else { - TestCase.runTestsWithHooks(language, require(filePath)); - } - - } - ); - } - ); - }); - })(language, testSuite[language]); -} \ No newline at end of file +// define tests for all tests in all languages in the test suite +for (const [languageIdentifier, files] of testSuite) { + describe("Testing language '" + languageIdentifier + "'", function () { + this.timeout(10000); + + for (const filePath of files) { + const fileName = path.basename(filePath, path.extname(filePath)); + + it("– should pass test case '" + fileName + "'", function () { + TestCase.runTestCase(languageIdentifier, filePath, update ? 'update' : 'insert'); + }); + } + }); +} diff --git a/tests/testrunner-tests.js b/tests/testrunner-tests.js index 24ad32cd8a..a7ca237359 100644 --- a/tests/testrunner-tests.js +++ b/tests/testrunner-tests.js @@ -1,166 +1,143 @@ -"use strict"; +'use strict'; -var assert = require("chai").assert; -var TokenStreamTransformer = require("./helper/token-stream-transformer"); -var TestCase = require("./helper/test-case"); +const { assert } = require('chai'); +const TokenStreamTransformer = require('./helper/token-stream-transformer'); +const TestCase = require('./helper/test-case'); -//region Token Stream Transformer -describe("The token stream transformer", - function () { - it("should handle all kinds of simple transformations", - function () { - var tokens = [ - {type: "type", content: "content"}, - "string" - ]; +describe('The token stream transformer', function () { - var expected = [ - ["type", "content"], - "string" - ]; + it('should handle all kinds of simple transformations', function () { + const tokens = [ + { type: 'type', content: 'content' }, + 'string' + ]; - assert.deepEqual(TokenStreamTransformer.simplify(tokens), expected); - } - ); - - - it("should handle nested structures", - function () { - var tokens = [ - { - type: "type", - content: [ - { - type: "insideType", content: - [ - {type: "insideInsideType", content: "content"} - ] - } - ] - } - ]; - - var expected = [ - ["type", [ - ["insideType", [ - ["insideInsideType", "content"] - ]] - ]] - ]; + const expected = [ + ['type', 'content'], + 'string' + ]; - assert.deepEqual(TokenStreamTransformer.simplify(tokens), expected); - } - ); - - - it("should strip empty tokens", - function () { - var tokenStream = [ - "", - "\r\n", - "\t", - " " - ]; - - var expectedSimplified = []; - - assert.deepEqual(TokenStreamTransformer.simplify(tokenStream), expectedSimplified); - } - ); + assert.deepEqual(TokenStreamTransformer.simplify(tokens), expected); + }); - it("should strip empty token tree branches", - function () { - var tokenStream = [ + it('should handle nested structures', function () { + const tokens = [ + { + type: 'type', + content: [ { - type: "type", + type: 'insideType', content: [ - ["", ""], - "", - {type: "nested", content: [""]} + { type: 'insideInsideType', content: 'content' } ] - }, - [[[[[[[""]]]]]]] - ]; - - var expectedSimplified = [ - ["type", [ - ["nested", []] - ]] - ]; - - assert.deepEqual(TokenStreamTransformer.simplify(tokenStream), expectedSimplified); + } + ] } - ); - - - it("should ignore all properties in tokens except value and content", - function () { - - var tokenStream = [ - {type: "type", content: "content", alias: "alias"} - ]; - - var expectedSimplified = [ - ["type", "content"] - ]; - - assert.deepEqual(TokenStreamTransformer.simplify(tokenStream), expectedSimplified); + ]; + + const expected = [ + ['type', [ + ['insideType', [ + ['insideInsideType', 'content'] + ]] + ]] + ]; + + assert.deepEqual(TokenStreamTransformer.simplify(tokens), expected); + }); + + + it('should strip empty tokens', function () { + const tokenStream = [ + '', + '\r\n', + '\t', + ' ' + ]; + + const expectedSimplified = []; + + assert.deepEqual(TokenStreamTransformer.simplify(tokenStream), expectedSimplified); + }); + + + it('should strip empty token tree branches', function () { + const tokenStream = [ + { + type: 'type', + content: [ + '', + { type: 'nested', content: [''] }, + '' + ] + }, + '' + ]; + + const expectedSimplified = [ + ['type', [ + ['nested', []] + ]] + ]; + + assert.deepEqual(TokenStreamTransformer.simplify(tokenStream), expectedSimplified); + }); + + + it('should ignore all properties in tokens except value and content', function () { + + const tokenStream = [ + { type: 'type', content: 'content', alias: 'alias' } + ]; + + const expectedSimplified = [ + ['type', 'content'] + ]; + + assert.deepEqual(TokenStreamTransformer.simplify(tokenStream), expectedSimplified); + }); +}); + +describe('The language name parsing', function () { + + it('should use the last language as the main language if no language is specified', function () { + assert.deepEqual( + TestCase.parseLanguageNames('a'), + { + languages: ['a'], + mainLanguage: 'a' } ); - } -); -//endregion - - -//region Language name parsing -describe("The language name parsing", - function () { - it("should use the last language as the main language if no language is specified", - function () { - assert.deepEqual( - TestCase.parseLanguageNames("a"), - { - languages: ["a"], - mainLanguage: "a" - } - ); - assert.deepEqual( - TestCase.parseLanguageNames("a+b+c"), - { - languages: ["a", "b", "c"], - mainLanguage: "c" - } - ); + assert.deepEqual( + TestCase.parseLanguageNames('a+b+c'), + { + languages: ['a', 'b', 'c'], + mainLanguage: 'c' } ); + }); - it("should use the specified language as main language", - function () { - assert.deepEqual( - TestCase.parseLanguageNames("a+b!+c"), - { - languages: ["a", "b", "c"], - mainLanguage: "b" - } - ); + it('should use the specified language as main language', function () { + assert.deepEqual( + TestCase.parseLanguageNames('a+b!+c'), + { + languages: ['a', 'b', 'c'], + mainLanguage: 'b' } ); + }); - it("should throw an error if there are multiple main languages", - function () { - assert.throw( - function () { - TestCase.parseLanguageNames("a+b!+c!"); - }, - "There are multiple main languages defined." - ); - } + it('should throw an error if there are multiple main languages', function () { + assert.throw( + () => { + TestCase.parseLanguageNames('a+b!+c!'); + }, + 'There are multiple main languages defined.' ); - } -); -//endregion + }); +}); diff --git a/themes/prism-coy.css b/themes/prism-coy.css index 6f04162e3c..ed1d399e14 100644 --- a/themes/prism-coy.css +++ b/themes/prism-coy.css @@ -9,6 +9,7 @@ pre[class*="language-"] { color: black; background: none; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; @@ -31,10 +32,12 @@ pre[class*="language-"] { position: relative; margin: .5em 0; overflow: visible; - padding: 0; + padding: 1px; } -pre[class*="language-"]>code { + +pre[class*="language-"] > code { position: relative; + z-index: 1; border-left: 10px solid #358ccb; box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf; background-color: #fdfdfd; @@ -44,7 +47,7 @@ pre[class*="language-"]>code { background-attachment: local; } -code[class*="language"] { +code[class*="language-"] { max-height: inherit; height: inherit; padding: 0 1em; @@ -52,7 +55,7 @@ code[class*="language"] { overflow: auto; } -/* Margin bottom to accomodate shadow */ +/* Margin bottom to accommodate shadow */ :not(pre) > code[class*="language-"], pre[class*="language-"] { background-color: #fdfdfd; @@ -76,7 +79,6 @@ pre[class*="language-"] { pre[class*="language-"]:before, pre[class*="language-"]:after { content: ''; - z-index: -2; display: block; position: absolute; bottom: 0.75em; @@ -92,7 +94,6 @@ pre[class*="language-"]:after { transform: rotate(-2deg); } -:not(pre) > code[class*="language-"]:after, pre[class*="language-"]:after { right: 0.75em; left: auto; @@ -177,7 +178,7 @@ pre[class*="language-"]:after { cursor: help; } -.namespace { +.token.namespace { opacity: .7; } @@ -190,23 +191,16 @@ pre[class*="language-"]:after { } -/* Plugin styles */ -.token.tab:not(:empty):before, -.token.cr:before, -.token.lf:before { - color: #e0d7d1; -} - /* Plugin styles: Line Numbers */ -pre[class*="language-"].line-numbers { +pre[class*="language-"].line-numbers.line-numbers { padding-left: 0; } -pre[class*="language-"].line-numbers code { +pre[class*="language-"].line-numbers.line-numbers code { padding-left: 3.8em; } -pre[class*="language-"].line-numbers .line-numbers-rows { +pre[class*="language-"].line-numbers.line-numbers .line-numbers-rows { left: 0; } diff --git a/themes/prism-coy.min.css b/themes/prism-coy.min.css new file mode 100644 index 0000000000..62495e569c --- /dev/null +++ b/themes/prism-coy.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{position:relative;margin:.5em 0;overflow:visible;padding:1px}pre[class*=language-]>code{position:relative;z-index:1;border-left:10px solid #358ccb;box-shadow:-1px 0 0 0 #358ccb,0 0 0 1px #dfdfdf;background-color:#fdfdfd;background-image:linear-gradient(transparent 50%,rgba(69,142,209,.04) 50%);background-size:3em 3em;background-origin:content-box;background-attachment:local}code[class*=language-]{max-height:inherit;height:inherit;padding:0 1em;display:block;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background-color:#fdfdfd;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-bottom:1em}:not(pre)>code[class*=language-]{position:relative;padding:.2em;border-radius:.3em;color:#c92c2c;border:1px solid rgba(0,0,0,.1);display:inline;white-space:normal}pre[class*=language-]:after,pre[class*=language-]:before{content:'';display:block;position:absolute;bottom:.75em;left:.18em;width:40%;height:20%;max-height:13em;box-shadow:0 13px 8px #979797;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-ms-transform:rotate(-2deg);-o-transform:rotate(-2deg);transform:rotate(-2deg)}pre[class*=language-]:after{right:.75em;left:auto;-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-ms-transform:rotate(2deg);-o-transform:rotate(2deg);transform:rotate(2deg)}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#7d8b99}.token.punctuation{color:#5f6364}.token.boolean,.token.constant,.token.deleted,.token.function-name,.token.number,.token.property,.token.symbol,.token.tag{color:#c92c2c}.token.attr-name,.token.builtin,.token.char,.token.function,.token.inserted,.token.selector,.token.string{color:#2f9c0a}.token.entity,.token.operator,.token.url,.token.variable{color:#a67f59;background:rgba(255,255,255,.5)}.token.atrule,.token.attr-value,.token.class-name,.token.keyword{color:#1990b8}.token.important,.token.regex{color:#e90}.language-css .token.string,.style .token.string{color:#a67f59;background:rgba(255,255,255,.5)}.token.important{font-weight:400}.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.namespace{opacity:.7}@media screen and (max-width:767px){pre[class*=language-]:after,pre[class*=language-]:before{bottom:14px;box-shadow:none}}pre[class*=language-].line-numbers.line-numbers{padding-left:0}pre[class*=language-].line-numbers.line-numbers code{padding-left:3.8em}pre[class*=language-].line-numbers.line-numbers .line-numbers-rows{left:0}pre[class*=language-][data-line]{padding-top:0;padding-bottom:0;padding-left:0}pre[data-line] code{position:relative;padding-left:4em}pre .line-highlight{margin-top:0} \ No newline at end of file diff --git a/themes/prism-dark.css b/themes/prism-dark.css index 7f4572877b..ea98cd103e 100644 --- a/themes/prism-dark.css +++ b/themes/prism-dark.css @@ -10,6 +10,7 @@ pre[class*="language-"] { background: none; text-shadow: 0 -.1em .2em black; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; @@ -69,7 +70,7 @@ pre[class*="language-"] { opacity: .7; } -.namespace { +.token.namespace { opacity: .7; } diff --git a/themes/prism-dark.min.css b/themes/prism-dark.min.css new file mode 100644 index 0000000000..e592b5b769 --- /dev/null +++ b/themes/prism-dark.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;text-shadow:0 -.1em .2em #000;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}:not(pre)>code[class*=language-],pre[class*=language-]{background:#4c3f33}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border:.3em solid #7a6651;border-radius:.5em;box-shadow:1px 1px .5em #000 inset}:not(pre)>code[class*=language-]{padding:.15em .2em .05em;border-radius:.3em;border:.13em solid #7a6651;box-shadow:1px 1px .3em -.1em #000 inset;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#997f66}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.number,.token.property,.token.symbol,.token.tag{color:#d1939e}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#bce051}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f4b73d}.token.atrule,.token.attr-value,.token.keyword{color:#d1939e}.token.important,.token.regex{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.deleted{color:red} \ No newline at end of file diff --git a/themes/prism-funky.css b/themes/prism-funky.css index dd3be06188..21a89410fc 100644 --- a/themes/prism-funky.css +++ b/themes/prism-funky.css @@ -7,6 +7,7 @@ code[class*="language-"], pre[class*="language-"] { font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; @@ -58,7 +59,7 @@ code[class*="language-"] { color: #999; } -.namespace { +.token.namespace { opacity: .7; } @@ -83,7 +84,7 @@ code[class*="language-"] { .token.entity, .token.url, .language-css .token.string, -.toke.variable, +.token.variable, .token.inserted { color: yellowgreen; } @@ -114,3 +115,16 @@ code[class*="language-"] { .token.deleted { color: red; } + +/* Plugin styles: Diff Highlight */ +pre.diff-highlight.diff-highlight > code .token.deleted:not(.prefix), +pre > code.diff-highlight.diff-highlight .token.deleted:not(.prefix) { + background-color: rgba(255, 0, 0, .3); + display: inline; +} + +pre.diff-highlight.diff-highlight > code .token.inserted:not(.prefix), +pre > code.diff-highlight.diff-highlight .token.inserted:not(.prefix) { + background-color: rgba(0, 255, 128, .3); + display: inline; +} diff --git a/themes/prism-funky.min.css b/themes/prism-funky.min.css new file mode 100644 index 0000000000..2e67a7a28f --- /dev/null +++ b/themes/prism-funky.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:.4em .8em;margin:.5em 0;overflow:auto;background:url('data:image/svg+xml;charset=utf-8,%0D%0A%0D%0A%0D%0A<%2Fsvg>');background-size:1em 1em}code[class*=language-]{background:#000;color:#fff;box-shadow:-.3em 0 0 .3em #000,.3em 0 0 .3em #000}:not(pre)>code[class*=language-]{padding:.2em;border-radius:.3em;box-shadow:none;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#aaa}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.number,.token.property,.token.symbol,.token.tag{color:#0cf}.token.attr-name,.token.builtin,.token.char,.token.selector,.token.string{color:#ff0}.language-css .token.string,.token.entity,.token.inserted,.token.operator,.token.url,.token.variable{color:#9acd32}.token.atrule,.token.attr-value,.token.keyword{color:#ff1493}.token.important,.token.regex{color:orange}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.deleted{color:red}pre.diff-highlight.diff-highlight>code .token.deleted:not(.prefix),pre>code.diff-highlight.diff-highlight .token.deleted:not(.prefix){background-color:rgba(255,0,0,.3);display:inline}pre.diff-highlight.diff-highlight>code .token.inserted:not(.prefix),pre>code.diff-highlight.diff-highlight .token.inserted:not(.prefix){background-color:rgba(0,255,128,.3);display:inline} \ No newline at end of file diff --git a/themes/prism-okaidia.css b/themes/prism-okaidia.css index 3e0da3575f..cf04068a45 100644 --- a/themes/prism-okaidia.css +++ b/themes/prism-okaidia.css @@ -10,6 +10,7 @@ pre[class*="language-"] { background: none; text-shadow: 0 1px rgba(0, 0, 0, 0.3); font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; @@ -51,14 +52,14 @@ pre[class*="language-"] { .token.prolog, .token.doctype, .token.cdata { - color: slategray; + color: #8292a2; } .token.punctuation { color: #f8f8f2; } -.namespace { +.token.namespace { opacity: .7; } @@ -95,7 +96,8 @@ pre[class*="language-"] { .token.atrule, .token.attr-value, -.token.function { +.token.function, +.token.class-name { color: #e6db74; } diff --git a/themes/prism-okaidia.min.css b/themes/prism-okaidia.min.css new file mode 100644 index 0000000000..dc0b418e32 --- /dev/null +++ b/themes/prism-okaidia.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#f8f8f2;background:0 0;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background:#272822}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#8292a2}.token.punctuation{color:#f8f8f2}.token.namespace{opacity:.7}.token.constant,.token.deleted,.token.property,.token.symbol,.token.tag{color:#f92672}.token.boolean,.token.number{color:#ae81ff}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#a6e22e}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url,.token.variable{color:#f8f8f2}.token.atrule,.token.attr-value,.token.class-name,.token.function{color:#e6db74}.token.keyword{color:#66d9ef}.token.important,.token.regex{color:#fd971f}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} \ No newline at end of file diff --git a/themes/prism-solarizedlight.css b/themes/prism-solarizedlight.css index bad770395b..65e4a65860 100644 --- a/themes/prism-solarizedlight.css +++ b/themes/prism-solarizedlight.css @@ -32,6 +32,7 @@ code[class*="language-"], pre[class*="language-"] { color: #657b83; /* base00 */ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; @@ -90,7 +91,7 @@ pre[class*="language-"] { color: #586e75; /* base01 */ } -.namespace { +.token.namespace { opacity: .7; } @@ -125,7 +126,8 @@ pre[class*="language-"] { color: #859900; /* green */ } -.token.function { +.token.function, +.token.class-name { color: #b58900; /* yellow */ } @@ -145,4 +147,4 @@ pre[class*="language-"] { .token.entity { cursor: help; -} \ No newline at end of file +} diff --git a/themes/prism-solarizedlight.min.css b/themes/prism-solarizedlight.min.css new file mode 100644 index 0000000000..8deecf9e55 --- /dev/null +++ b/themes/prism-solarizedlight.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#657b83;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{background:#073642}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{background:#073642}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}:not(pre)>code[class*=language-],pre[class*=language-]{background-color:#fdf6e3}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#93a1a1}.token.punctuation{color:#586e75}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#268bd2}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string,.token.url{color:#2aa198}.token.entity{color:#657b83;background:#eee8d5}.token.atrule,.token.attr-value,.token.keyword{color:#859900}.token.class-name,.token.function{color:#b58900}.token.important,.token.regex,.token.variable{color:#cb4b16}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} \ No newline at end of file diff --git a/themes/prism-tomorrow.css b/themes/prism-tomorrow.css index 6add2d2620..a0eeff0a38 100644 --- a/themes/prism-tomorrow.css +++ b/themes/prism-tomorrow.css @@ -9,6 +9,7 @@ pre[class*="language-"] { color: #ccc; background: none; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; diff --git a/themes/prism-tomorrow.min.css b/themes/prism-tomorrow.min.css new file mode 100644 index 0000000000..8fce55009d --- /dev/null +++ b/themes/prism-tomorrow.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#ccc;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green} \ No newline at end of file diff --git a/themes/prism-twilight.css b/themes/prism-twilight.css index 504ca7049c..63cc4c6b86 100644 --- a/themes/prism-twilight.css +++ b/themes/prism-twilight.css @@ -8,6 +8,7 @@ pre[class*="language-"] { color: white; background: none; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; text-shadow: 0 -.1em .2em black; white-space: pre; @@ -84,7 +85,7 @@ code[class*="language-"]::selection, code[class*="language-"] ::selection { opacity: .7; } -.namespace { +.token.namespace { opacity: .7; } @@ -139,11 +140,6 @@ code[class*="language-"]::selection, code[class*="language-"] ::selection { cursor: help; } -pre[data-line] { - padding: 1em 0 1em 3em; - position: relative; -} - /* Markup */ .language-markup .token.tag, .language-markup .token.attr-name, @@ -157,42 +153,17 @@ pre[data-line] { z-index: 1; } -.line-highlight { +.line-highlight.line-highlight { background: hsla(0, 0%, 33%, 0.25); /* #545454 */ background: linear-gradient(to right, hsla(0, 0%, 33%, .1) 70%, hsla(0, 0%, 33%, 0)); /* #545454 */ border-bottom: 1px dashed hsl(0, 0%, 33%); /* #545454 */ border-top: 1px dashed hsl(0, 0%, 33%); /* #545454 */ - left: 0; - line-height: inherit; margin-top: 0.75em; /* Same as .prism’s padding-top */ - padding: inherit 0; - pointer-events: none; - position: absolute; - right: 0; - white-space: pre; z-index: 0; } -.line-highlight:before, -.line-highlight[data-end]:after { +.line-highlight.line-highlight:before, +.line-highlight.line-highlight[data-end]:after { background-color: hsl(215, 15%, 59%); /* #8794A6 */ - border-radius: 999px; - box-shadow: 0 1px white; color: hsl(24, 20%, 95%); /* #F5F2F0 */ - content: attr(data-start); - font: bold 65%/1.5 sans-serif; - left: .6em; - min-width: 1em; - padding: 0 .5em; - position: absolute; - text-align: center; - text-shadow: none; - top: .4em; - vertical-align: .3em; -} - -.line-highlight[data-end]:after { - bottom: .4em; - content: attr(data-end); - top: auto; } diff --git a/themes/prism-twilight.min.css b/themes/prism-twilight.min.css new file mode 100644 index 0000000000..e598be8865 --- /dev/null +++ b/themes/prism-twilight.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;text-shadow:0 -.1em .2em #000;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}:not(pre)>code[class*=language-],pre[class*=language-]{background:#141414}pre[class*=language-]{border-radius:.5em;border:.3em solid #545454;box-shadow:1px 1px .5em #000 inset;margin:.5em 0;overflow:auto;padding:1em}pre[class*=language-]::-moz-selection{background:#27292a}pre[class*=language-]::selection{background:#27292a}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:hsla(0,0%,93%,.15)}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:hsla(0,0%,93%,.15)}:not(pre)>code[class*=language-]{border-radius:.3em;border:.13em solid #545454;box-shadow:1px 1px .3em -.1em #000 inset;padding:.15em .2em .05em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#777}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.deleted,.token.number,.token.tag{color:#ce6849}.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol{color:#f9ed99}.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable{color:#909e6a}.token.atrule{color:#7385a5}.token.important,.token.regex{color:#e8c062}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag{color:#ac885c}.token{position:relative;z-index:1}.line-highlight.line-highlight{background:hsla(0,0%,33%,.25);background:linear-gradient(to right,hsla(0,0%,33%,.1) 70%,hsla(0,0%,33%,0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;margin-top:.75em;z-index:0}.line-highlight.line-highlight:before,.line-highlight.line-highlight[data-end]:after{background-color:#8693a6;color:#f4f1ef} \ No newline at end of file diff --git a/themes/prism.css b/themes/prism.css index 9010cb637e..5b8ed2d132 100644 --- a/themes/prism.css +++ b/themes/prism.css @@ -10,6 +10,7 @@ pre[class*="language-"] { background: none; text-shadow: 0 1px white; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1em; text-align: left; white-space: pre; word-spacing: normal; @@ -76,7 +77,7 @@ pre[class*="language-"] { color: #999; } -.namespace { +.token.namespace { opacity: .7; } @@ -105,6 +106,7 @@ pre[class*="language-"] { .language-css .token.string, .style .token.string { color: #9a6e3a; + /* This background color was intended by the author of this theme. */ background: hsla(0, 0%, 100%, .5); } diff --git a/themes/prism.min.css b/themes/prism.min.css new file mode 100644 index 0000000000..8c4cc0576b --- /dev/null +++ b/themes/prism.min.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} \ No newline at end of file diff --git a/tokens.html b/tokens.html new file mode 100644 index 0000000000..0fa13cce4f --- /dev/null +++ b/tokens.html @@ -0,0 +1,437 @@ + + + + + + +Prism tokens ▲ Prism + + + + + + + + + + + + +
        +
        + +

        Prism tokens

        +

        Prism identifies tokens in your code, which are in turn styled by CSS to produce the syntax highlighting. This page provides an overview of the standard tokens and corresponding examples.

        +
        + +
        +

        Standard tokens

        + +

        When defining a new language, you will need to provide token names for each 'type' of code, such as keywords and operators, so Prism's themes can assign colors (and other styles) accordingly. Prism's themes (both official and non-official) only guarantee coverage for these standard tokens, so it is recommended to make use of the following standard tokens to ensure that code will be highlighted.

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        General purpose
        keyword + Pre-defined and reserved words. + +
        for (const foo of bar) {
        +	if (foo === 'foobar') break;
        +	await foo;
        +}
        +
        builtin + Functions/Methods/Classes/Types that are available out of the box. + +
        pi = round(float('3.14159'), 2)
        +
        type SearchFunc = (source: string, subStr: string) => boolean;
        +
        class-name + The name of a class, interface, trait, or type. + +
        class Rectangle extends Square { /* ... */ }
        +
        public class CameraController : MonoBehaviour { /* ... */ }
        +
        function + The name of a function or method. + +
        function isEven(number) {
        +	return Number(number) % 2 === 0;
        +}
        +const isOdd = (number) => !isEven(number);
        +
        boolean + True and false, and pairs with similar concepts (e.g. yes and no). + +
        console.log(true === false); // prints false
        +console.log(true === !false); // prints true
        +
        number + A numerical value, regardless of base and order, and no matter real or imaginary. + +
        print(3.14159 * 42)
        +print(1e100 + .001j)
        +return foo & 0xdeadbeef
        +
        string + Literal text, including numbers and symbols and maybe even more special characters. + +
        let greeting = 'Hello World!';
        +
        char + A string that can comprise only a single character, enforced by the language. + +
        ['A', 'z', '0', '-', '\t', '\u{2728}']
        +
        symbol + A primitive data type found in some languages, can be thought of as an identifier. + +
        #myFirstSymbol "#myFirstSymbol is a symbol in Smalltalk"
        +
        regex + A regular expression. + +
        let entity = /&#x?[\da-f]{1,8};/;
        +
        url + A link to another page or resource. + +
        body {
        +	background: url(foo.png);
        +}
        +
        [Prism](https://prismjs.com) is a cool syntax highlighter.
        +
        operator + A symbol that represents an action or process, whether it's a mathematical operation, logical operation, and so on. + +
        x += (y + 4 >> -z === w) ? b ** c : ~a;
        +
        variable + The name of a variable. This token is intended to be used sparingly. It's generally used on special variables (e.g. Less or Bash), not general variables from imperative and procedural programming languages (e.g. C, JavaScript, Python). + +
        @nice-blue: #5B83AD;
        +@light-blue: lighten(@nice-blue, 20%);
        +
        echo $STRING
        +args=("$@")
        +echo ${args[0]} ${args[1]} ${args[2]}
        +
        constant + The name of a constant. + +
        const PI = 3.14159;
        +
        const THING: u32 = 0xABAD1DEA;
        +
        fprintf(stdout, "hello world\n");
        +
        property + An attribute/characteristic or object/map key. + +
        body {
        +	color: red;
        +	line-height: normal;
        +}
        +
        {
        +	"data": { "labels": ["foo", "bar"], },
        +	"error": null,
        +	"status": "Ok"
        +}
        +
        punctuation + Punctuation such as brackets, parentheses, commas, and more. + +
        def median(pool):
        +	copy = sorted(pool)
        +	size = len(copy)
        +	if size % 2 == 1:
        +		return copy[(size - 1) / 2]
        +	else:
        +		return (copy[size/2 - 1] + copy[size/2]) / 2
        +
        important + Anything that is important and needs special highlighting. + +
        body {
        +	color: red !important;
        +}
        +
        # This is a heading. Headings are important.
        +
        comment + Code comments. + +
        <!-- Here's a comment -->
        +<style>
        +	/* Here's another comment */
        +</style>
        +<script>
        +// Here's yet another comment
        +</script>
        +
        Markup languages
        tag + A markup tag (e.g. HTML and XML tags). + +
        <p>Hello World!</p>
        +
        attr-name, attr-value + Kind of like a property of a markup tag and its value/argument respectively. + +
        <p id="greeting">Hello World!</p>
        +<video width="1280" height="720" allowfullscreen controls>
        +	<source src="hello_world.mp4" type="video/mp4" />
        +</video>
        +
        namespace + Used to provide uniquely named elements and attributes in XML documents. Outside of markup languages, it is used to tokenize the package/namespace part of identifiers. + +
        <html:p foo:bar="baz" foo:weee></html:p>
        +
        class Foo extends foo.bar.Foo {
        +	java.util.List<foo.bar.Foo.Bar> bar(foo.bar.Baz bat) {
        +		throw new java.lang.UnsupportedOperationException();
        +	}
        +}
        +
        use std::sync::Arc;
        +
        prolog + The first part of an XML document. + +
        <?xml version="1.0" encoding="utf-8"?>
        +<svg></svg>
        +
        doctype + Document type declaration, specific to markup languages. + +
        <!DOCTYPE html>
        +<html></html>
        +
        cdata + Character data, specific to markup languages. + +
        <ns1:description><![CDATA[
        +  CDATA is <not> magical.
        +]]></ns1:description>
        +
        entity + Code used to display reserved characters in markup languages. + +
        &amp; &#x2665; &#160; &#x152;
        +
        Document-markup languages
        bold + Bolded text. Mostly found in document-markup languages. + +
        **I am bolded text!**
        +
        italic + Italicised text. Mostly found in document-markup languages. + +
        *I am italicised text!*
        +
        Stylesheets
        atrule + Literally @ rules (statements) in stylesheets. + +
        @font-family {
        +	font-family: Questrial;
        +	src: url(questrial.otf);
        +}
        +@media screen and (min-width: 768px) { /* ... */ }
        +
        selector + Code that identifies or picks something out of a group to operate on, such as the names of HTML elements in stylesheets. + +
        section h1,
        +#features li strong,
        +header h2,
        +footer p { /* ... */ }
        +
        Diff
        inserted, deleted + Added or modified line and deleted line respectively, mainly for diffs. In general, also the idea of something being increased and decreased/removed respectively. + +
        --- bar.yml	2014-12-16 11:43:41 +0800
        ++++ /Users/foo/Desktop/bar.yml	2014-12-31 11:28:08 +0800
        +@@ -4,5 +4,5 @@
        +project:
        +	sources: "src/*.cpp"
        +	headers: "src/*.h"
        +-    qt: core
        ++    qt: core gui
        +public_headers: "src/*.h"
        +
        +
        + +
        +

        Embedded languages

        + +

        In addition to the standard tokens above, Prism also has a token for languages that are embedded in another language, such as CSS in HTML, JS in HTML, Bash in Shell-session, and CSS in JS, allowing Prism's themes to highlight the tokens in the embedded languages more accurately. All embedded languages are wrapped in their own special token, which includes a CSS class language-xxxx corresponding to the embedded language.

        + +

        Open your browser's developer tools and check out the example below to see it in action!

        + +
        <!DOCTYPE html>
        +<html lang="en">
        +<head>
        +	<meta charset="utf-8" />
        +	<title>I can haz embedded CSS and JS</title>
        +	<style>
        +		@media print {
        +			p { color: red !important; }
        +		}
        +	</style>
        +</head>
        +<body>
        +	<h1>I can haz embedded CSS and JS</h1>
        +	<script>
        +	if (true) {
        +		console.log('foo');
        +	}
        +	</script>
        +
        +</body>
        +</html>
        +
        + +
        +

        Non-standard tokens

        + +

        Sometimes, a language might use a particular name to refer to certain pieces of code, but which is not one of Prism's standard token names, such as function-defintion. Since function-definition is not a standard token, you might want to alias it with a standard token such as function, which is semantically similar, and will ensure that Prism's themes will highlight it. Here's an example:

        + +
        fn main() {
        +	println!("Hello World");
        +	another_function();
        +}
        +
        + +
        + + + + + + + + + + + +