diff --git a/monaco-css/.gitignore b/monaco-css/.gitignore new file mode 100644 index 00000000..d9ef910d --- /dev/null +++ b/monaco-css/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/out/ +/release/ diff --git a/monaco-css/.npmignore b/monaco-css/.npmignore new file mode 100644 index 00000000..4262b0f9 --- /dev/null +++ b/monaco-css/.npmignore @@ -0,0 +1,12 @@ +/.vscode/ +/out/ +/scripts/ +/src/ +/test/ +/.gitignore +/.npmignore +/.prettierrc +/.prettierignore +/package-lock.json +/webpack.dev.config.js +/webpack.min.config.js diff --git a/monaco-css/.prettierignore b/monaco-css/.prettierignore new file mode 100644 index 00000000..3c58ccd1 --- /dev/null +++ b/monaco-css/.prettierignore @@ -0,0 +1,2 @@ +/out/ +/release/ diff --git a/monaco-css/.prettierrc b/monaco-css/.prettierrc new file mode 100644 index 00000000..c12f08c5 --- /dev/null +++ b/monaco-css/.prettierrc @@ -0,0 +1,8 @@ +{ + "arrowParens": "always", + "singleQuote": true, + "trailingComma": "none", + "semi": true, + "useTabs": true, + "printWidth": 100 +} diff --git a/monaco-css/.vscode/settings.json b/monaco-css/.vscode/settings.json new file mode 100644 index 00000000..e25fee75 --- /dev/null +++ b/monaco-css/.vscode/settings.json @@ -0,0 +1,9 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.trimTrailingWhitespace": true, + "search.exclude": { + "**/node_modules": true, + "**/release": true, + "**/out": true + } +} diff --git a/monaco-css/LICENSE.md b/monaco-css/LICENSE.md new file mode 100644 index 00000000..5ae193c9 --- /dev/null +++ b/monaco-css/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/monaco-css/README.md b/monaco-css/README.md new file mode 100644 index 00000000..6b4e68bc --- /dev/null +++ b/monaco-css/README.md @@ -0,0 +1,37 @@ +# Monaco CSS + +CSS language plugin for the Monaco Editor. It provides the following features when editing CSS, LESS and SCSS files: + +- Code completion +- Hovers +- Validation: Syntax errors and linting +- Find definition, references & highlights for symbols in the same file +- Document Symbols +- Color Decorators + +Linting an be configured through the API. See [here](https://github.com/Microsoft/monaco-css/blob/master/src/monaco.d.ts) for the API that the +CSS plugin offers to configure the CSS/LESS/SCSS language support. + +Internally the CSS plugin uses the [vscode-css-languageservice](https://github.com/Microsoft/vscode-css-languageservice) +node module, providing the implementation of the functionally listed above. The same module is also used +in [Visual Studio Code](https://github.com/Microsoft/vscode) to power the CSS, LESS and SCSS editing experience. + +## Issues + +Please file issues concering `monaco-css` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues). + +## Installing + +This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module. + +## Development + +- `npm install .` +- compile with `npm run compile` +- watch with `npm run watch` +- `npm run prepublishOnly` +- open `$/monaco-css/test/index.html` in your favorite browser. + +## License + +[MIT](https://github.com/Microsoft/monaco-css/blob/master/LICENSE.md) diff --git a/monaco-css/SECURITY.md b/monaco-css/SECURITY.md new file mode 100644 index 00000000..10541931 --- /dev/null +++ b/monaco-css/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + diff --git a/monaco-css/monaco.d.ts b/monaco-css/monaco.d.ts new file mode 100644 index 00000000..15b256bf --- /dev/null +++ b/monaco-css/monaco.d.ts @@ -0,0 +1,171 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// + +declare namespace monaco.languages.css { + export interface Options { + readonly validate?: boolean; + readonly lint?: { + readonly compatibleVendorPrefixes?: 'ignore' | 'warning' | 'error'; + readonly vendorPrefix?: 'ignore' | 'warning' | 'error'; + readonly duplicateProperties?: 'ignore' | 'warning' | 'error'; + readonly emptyRules?: 'ignore' | 'warning' | 'error'; + readonly importStatement?: 'ignore' | 'warning' | 'error'; + readonly boxModel?: 'ignore' | 'warning' | 'error'; + readonly universalSelector?: 'ignore' | 'warning' | 'error'; + readonly zeroUnits?: 'ignore' | 'warning' | 'error'; + readonly fontFaceProperties?: 'ignore' | 'warning' | 'error'; + readonly hexColorLength?: 'ignore' | 'warning' | 'error'; + readonly argumentsInColorFunction?: 'ignore' | 'warning' | 'error'; + readonly unknownProperties?: 'ignore' | 'warning' | 'error'; + readonly ieHack?: 'ignore' | 'warning' | 'error'; + readonly unknownVendorSpecificProperties?: 'ignore' | 'warning' | 'error'; + readonly propertyIgnoredDueToDisplay?: 'ignore' | 'warning' | 'error'; + readonly important?: 'ignore' | 'warning' | 'error'; + readonly float?: 'ignore' | 'warning' | 'error'; + readonly idSelector?: 'ignore' | 'warning' | 'error'; + }; + /** + * Configures the CSS data types known by the langauge service. + */ + readonly data?: CSSDataConfiguration; + } + export interface ModeConfiguration { + /** + * Defines whether the built-in completionItemProvider is enabled. + */ + readonly completionItems?: boolean; + /** + * Defines whether the built-in hoverProvider is enabled. + */ + readonly hovers?: boolean; + /** + * Defines whether the built-in documentSymbolProvider is enabled. + */ + readonly documentSymbols?: boolean; + /** + * Defines whether the built-in definitions provider is enabled. + */ + readonly definitions?: boolean; + /** + * Defines whether the built-in references provider is enabled. + */ + readonly references?: boolean; + /** + * Defines whether the built-in references provider is enabled. + */ + readonly documentHighlights?: boolean; + /** + * Defines whether the built-in rename provider is enabled. + */ + readonly rename?: boolean; + /** + * Defines whether the built-in color provider is enabled. + */ + readonly colors?: boolean; + /** + * Defines whether the built-in foldingRange provider is enabled. + */ + readonly foldingRanges?: boolean; + /** + * Defines whether the built-in diagnostic provider is enabled. + */ + readonly diagnostics?: boolean; + /** + * Defines whether the built-in selection range provider is enabled. + */ + readonly selectionRanges?: boolean; + } + export interface LanguageServiceDefaults { + readonly languageId: string; + readonly onDidChange: IEvent; + readonly modeConfiguration: ModeConfiguration; + readonly options: Options; + setOptions(options: Options): void; + setModeConfiguration(modeConfiguration: ModeConfiguration): void; + /** @deprecated Use options instead */ + readonly diagnosticsOptions: DiagnosticsOptions; + /** @deprecated Use setOptions instead */ + setDiagnosticsOptions(options: DiagnosticsOptions): void; + } + /** @deprecated Use Options instead */ + export type DiagnosticsOptions = Options; + export const cssDefaults: LanguageServiceDefaults; + export const scssDefaults: LanguageServiceDefaults; + export const lessDefaults: LanguageServiceDefaults; + export interface CSSDataConfiguration { + /** + * Defines whether the standard CSS properties, at-directives, pseudoClasses and pseudoElements are shown. + */ + useDefaultDataProvider?: boolean; + /** + * Provides a set of custom data providers. + */ + dataProviders?: { + [providerId: string]: CSSDataV1; + }; + } + /** + * Custom CSS properties, at-directives, pseudoClasses and pseudoElements + * https://github.com/microsoft/vscode-css-languageservice/blob/main/docs/customData.md + */ + export interface CSSDataV1 { + version: 1 | 1.1; + properties?: IPropertyData[]; + atDirectives?: IAtDirectiveData[]; + pseudoClasses?: IPseudoClassData[]; + pseudoElements?: IPseudoElementData[]; + } + export type EntryStatus = 'standard' | 'experimental' | 'nonstandard' | 'obsolete'; + export interface IReference { + name: string; + url: string; + } + export interface IPropertyData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + restrictions?: string[]; + status?: EntryStatus; + syntax?: string; + values?: IValueData[]; + references?: IReference[]; + relevance?: number; + } + export interface IAtDirectiveData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface IPseudoClassData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface IPseudoElementData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface IValueData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface MarkupContent { + kind: MarkupKind; + value: string; + } + export type MarkupKind = 'plaintext' | 'markdown'; +} diff --git a/monaco-css/package-lock.json b/monaco-css/package-lock.json new file mode 100644 index 00000000..2b226d25 --- /dev/null +++ b/monaco-css/package-lock.json @@ -0,0 +1,497 @@ +{ + "name": "monaco-css", + "version": "3.9.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@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 + }, + "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" + } + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "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" + } + }, + "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 + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "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 + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "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 + }, + "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" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "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 + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "husky": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-5.1.3.tgz", + "integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==", + "dev": true + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "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 + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "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" + } + }, + "monaco-editor-core": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.30.0.tgz", + "integrity": "sha512-vFJ7BEOCqLv4xWgFW+UheI/PtccHHNht29lNmo79Re1kNhWCBLLb2nThjRMLPO1rd41vX9hhd9C07/iKOk9/jQ==", + "dev": true + }, + "monaco-languages": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-2.11.0.tgz", + "integrity": "sha512-fpeP8XUPejcdoUEMZ5bo4MW8VzEadhrsuyDtT48p2a2PSRT/CXptQm4eGnIfgxf5R95jrCZ0456c5dSEPBuktA==", + "dev": true + }, + "monaco-plugin-helpers": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz", + "integrity": "sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw==", + "dev": true, + "requires": { + "typescript": "^2.7.2" + }, + "dependencies": { + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + } + } + }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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 + }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, + "pretty-quick": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.0.tgz", + "integrity": "sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + } + }, + "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" + } + }, + "requirejs": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", + "dev": true + }, + "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 + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "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 + } + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "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" + } + }, + "terser": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz", + "integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + } + }, + "typescript": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", + "dev": true + }, + "vscode-css-languageservice": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.1.8.tgz", + "integrity": "sha512-Si1sMykS8U/p8LYgLGPCfZD1YFT0AtvUJQp9XJGw64DZWhtwYo28G2l64USLS9ge4ZPMZpwdpOK7PfbVKfgiiA==", + "dev": true, + "requires": { + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.2.tgz", + "integrity": "sha512-T7uPC18+f8mYE4lbVZwb3OSmvwTZm3cuFhrdx9Bn2l11lmp3SvSuSVjy2JtvrghzjAo4G6Trqny2m9XGnFnWVA==", + "dev": true + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", + "dev": true + }, + "vscode-nls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.0.0.tgz", + "integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==", + "dev": true + }, + "vscode-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz", + "integrity": "sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA==", + "dev": true + }, + "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" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/monaco-css/package.json b/monaco-css/package.json new file mode 100644 index 00000000..bb9493ee --- /dev/null +++ b/monaco-css/package.json @@ -0,0 +1,43 @@ +{ + "name": "monaco-css", + "version": "3.9.0", + "description": "CSS, LESS and SCSS plugin for the Monaco Editor", + "scripts": { + "compile": "mrmdir ./out && tsc -p ./src/tsconfig.json && tsc -p ./src/tsconfig.esm.json && node ./scripts/dts && prettier --write ./monaco.d.ts", + "watch": "tsc -p ./src --watch", + "prepublishOnly": "mrmdir ./release && npm run compile && node ./scripts/release.js && node ./scripts/bundle && mcopy ./monaco.d.ts ./release/monaco.d.ts && mcopy ./out/esm/monaco.contribution.d.ts ./release/esm/monaco.contribution.d.ts && mcopy ./out/esm/fillers/monaco-editor-core.d.ts ./release/esm/fillers/monaco-editor-core.d.ts", + "install-service-next": "npm install vscode-css-languageservice@next -f -D && npm install vscode-languageserver-types@next -f -D", + "install-service-local": "npm install ../vscode-css-languageservice -f -D && npm install ../vscode-languageserver-node/types -f -D", + "prettier": "prettier --write ." + }, + "author": "Microsoft Corporation", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/monaco-css" + }, + "bugs": { + "url": "https://github.com/Microsoft/monaco-css/issues" + }, + "module": "./release/esm/monaco.contribution.js", + "typings": "./release/esm/monaco.contribution.d.ts", + "devDependencies": { + "husky": "^5.1.3", + "monaco-editor-core": "0.30.0", + "monaco-languages": "2.11.0", + "monaco-plugin-helpers": "^1.0.3", + "prettier": "^2.2.1", + "pretty-quick": "^3.1.0", + "requirejs": "^2.3.6", + "typescript": "4.3.2", + "terser": "^5.7.0", + "vscode-css-languageservice": "^5.1.8", + "vscode-languageserver-types": "3.16.0", + "vscode-languageserver-textdocument": "^1.0.2" + }, + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } + } +} diff --git a/monaco-css/scripts/bundle.js b/monaco-css/scripts/bundle.js new file mode 100644 index 00000000..f2816855 --- /dev/null +++ b/monaco-css/scripts/bundle.js @@ -0,0 +1,86 @@ +const requirejs = require('requirejs'); +const path = require('path'); +const fs = require('fs'); +const Terser = require('terser'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.resolve(__dirname, '..'); + +const sha1 = helpers.getGitVersion(REPO_ROOT); +const semver = require('../package.json').version; +const headerVersion = semver + '(' + sha1 + ')'; + +const BUNDLED_FILE_HEADER = [ + '/*!-----------------------------------------------------------------------------', + ' * Copyright (c) Microsoft Corporation. All rights reserved.', + ' * monaco-css version: ' + headerVersion, + ' * Released under the MIT license', + ' * https://github.com/Microsoft/monaco-css/blob/master/LICENSE.md', + ' *-----------------------------------------------------------------------------*/', + '' +].join('\n'); + +bundleOne('monaco.contribution'); +bundleOne('cssMode', ['vs/language/css/monaco.contribution']); +bundleOne('cssWorker'); + +function bundleOne(moduleId, exclude) { + requirejs.optimize( + { + baseUrl: 'out/amd/', + name: 'vs/language/css/' + moduleId, + out: 'release/dev/' + moduleId + '.js', + exclude: exclude, + paths: { + 'vs/language/css': REPO_ROOT + '/out/amd', + 'vs/language/css/fillers/monaco-editor-core': + REPO_ROOT + '/out/amd/fillers/monaco-editor-core-amd' + }, + optimize: 'none', + packages: [ + { + name: 'vscode-css-languageservice', + location: path.join(REPO_ROOT, 'node_modules/vscode-css-languageservice/lib/umd'), + main: 'cssLanguageService' + }, + { + name: 'vscode-languageserver-types', + location: path.join(REPO_ROOT, 'node_modules/vscode-languageserver-types/lib/umd'), + main: 'main' + }, + { + name: 'vscode-languageserver-textdocument', + location: path.join(REPO_ROOT, 'node_modules/vscode-languageserver-textdocument/lib/umd'), + main: 'main' + }, + { + name: 'vscode-uri', + location: path.join(REPO_ROOT, 'node_modules/vscode-uri/lib/umd'), + main: 'index' + }, + { + name: 'vscode-nls', + location: path.join(REPO_ROOT, '/out/amd/fillers'), + main: 'vscode-nls' + } + ] + }, + async function (buildResponse) { + const devFilePath = path.join(REPO_ROOT, 'release/dev/' + moduleId + '.js'); + const minFilePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js'); + const fileContents = fs.readFileSync(devFilePath).toString(); + console.log(); + console.log(`Minifying ${devFilePath}...`); + const result = await Terser.minify(fileContents, { + output: { + comments: 'some' + } + }); + console.log(`Done minifying ${devFilePath}.`); + try { + fs.mkdirSync(path.join(REPO_ROOT, 'release/min')); + } catch (err) {} + fs.writeFileSync(minFilePath, BUNDLED_FILE_HEADER + result.code); + } + ); +} diff --git a/monaco-css/scripts/dts.js b/monaco-css/scripts/dts.js new file mode 100644 index 00000000..f63d2367 --- /dev/null +++ b/monaco-css/scripts/dts.js @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const path = require('path'); +const fs = require('fs'); + +const REPO_ROOT = path.join(__dirname, '../'); +const SRC_PATH = path.join(REPO_ROOT, 'out/amd/monaco.contribution.d.ts'); +const DST_PATH = path.join(REPO_ROOT, 'monaco.d.ts'); + +const lines = fs + .readFileSync(SRC_PATH) + .toString() + .split(/\r\n|\r|\n/); +let result = [ + `/*---------------------------------------------------------------------------------------------`, + ` * Copyright (c) Microsoft Corporation. All rights reserved.`, + ` * Licensed under the MIT License. See License.txt in the project root for license information.`, + ` *--------------------------------------------------------------------------------------------*/`, + ``, + `/// `, + ``, + `declare namespace monaco.languages.css {` +]; +for (let line of lines) { + if (/^import/.test(line)) { + continue; + } + line = line.replace(/ /g, '\t'); + line = line.replace(/declare /g, ''); + if (line.length > 0) { + line = `\t${line}`; + result.push(line); + } +} +result.push(`}`); +result.push(``); + +fs.writeFileSync(DST_PATH, result.join('\n')); diff --git a/monaco-css/scripts/release.js b/monaco-css/scripts/release.js new file mode 100644 index 00000000..67bf82f2 --- /dev/null +++ b/monaco-css/scripts/release.js @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const path = require('path'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.join(__dirname, '../'); + +helpers.packageESM({ + repoRoot: REPO_ROOT, + esmSource: 'out/esm', + esmDestination: 'release/esm', + entryPoints: ['monaco.contribution.js', 'cssMode.js', 'css.worker.js'], + resolveAlias: { + 'vscode-nls': path.join(REPO_ROOT, 'out/esm/fillers/vscode-nls.js') + }, + resolveSkip: ['monaco-editor-core'], + destinationFolderSimplification: { + node_modules: '_deps', + 'vscode-languageserver-types/lib/esm': 'vscode-languageserver-types', + 'vscode-uri/lib/esm': 'vscode-uri', + 'vscode-css-languageservice/lib/esm': 'vscode-css-languageservice' + } +}); diff --git a/monaco-css/src/css.worker.ts b/monaco-css/src/css.worker.ts new file mode 100644 index 00000000..ececcade --- /dev/null +++ b/monaco-css/src/css.worker.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker'; +import { CSSWorker } from './cssWorker'; + +self.onmessage = () => { + // ignore the first message + worker.initialize((ctx, createData) => { + return new CSSWorker(ctx, createData); + }); +}; diff --git a/monaco-css/src/cssMode.ts b/monaco-css/src/cssMode.ts new file mode 100644 index 00000000..ec3ea260 --- /dev/null +++ b/monaco-css/src/cssMode.ts @@ -0,0 +1,122 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { WorkerManager } from './workerManager'; +import type { CSSWorker } from './cssWorker'; +import { LanguageServiceDefaults } from './monaco.contribution'; +import * as languageFeatures from './languageFeatures'; +import { Uri, IDisposable, languages } from './fillers/monaco-editor-core'; + +export function setupMode(defaults: LanguageServiceDefaults): IDisposable { + const disposables: IDisposable[] = []; + const providers: IDisposable[] = []; + + const client = new WorkerManager(defaults); + disposables.push(client); + + const worker: languageFeatures.WorkerAccessor = (...uris: Uri[]): Promise => { + return client.getLanguageServiceWorker(...uris); + }; + + function registerProviders(): void { + const { languageId, modeConfiguration } = defaults; + + disposeAll(providers); + + if (modeConfiguration.completionItems) { + providers.push( + languages.registerCompletionItemProvider( + languageId, + new languageFeatures.CompletionAdapter(worker) + ) + ); + } + if (modeConfiguration.hovers) { + providers.push( + languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker)) + ); + } + if (modeConfiguration.documentHighlights) { + providers.push( + languages.registerDocumentHighlightProvider( + languageId, + new languageFeatures.DocumentHighlightAdapter(worker) + ) + ); + } + if (modeConfiguration.definitions) { + providers.push( + languages.registerDefinitionProvider( + languageId, + new languageFeatures.DefinitionAdapter(worker) + ) + ); + } + if (modeConfiguration.references) { + providers.push( + languages.registerReferenceProvider( + languageId, + new languageFeatures.ReferenceAdapter(worker) + ) + ); + } + if (modeConfiguration.documentSymbols) { + providers.push( + languages.registerDocumentSymbolProvider( + languageId, + new languageFeatures.DocumentSymbolAdapter(worker) + ) + ); + } + if (modeConfiguration.rename) { + providers.push( + languages.registerRenameProvider(languageId, new languageFeatures.RenameAdapter(worker)) + ); + } + if (modeConfiguration.colors) { + providers.push( + languages.registerColorProvider( + languageId, + new languageFeatures.DocumentColorAdapter(worker) + ) + ); + } + if (modeConfiguration.foldingRanges) { + providers.push( + languages.registerFoldingRangeProvider( + languageId, + new languageFeatures.FoldingRangeAdapter(worker) + ) + ); + } + if (modeConfiguration.diagnostics) { + providers.push(new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults)); + } + if (modeConfiguration.selectionRanges) { + providers.push( + languages.registerSelectionRangeProvider( + languageId, + new languageFeatures.SelectionRangeAdapter(worker) + ) + ); + } + } + + registerProviders(); + + disposables.push(asDisposable(providers)); + + return asDisposable(disposables); +} + +function asDisposable(disposables: IDisposable[]): IDisposable { + return { dispose: () => disposeAll(disposables) }; +} + +function disposeAll(disposables: IDisposable[]) { + while (disposables.length) { + disposables.pop().dispose(); + } +} diff --git a/monaco-css/src/cssWorker.ts b/monaco-css/src/cssWorker.ts new file mode 100644 index 00000000..31fff0a1 --- /dev/null +++ b/monaco-css/src/cssWorker.ts @@ -0,0 +1,181 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { worker } from './fillers/monaco-editor-core'; +import * as cssService from 'vscode-css-languageservice'; +import { Options } from './monaco.contribution'; + +export class CSSWorker { + // --- model sync ----------------------- + + private _ctx: worker.IWorkerContext; + private _languageService: cssService.LanguageService; + private _languageSettings: cssService.LanguageSettings; + private _languageId: string; + + constructor(ctx: worker.IWorkerContext, createData: ICreateData) { + this._ctx = ctx; + this._languageSettings = createData.options; + this._languageId = createData.languageId; + + const data = createData.options.data; + + const useDefaultDataProvider = data?.useDefaultDataProvider; + const customDataProviders: cssService.ICSSDataProvider[] = []; + if (data?.dataProviders) { + for (const id in data.dataProviders) { + customDataProviders.push(cssService.newCSSDataProvider(data.dataProviders[id])); + } + } + const lsOptions: cssService.LanguageServiceOptions = { customDataProviders, useDefaultDataProvider }; + + switch (this._languageId) { + case 'css': + this._languageService = cssService.getCSSLanguageService(lsOptions); + break; + case 'less': + this._languageService = cssService.getLESSLanguageService(lsOptions); + break; + case 'scss': + this._languageService = cssService.getSCSSLanguageService(lsOptions); + break; + default: + throw new Error('Invalid language id: ' + this._languageId); + } + this._languageService.configure(this._languageSettings); + } + + // --- language service host --------------- + + async doValidation(uri: string): Promise { + let document = this._getTextDocument(uri); + if (document) { + let stylesheet = this._languageService.parseStylesheet(document); + let diagnostics = this._languageService.doValidation(document, stylesheet); + return Promise.resolve(diagnostics); + } + return Promise.resolve([]); + } + async doComplete(uri: string, position: cssService.Position): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let completions = this._languageService.doComplete(document, position, stylesheet); + return Promise.resolve(completions); + } + async doHover(uri: string, position: cssService.Position): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let hover = this._languageService.doHover(document, position, stylesheet); + return Promise.resolve(hover); + } + async findDefinition(uri: string, position: cssService.Position): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let definition = this._languageService.findDefinition(document, position, stylesheet); + return Promise.resolve(definition); + } + async findReferences(uri: string, position: cssService.Position): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let references = this._languageService.findReferences(document, position, stylesheet); + return Promise.resolve(references); + } + async findDocumentHighlights( + uri: string, + position: cssService.Position + ): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let highlights = this._languageService.findDocumentHighlights(document, position, stylesheet); + return Promise.resolve(highlights); + } + async findDocumentSymbols(uri: string): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let symbols = this._languageService.findDocumentSymbols(document, stylesheet); + return Promise.resolve(symbols); + } + async doCodeActions( + uri: string, + range: cssService.Range, + context: cssService.CodeActionContext + ): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let actions = this._languageService.doCodeActions(document, range, context, stylesheet); + return Promise.resolve(actions); + } + async findDocumentColors(uri: string): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let colorSymbols = this._languageService.findDocumentColors(document, stylesheet); + return Promise.resolve(colorSymbols); + } + async getColorPresentations( + uri: string, + color: cssService.Color, + range: cssService.Range + ): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let colorPresentations = this._languageService.getColorPresentations( + document, + stylesheet, + color, + range + ); + return Promise.resolve(colorPresentations); + } + async getFoldingRanges( + uri: string, + context?: { rangeLimit?: number } + ): Promise { + let document = this._getTextDocument(uri); + let ranges = this._languageService.getFoldingRanges(document, context); + return Promise.resolve(ranges); + } + async getSelectionRanges( + uri: string, + positions: cssService.Position[] + ): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let ranges = this._languageService.getSelectionRanges(document, positions, stylesheet); + return Promise.resolve(ranges); + } + async doRename( + uri: string, + position: cssService.Position, + newName: string + ): Promise { + let document = this._getTextDocument(uri); + let stylesheet = this._languageService.parseStylesheet(document); + let renames = this._languageService.doRename(document, position, newName, stylesheet); + return Promise.resolve(renames); + } + private _getTextDocument(uri: string): cssService.TextDocument { + let models = this._ctx.getMirrorModels(); + for (let model of models) { + if (model.uri.toString() === uri) { + return cssService.TextDocument.create( + uri, + this._languageId, + model.version, + model.getValue() + ); + } + } + return null; + } +} + +export interface ICreateData { + languageId: string; + options: Options +} + +export function create(ctx: worker.IWorkerContext, createData: ICreateData): CSSWorker { + return new CSSWorker(ctx, createData); +} diff --git a/monaco-css/src/fillers/monaco-editor-core-amd.ts b/monaco-css/src/fillers/monaco-editor-core-amd.ts new file mode 100644 index 00000000..59874efb --- /dev/null +++ b/monaco-css/src/fillers/monaco-editor-core-amd.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// Resolves with the global monaco API + +declare var define; + +define([], function () { + return (self).monaco; +}); diff --git a/monaco-css/src/fillers/monaco-editor-core.ts b/monaco-css/src/fillers/monaco-editor-core.ts new file mode 100644 index 00000000..cd996aa7 --- /dev/null +++ b/monaco-css/src/fillers/monaco-editor-core.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export * from 'monaco-editor-core'; diff --git a/monaco-css/src/fillers/vscode-nls.ts b/monaco-css/src/fillers/vscode-nls.ts new file mode 100644 index 00000000..38f7b334 --- /dev/null +++ b/monaco-css/src/fillers/vscode-nls.ts @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface Options { + locale?: string; + cacheLanguageResolution?: boolean; +} +export interface LocalizeInfo { + key: string; + comment: string[]; +} +export interface LocalizeFunc { + (info: LocalizeInfo, message: string, ...args: any[]): string; + (key: string, message: string, ...args: any[]): string; +} +export interface LoadFunc { + (file?: string): LocalizeFunc; +} + +function format(message: string, args: any[]): string { + let result: string; + + if (args.length === 0) { + result = message; + } else { + result = message.replace(/\{(\d+)\}/g, (match, rest) => { + let index = rest[0]; + return typeof args[index] !== 'undefined' ? args[index] : match; + }); + } + return result; +} + +function localize(key: string | LocalizeInfo, message: string, ...args: any[]): string { + return format(message, args); +} + +export function loadMessageBundle(file?: string): LocalizeFunc { + return localize; +} + +export function config(opt?: Options | string): LoadFunc { + return loadMessageBundle; +} diff --git a/monaco-css/src/languageFeatures.ts b/monaco-css/src/languageFeatures.ts new file mode 100644 index 00000000..3e998317 --- /dev/null +++ b/monaco-css/src/languageFeatures.ts @@ -0,0 +1,725 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LanguageServiceDefaults } from './monaco.contribution'; +import type { CSSWorker } from './cssWorker'; +import * as cssService from 'vscode-css-languageservice'; +import { + languages, + editor, + IMarkdownString, + Uri, + Position, + IRange, + Range, + CancellationToken, + IDisposable, + MarkerSeverity +} from './fillers/monaco-editor-core'; +import { TextEdit } from 'vscode-css-languageservice'; +import { InsertReplaceEdit } from 'vscode-languageserver-types'; + +export interface WorkerAccessor { + (first: Uri, ...more: Uri[]): Promise; +} + +// --- diagnostics --- --- + +export class DiagnosticsAdapter { + private _disposables: IDisposable[] = []; + private _listener: { [uri: string]: IDisposable } = Object.create(null); + + constructor( + private _languageId: string, + private _worker: WorkerAccessor, + defaults: LanguageServiceDefaults + ) { + const onModelAdd = (model: editor.IModel): void => { + let modeId = model.getLanguageId(); + if (modeId !== this._languageId) { + return; + } + + let handle: number; + this._listener[model.uri.toString()] = model.onDidChangeContent(() => { + window.clearTimeout(handle); + handle = window.setTimeout(() => this._doValidate(model.uri, modeId), 500); + }); + + this._doValidate(model.uri, modeId); + }; + + const onModelRemoved = (model: editor.IModel): void => { + editor.setModelMarkers(model, this._languageId, []); + + let uriStr = model.uri.toString(); + let listener = this._listener[uriStr]; + if (listener) { + listener.dispose(); + delete this._listener[uriStr]; + } + }; + + this._disposables.push(editor.onDidCreateModel(onModelAdd)); + this._disposables.push(editor.onWillDisposeModel(onModelRemoved)); + this._disposables.push( + editor.onDidChangeModelLanguage((event) => { + onModelRemoved(event.model); + onModelAdd(event.model); + }) + ); + + defaults.onDidChange((_) => { + editor.getModels().forEach((model) => { + if (model.getLanguageId() === this._languageId) { + onModelRemoved(model); + onModelAdd(model); + } + }); + }); + + this._disposables.push({ + dispose: () => { + for (let key in this._listener) { + this._listener[key].dispose(); + } + } + }); + + editor.getModels().forEach(onModelAdd); + } + + public dispose(): void { + this._disposables.forEach((d) => d && d.dispose()); + this._disposables = []; + } + + private _doValidate(resource: Uri, languageId: string): void { + this._worker(resource) + .then((worker) => { + return worker.doValidation(resource.toString()); + }) + .then((diagnostics) => { + const markers = diagnostics.map((d) => toDiagnostics(resource, d)); + let model = editor.getModel(resource); + if (model && model.getLanguageId() === languageId) { + editor.setModelMarkers(model, languageId, markers); + } + }) + .then(undefined, (err) => { + console.error(err); + }); + } +} + +function toSeverity(lsSeverity: number): MarkerSeverity { + switch (lsSeverity) { + case cssService.DiagnosticSeverity.Error: + return MarkerSeverity.Error; + case cssService.DiagnosticSeverity.Warning: + return MarkerSeverity.Warning; + case cssService.DiagnosticSeverity.Information: + return MarkerSeverity.Info; + case cssService.DiagnosticSeverity.Hint: + return MarkerSeverity.Hint; + default: + return MarkerSeverity.Info; + } +} + +function toDiagnostics(resource: Uri, diag: cssService.Diagnostic): editor.IMarkerData { + let code = typeof diag.code === 'number' ? String(diag.code) : diag.code; + + return { + severity: toSeverity(diag.severity), + startLineNumber: diag.range.start.line + 1, + startColumn: diag.range.start.character + 1, + endLineNumber: diag.range.end.line + 1, + endColumn: diag.range.end.character + 1, + message: diag.message, + code: code, + source: diag.source + }; +} + +// --- completion ------ + +function fromPosition(position: Position): cssService.Position { + if (!position) { + return void 0; + } + return { character: position.column - 1, line: position.lineNumber - 1 }; +} + +function fromRange(range: IRange): cssService.Range { + if (!range) { + return void 0; + } + return { + start: { + line: range.startLineNumber - 1, + character: range.startColumn - 1 + }, + end: { line: range.endLineNumber - 1, character: range.endColumn - 1 } + }; +} + +function toRange(range: cssService.Range): Range { + if (!range) { + return void 0; + } + return new Range( + range.start.line + 1, + range.start.character + 1, + range.end.line + 1, + range.end.character + 1 + ); +} + +function isInsertReplaceEdit(edit: TextEdit | InsertReplaceEdit): edit is InsertReplaceEdit { + return ( + typeof (edit).insert !== 'undefined' && + typeof (edit).replace !== 'undefined' + ); +} + +function toCompletionItemKind(kind: number): languages.CompletionItemKind { + let mItemKind = languages.CompletionItemKind; + + switch (kind) { + case cssService.CompletionItemKind.Text: + return mItemKind.Text; + case cssService.CompletionItemKind.Method: + return mItemKind.Method; + case cssService.CompletionItemKind.Function: + return mItemKind.Function; + case cssService.CompletionItemKind.Constructor: + return mItemKind.Constructor; + case cssService.CompletionItemKind.Field: + return mItemKind.Field; + case cssService.CompletionItemKind.Variable: + return mItemKind.Variable; + case cssService.CompletionItemKind.Class: + return mItemKind.Class; + case cssService.CompletionItemKind.Interface: + return mItemKind.Interface; + case cssService.CompletionItemKind.Module: + return mItemKind.Module; + case cssService.CompletionItemKind.Property: + return mItemKind.Property; + case cssService.CompletionItemKind.Unit: + return mItemKind.Unit; + case cssService.CompletionItemKind.Value: + return mItemKind.Value; + case cssService.CompletionItemKind.Enum: + return mItemKind.Enum; + case cssService.CompletionItemKind.Keyword: + return mItemKind.Keyword; + case cssService.CompletionItemKind.Snippet: + return mItemKind.Snippet; + case cssService.CompletionItemKind.Color: + return mItemKind.Color; + case cssService.CompletionItemKind.File: + return mItemKind.File; + case cssService.CompletionItemKind.Reference: + return mItemKind.Reference; + } + return mItemKind.Property; +} + +function toTextEdit(textEdit: cssService.TextEdit): editor.ISingleEditOperation { + if (!textEdit) { + return void 0; + } + return { + range: toRange(textEdit.range), + text: textEdit.newText + }; +} + +function toCommand(c: cssService.Command | undefined): languages.Command { + return c && c.command === 'editor.action.triggerSuggest' ? { id: c.command, title: c.title, arguments: c.arguments } : undefined +} + +export class CompletionAdapter implements languages.CompletionItemProvider { + constructor(private _worker: WorkerAccessor) {} + + public get triggerCharacters(): string[] { + return ['/', '-', ':']; + } + + provideCompletionItems( + model: editor.IReadOnlyModel, + position: Position, + context: languages.CompletionContext, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doComplete(resource.toString(), fromPosition(position)); + }) + .then((info) => { + if (!info) { + return; + } + const wordInfo = model.getWordUntilPosition(position); + const wordRange = new Range( + position.lineNumber, + wordInfo.startColumn, + position.lineNumber, + wordInfo.endColumn + ); + + let items: languages.CompletionItem[] = info.items.map((entry) => { + let item: languages.CompletionItem = { + label: entry.label, + insertText: entry.insertText || entry.label, + sortText: entry.sortText, + filterText: entry.filterText, + documentation: entry.documentation, + detail: entry.detail, + command: toCommand(entry.command), + range: wordRange, + kind: toCompletionItemKind(entry.kind) + }; + if (entry.textEdit) { + if (isInsertReplaceEdit(entry.textEdit)) { + item.range = { + insert: toRange(entry.textEdit.insert), + replace: toRange(entry.textEdit.replace) + }; + } else { + item.range = toRange(entry.textEdit.range); + } + item.insertText = entry.textEdit.newText; + } + if (entry.additionalTextEdits) { + item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit); + } + if (entry.insertTextFormat === cssService.InsertTextFormat.Snippet) { + item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet; + } + return item; + }); + + return { + isIncomplete: info.isIncomplete, + suggestions: items + }; + }); + } +} + +function isMarkupContent(thing: any): thing is cssService.MarkupContent { + return ( + thing && typeof thing === 'object' && typeof (thing).kind === 'string' + ); +} + +function toMarkdownString( + entry: cssService.MarkupContent | cssService.MarkedString +): IMarkdownString { + if (typeof entry === 'string') { + return { + value: entry + }; + } + if (isMarkupContent(entry)) { + if (entry.kind === 'plaintext') { + return { + value: entry.value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') + }; + } + return { + value: entry.value + }; + } + + return { value: '```' + entry.language + '\n' + entry.value + '\n```\n' }; +} + +function toMarkedStringArray( + contents: cssService.MarkupContent | cssService.MarkedString | cssService.MarkedString[] +): IMarkdownString[] { + if (!contents) { + return void 0; + } + if (Array.isArray(contents)) { + return contents.map(toMarkdownString); + } + return [toMarkdownString(contents)]; +} + +// --- hover ------ + +export class HoverAdapter implements languages.HoverProvider { + constructor(private _worker: WorkerAccessor) {} + + provideHover( + model: editor.IReadOnlyModel, + position: Position, + token: CancellationToken + ): Promise { + let resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doHover(resource.toString(), fromPosition(position)); + }) + .then((info) => { + if (!info) { + return; + } + return { + range: toRange(info.range), + contents: toMarkedStringArray(info.contents) + }; + }); + } +} + +// --- document highlights ------ + +function toDocumentHighlightKind(kind: number): languages.DocumentHighlightKind { + switch (kind) { + case cssService.DocumentHighlightKind.Read: + return languages.DocumentHighlightKind.Read; + case cssService.DocumentHighlightKind.Write: + return languages.DocumentHighlightKind.Write; + case cssService.DocumentHighlightKind.Text: + return languages.DocumentHighlightKind.Text; + } + return languages.DocumentHighlightKind.Text; +} + +export class DocumentHighlightAdapter implements languages.DocumentHighlightProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideDocumentHighlights( + model: editor.IReadOnlyModel, + position: Position, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.findDocumentHighlights(resource.toString(), fromPosition(position)); + }) + .then((entries) => { + if (!entries) { + return; + } + return entries.map((entry) => { + return { + range: toRange(entry.range), + kind: toDocumentHighlightKind(entry.kind) + }; + }); + }); + } +} + +// --- definition ------ + +function toLocation(location: cssService.Location): languages.Location { + return { + uri: Uri.parse(location.uri), + range: toRange(location.range) + }; +} + +export class DefinitionAdapter { + constructor(private _worker: WorkerAccessor) {} + + public provideDefinition( + model: editor.IReadOnlyModel, + position: Position, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.findDefinition(resource.toString(), fromPosition(position)); + }) + .then((definition) => { + if (!definition) { + return; + } + return [toLocation(definition)]; + }); + } +} + +// --- references ------ + +export class ReferenceAdapter implements languages.ReferenceProvider { + constructor(private _worker: WorkerAccessor) {} + + provideReferences( + model: editor.IReadOnlyModel, + position: Position, + context: languages.ReferenceContext, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.findReferences(resource.toString(), fromPosition(position)); + }) + .then((entries) => { + if (!entries) { + return; + } + return entries.map(toLocation); + }); + } +} + +// --- rename ------ + +function toWorkspaceEdit(edit: cssService.WorkspaceEdit): languages.WorkspaceEdit { + if (!edit || !edit.changes) { + return void 0; + } + let resourceEdits: languages.WorkspaceTextEdit[] = []; + for (let uri in edit.changes) { + const _uri = Uri.parse(uri); + // let edits: languages.TextEdit[] = []; + for (let e of edit.changes[uri]) { + resourceEdits.push({ + resource: _uri, + edit: { + range: toRange(e.range), + text: e.newText + } + }); + } + } + return { + edits: resourceEdits + }; +} + +export class RenameAdapter implements languages.RenameProvider { + constructor(private _worker: WorkerAccessor) {} + + provideRenameEdits( + model: editor.IReadOnlyModel, + position: Position, + newName: string, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doRename(resource.toString(), fromPosition(position), newName); + }) + .then((edit) => { + return toWorkspaceEdit(edit); + }); + } +} + +// --- document symbols ------ + +function toSymbolKind(kind: cssService.SymbolKind): languages.SymbolKind { + let mKind = languages.SymbolKind; + + switch (kind) { + case cssService.SymbolKind.File: + return mKind.Array; + case cssService.SymbolKind.Module: + return mKind.Module; + case cssService.SymbolKind.Namespace: + return mKind.Namespace; + case cssService.SymbolKind.Package: + return mKind.Package; + case cssService.SymbolKind.Class: + return mKind.Class; + case cssService.SymbolKind.Method: + return mKind.Method; + case cssService.SymbolKind.Property: + return mKind.Property; + case cssService.SymbolKind.Field: + return mKind.Field; + case cssService.SymbolKind.Constructor: + return mKind.Constructor; + case cssService.SymbolKind.Enum: + return mKind.Enum; + case cssService.SymbolKind.Interface: + return mKind.Interface; + case cssService.SymbolKind.Function: + return mKind.Function; + case cssService.SymbolKind.Variable: + return mKind.Variable; + case cssService.SymbolKind.Constant: + return mKind.Constant; + case cssService.SymbolKind.String: + return mKind.String; + case cssService.SymbolKind.Number: + return mKind.Number; + case cssService.SymbolKind.Boolean: + return mKind.Boolean; + case cssService.SymbolKind.Array: + return mKind.Array; + } + return mKind.Function; +} + +export class DocumentSymbolAdapter implements languages.DocumentSymbolProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideDocumentSymbols( + model: editor.IReadOnlyModel, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.findDocumentSymbols(resource.toString())) + .then((items) => { + if (!items) { + return; + } + return items.map((item) => ({ + name: item.name, + detail: '', + containerName: item.containerName, + kind: toSymbolKind(item.kind), + tags: [], + range: toRange(item.location.range), + selectionRange: toRange(item.location.range) + })); + }); + } +} + +export class DocumentColorAdapter implements languages.DocumentColorProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideDocumentColors( + model: editor.IReadOnlyModel, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.findDocumentColors(resource.toString())) + .then((infos) => { + if (!infos) { + return; + } + return infos.map((item) => ({ + color: item.color, + range: toRange(item.range) + })); + }); + } + + public provideColorPresentations( + model: editor.IReadOnlyModel, + info: languages.IColorInformation, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => + worker.getColorPresentations(resource.toString(), info.color, fromRange(info.range)) + ) + .then((presentations) => { + if (!presentations) { + return; + } + return presentations.map((presentation) => { + let item: languages.IColorPresentation = { + label: presentation.label + }; + if (presentation.textEdit) { + item.textEdit = toTextEdit(presentation.textEdit); + } + if (presentation.additionalTextEdits) { + item.additionalTextEdits = presentation.additionalTextEdits.map(toTextEdit); + } + return item; + }); + }); + } +} + +export class FoldingRangeAdapter implements languages.FoldingRangeProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideFoldingRanges( + model: editor.IReadOnlyModel, + context: languages.FoldingContext, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.getFoldingRanges(resource.toString(), context)) + .then((ranges) => { + if (!ranges) { + return; + } + return ranges.map((range) => { + let result: languages.FoldingRange = { + start: range.startLine + 1, + end: range.endLine + 1 + }; + if (typeof range.kind !== 'undefined') { + result.kind = toFoldingRangeKind(range.kind); + } + return result; + }); + }); + } +} + +function toFoldingRangeKind(kind: cssService.FoldingRangeKind): languages.FoldingRangeKind { + switch (kind) { + case cssService.FoldingRangeKind.Comment: + return languages.FoldingRangeKind.Comment; + case cssService.FoldingRangeKind.Imports: + return languages.FoldingRangeKind.Imports; + case cssService.FoldingRangeKind.Region: + return languages.FoldingRangeKind.Region; + } +} + +export class SelectionRangeAdapter implements languages.SelectionRangeProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideSelectionRanges( + model: editor.IReadOnlyModel, + positions: Position[], + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.getSelectionRanges(resource.toString(), positions.map(fromPosition))) + .then((selectionRanges) => { + if (!selectionRanges) { + return; + } + return selectionRanges.map((selectionRange) => { + const result: languages.SelectionRange[] = []; + while (selectionRange) { + result.push({ range: toRange(selectionRange.range) }); + selectionRange = selectionRange.parent; + } + return result; + }); + }); + } +} diff --git a/monaco-css/src/monaco.contribution.ts b/monaco-css/src/monaco.contribution.ts new file mode 100644 index 00000000..b9e05bc4 --- /dev/null +++ b/monaco-css/src/monaco.contribution.ts @@ -0,0 +1,318 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as mode from './cssMode'; +import { languages, Emitter, IEvent } from './fillers/monaco-editor-core'; + +export interface Options { + readonly validate?: boolean; + readonly lint?: { + readonly compatibleVendorPrefixes?: 'ignore' | 'warning' | 'error'; + readonly vendorPrefix?: 'ignore' | 'warning' | 'error'; + readonly duplicateProperties?: 'ignore' | 'warning' | 'error'; + readonly emptyRules?: 'ignore' | 'warning' | 'error'; + readonly importStatement?: 'ignore' | 'warning' | 'error'; + readonly boxModel?: 'ignore' | 'warning' | 'error'; + readonly universalSelector?: 'ignore' | 'warning' | 'error'; + readonly zeroUnits?: 'ignore' | 'warning' | 'error'; + readonly fontFaceProperties?: 'ignore' | 'warning' | 'error'; + readonly hexColorLength?: 'ignore' | 'warning' | 'error'; + readonly argumentsInColorFunction?: 'ignore' | 'warning' | 'error'; + readonly unknownProperties?: 'ignore' | 'warning' | 'error'; + readonly ieHack?: 'ignore' | 'warning' | 'error'; + readonly unknownVendorSpecificProperties?: 'ignore' | 'warning' | 'error'; + readonly propertyIgnoredDueToDisplay?: 'ignore' | 'warning' | 'error'; + readonly important?: 'ignore' | 'warning' | 'error'; + readonly float?: 'ignore' | 'warning' | 'error'; + readonly idSelector?: 'ignore' | 'warning' | 'error'; + }; + /** + * Configures the CSS data types known by the langauge service. + */ + readonly data?: CSSDataConfiguration; +} + +export interface ModeConfiguration { + /** + * Defines whether the built-in completionItemProvider is enabled. + */ + readonly completionItems?: boolean; + + /** + * Defines whether the built-in hoverProvider is enabled. + */ + readonly hovers?: boolean; + + /** + * Defines whether the built-in documentSymbolProvider is enabled. + */ + readonly documentSymbols?: boolean; + + /** + * Defines whether the built-in definitions provider is enabled. + */ + readonly definitions?: boolean; + + /** + * Defines whether the built-in references provider is enabled. + */ + readonly references?: boolean; + + /** + * Defines whether the built-in references provider is enabled. + */ + readonly documentHighlights?: boolean; + + /** + * Defines whether the built-in rename provider is enabled. + */ + readonly rename?: boolean; + + /** + * Defines whether the built-in color provider is enabled. + */ + readonly colors?: boolean; + + /** + * Defines whether the built-in foldingRange provider is enabled. + */ + readonly foldingRanges?: boolean; + + /** + * Defines whether the built-in diagnostic provider is enabled. + */ + readonly diagnostics?: boolean; + + /** + * Defines whether the built-in selection range provider is enabled. + */ + readonly selectionRanges?: boolean; +} + +export interface LanguageServiceDefaults { + readonly languageId: string; + readonly onDidChange: IEvent; + + readonly modeConfiguration: ModeConfiguration; + readonly options: Options; + setOptions(options: Options): void; + setModeConfiguration(modeConfiguration: ModeConfiguration): void; + + /** @deprecated Use options instead */ + readonly diagnosticsOptions: DiagnosticsOptions; + /** @deprecated Use setOptions instead */ + setDiagnosticsOptions(options: DiagnosticsOptions): void; +} + +/** @deprecated Use Options instead */ +export type DiagnosticsOptions = Options; + +// --- CSS configuration and defaults --------- + +class LanguageServiceDefaultsImpl implements LanguageServiceDefaults { + private _onDidChange = new Emitter(); + private _options: Options; + private _modeConfiguration: ModeConfiguration; + private _languageId: string; + + constructor( + languageId: string, + options: Options, + modeConfiguration: ModeConfiguration + ) { + this._languageId = languageId; + this.setOptions(options); + this.setModeConfiguration(modeConfiguration); + } + + get onDidChange(): IEvent { + return this._onDidChange.event; + } + + get languageId(): string { + return this._languageId; + } + + get modeConfiguration(): ModeConfiguration { + return this._modeConfiguration; + } + + get diagnosticsOptions(): Options { + return this.options; + } + + get options(): Options { + return this._options; + } + + setOptions(options: Options): void { + this._options = options || Object.create(null); + this._onDidChange.fire(this); + } + + setDiagnosticsOptions(options: Options): void { + this.setOptions(options); + } + + setModeConfiguration(modeConfiguration: ModeConfiguration): void { + this._modeConfiguration = modeConfiguration || Object.create(null); + this._onDidChange.fire(this); + } +} + +const optionsDefault: Required = { + validate: true, + lint: { + compatibleVendorPrefixes: 'ignore', + vendorPrefix: 'warning', + duplicateProperties: 'warning', + emptyRules: 'warning', + importStatement: 'ignore', + boxModel: 'ignore', + universalSelector: 'ignore', + zeroUnits: 'ignore', + fontFaceProperties: 'warning', + hexColorLength: 'error', + argumentsInColorFunction: 'error', + unknownProperties: 'warning', + ieHack: 'ignore', + unknownVendorSpecificProperties: 'ignore', + propertyIgnoredDueToDisplay: 'warning', + important: 'ignore', + float: 'ignore', + idSelector: 'ignore' + }, + data: { useDefaultDataProvider: true } +}; + +const modeConfigurationDefault: Required = { + completionItems: true, + hovers: true, + documentSymbols: true, + definitions: true, + references: true, + documentHighlights: true, + rename: true, + colors: true, + foldingRanges: true, + diagnostics: true, + selectionRanges: true +}; + +export const cssDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( + 'css', + optionsDefault, + modeConfigurationDefault +); +export const scssDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( + 'scss', + optionsDefault, + modeConfigurationDefault +); +export const lessDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( + 'less', + optionsDefault, + modeConfigurationDefault +); + +// export to the global based API +(languages).css = { cssDefaults, lessDefaults, scssDefaults }; + +// --- Registration to monaco editor --- + +function getMode(): Promise { + return import('./cssMode'); +} + +languages.onLanguage('less', () => { + getMode().then((mode) => mode.setupMode(lessDefaults)); +}); + +languages.onLanguage('scss', () => { + getMode().then((mode) => mode.setupMode(scssDefaults)); +}); + +languages.onLanguage('css', () => { + getMode().then((mode) => mode.setupMode(cssDefaults)); +}); + + +// CSS Data + +export interface CSSDataConfiguration { + /** + * Defines whether the standard CSS properties, at-directives, pseudoClasses and pseudoElements are shown. + */ + useDefaultDataProvider?: boolean; + /** + * Provides a set of custom data providers. + */ + dataProviders?: { [providerId: string]: CSSDataV1 }; +} + +/** + * Custom CSS properties, at-directives, pseudoClasses and pseudoElements + * https://github.com/microsoft/vscode-css-languageservice/blob/main/docs/customData.md + */ +export interface CSSDataV1 { + version: 1 | 1.1; + properties?: IPropertyData[]; + atDirectives?: IAtDirectiveData[]; + pseudoClasses?: IPseudoClassData[]; + pseudoElements?: IPseudoElementData[]; +} + +export type EntryStatus = 'standard' | 'experimental' | 'nonstandard' | 'obsolete'; + +export interface IReference { + name: string; + url: string; +} + +export interface IPropertyData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + restrictions?: string[]; + status?: EntryStatus; + syntax?: string; + values?: IValueData[]; + references?: IReference[]; + relevance?: number; +} +export interface IAtDirectiveData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} +export interface IPseudoClassData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} +export interface IPseudoElementData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} + +export interface IValueData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} +export interface MarkupContent { + kind: MarkupKind; + value: string; +} +export declare type MarkupKind = 'plaintext' | 'markdown'; diff --git a/monaco-css/src/tsconfig.esm.json b/monaco-css/src/tsconfig.esm.json new file mode 100644 index 00000000..3edf3ca4 --- /dev/null +++ b/monaco-css/src/tsconfig.esm.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "node", + "outDir": "../out/esm", + "declaration": true, + "target": "es5", + "lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"] + } +} diff --git a/monaco-css/src/tsconfig.json b/monaco-css/src/tsconfig.json new file mode 100644 index 00000000..707f714d --- /dev/null +++ b/monaco-css/src/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "amd", + "moduleResolution": "node", + "outDir": "../out/amd", + "declaration": true, + "target": "es5", + "lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"] + } +} diff --git a/monaco-css/src/workerManager.ts b/monaco-css/src/workerManager.ts new file mode 100644 index 00000000..335396d5 --- /dev/null +++ b/monaco-css/src/workerManager.ts @@ -0,0 +1,87 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LanguageServiceDefaults } from './monaco.contribution'; +import type { CSSWorker } from './cssWorker'; +import { editor, IDisposable, Uri } from './fillers/monaco-editor-core'; + +const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min + +export class WorkerManager { + private _defaults: LanguageServiceDefaults; + private _idleCheckInterval: number; + private _lastUsedTime: number; + private _configChangeListener: IDisposable; + + private _worker: editor.MonacoWebWorker; + private _client: Promise; + + constructor(defaults: LanguageServiceDefaults) { + this._defaults = defaults; + this._worker = null; + this._idleCheckInterval = window.setInterval(() => this._checkIfIdle(), 30 * 1000); + this._lastUsedTime = 0; + this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker()); + } + + private _stopWorker(): void { + if (this._worker) { + this._worker.dispose(); + this._worker = null; + } + this._client = null; + } + + dispose(): void { + clearInterval(this._idleCheckInterval); + this._configChangeListener.dispose(); + this._stopWorker(); + } + + private _checkIfIdle(): void { + if (!this._worker) { + return; + } + let timePassedSinceLastUsed = Date.now() - this._lastUsedTime; + if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) { + this._stopWorker(); + } + } + + private _getClient(): Promise { + this._lastUsedTime = Date.now(); + + if (!this._client) { + this._worker = editor.createWebWorker({ + // module that exports the create() method and returns a `CSSWorker` instance + moduleId: 'vs/language/css/cssWorker', + + label: this._defaults.languageId, + + // passed in to the create() method + createData: { + options: this._defaults.options, + languageId: this._defaults.languageId + } + }); + + this._client = >(this._worker.getProxy()); + } + + return this._client; + } + + getLanguageServiceWorker(...resources: Uri[]): Promise { + let _client: CSSWorker; + return this._getClient() + .then((client) => { + _client = client; + }) + .then((_) => { + return this._worker.withSyncedResources(resources); + }) + .then((_) => _client); + } +} diff --git a/monaco-css/test/index.html b/monaco-css/test/index.html new file mode 100644 index 00000000..d858437b --- /dev/null +++ b/monaco-css/test/index.html @@ -0,0 +1,877 @@ + + + + + + + + +

Monaco Editor CSS test page

+
+ + + + + + + + + diff --git a/monaco-editor-webpack-plugin/.github/commands.yml b/monaco-editor-webpack-plugin/.github/commands.yml new file mode 100644 index 00000000..a77371d3 --- /dev/null +++ b/monaco-editor-webpack-plugin/.github/commands.yml @@ -0,0 +1,62 @@ +{ + perform: true, + commands: [ + { + type: 'comment', + name: 'question', + allowUsers: [], + action: 'updateLabels', + addLabel: '*question' + }, + { + type: 'label', + name: '*question', + allowTriggerByBot: true, + action: 'close', + comment: "Please ask your question on [StackOverflow](https://stackoverflow.com/questions/tagged/monaco-editor). We have a great community over [there](https://stackoverflow.com/questions/tagged/monaco-editor). They have already answered hundreds of questions and are happy to answer yours as well. You can also try [searching through existing issues](https://github.com/microsoft/monaco-editor/issues?utf8=%E2%9C%93&q=is%3Aissue+), looking at [API usage samples](https://microsoft.github.io/monaco-editor/playground.html) or at [integration samples](https://github.com/Microsoft/monaco-editor-samples). See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" + }, + { + type: 'label', + name: '*out-of-scope', + allowTriggerByBot: true, + action: 'close', + comment: "We closed this issue because we don't plan to address it in the foreseeable future. You can find more detailed information about our decision-making process [here](https://aka.ms/vscode-out-of-scope). If you disagree and feel that this issue is crucial: We are happy to listen and to reconsider.\n\nIf you wonder what we are up to, please see our [roadmap](https://aka.ms/vscoderoadmap) and [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nThanks for your understanding and happy coding!" + }, + { + type: 'label', + name: '*as-designed', + allowTriggerByBot: true, + action: 'close', + comment: "The described behavior is how it is expected to work. If you disagree, please explain what is expected and what is not in more detail. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" + }, + { + type: 'label', + name: '*english-please', + allowTriggerByBot: true, + action: 'close', + comment: "This issue is being closed because its description is not in English, that makes it hard for us to work on it. Please open a new issue with an English description. You might find [Bing Translator](https://www.bing.com/translator) useful." + }, + { + type: 'comment', + name: 'duplicate', + allowUsers: [], + action: 'updateLabels', + addLabel: '*duplicate' + }, + { + type: 'label', + name: '*duplicate', + allowTriggerByBot: true, + action: 'close', + comment: "Thanks for creating this issue! We figured it's covering the same as another one we already have. Thus, we closed this one as a duplicate. You can search for existing issues [here](https://github.com/Microsoft/monaco-editor/issues). See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" + }, + { + type: 'comment', + name: 'needsMoreInfo', + allowUsers: [], + action: 'updateLabels', + addLabel: 'needs more info', + comment: "Thanks for creating this issue! We figured it's missing some basic information or in some other way doesn't follow our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines. Please take the time to review these and update the issue.\n\nHappy Coding!" + }, + ] +} diff --git a/monaco-editor-webpack-plugin/.github/locker.yml b/monaco-editor-webpack-plugin/.github/locker.yml new file mode 100644 index 00000000..e1161b88 --- /dev/null +++ b/monaco-editor-webpack-plugin/.github/locker.yml @@ -0,0 +1,6 @@ +{ + daysAfterClose: 45, + daysSinceLastUpdate: 3, + ignoredLabels: ['*out-of-scope'], + perform: true +} diff --git a/monaco-editor-webpack-plugin/.github/needs_more_info.yml b/monaco-editor-webpack-plugin/.github/needs_more_info.yml new file mode 100644 index 00000000..8cdd234d --- /dev/null +++ b/monaco-editor-webpack-plugin/.github/needs_more_info.yml @@ -0,0 +1,6 @@ +{ + daysUntilClose: 7, + needsMoreInfoLabel: 'needs more info', + perform: true, + closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!" +} diff --git a/monaco-editor-webpack-plugin/.gitignore b/monaco-editor-webpack-plugin/.gitignore new file mode 100644 index 00000000..4e451a19 --- /dev/null +++ b/monaco-editor-webpack-plugin/.gitignore @@ -0,0 +1,5 @@ +/node_modules/ +/test/node_modules/ +/test/dist/*.js +/test/dist/*.ttf +/out/ diff --git a/monaco-editor-webpack-plugin/.npmignore b/monaco-editor-webpack-plugin/.npmignore new file mode 100644 index 00000000..6f816447 --- /dev/null +++ b/monaco-editor-webpack-plugin/.npmignore @@ -0,0 +1,2 @@ +/src/ +/test/ diff --git a/monaco-editor-webpack-plugin/.vscode/launch.json b/monaco-editor-webpack-plugin/.vscode/launch.json new file mode 100644 index 00000000..d9a608ad --- /dev/null +++ b/monaco-editor-webpack-plugin/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}/test/", + "name": "Launch Program", + "program": "${workspaceFolder}/node_modules/.bin/webpack", + "args": [ + "--config", + "webpack.config.js" + ], + } + ] +} \ No newline at end of file diff --git a/monaco-editor-webpack-plugin/.vscode/settings.json b/monaco-editor-webpack-plugin/.vscode/settings.json new file mode 100644 index 00000000..0cdcfa25 --- /dev/null +++ b/monaco-editor-webpack-plugin/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "editor.tabSize": 2, + "editor.insertSpaces": true +} diff --git a/monaco-editor-webpack-plugin/LICENSE b/monaco-editor-webpack-plugin/LICENSE new file mode 100644 index 00000000..21071075 --- /dev/null +++ b/monaco-editor-webpack-plugin/LICENSE @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/monaco-editor-webpack-plugin/README.md b/monaco-editor-webpack-plugin/README.md new file mode 100644 index 00000000..b0bf59d6 --- /dev/null +++ b/monaco-editor-webpack-plugin/README.md @@ -0,0 +1,102 @@ +# Monaco Editor Webpack Loader Plugin + +A plugin to simplify loading the [Monaco Editor](https://github.com/Microsoft/monaco-editor) with [webpack](https://webpack.js.org/). + +## Installing +```sh +npm install monaco-editor-webpack-plugin +``` + +## Using +* `webpack.config.js`: +```js +const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); +const path = require('path'); + +module.exports = { + entry: './index.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'app.js' + }, + module: { + rules: [{ + test: /\.css$/, + use: ['style-loader', 'css-loader'] + }, { + test: /\.ttf$/, + use: ['file-loader'] + }] + }, + plugins: [ + new MonacoWebpackPlugin() + ] +}; +``` + +* `index.js`: +```js +import * as monaco from 'monaco-editor' +// or import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; +// if shipping only a subset of the features & languages is desired + +monaco.editor.create(document.getElementById('container'), { + value: 'console.log("Hello, world")', + language: 'javascript' +}); +``` + +## Options + +Options can be passed in to `MonacoWebpackPlugin`. They can be used to generate a smaller editor bundle by selecting only certain languages or only certain editor features: + +* `filename` (`string`) - custom filename template for worker scripts, respects the same options as [loader-utils' interpolateName](https://github.com/webpack/loader-utils#interpolatename). Useful for adding content-based hashes so that files can be served with long-lived caching headers. + * default value: `'[name].worker.js'`. +* `publicPath` (`string`) - custom public path for worker scripts, overrides the public path from which files generated by this plugin will be served. This wins out over Webpack's dynamic runtime path and can be useful to avoid attempting to load workers cross-origin when using a CDN for other static resources. Use e.g. '/' if you want to load your resources from the current origin.. + * default value: `''`. +* `languages` (`string[]`) - include only a subset of the languages supported. + * default value: `['abap', 'apex', 'azcli', 'bat', 'bicep', 'cameligo', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dart', 'dockerfile', 'ecl', 'elixir', 'flow9', 'fsharp', 'go', 'graphql', 'handlebars', 'hcl', 'html', 'ini', 'java', 'javascript', 'json', 'julia', 'kotlin', 'less', 'lexon', 'liquid', 'lua', 'm3', 'markdown', 'mips', 'msdax', 'mysql', 'objective-c', 'pascal', 'pascaligo', 'perl', 'pgsql', 'php', 'pla', 'postiats', 'powerquery', 'powershell', 'protobuf', 'pug', 'python', 'qsharp', 'r', 'razor', 'redis', 'redshift', 'restructuredtext', 'ruby', 'rust', 'sb', 'scala', 'scheme', 'scss', 'shell', 'solidity', 'sophia', 'sparql', 'sql', 'st', 'swift', 'systemverilog', 'tcl', 'twig', 'typescript', 'vb', 'xml', 'yaml']`. + + Some languages share the same web worker. If one of the following languages is included, you must also include the language responsible for instantiating their shared worker: + + | Language | Instantiator | + | ------------- | ------------- | + | javascript | typescript | + | handlebars | html | + | scss, less | css | + + + +* `features` (`string[]`) - include only a subset of the editor features. + * default value: `['accessibilityHelp', 'anchorSelect', 'bracketMatching', 'caretOperations', 'clipboard', 'codeAction', 'codelens', 'colorPicker', 'comment', 'contextmenu', 'coreCommands', 'cursorUndo', 'dnd', 'documentSymbols', 'find', 'folding', 'fontZoom', 'format', 'gotoError', 'gotoLine', 'gotoSymbol', 'hover', 'iPadShowKeyboard', 'inPlaceReplace', 'indentation', 'inlayHints', 'inlineCompletions', 'inspectTokens', 'linesOperations', 'linkedEditing', 'links', 'multicursor', 'parameterHints', 'quickCommand', 'quickHelp', 'quickOutline', 'referenceSearch', 'rename', 'smartSelect', 'snippets', 'suggest', 'toggleHighContrast', 'toggleTabFocusMode', 'transpose', 'unusualLineTerminators', 'viewportSemanticTokens', 'wordHighlighter', 'wordOperations', 'wordPartOperations']`. + * excluded features: It is also possible to exclude certain default features prefixing them with an exclamation mark '!'. + +* `globalAPI` (`boolean`) - specify whether the editor API should be exposed through a global `monaco` object or not. This option is applicable to `0.22.0` and newer version of `monaco-editor`. Since `0.22.0`, the ESM version of the monaco editor does no longer define a global `monaco` object unless `global.MonacoEnvironment = { globalAPI: true }` is set ([change log](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md#0220-29012021)). + * default value: `false`. + +## Version Matrix + +| `monaco-editor-webpack-plugin` | `monaco-editor` | +|---|---| +| `6.*.*` | `0.30.*` | +| `5.*.*` | `0.29.*` | +| `4.*.*` | `0.25.*`, `0.26.*`, `0.27.*`, `0.28.*` | +| `3.*.*` | `0.22.*`, `0.23.*`, `0.24.*` | +| `2.*.*` | `0.21.*` | +| `1.9.*` | `0.20.*` | +| `1.8.*` | `0.19.*` | +| `1.7.*` | `0.18.*` | + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/monaco-editor-webpack-plugin/SECURITY.md b/monaco-editor-webpack-plugin/SECURITY.md new file mode 100644 index 00000000..a050f362 --- /dev/null +++ b/monaco-editor-webpack-plugin/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + diff --git a/monaco-editor-webpack-plugin/package-lock.json b/monaco-editor-webpack-plugin/package-lock.json new file mode 100644 index 00000000..72c5927e --- /dev/null +++ b/monaco-editor-webpack-plugin/package-lock.json @@ -0,0 +1,1337 @@ +{ + "name": "monaco-editor-webpack-plugin", + "version": "6.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true + }, + "@types/eslint": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", + "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz", + "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "dev": true + }, + "@types/node": { + "version": "14.14.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", + "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", + "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", + "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", + "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", + "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", + "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", + "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", + "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", + "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", + "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", + "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/helper-wasm-section": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-opt": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "@webassemblyjs/wast-printer": "1.11.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", + "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", + "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", + "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", + "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.1.tgz", + "integrity": "sha512-B+4uBUYhpzDXmwuo3V9yBH6cISwxEI4J+NO5ggDaGEEHb0osY/R7MzeKc0bHURXQuZjMM4qD+bSJCKIuI3eNBQ==", + "dev": true + }, + "@webpack-cli/info": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.2.tgz", + "integrity": "sha512-5U9kUJHnwU+FhKH4PWGZuBC1hTEPYyxGSL5jjoBI96Gx8qcYJGOikpiIpFoTq8mmgX3im2zAo2wanv/alD74KQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.0.tgz", + "integrity": "sha512-k2p2VrONcYVX1wRRrf0f3X2VGltLWcv+JzXRBDmvCxGlCeESx4OXw91TsWeKOkp784uNoVQo313vxJFHXPPwfw==", + "dev": true + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "acorn": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.5.tgz", + "integrity": "sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg==", + "dev": true + }, + "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" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "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 + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "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" + } + }, + "browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001228", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", + "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.736", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.736.tgz", + "integrity": "sha512-DY8dA7gR51MSo66DqitEQoUMQ0Z+A2DSXFi7tK304bdTVqczCAfUuyQw6Wdg8hIoo5zIxkU1L24RQtUce1Ioig==", + "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 + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "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 + }, + "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" + } + }, + "css-loader": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.1.1.tgz", + "integrity": "sha512-5FfhpjwtuRgxqmusDidowqmLlcb+1HgnEDMsi2JhiUrZUcoc+cqw+mUtMIF/+OfeMYaaFCLYp1TaIt9H6I/fKA==", + "dev": true, + "requires": { + "camelcase": "^6.2.0", + "cssesc": "^3.0.0", + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.6", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "enhanced-resolve": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz", + "integrity": "sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.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" + } + }, + "envinfo": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", + "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", + "dev": true + }, + "es-module-lexer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.4.1.tgz", + "integrity": "sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "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" + } + }, + "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.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "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 + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "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-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "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-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 + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "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.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "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-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "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 + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.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 + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "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 + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.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" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "dev": true, + "requires": { + "mime-db": "1.46.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "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": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "monaco-editor": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.30.0.tgz", + "integrity": "sha512-/k++/ofRmwnwWTpOWYOMGVcqBrqrlt3MP0Mt/cRTQojW7A9fnekcvPQ2iIFA0YSZdPWPN9yYXrYq0xqiUuxT/A==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node-releases": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", + "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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-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 + }, + "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 + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "postcss": { + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map": "^0.6.1" + }, + "dependencies": { + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "dev": true + } + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "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 + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.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 + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "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 + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "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 + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "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" + } + }, + "tapable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", + "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "dev": true + }, + "terser": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==", + "dev": true, + "requires": { + "jest-worker": "^26.6.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.5.1" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "typescript": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", + "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", + "dev": true + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "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.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "watchpack": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", + "integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.24.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.24.3.tgz", + "integrity": "sha512-x7lrWZ7wlWAdyKdML6YPvfVZkhD1ICuIZGODE5SzKJjqI9A4SpqGTjGJTc6CwaHqn19gGaoOR3ONJ46nYsn9rw==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.46", + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/wasm-edit": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "acorn": "^8.0.4", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.7.0", + "es-module-lexer": "^0.4.0", + "eslint-scope": "^5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.1", + "watchpack": "^2.0.0", + "webpack-sources": "^2.1.1" + } + }, + "webpack-cli": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.5.0.tgz", + "integrity": "sha512-wXg/ef6Ibstl2f50mnkcHblRPN/P9J4Nlod5Hg9HGFgSeF8rsqDGHJeVe4aR26q9l62TUJi6vmvC2Qz96YJw1Q==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.0.1", + "@webpack-cli/info": "^1.2.2", + "@webpack-cli/serve": "^1.3.0", + "colorette": "^1.2.1", + "commander": "^7.0.0", + "enquirer": "^2.3.6", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", + "integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "dev": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.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" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "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 + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/monaco-editor-webpack-plugin/package.json b/monaco-editor-webpack-plugin/package.json new file mode 100644 index 00000000..0d165498 --- /dev/null +++ b/monaco-editor-webpack-plugin/package.json @@ -0,0 +1,47 @@ +{ + "name": "monaco-editor-webpack-plugin", + "version": "6.0.0", + "description": "A webpack plugin for the Monaco Editor", + "main": "out/index.js", + "typings": "./out/index.d.ts", + "scripts": { + "test": "node ./node_modules/webpack/bin/webpack.js --config test/webpack.config.js --progress", + "test-cross-origin": "node ./node_modules/webpack/bin/webpack.js --config test/webpack-cross-origin.config.js --progress", + "watch": "tsc -w -p tsconfig.json", + "import-editor": "node ./scripts/import-editor.js", + "prepublishOnly": "tsc -p tsconfig.json" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/microsoft/monaco-editor-webpack-plugin.git" + }, + "keywords": [ + "webpack", + "monaco", + "editor", + "loader" + ], + "author": "Microsoft Corporation", + "license": "MIT", + "bugs": { + "url": "https://github.com/microsoft/monaco-editor-webpack-plugin/issues" + }, + "homepage": "https://github.com/microsoft/monaco-editor-webpack-plugin#readme", + "peerDependencies": { + "webpack": "^4.5.0 || 5.x", + "monaco-editor": "0.30.x" + }, + "devDependencies": { + "css-loader": "^5.1.1", + "file-loader": "^6.2.0", + "glob": "^7.1.6", + "monaco-editor": "^0.30.0", + "style-loader": "^2.0.0", + "typescript": "^4.2.3", + "webpack": "^5.24.3", + "webpack-cli": "^4.5.0" + }, + "dependencies": { + "loader-utils": "^2.0.0" + } +} diff --git a/monaco-editor-webpack-plugin/scripts/import-editor.js b/monaco-editor-webpack-plugin/scripts/import-editor.js new file mode 100644 index 00000000..b2af4f41 --- /dev/null +++ b/monaco-editor-webpack-plugin/scripts/import-editor.js @@ -0,0 +1,271 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See LICENSE in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const glob = require('glob'); +const path = require('path'); +const fs = require('fs'); + +const customFeatureLabels = { + 'vs/editor/browser/controller/coreCommands': 'coreCommands', + 'vs/editor/contrib/caretOperations/caretOperations': 'caretOperations', + 'vs/editor/contrib/caretOperations/transpose': 'transpose', + 'vs/editor/contrib/colorPicker/colorDetector': 'colorDetector', + 'vs/editor/contrib/rename/onTypeRename': 'onTypeRename', + 'vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition': 'gotoSymbol', + 'vs/editor/contrib/snippet/snippetController2': 'snippets', + 'vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess': 'gotoLine', + 'vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess': 'quickCommand', + 'vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess': 'quickOutline', + 'vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess': 'quickHelp', +}; + +generateLanguages(); +generateFeatures(); + +/** + * @returns { Promise<{ label: string; entry: string; }[]> } + */ +function getBasicLanguages() { + return new Promise((resolve, reject) => { + glob('./node_modules/monaco-editor/esm/vs/basic-languages/*/*.contribution.js', { cwd: path.dirname(__dirname) }, (err, files) => { + if (err) { + reject(err); + return; + } + + resolve(files.map((file) => { + const entry = file.substring('./node_modules/monaco-editor/esm/'.length).replace(/\.js$/, ''); + const label = path.basename(file).replace(/\.contribution\.js$/, ''); + return { + label: label, + entry: entry + }; + })); + }); + }); +} + +/** + * @returns { Promise } + */ +function readAdvancedLanguages() { + return new Promise((resolve, reject) => { + glob('./node_modules/monaco-editor/esm/vs/language/*/monaco.contribution.js', { cwd: path.dirname(__dirname) }, (err, files) => { + if (err) { + reject(err); + return; + } + + resolve( + files + .map(file => file.substring('./node_modules/monaco-editor/esm/vs/language/'.length)) + .map(file => file.substring(0, file.length - '/monaco.contribution.js'.length)) + ); + }); + }); +} + +/** + * @returns { Promise<{ label: string; entry: string; worker: { id: string; entry: string; }; }[]> } + */ +function getAdvancedLanguages() { + return readAdvancedLanguages().then((languages) => { + let result = []; + for (const lang of languages) { + let shortLang = (lang === 'typescript' ? 'ts' : lang); + const entry = `vs/language/${lang}/monaco.contribution`; + checkFileExists(entry); + const workerId = `vs/language/${lang}/${shortLang}Worker`; + checkFileExists(workerId); + const workerEntry = `vs/language/${lang}/${shortLang}.worker`; + checkFileExists(workerEntry); + result.push({ + label: lang, + entry: entry, + worker: { + id: workerId, + entry: workerEntry + } + }); + } + return result; + }); + + function checkFileExists(moduleName) { + const filePath = path.join(__dirname, '..', 'node_modules/monaco-editor/esm', `${moduleName}.js`); + if (!fs.existsSync(filePath)) { + console.error(`Could not find ${filePath}.`); + process.exit(1); + } + } +} + +function generateLanguages() { + return Promise.all([getBasicLanguages(), getAdvancedLanguages()]).then(([basicLanguages, advancedLanguages]) => { + basicLanguages.sort(strcmp); + advancedLanguages.sort(strcmp); + + let i = 0, len = basicLanguages.length; + let j = 0, lenJ = advancedLanguages.length; + let result = []; + while (i < len || j < lenJ) { + if (i < len && j < lenJ) { + if (basicLanguages[i].label === advancedLanguages[j].label) { + let entry = []; + entry.push(basicLanguages[i].entry); + entry.push(advancedLanguages[j].entry); + result.push({ + label: basicLanguages[i].label, + entry: entry, + worker: advancedLanguages[j].worker + }); + i++; + j++; + } else if (basicLanguages[i].label < advancedLanguages[j].label) { + result.push(basicLanguages[i]); + i++; + } else { + result.push(advancedLanguages[j]); + j++; + } + } else if (i < len) { + result.push(basicLanguages[i]); + i++; + } else { + result.push(advancedLanguages[j]); + j++; + } + } + + const code = `// +// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY. +// GENERATED USING node scripts/import-editor.js +// +import { IFeatureDefinition } from "./types"; + +export const languagesArr: IFeatureDefinition[] = ${ + JSON.stringify(result, null, ' ') + .replace(/"label":/g, 'label:') + .replace(/"entry":/g, 'entry:') + .replace(/"worker":/g, 'worker:') + .replace(/"id":/g, 'id:') + .replace(/"/g, '\'') + }; + +export type EditorLanguage = ${ + result.map(el => `'${el.label}'`).join(' | ') + }; + +` + fs.writeFileSync(path.join(__dirname, '../src/languages.ts'), code.replace(/\r\n/g, '\n')); + + const readmeLanguages = ( + JSON.stringify(result.map(r => r.label)) + .replace(/"/g, '\'') + .replace(/','/g, '\', \'') + ); + let readme = fs.readFileSync(path.join(__dirname, '../README.md')).toString(); + readme = readme.replace(/([^<]+)/, `\`${readmeLanguages}\``); + fs.writeFileSync(path.join(__dirname, '../README.md'), readme); + }); +} + +function strcmp(a, b) { + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + return 0; +} + +/** + * @returns { string[] } + */ +function generateFeatures() { + const skipImports = [ + 'vs/editor/browser/widget/codeEditorWidget', + 'vs/editor/browser/widget/diffEditorWidget', + 'vs/editor/browser/widget/diffNavigator', + 'vs/editor/common/standaloneStrings', + 'vs/editor/contrib/tokenization/tokenization', + 'vs/editor/editor.all', + 'vs/base/browser/ui/codicons/codiconStyles', + 'vs/editor/contrib/gotoSymbol/documentSymbols', + ]; + + let features = []; + const files = ( + fs.readFileSync(path.join(__dirname, '../node_modules/monaco-editor/esm/vs/editor/edcore.main.js')).toString() + + fs.readFileSync(path.join(__dirname, '../node_modules/monaco-editor/esm/vs/editor/editor.all.js')).toString() + ); + files.split(/\r\n|\n/).forEach(line => { + const m = line.match(/import '([^']+)'/); + if (m) { + const tmp = path.posix.join('vs/editor', m[1]).replace(/\.js$/, ''); + if (skipImports.indexOf(tmp) === -1) { + features.push(tmp); + } + } + }); + + let result = features.map((feature) => { + return { + label: customFeatureLabels[feature] || path.basename(path.dirname(feature)), + entry: feature + }; + }); + + result.sort((a, b) => { + const labelCmp = strcmp(a.label, b.label); + if (labelCmp === 0) { + return strcmp(a.entry, b.entry); + } + return labelCmp; + }); + + for (let i = 0; i < result.length; i++) { + if (i + 1 < result.length && result[i].label === result[i + 1].label) { + if (typeof result[i].entry === 'string') { + result[i].entry = [result[i].entry]; + } + result[i].entry.push(result[i + 1].entry); + result.splice(i + 1, 1); + } + } + + const code = `// +// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY. +// GENERATED USING node scripts/import-editor.js +// +import { IFeatureDefinition } from "./types"; + +export const featuresArr: IFeatureDefinition[] = ${ + JSON.stringify(result, null, ' ') + .replace(/"label":/g, 'label:') + .replace(/"entry":/g, 'entry:') + .replace(/"/g, '\'') + }; + +export type EditorFeature = ${ + result.map(el => `'${el.label}'`).join(' | ') + }; + +export type NegatedEditorFeature = ${ + result.map(el => `'!${el.label}'`).join(' | ') + }; +` + fs.writeFileSync(path.join(__dirname, '../src/features.ts'), code.replace(/\r\n/g, '\n')); + + const readmeFeatures = ( + JSON.stringify(result.map(r => r.label)) + .replace(/"/g, '\'') + .replace(/','/g, '\', \'') + ); + let readme = fs.readFileSync(path.join(__dirname, '../README.md')).toString(); + readme = readme.replace(/([^<]+)/, `\`${readmeFeatures}\``); + fs.writeFileSync(path.join(__dirname, '../README.md'), readme); +} diff --git a/monaco-editor-webpack-plugin/src/features.ts b/monaco-editor-webpack-plugin/src/features.ts new file mode 100644 index 00000000..0ed3f829 --- /dev/null +++ b/monaco-editor-webpack-plugin/src/features.ts @@ -0,0 +1,211 @@ +// +// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY. +// GENERATED USING node scripts/import-editor.js +// +import { IFeatureDefinition } from "./types"; + +export const featuresArr: IFeatureDefinition[] = [ + { + label: 'accessibilityHelp', + entry: 'vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp' + }, + { + label: 'anchorSelect', + entry: 'vs/editor/contrib/anchorSelect/anchorSelect' + }, + { + label: 'bracketMatching', + entry: 'vs/editor/contrib/bracketMatching/bracketMatching' + }, + { + label: 'caretOperations', + entry: 'vs/editor/contrib/caretOperations/caretOperations' + }, + { + label: 'clipboard', + entry: 'vs/editor/contrib/clipboard/clipboard' + }, + { + label: 'codeAction', + entry: 'vs/editor/contrib/codeAction/codeActionContributions' + }, + { + label: 'codelens', + entry: 'vs/editor/contrib/codelens/codelensController' + }, + { + label: 'colorPicker', + entry: 'vs/editor/contrib/colorPicker/colorContributions' + }, + { + label: 'comment', + entry: 'vs/editor/contrib/comment/comment' + }, + { + label: 'contextmenu', + entry: 'vs/editor/contrib/contextmenu/contextmenu' + }, + { + label: 'coreCommands', + entry: 'vs/editor/browser/controller/coreCommands' + }, + { + label: 'cursorUndo', + entry: 'vs/editor/contrib/cursorUndo/cursorUndo' + }, + { + label: 'dnd', + entry: 'vs/editor/contrib/dnd/dnd' + }, + { + label: 'documentSymbols', + entry: 'vs/editor/contrib/documentSymbols/documentSymbols' + }, + { + label: 'find', + entry: 'vs/editor/contrib/find/findController' + }, + { + label: 'folding', + entry: 'vs/editor/contrib/folding/folding' + }, + { + label: 'fontZoom', + entry: 'vs/editor/contrib/fontZoom/fontZoom' + }, + { + label: 'format', + entry: 'vs/editor/contrib/format/formatActions' + }, + { + label: 'gotoError', + entry: 'vs/editor/contrib/gotoError/gotoError' + }, + { + label: 'gotoLine', + entry: 'vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess' + }, + { + label: 'gotoSymbol', + entry: [ + 'vs/editor/contrib/gotoSymbol/goToCommands', + 'vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition' + ] + }, + { + label: 'hover', + entry: 'vs/editor/contrib/hover/hover' + }, + { + label: 'iPadShowKeyboard', + entry: 'vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard' + }, + { + label: 'inPlaceReplace', + entry: 'vs/editor/contrib/inPlaceReplace/inPlaceReplace' + }, + { + label: 'indentation', + entry: 'vs/editor/contrib/indentation/indentation' + }, + { + label: 'inlayHints', + entry: 'vs/editor/contrib/inlayHints/inlayHintsController' + }, + { + label: 'inlineCompletions', + entry: 'vs/editor/contrib/inlineCompletions/ghostTextController' + }, + { + label: 'inspectTokens', + entry: 'vs/editor/standalone/browser/inspectTokens/inspectTokens' + }, + { + label: 'linesOperations', + entry: 'vs/editor/contrib/linesOperations/linesOperations' + }, + { + label: 'linkedEditing', + entry: 'vs/editor/contrib/linkedEditing/linkedEditing' + }, + { + label: 'links', + entry: 'vs/editor/contrib/links/links' + }, + { + label: 'multicursor', + entry: 'vs/editor/contrib/multicursor/multicursor' + }, + { + label: 'parameterHints', + entry: 'vs/editor/contrib/parameterHints/parameterHints' + }, + { + label: 'quickCommand', + entry: 'vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess' + }, + { + label: 'quickHelp', + entry: 'vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess' + }, + { + label: 'quickOutline', + entry: 'vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess' + }, + { + label: 'referenceSearch', + entry: 'vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch' + }, + { + label: 'rename', + entry: 'vs/editor/contrib/rename/rename' + }, + { + label: 'smartSelect', + entry: 'vs/editor/contrib/smartSelect/smartSelect' + }, + { + label: 'snippets', + entry: 'vs/editor/contrib/snippet/snippetController2' + }, + { + label: 'suggest', + entry: 'vs/editor/contrib/suggest/suggestController' + }, + { + label: 'toggleHighContrast', + entry: 'vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast' + }, + { + label: 'toggleTabFocusMode', + entry: 'vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode' + }, + { + label: 'transpose', + entry: 'vs/editor/contrib/caretOperations/transpose' + }, + { + label: 'unusualLineTerminators', + entry: 'vs/editor/contrib/unusualLineTerminators/unusualLineTerminators' + }, + { + label: 'viewportSemanticTokens', + entry: 'vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens' + }, + { + label: 'wordHighlighter', + entry: 'vs/editor/contrib/wordHighlighter/wordHighlighter' + }, + { + label: 'wordOperations', + entry: 'vs/editor/contrib/wordOperations/wordOperations' + }, + { + label: 'wordPartOperations', + entry: 'vs/editor/contrib/wordPartOperations/wordPartOperations' + } +]; + +export type EditorFeature = 'accessibilityHelp' | 'anchorSelect' | 'bracketMatching' | 'caretOperations' | 'clipboard' | 'codeAction' | 'codelens' | 'colorPicker' | 'comment' | 'contextmenu' | 'coreCommands' | 'cursorUndo' | 'dnd' | 'documentSymbols' | 'find' | 'folding' | 'fontZoom' | 'format' | 'gotoError' | 'gotoLine' | 'gotoSymbol' | 'hover' | 'iPadShowKeyboard' | 'inPlaceReplace' | 'indentation' | 'inlayHints' | 'inlineCompletions' | 'inspectTokens' | 'linesOperations' | 'linkedEditing' | 'links' | 'multicursor' | 'parameterHints' | 'quickCommand' | 'quickHelp' | 'quickOutline' | 'referenceSearch' | 'rename' | 'smartSelect' | 'snippets' | 'suggest' | 'toggleHighContrast' | 'toggleTabFocusMode' | 'transpose' | 'unusualLineTerminators' | 'viewportSemanticTokens' | 'wordHighlighter' | 'wordOperations' | 'wordPartOperations'; + +export type NegatedEditorFeature = '!accessibilityHelp' | '!anchorSelect' | '!bracketMatching' | '!caretOperations' | '!clipboard' | '!codeAction' | '!codelens' | '!colorPicker' | '!comment' | '!contextmenu' | '!coreCommands' | '!cursorUndo' | '!dnd' | '!documentSymbols' | '!find' | '!folding' | '!fontZoom' | '!format' | '!gotoError' | '!gotoLine' | '!gotoSymbol' | '!hover' | '!iPadShowKeyboard' | '!inPlaceReplace' | '!indentation' | '!inlayHints' | '!inlineCompletions' | '!inspectTokens' | '!linesOperations' | '!linkedEditing' | '!links' | '!multicursor' | '!parameterHints' | '!quickCommand' | '!quickHelp' | '!quickOutline' | '!referenceSearch' | '!rename' | '!smartSelect' | '!snippets' | '!suggest' | '!toggleHighContrast' | '!toggleTabFocusMode' | '!transpose' | '!unusualLineTerminators' | '!viewportSemanticTokens' | '!wordHighlighter' | '!wordOperations' | '!wordPartOperations'; diff --git a/monaco-editor-webpack-plugin/src/index.ts b/monaco-editor-webpack-plugin/src/index.ts new file mode 100644 index 00000000..7a40aff8 --- /dev/null +++ b/monaco-editor-webpack-plugin/src/index.ts @@ -0,0 +1,300 @@ +import type * as webpack from 'webpack'; +import * as path from 'path'; +import * as loaderUtils from 'loader-utils'; +import * as fs from 'fs'; +import { AddWorkerEntryPointPlugin } from './plugins/AddWorkerEntryPointPlugin'; +import { languagesArr, EditorLanguage } from './languages'; +import { featuresArr, EditorFeature, NegatedEditorFeature } from './features'; +import { IFeatureDefinition } from './types'; + +const INCLUDE_LOADER_PATH = require.resolve('./loaders/include'); + +const EDITOR_MODULE: IFeatureDefinition = { + label: 'editorWorkerService', + entry: undefined, + worker: { + id: 'vs/editor/editor', + entry: 'vs/editor/editor.worker' + }, +}; + +const languagesById: { [language: string]: IFeatureDefinition; } = {}; +languagesArr.forEach(language => languagesById[language.label] = language); + +const featuresById: { [feature: string]: IFeatureDefinition; } = {}; +featuresArr.forEach(feature => featuresById[feature.label] = feature); + +/** + * Return a resolved path for a given Monaco file. + */ +function resolveMonacoPath(filePath: string): string { + try { + return require.resolve(path.join('monaco-editor/esm', filePath)); + } catch(err) { + try { + return require.resolve(path.join(process.cwd(), 'node_modules/monaco-editor/esm', filePath)); + } catch(err){ + return require.resolve(filePath); + } + } +} + +/** + * Return the interpolated final filename for a worker, respecting the file name template. + */ +function getWorkerFilename(filename: string, entry: string): string { + return loaderUtils.interpolateName({ resourcePath: entry }, filename, { + content: fs.readFileSync(resolveMonacoPath(entry)) + }); +} + +function getFeaturesIds(userFeatures: string[]): string[] { + function notContainedIn(arr: string[]) { + return (element: string) => arr.indexOf(element) === -1; + } + + let featuresIds: string[]; + + if (userFeatures.length) { + const excludedFeatures = userFeatures.filter(f => f[0] === '!').map(f => f.slice(1)); + if (excludedFeatures.length) { + featuresIds = Object.keys(featuresById).filter(notContainedIn(excludedFeatures)) + } else { + featuresIds = userFeatures; + } + } else { + featuresIds = Object.keys(featuresById); + } + + return featuresIds; +} + +interface IMonacoEditorWebpackPluginOpts { + /** + * Include only a subset of the languages supported. + */ + languages?: EditorLanguage[]; + + /** + * Custom languages (outside of the ones shipped with the `monaco-editor`). + */ + customLanguages?: IFeatureDefinition[]; + + /** + * Include only a subset of the editor features. + * Use e.g. '!contextmenu' to exclude a certain feature. + */ + features?: (EditorFeature | NegatedEditorFeature)[]; + + /** + * Specify a filename template to use for generated files. + * Use e.g. '[name].worker.[contenthash].js' to include content-based hashes. + */ + filename?: string; + + /** + * Override the public path from which files generated by this plugin will be served. + * This wins out over Webpack's dynamic runtime path and can be useful to avoid attempting to load workers cross- + * origin when using a CDN for other static resources. + * Use e.g. '/' if you want to load your resources from the current origin. + */ + publicPath?: string; + + /** + * Specify whether the editor API should be exposed through a global `monaco` object or not. This + * option is applicable to `0.22.0` and newer version of `monaco-editor`. Since `0.22.0`, the ESM + * version of the monaco editor does no longer define a global `monaco` object unless + * `global.MonacoEnvironment = { globalAPI: true }` is set ([change + * log](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md#0220-29012021)). + */ + globalAPI?: boolean; +} + +interface IInternalMonacoEditorWebpackPluginOpts { + languages: IFeatureDefinition[]; + features: IFeatureDefinition[]; + filename: string; + publicPath: string; + globalAPI: boolean; +} + +class MonacoEditorWebpackPlugin implements webpack.WebpackPluginInstance { + + private readonly options: IInternalMonacoEditorWebpackPluginOpts; + + constructor(options: IMonacoEditorWebpackPluginOpts = {}) { + const languages = options.languages || Object.keys(languagesById); + const customLanguages = options.customLanguages || []; + const features = getFeaturesIds(options.features || []); + this.options = { + languages: coalesce(languages.map(id => languagesById[id])).concat(customLanguages), + features: coalesce(features.map(id => featuresById[id])), + filename: options.filename || "[name].worker.js", + publicPath: options.publicPath || '', + globalAPI: options.globalAPI || false, + }; + } + + apply(compiler: webpack.Compiler): void { + const { languages, features, filename, publicPath, globalAPI } = this.options; + const compilationPublicPath = getCompilationPublicPath(compiler); + const modules = [EDITOR_MODULE].concat(languages).concat(features); + const workers: ILabeledWorkerDefinition[] = []; + modules.forEach((module) => { + if (module.worker) { + workers.push({ + label: module.label, + id: module.worker.id, + entry: module.worker.entry + }); + } + }); + const rules = createLoaderRules(languages, features, workers, filename, publicPath, compilationPublicPath, globalAPI); + const plugins = createPlugins(compiler, workers, filename); + addCompilerRules(compiler, rules); + addCompilerPlugins(compiler, plugins); + } +} + +interface ILabeledWorkerDefinition { + label: string; + id: string; + entry: string; +} + +function addCompilerRules(compiler: webpack.Compiler, rules: webpack.RuleSetRule[]): void { + const compilerOptions = compiler.options; + if (!compilerOptions.module) { + compilerOptions.module = { rules: rules }; + } else { + const moduleOptions = compilerOptions.module; + moduleOptions.rules = (moduleOptions.rules || []).concat(rules); + } +} + +function addCompilerPlugins(compiler: webpack.Compiler, plugins: webpack.WebpackPluginInstance[]) { + plugins.forEach((plugin) => plugin.apply(compiler)); +} + +function getCompilationPublicPath(compiler: webpack.Compiler): string { + if (compiler.options.output && compiler.options.output.publicPath) { + if (typeof compiler.options.output.publicPath === 'string') { + return compiler.options.output.publicPath; + } else { + console.warn(`Cannot handle options.publicPath (expected a string)`); + } + } + return ''; +} + +function createLoaderRules(languages: IFeatureDefinition[], features: IFeatureDefinition[], workers: ILabeledWorkerDefinition[], filename: string, pluginPublicPath: string, compilationPublicPath: string, globalAPI: boolean): webpack.RuleSetRule[] { + if (!languages.length && !features.length) { + return []; + } + const languagePaths = flatArr(coalesce(languages.map(language => language.entry))); + const featurePaths = flatArr(coalesce(features.map(feature => feature.entry))); + const workerPaths = fromPairs(workers.map(({ label, entry }) => [label, getWorkerFilename(filename, entry)])); + if (workerPaths['typescript']) { + // javascript shares the same worker + workerPaths['javascript'] = workerPaths['typescript']; + } + if (workerPaths['css']) { + // scss and less share the same worker + workerPaths['less'] = workerPaths['css']; + workerPaths['scss'] = workerPaths['css']; + } + + if (workerPaths['html']) { + // handlebars, razor and html share the same worker + workerPaths['handlebars'] = workerPaths['html']; + workerPaths['razor'] = workerPaths['html']; + } + + // Determine the public path from which to load worker JS files. In order of precedence: + // 1. Plugin-specific public path. + // 2. Dynamic runtime public path. + // 3. Compilation public path. + const pathPrefix = Boolean(pluginPublicPath) + ? JSON.stringify(pluginPublicPath) + : `typeof __webpack_public_path__ === 'string' ` + + `? __webpack_public_path__ ` + + `: ${JSON.stringify(compilationPublicPath)}` + + const globals = { + 'MonacoEnvironment': `(function (paths) { + function stripTrailingSlash(str) { + return str.replace(/\\/$/, ''); + } + return { + globalAPI: ${globalAPI}, + getWorkerUrl: function (moduleId, label) { + var pathPrefix = ${pathPrefix}; + var result = (pathPrefix ? stripTrailingSlash(pathPrefix) + '/' : '') + paths[label]; + if (/^((http:)|(https:)|(file:)|(\\/\\/))/.test(result)) { + var currentUrl = String(window.location); + var currentOrigin = currentUrl.substr(0, currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length); + if (result.substring(0, currentOrigin.length) !== currentOrigin) { + if(/^(\\/\\/)/.test(result)) { + result = window.location.protocol + result + } + var js = '/*' + label + '*/importScripts("' + result + '");'; + var blob = new Blob([js], { type: 'application/javascript' }); + return URL.createObjectURL(blob); + } + } + return result; + } + }; + })(${JSON.stringify(workerPaths, null, 2)})`, + }; + return [ + { + test: /monaco-editor[/\\]esm[/\\]vs[/\\]editor[/\\]editor.(api|main).js/, + use: [{ + loader: INCLUDE_LOADER_PATH, + options: { + globals, + pre: featurePaths.map((importPath) => resolveMonacoPath(importPath)), + post: languagePaths.map((importPath) => resolveMonacoPath(importPath)), + }, + }], + }, + ]; +} + +function createPlugins(compiler: webpack.Compiler, workers: ILabeledWorkerDefinition[], filename: string): AddWorkerEntryPointPlugin[] { + const webpack = compiler.webpack ?? require('webpack'); + + return ( + ([]) + .concat(workers.map(({ id, entry }) => + new AddWorkerEntryPointPlugin({ + id, + entry: resolveMonacoPath(entry), + filename: getWorkerFilename(filename, entry), + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }), + ], + }) + )) + ); +} + +function flatArr(items: (T | T[])[]): T[] { + return items.reduce((acc: T[], item: T | T[]) => { + if (Array.isArray(item)) { + return ([]).concat(acc).concat(item); + } + return ([]).concat(acc).concat([item]); + }, []); +} + +function fromPairs(values: [string, T][]): { [key: string]: T; } { + return values.reduce((acc, [key, value]) => Object.assign(acc, { [key]: value }), <{ [key: string]: T; }>{}); +} + +function coalesce(array: ReadonlyArray): T[] { + return array.filter(Boolean); +} + +export = MonacoEditorWebpackPlugin; diff --git a/monaco-editor-webpack-plugin/src/languages.ts b/monaco-editor-webpack-plugin/src/languages.ts new file mode 100644 index 00000000..5b982ec2 --- /dev/null +++ b/monaco-editor-webpack-plugin/src/languages.ts @@ -0,0 +1,344 @@ +// +// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY. +// GENERATED USING node scripts/import-editor.js +// +import { IFeatureDefinition } from "./types"; + +export const languagesArr: IFeatureDefinition[] = [ + { + label: 'abap', + entry: 'vs/basic-languages/abap/abap.contribution' + }, + { + label: 'apex', + entry: 'vs/basic-languages/apex/apex.contribution' + }, + { + label: 'azcli', + entry: 'vs/basic-languages/azcli/azcli.contribution' + }, + { + label: 'bat', + entry: 'vs/basic-languages/bat/bat.contribution' + }, + { + label: 'bicep', + entry: 'vs/basic-languages/bicep/bicep.contribution' + }, + { + label: 'cameligo', + entry: 'vs/basic-languages/cameligo/cameligo.contribution' + }, + { + label: 'clojure', + entry: 'vs/basic-languages/clojure/clojure.contribution' + }, + { + label: 'coffee', + entry: 'vs/basic-languages/coffee/coffee.contribution' + }, + { + label: 'cpp', + entry: 'vs/basic-languages/cpp/cpp.contribution' + }, + { + label: 'csharp', + entry: 'vs/basic-languages/csharp/csharp.contribution' + }, + { + label: 'csp', + entry: 'vs/basic-languages/csp/csp.contribution' + }, + { + label: 'css', + entry: [ + 'vs/basic-languages/css/css.contribution', + 'vs/language/css/monaco.contribution' + ], + worker: { + id: 'vs/language/css/cssWorker', + entry: 'vs/language/css/css.worker' + } + }, + { + label: 'dart', + entry: 'vs/basic-languages/dart/dart.contribution' + }, + { + label: 'dockerfile', + entry: 'vs/basic-languages/dockerfile/dockerfile.contribution' + }, + { + label: 'ecl', + entry: 'vs/basic-languages/ecl/ecl.contribution' + }, + { + label: 'elixir', + entry: 'vs/basic-languages/elixir/elixir.contribution' + }, + { + label: 'flow9', + entry: 'vs/basic-languages/flow9/flow9.contribution' + }, + { + label: 'fsharp', + entry: 'vs/basic-languages/fsharp/fsharp.contribution' + }, + { + label: 'go', + entry: 'vs/basic-languages/go/go.contribution' + }, + { + label: 'graphql', + entry: 'vs/basic-languages/graphql/graphql.contribution' + }, + { + label: 'handlebars', + entry: 'vs/basic-languages/handlebars/handlebars.contribution' + }, + { + label: 'hcl', + entry: 'vs/basic-languages/hcl/hcl.contribution' + }, + { + label: 'html', + entry: [ + 'vs/basic-languages/html/html.contribution', + 'vs/language/html/monaco.contribution' + ], + worker: { + id: 'vs/language/html/htmlWorker', + entry: 'vs/language/html/html.worker' + } + }, + { + label: 'ini', + entry: 'vs/basic-languages/ini/ini.contribution' + }, + { + label: 'java', + entry: 'vs/basic-languages/java/java.contribution' + }, + { + label: 'javascript', + entry: 'vs/basic-languages/javascript/javascript.contribution' + }, + { + label: 'json', + entry: 'vs/language/json/monaco.contribution', + worker: { + id: 'vs/language/json/jsonWorker', + entry: 'vs/language/json/json.worker' + } + }, + { + label: 'julia', + entry: 'vs/basic-languages/julia/julia.contribution' + }, + { + label: 'kotlin', + entry: 'vs/basic-languages/kotlin/kotlin.contribution' + }, + { + label: 'less', + entry: 'vs/basic-languages/less/less.contribution' + }, + { + label: 'lexon', + entry: 'vs/basic-languages/lexon/lexon.contribution' + }, + { + label: 'liquid', + entry: 'vs/basic-languages/liquid/liquid.contribution' + }, + { + label: 'lua', + entry: 'vs/basic-languages/lua/lua.contribution' + }, + { + label: 'm3', + entry: 'vs/basic-languages/m3/m3.contribution' + }, + { + label: 'markdown', + entry: 'vs/basic-languages/markdown/markdown.contribution' + }, + { + label: 'mips', + entry: 'vs/basic-languages/mips/mips.contribution' + }, + { + label: 'msdax', + entry: 'vs/basic-languages/msdax/msdax.contribution' + }, + { + label: 'mysql', + entry: 'vs/basic-languages/mysql/mysql.contribution' + }, + { + label: 'objective-c', + entry: 'vs/basic-languages/objective-c/objective-c.contribution' + }, + { + label: 'pascal', + entry: 'vs/basic-languages/pascal/pascal.contribution' + }, + { + label: 'pascaligo', + entry: 'vs/basic-languages/pascaligo/pascaligo.contribution' + }, + { + label: 'perl', + entry: 'vs/basic-languages/perl/perl.contribution' + }, + { + label: 'pgsql', + entry: 'vs/basic-languages/pgsql/pgsql.contribution' + }, + { + label: 'php', + entry: 'vs/basic-languages/php/php.contribution' + }, + { + label: 'pla', + entry: 'vs/basic-languages/pla/pla.contribution' + }, + { + label: 'postiats', + entry: 'vs/basic-languages/postiats/postiats.contribution' + }, + { + label: 'powerquery', + entry: 'vs/basic-languages/powerquery/powerquery.contribution' + }, + { + label: 'powershell', + entry: 'vs/basic-languages/powershell/powershell.contribution' + }, + { + label: 'protobuf', + entry: 'vs/basic-languages/protobuf/protobuf.contribution' + }, + { + label: 'pug', + entry: 'vs/basic-languages/pug/pug.contribution' + }, + { + label: 'python', + entry: 'vs/basic-languages/python/python.contribution' + }, + { + label: 'qsharp', + entry: 'vs/basic-languages/qsharp/qsharp.contribution' + }, + { + label: 'r', + entry: 'vs/basic-languages/r/r.contribution' + }, + { + label: 'razor', + entry: 'vs/basic-languages/razor/razor.contribution' + }, + { + label: 'redis', + entry: 'vs/basic-languages/redis/redis.contribution' + }, + { + label: 'redshift', + entry: 'vs/basic-languages/redshift/redshift.contribution' + }, + { + label: 'restructuredtext', + entry: 'vs/basic-languages/restructuredtext/restructuredtext.contribution' + }, + { + label: 'ruby', + entry: 'vs/basic-languages/ruby/ruby.contribution' + }, + { + label: 'rust', + entry: 'vs/basic-languages/rust/rust.contribution' + }, + { + label: 'sb', + entry: 'vs/basic-languages/sb/sb.contribution' + }, + { + label: 'scala', + entry: 'vs/basic-languages/scala/scala.contribution' + }, + { + label: 'scheme', + entry: 'vs/basic-languages/scheme/scheme.contribution' + }, + { + label: 'scss', + entry: 'vs/basic-languages/scss/scss.contribution' + }, + { + label: 'shell', + entry: 'vs/basic-languages/shell/shell.contribution' + }, + { + label: 'solidity', + entry: 'vs/basic-languages/solidity/solidity.contribution' + }, + { + label: 'sophia', + entry: 'vs/basic-languages/sophia/sophia.contribution' + }, + { + label: 'sparql', + entry: 'vs/basic-languages/sparql/sparql.contribution' + }, + { + label: 'sql', + entry: 'vs/basic-languages/sql/sql.contribution' + }, + { + label: 'st', + entry: 'vs/basic-languages/st/st.contribution' + }, + { + label: 'swift', + entry: 'vs/basic-languages/swift/swift.contribution' + }, + { + label: 'systemverilog', + entry: 'vs/basic-languages/systemverilog/systemverilog.contribution' + }, + { + label: 'tcl', + entry: 'vs/basic-languages/tcl/tcl.contribution' + }, + { + label: 'twig', + entry: 'vs/basic-languages/twig/twig.contribution' + }, + { + label: 'typescript', + entry: [ + 'vs/basic-languages/typescript/typescript.contribution', + 'vs/language/typescript/monaco.contribution' + ], + worker: { + id: 'vs/language/typescript/tsWorker', + entry: 'vs/language/typescript/ts.worker' + } + }, + { + label: 'vb', + entry: 'vs/basic-languages/vb/vb.contribution' + }, + { + label: 'xml', + entry: 'vs/basic-languages/xml/xml.contribution' + }, + { + label: 'yaml', + entry: 'vs/basic-languages/yaml/yaml.contribution' + } +]; + +export type EditorLanguage = 'abap' | 'apex' | 'azcli' | 'bat' | 'bicep' | 'cameligo' | 'clojure' | 'coffee' | 'cpp' | 'csharp' | 'csp' | 'css' | 'dart' | 'dockerfile' | 'ecl' | 'elixir' | 'flow9' | 'fsharp' | 'go' | 'graphql' | 'handlebars' | 'hcl' | 'html' | 'ini' | 'java' | 'javascript' | 'json' | 'julia' | 'kotlin' | 'less' | 'lexon' | 'liquid' | 'lua' | 'm3' | 'markdown' | 'mips' | 'msdax' | 'mysql' | 'objective-c' | 'pascal' | 'pascaligo' | 'perl' | 'pgsql' | 'php' | 'pla' | 'postiats' | 'powerquery' | 'powershell' | 'protobuf' | 'pug' | 'python' | 'qsharp' | 'r' | 'razor' | 'redis' | 'redshift' | 'restructuredtext' | 'ruby' | 'rust' | 'sb' | 'scala' | 'scheme' | 'scss' | 'shell' | 'solidity' | 'sophia' | 'sparql' | 'sql' | 'st' | 'swift' | 'systemverilog' | 'tcl' | 'twig' | 'typescript' | 'vb' | 'xml' | 'yaml'; + diff --git a/monaco-editor-webpack-plugin/src/loader-utils.d.ts b/monaco-editor-webpack-plugin/src/loader-utils.d.ts new file mode 100644 index 00000000..7e4d59ac --- /dev/null +++ b/monaco-editor-webpack-plugin/src/loader-utils.d.ts @@ -0,0 +1,4 @@ + +declare module 'loader-utils' { + export function interpolateName(loaderContext: any, name: string, options?: any): string; +} diff --git a/monaco-editor-webpack-plugin/src/loaders/include.ts b/monaco-editor-webpack-plugin/src/loaders/include.ts new file mode 100644 index 00000000..1e7428cc --- /dev/null +++ b/monaco-editor-webpack-plugin/src/loaders/include.ts @@ -0,0 +1,22 @@ +const loaderUtils = require('loader-utils'); + +export function pitch(this: any, remainingRequest: any) { + const { globals = undefined, pre = [], post = [] } = loaderUtils.getOptions(this) || {}; + + // HACK: NamedModulesPlugin overwrites existing modules when requesting the same module via + // different loaders, so we need to circumvent this by appending a suffix to make the name unique + // See https://github.com/webpack/webpack/issues/4613#issuecomment-325178346 for details + if (this._module && this._module.userRequest) { + this._module.userRequest = `include-loader!${this._module.userRequest}`; + } + + return [ + ...(globals + ? Object.keys(globals).map((key) => `self[${JSON.stringify(key)}] = ${globals[key]};`) + : [] + ), + ...pre.map((include: any) => `require(${loaderUtils.stringifyRequest(this, include)});`), + `module.exports = require(${loaderUtils.stringifyRequest(this, `!!${remainingRequest}`)});`, + ...post.map((include: any) => `require(${loaderUtils.stringifyRequest(this, include)});`), + ].join('\n'); +}; diff --git a/monaco-editor-webpack-plugin/src/plugins/AddWorkerEntryPointPlugin.ts b/monaco-editor-webpack-plugin/src/plugins/AddWorkerEntryPointPlugin.ts new file mode 100644 index 00000000..34be2c2c --- /dev/null +++ b/monaco-editor-webpack-plugin/src/plugins/AddWorkerEntryPointPlugin.ts @@ -0,0 +1,52 @@ +import type * as webpack from 'webpack'; + +export interface IAddWorkerEntryPointPluginOptions { + id: string; + entry: string; + filename: string; + chunkFilename?: string; + plugins: webpack.WebpackPluginInstance[]; +} + +function getCompilerHook(compiler: webpack.Compiler, { id, entry, filename, chunkFilename, plugins }: IAddWorkerEntryPointPluginOptions) { + const webpack = compiler.webpack ?? require('webpack'); + + return function (compilation: webpack.Compilation, callback: (error?: Error | null | false) => void) { + const outputOptions = { + filename, + chunkFilename, + publicPath: compilation.outputOptions.publicPath, + // HACK: globalObject is necessary to fix https://github.com/webpack/webpack/issues/6642 + globalObject: 'this', + }; + const childCompiler = compilation.createChildCompiler(id, outputOptions, [ + new webpack.webworker.WebWorkerTemplatePlugin(), + new webpack.LoaderTargetPlugin('webworker'), + ]); + const SingleEntryPlugin = webpack.EntryPlugin ?? webpack.SingleEntryPlugin; + new SingleEntryPlugin(compiler.context, entry, 'main').apply(childCompiler); + plugins.forEach((plugin) => plugin.apply(childCompiler)); + + childCompiler.runAsChild((err?: Error) => callback(err)); + } +} + +export class AddWorkerEntryPointPlugin implements webpack.WebpackPluginInstance { + + private readonly options: IAddWorkerEntryPointPluginOptions; + + constructor({ id, entry, filename, chunkFilename = undefined, plugins }: IAddWorkerEntryPointPluginOptions) { + this.options = { id, entry, filename, chunkFilename, plugins }; + } + + apply(compiler: webpack.Compiler) { + const webpack = compiler.webpack ?? require('webpack'); + const compilerHook = getCompilerHook(compiler, this.options); + const majorVersion = webpack.version.split('.')[0] + if (parseInt(majorVersion) < 4) { + (compiler).plugin('make', compilerHook); + } else { + compiler.hooks.make.tapAsync('AddWorkerEntryPointPlugin', compilerHook); + } + } +} diff --git a/monaco-editor-webpack-plugin/src/types.ts b/monaco-editor-webpack-plugin/src/types.ts new file mode 100644 index 00000000..f7a6b470 --- /dev/null +++ b/monaco-editor-webpack-plugin/src/types.ts @@ -0,0 +1,11 @@ + +export interface IWorkerDefinition { + id: string; + entry: string; +} + +export interface IFeatureDefinition { + label: string; + entry: string | string[] | undefined; + worker?: IWorkerDefinition; +} diff --git a/monaco-editor-webpack-plugin/test/dist/index.html b/monaco-editor-webpack-plugin/test/dist/index.html new file mode 100644 index 00000000..ea2d71c9 --- /dev/null +++ b/monaco-editor-webpack-plugin/test/dist/index.html @@ -0,0 +1,13 @@ + + + + + + + Document + + +
+ + + \ No newline at end of file diff --git a/monaco-editor-webpack-plugin/test/index.js b/monaco-editor-webpack-plugin/test/index.js new file mode 100644 index 00000000..f7958c89 --- /dev/null +++ b/monaco-editor-webpack-plugin/test/index.js @@ -0,0 +1,7 @@ + +import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; + +monaco.editor.create(document.getElementById('container'), { + value: 'console.log("Hello, world")', + language: 'javascript' +}); \ No newline at end of file diff --git a/monaco-editor-webpack-plugin/test/webpack-cross-origin.config.js b/monaco-editor-webpack-plugin/test/webpack-cross-origin.config.js new file mode 100644 index 00000000..32abce38 --- /dev/null +++ b/monaco-editor-webpack-plugin/test/webpack-cross-origin.config.js @@ -0,0 +1,27 @@ +const MonacoWebpackPlugin = require('../out/index.js'); +const path = require('path'); + +const ASSET_PATH = 'http://localhost:8088/monaco-editor-webpack-plugin/test/dist/'; + +module.exports = { + mode: 'development', + entry: './index.js', + context: __dirname, + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'app.js', + publicPath: ASSET_PATH + }, + module: { + rules: [{ + test: /\.css$/, + use: ['style-loader', 'css-loader'] + }, { + test: /\.ttf$/, + use: ['file-loader'] + }] + }, + plugins: [ + new MonacoWebpackPlugin() + ] +}; diff --git a/monaco-editor-webpack-plugin/test/webpack.config.js b/monaco-editor-webpack-plugin/test/webpack.config.js new file mode 100644 index 00000000..da8d2b0a --- /dev/null +++ b/monaco-editor-webpack-plugin/test/webpack.config.js @@ -0,0 +1,24 @@ +const MonacoWebpackPlugin = require('../out/index.js'); +const path = require('path'); + +module.exports = { + mode: 'development', + entry: './index.js', + context: __dirname, + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'app.js' + }, + module: { + rules: [{ + test: /\.css$/, + use: ['style-loader', 'css-loader'] + }, { + test: /\.ttf$/, + use: ['file-loader'] + }] + }, + plugins: [ + new MonacoWebpackPlugin() + ] +}; diff --git a/monaco-editor-webpack-plugin/tsconfig.json b/monaco-editor-webpack-plugin/tsconfig.json new file mode 100644 index 00000000..a377061c --- /dev/null +++ b/monaco-editor-webpack-plugin/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "outDir": "out", + "target": "es6", + "declaration": true, + "strict": true + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/monaco-html/.gitignore b/monaco-html/.gitignore new file mode 100644 index 00000000..d9ef910d --- /dev/null +++ b/monaco-html/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/out/ +/release/ diff --git a/monaco-html/.npmignore b/monaco-html/.npmignore new file mode 100644 index 00000000..4262b0f9 --- /dev/null +++ b/monaco-html/.npmignore @@ -0,0 +1,12 @@ +/.vscode/ +/out/ +/scripts/ +/src/ +/test/ +/.gitignore +/.npmignore +/.prettierrc +/.prettierignore +/package-lock.json +/webpack.dev.config.js +/webpack.min.config.js diff --git a/monaco-html/.prettierignore b/monaco-html/.prettierignore new file mode 100644 index 00000000..3c58ccd1 --- /dev/null +++ b/monaco-html/.prettierignore @@ -0,0 +1,2 @@ +/out/ +/release/ diff --git a/monaco-html/.prettierrc b/monaco-html/.prettierrc new file mode 100644 index 00000000..c12f08c5 --- /dev/null +++ b/monaco-html/.prettierrc @@ -0,0 +1,8 @@ +{ + "arrowParens": "always", + "singleQuote": true, + "trailingComma": "none", + "semi": true, + "useTabs": true, + "printWidth": 100 +} diff --git a/monaco-html/.vscode/settings.json b/monaco-html/.vscode/settings.json new file mode 100644 index 00000000..e25fee75 --- /dev/null +++ b/monaco-html/.vscode/settings.json @@ -0,0 +1,9 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.trimTrailingWhitespace": true, + "search.exclude": { + "**/node_modules": true, + "**/release": true, + "**/out": true + } +} diff --git a/monaco-html/LICENSE.md b/monaco-html/LICENSE.md new file mode 100644 index 00000000..5ae193c9 --- /dev/null +++ b/monaco-html/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/monaco-html/README.md b/monaco-html/README.md new file mode 100644 index 00000000..cb80ab18 --- /dev/null +++ b/monaco-html/README.md @@ -0,0 +1,33 @@ +# Monaco HTML + +HTML language plugin for the Monaco Editor. It provides the following features when editing HTML files: + +- Code completion +- Formatting +- Document Highlights +- Link detection +- Syntax highlighting + +Internally the HTML plugin uses the [vscode-html-languageservice](https://github.com/Microsoft/vscode-html-languageservice) +node module, providing the implementation of the functionally listed above. The same module is also used +in [Visual Studio Code](https://github.com/Microsoft/vscode) to power the HTML editing experience. + +## Issues + +Please file issues concering `monaco-html` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues). + +## Installing + +This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module. + +## Development + +- `git clone https://github.com/Microsoft/monaco-html` +- `cd monaco-html` +- `npm install .` +- `npm run watch` +- open `$/monaco-html/test/index.html` in your favorite browser. + +## License + +[MIT](https://github.com/Microsoft/monaco-html/blob/master/LICENSE.md) diff --git a/monaco-html/SECURITY.md b/monaco-html/SECURITY.md new file mode 100644 index 00000000..10541931 --- /dev/null +++ b/monaco-html/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + diff --git a/monaco-html/ThirdPartyNotices.txt b/monaco-html/ThirdPartyNotices.txt new file mode 100644 index 00000000..876af198 --- /dev/null +++ b/monaco-html/ThirdPartyNotices.txt @@ -0,0 +1,109 @@ +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +This project incorporates components from the projects listed below. The original copyright notices and the licenses +under which Microsoft received such components are set forth below. Microsoft reserves all rights not expressly granted +herein, whether by implication, estoppel or otherwise. + + + + +%% HTML 5.1 W3C Working Draft version 08 October 2015 (http://www.w3.org/TR/2015/WD-html51-20151008/) +========================================= +Copyright © 2015 W3C® (MIT, ERCIM, Keio, Beihang). This software or document includes material copied +from or derived from HTML 5.1 W3C Working Draft (http://www.w3.org/TR/2015/WD-html51-20151008/.) + +THIS DOCUMENT IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF +THE DOCUMENT ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY +PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE +DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF. + +The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to this document or its contents +without specific, written prior permission. Title to copyright in this document will at all times remain with copyright holders. +========================================= +END OF HTML 5.1 W3C Working Draft NOTICES AND INFORMATION + + + + +%% JS Beautifier version 1.6.2 (https://github.com/beautify-web/js-beautify) +========================================= +The MIT License (MIT) + +Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF js-beautify NOTICES AND INFORMATION + + + + +%% Ionic documentation version 1.2.4 (https://github.com/driftyco/ionic-site) +========================================= +Copyright Drifty Co. http://drifty.com/. + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and + +You must cause any modified files to carry prominent notices stating that You changed the files; and + +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS +========================================= +END OF Ionic documentation NOTICES AND INFORMATION diff --git a/monaco-html/monaco.d.ts b/monaco-html/monaco.d.ts new file mode 100644 index 00000000..d7df5c73 --- /dev/null +++ b/monaco-html/monaco.d.ts @@ -0,0 +1,172 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// + +declare namespace monaco.languages.html { + export interface HTMLFormatConfiguration { + readonly tabSize: number; + readonly insertSpaces: boolean; + readonly wrapLineLength: number; + readonly unformatted: string; + readonly contentUnformatted: string; + readonly indentInnerHtml: boolean; + readonly preserveNewLines: boolean; + readonly maxPreserveNewLines: number; + readonly indentHandlebars: boolean; + readonly endWithNewline: boolean; + readonly extraLiners: string; + readonly wrapAttributes: 'auto' | 'force' | 'force-aligned' | 'force-expand-multiline'; + } + export interface CompletionConfiguration { + readonly [providerId: string]: boolean; + } + export interface Options { + /** + * If set, comments are tolerated. If set to false, syntax errors will be emitted for comments. + */ + readonly format?: HTMLFormatConfiguration; + /** + * A list of known schemas and/or associations of schemas to file names. + */ + readonly suggest?: CompletionConfiguration; + /** + * Configures the HTML data types known by the HTML langauge service. + */ + readonly data?: HTMLDataConfiguration; + } + export interface ModeConfiguration { + /** + * Defines whether the built-in completionItemProvider is enabled. + */ + readonly completionItems?: boolean; + /** + * Defines whether the built-in hoverProvider is enabled. + */ + readonly hovers?: boolean; + /** + * Defines whether the built-in documentSymbolProvider is enabled. + */ + readonly documentSymbols?: boolean; + /** + * Defines whether the built-in definitions provider is enabled. + */ + readonly links?: boolean; + /** + * Defines whether the built-in references provider is enabled. + */ + readonly documentHighlights?: boolean; + /** + * Defines whether the built-in rename provider is enabled. + */ + readonly rename?: boolean; + /** + * Defines whether the built-in color provider is enabled. + */ + readonly colors?: boolean; + /** + * Defines whether the built-in foldingRange provider is enabled. + */ + readonly foldingRanges?: boolean; + /** + * Defines whether the built-in diagnostic provider is enabled. + */ + readonly diagnostics?: boolean; + /** + * Defines whether the built-in selection range provider is enabled. + */ + readonly selectionRanges?: boolean; + /** + * Defines whether the built-in documentFormattingEdit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + /** + * Defines whether the built-in documentRangeFormattingEdit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; + } + export interface LanguageServiceDefaults { + readonly languageId: string; + readonly modeConfiguration: ModeConfiguration; + readonly onDidChange: IEvent; + readonly options: Options; + setOptions(options: Options): void; + setModeConfiguration(modeConfiguration: ModeConfiguration): void; + } + export const htmlLanguageService: LanguageServiceRegistration; + export const htmlDefaults: LanguageServiceDefaults; + export const handlebarLanguageService: LanguageServiceRegistration; + export const handlebarDefaults: LanguageServiceDefaults; + export const razorLanguageService: LanguageServiceRegistration; + export const razorDefaults: LanguageServiceDefaults; + export interface LanguageServiceRegistration extends IDisposable { + readonly defaults: LanguageServiceDefaults; + } + /** + * Registers a new HTML language service for the languageId. + * Note: 'html', 'handlebar' and 'razor' are registered by default. + * + * Use this method to register additional language ids with a HTML service. + * The language server has to be registered before an editor model is opened. + */ + export function registerHTMLLanguageService( + languageId: string, + options?: Options, + modeConfiguration?: ModeConfiguration + ): LanguageServiceRegistration; + export interface HTMLDataConfiguration { + /** + * Defines whether the standard HTML tags and attributes are shown + */ + readonly useDefaultDataProvider?: boolean; + /** + * Provides a set of custom data providers. + */ + readonly dataProviders?: { + [providerId: string]: HTMLDataV1; + }; + } + /** + * Custom HTML tags attributes and attribute values + * https://github.com/microsoft/vscode-html-languageservice/blob/main/docs/customData.md + */ + export interface HTMLDataV1 { + readonly version: 1 | 1.1; + readonly tags?: ITagData[]; + readonly globalAttributes?: IAttributeData[]; + readonly valueSets?: IValueSet[]; + } + export interface IReference { + readonly name: string; + readonly url: string; + } + export interface ITagData { + readonly name: string; + readonly description?: string | MarkupContent; + readonly attributes: IAttributeData[]; + readonly references?: IReference[]; + } + export interface IAttributeData { + readonly name: string; + readonly description?: string | MarkupContent; + readonly valueSet?: string; + readonly values?: IValueData[]; + readonly references?: IReference[]; + } + export interface IValueData { + readonly name: string; + readonly description?: string | MarkupContent; + readonly references?: IReference[]; + } + export interface IValueSet { + readonly name: string; + readonly values: IValueData[]; + } + export interface MarkupContent { + readonly kind: MarkupKind; + readonly value: string; + } + export type MarkupKind = 'plaintext' | 'markdown'; +} diff --git a/monaco-html/package-lock.json b/monaco-html/package-lock.json new file mode 100644 index 00000000..78b0b75b --- /dev/null +++ b/monaco-html/package-lock.json @@ -0,0 +1,497 @@ +{ + "name": "monaco-html", + "version": "3.9.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@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 + }, + "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" + } + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "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" + } + }, + "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 + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "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 + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "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 + }, + "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" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "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 + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "husky": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-5.1.3.tgz", + "integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==", + "dev": true + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "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 + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "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" + } + }, + "monaco-editor-core": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.30.0.tgz", + "integrity": "sha512-vFJ7BEOCqLv4xWgFW+UheI/PtccHHNht29lNmo79Re1kNhWCBLLb2nThjRMLPO1rd41vX9hhd9C07/iKOk9/jQ==", + "dev": true + }, + "monaco-languages": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-2.11.0.tgz", + "integrity": "sha512-fpeP8XUPejcdoUEMZ5bo4MW8VzEadhrsuyDtT48p2a2PSRT/CXptQm4eGnIfgxf5R95jrCZ0456c5dSEPBuktA==", + "dev": true + }, + "monaco-plugin-helpers": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz", + "integrity": "sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw==", + "dev": true, + "requires": { + "typescript": "^2.7.2" + }, + "dependencies": { + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + } + } + }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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 + }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, + "pretty-quick": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.0.tgz", + "integrity": "sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + } + }, + "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" + } + }, + "requirejs": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", + "dev": true + }, + "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 + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "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 + } + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "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" + } + }, + "terser": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + } + }, + "typescript": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", + "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", + "dev": true + }, + "vscode-html-languageservice": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-4.1.1.tgz", + "integrity": "sha512-rrDyCiOgMwOPgchpPGAeLzjYVVEW/Ror2/a1BWUEI3S9+NQhA9vj4SQkzmH6g2Bq9S9SV0OQeadD+xphOf1N3w==", + "dev": true, + "requires": { + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.2.tgz", + "integrity": "sha512-T7uPC18+f8mYE4lbVZwb3OSmvwTZm3cuFhrdx9Bn2l11lmp3SvSuSVjy2JtvrghzjAo4G6Trqny2m9XGnFnWVA==", + "dev": true + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", + "dev": true + }, + "vscode-nls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.0.0.tgz", + "integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==", + "dev": true + }, + "vscode-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz", + "integrity": "sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA==", + "dev": true + }, + "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" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/monaco-html/package.json b/monaco-html/package.json new file mode 100644 index 00000000..1e0c0288 --- /dev/null +++ b/monaco-html/package.json @@ -0,0 +1,43 @@ +{ + "name": "monaco-html", + "version": "3.9.0", + "description": "HTML plugin for the Monaco Editor", + "scripts": { + "compile": "mrmdir ./out && tsc -p ./src/tsconfig.json && tsc -p ./src/tsconfig.esm.json && node ./scripts/dts && prettier --write ./monaco.d.ts", + "watch": "tsc -p ./src --watch", + "prepublishOnly": "mrmdir ./release && npm run compile && node ./scripts/release.js && node ./scripts/bundle && mcopy ./monaco.d.ts ./release/monaco.d.ts && mcopy ./out/esm/monaco.contribution.d.ts ./release/esm/monaco.contribution.d.ts && mcopy ./out/esm/fillers/monaco-editor-core.d.ts ./release/esm/fillers/monaco-editor-core.d.ts", + "install-service-next": "npm install vscode-html-languageservice@next -f -D && npm install vscode-languageserver-types@next -f -D", + "install-service-local": "npm install ../vscode-html-languageservice -f -D && npm install ../vscode-languageserver-node/types -f -D", + "prettier": "prettier --write ." + }, + "author": "Microsoft Corporation", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/monaco-html" + }, + "bugs": { + "url": "https://github.com/Microsoft/monaco-editor/issues" + }, + "module": "./release/esm/monaco.contribution.js", + "typings": "./release/esm/monaco.contribution.d.ts", + "devDependencies": { + "husky": "^5.1.3", + "monaco-editor-core": "0.30.0", + "monaco-languages": "^2.11.0", + "monaco-plugin-helpers": "^1.0.3", + "prettier": "^2.2.1", + "pretty-quick": "^3.1.0", + "requirejs": "^2.3.6", + "terser": "^5.6.0", + "typescript": "^4.2.3", + "vscode-html-languageservice": "^4.1.1", + "vscode-languageserver-textdocument": "^1.0.2", + "vscode-languageserver-types": "3.16.0" + }, + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } + } +} diff --git a/monaco-html/scripts/bundle.js b/monaco-html/scripts/bundle.js new file mode 100644 index 00000000..b7b0c4bb --- /dev/null +++ b/monaco-html/scripts/bundle.js @@ -0,0 +1,86 @@ +const requirejs = require('requirejs'); +const path = require('path'); +const fs = require('fs'); +const terser = require('terser'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.resolve(__dirname, '..'); + +const sha1 = helpers.getGitVersion(REPO_ROOT); +const semver = require('../package.json').version; +const headerVersion = semver + '(' + sha1 + ')'; + +const BUNDLED_FILE_HEADER = [ + '/*!-----------------------------------------------------------------------------', + ' * Copyright (c) Microsoft Corporation. All rights reserved.', + ' * monaco-html version: ' + headerVersion, + ' * Released under the MIT license', + ' * https://github.com/Microsoft/monaco-html/blob/master/LICENSE.md', + ' *-----------------------------------------------------------------------------*/', + '' +].join('\n'); + +bundleOne('monaco.contribution'); +bundleOne('htmlMode', ['vs/language/html/monaco.contribution']); +bundleOne('htmlWorker'); + +function bundleOne(moduleId, exclude) { + requirejs.optimize( + { + baseUrl: 'out/amd/', + name: 'vs/language/html/' + moduleId, + out: 'release/dev/' + moduleId + '.js', + exclude: exclude, + paths: { + 'vs/language/html': REPO_ROOT + '/out/amd', + 'vs/language/html/fillers/monaco-editor-core': + REPO_ROOT + '/out/amd/fillers/monaco-editor-core-amd' + }, + optimize: 'none', + packages: [ + { + name: 'vscode-html-languageservice', + location: path.join(REPO_ROOT, 'node_modules/vscode-html-languageservice/lib/umd'), + main: 'htmlLanguageService' + }, + { + name: 'vscode-languageserver-types', + location: path.join(REPO_ROOT, 'node_modules/vscode-languageserver-types/lib/umd'), + main: 'main' + }, + { + name: 'vscode-languageserver-textdocument', + location: path.join(REPO_ROOT, 'node_modules/vscode-languageserver-textdocument/lib/umd'), + main: 'main' + }, + { + name: 'vscode-uri', + location: path.join(REPO_ROOT, 'node_modules/vscode-uri/lib/umd'), + main: 'index' + }, + { + name: 'vscode-nls', + location: path.join(REPO_ROOT, '/out/amd/fillers'), + main: 'vscode-nls' + } + ] + }, + async function (buildResponse) { + const devFilePath = path.join(REPO_ROOT, 'release/dev/' + moduleId + '.js'); + const minFilePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js'); + const fileContents = fs.readFileSync(devFilePath).toString(); + console.log(); + console.log(`Minifying ${devFilePath}...`); + const result = await terser.minify(fileContents, { + output: { + comments: 'some' + } + }); + console.log(`Done minifying ${devFilePath}.`); + try { + fs.mkdirSync(path.join(REPO_ROOT, 'release/min')); + } catch (err) {} + fs.writeFileSync(minFilePath, BUNDLED_FILE_HEADER + result.code); + } + ); +} diff --git a/monaco-html/scripts/dts.js b/monaco-html/scripts/dts.js new file mode 100644 index 00000000..04810be7 --- /dev/null +++ b/monaco-html/scripts/dts.js @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const path = require('path'); +const fs = require('fs'); + +const REPO_ROOT = path.join(__dirname, '../'); +const SRC_PATH = path.join(REPO_ROOT, 'out/amd/monaco.contribution.d.ts'); +const DST_PATH = path.join(REPO_ROOT, 'monaco.d.ts'); + +const lines = fs + .readFileSync(SRC_PATH) + .toString() + .split(/\r\n|\r|\n/); +let result = [ + `/*---------------------------------------------------------------------------------------------`, + ` * Copyright (c) Microsoft Corporation. All rights reserved.`, + ` * Licensed under the MIT License. See License.txt in the project root for license information.`, + ` *--------------------------------------------------------------------------------------------*/`, + ``, + `/// `, + ``, + `declare namespace monaco.languages.html {` +]; +for (let line of lines) { + if (/^import/.test(line)) { + continue; + } + line = line.replace(/ /g, '\t'); + line = line.replace(/declare /g, ''); + if (line.length > 0) { + line = `\t${line}`; + result.push(line); + } +} +result.push(`}`); +result.push(``); + +fs.writeFileSync(DST_PATH, result.join('\n')); diff --git a/monaco-html/scripts/release.js b/monaco-html/scripts/release.js new file mode 100644 index 00000000..5a5a1d84 --- /dev/null +++ b/monaco-html/scripts/release.js @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const path = require('path'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.join(__dirname, '../'); + +helpers.packageESM({ + repoRoot: REPO_ROOT, + esmSource: 'out/esm', + esmDestination: 'release/esm', + entryPoints: ['monaco.contribution.js', 'htmlMode.js', 'html.worker.js'], + resolveAlias: { + 'vscode-nls': path.join(REPO_ROOT, 'out/esm/fillers/vscode-nls.js') + }, + resolveSkip: ['monaco-editor-core'], + destinationFolderSimplification: { + node_modules: '_deps', + 'vscode-languageserver-types/lib/esm': 'vscode-languageserver-types', + 'vscode-uri/lib/esm': 'vscode-uri', + 'vscode-html-languageservice/lib/esm': 'vscode-html-languageservice' + } +}); diff --git a/monaco-html/src/fillers/monaco-editor-core-amd.ts b/monaco-html/src/fillers/monaco-editor-core-amd.ts new file mode 100644 index 00000000..59874efb --- /dev/null +++ b/monaco-html/src/fillers/monaco-editor-core-amd.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// Resolves with the global monaco API + +declare var define; + +define([], function () { + return (self).monaco; +}); diff --git a/monaco-html/src/fillers/monaco-editor-core.ts b/monaco-html/src/fillers/monaco-editor-core.ts new file mode 100644 index 00000000..cd996aa7 --- /dev/null +++ b/monaco-html/src/fillers/monaco-editor-core.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export * from 'monaco-editor-core'; diff --git a/monaco-html/src/fillers/vscode-nls.ts b/monaco-html/src/fillers/vscode-nls.ts new file mode 100644 index 00000000..38f7b334 --- /dev/null +++ b/monaco-html/src/fillers/vscode-nls.ts @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface Options { + locale?: string; + cacheLanguageResolution?: boolean; +} +export interface LocalizeInfo { + key: string; + comment: string[]; +} +export interface LocalizeFunc { + (info: LocalizeInfo, message: string, ...args: any[]): string; + (key: string, message: string, ...args: any[]): string; +} +export interface LoadFunc { + (file?: string): LocalizeFunc; +} + +function format(message: string, args: any[]): string { + let result: string; + + if (args.length === 0) { + result = message; + } else { + result = message.replace(/\{(\d+)\}/g, (match, rest) => { + let index = rest[0]; + return typeof args[index] !== 'undefined' ? args[index] : match; + }); + } + return result; +} + +function localize(key: string | LocalizeInfo, message: string, ...args: any[]): string { + return format(message, args); +} + +export function loadMessageBundle(file?: string): LocalizeFunc { + return localize; +} + +export function config(opt?: Options | string): LoadFunc { + return loadMessageBundle; +} diff --git a/monaco-html/src/html.worker.ts b/monaco-html/src/html.worker.ts new file mode 100644 index 00000000..3251956c --- /dev/null +++ b/monaco-html/src/html.worker.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker'; +import { HTMLWorker } from './htmlWorker'; + +self.onmessage = () => { + // ignore the first message + worker.initialize((ctx, createData) => { + return new HTMLWorker(ctx, createData); + }); +}; diff --git a/monaco-html/src/htmlMode.ts b/monaco-html/src/htmlMode.ts new file mode 100644 index 00000000..95b560cb --- /dev/null +++ b/monaco-html/src/htmlMode.ts @@ -0,0 +1,164 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { WorkerManager } from './workerManager'; +import type { HTMLWorker } from './htmlWorker'; +import { LanguageServiceDefaults } from './monaco.contribution'; +import * as languageFeatures from './languageFeatures'; +import { Uri, IDisposable, languages } from './fillers/monaco-editor-core'; + +export function setupMode1(defaults: LanguageServiceDefaults): void { + const client = new WorkerManager(defaults); + + const worker: languageFeatures.WorkerAccessor = (...uris: Uri[]): Promise => { + return client.getLanguageServiceWorker(...uris); + }; + + let languageId = defaults.languageId; + + // all modes + languages.registerCompletionItemProvider( + languageId, + new languageFeatures.CompletionAdapter(worker) + ); + languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker)); + + languages.registerDocumentHighlightProvider( + languageId, + new languageFeatures.DocumentHighlightAdapter(worker) + ); + languages.registerLinkProvider(languageId, new languageFeatures.DocumentLinkAdapter(worker)); + languages.registerFoldingRangeProvider( + languageId, + new languageFeatures.FoldingRangeAdapter(worker) + ); + languages.registerDocumentSymbolProvider( + languageId, + new languageFeatures.DocumentSymbolAdapter(worker) + ); + languages.registerSelectionRangeProvider( + languageId, + new languageFeatures.SelectionRangeAdapter(worker) + ); + languages.registerRenameProvider(languageId, new languageFeatures.RenameAdapter(worker)); + + // only html + if (languageId === 'html') { + languages.registerDocumentFormattingEditProvider( + languageId, + new languageFeatures.DocumentFormattingEditProvider(worker) + ); + languages.registerDocumentRangeFormattingEditProvider( + languageId, + new languageFeatures.DocumentRangeFormattingEditProvider(worker) + ); + } +} + +export function setupMode(defaults: LanguageServiceDefaults): IDisposable { + const disposables: IDisposable[] = []; + const providers: IDisposable[] = []; + + const client = new WorkerManager(defaults); + disposables.push(client); + + const worker: languageFeatures.WorkerAccessor = (...uris: Uri[]): Promise => { + return client.getLanguageServiceWorker(...uris); + }; + + function registerProviders(): void { + const { languageId, modeConfiguration } = defaults; + + disposeAll(providers); + + if (modeConfiguration.completionItems) { + providers.push( + languages.registerCompletionItemProvider( + languageId, + new languageFeatures.CompletionAdapter(worker) + ) + ); + } + if (modeConfiguration.hovers) { + providers.push( + languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker)) + ); + } + if (modeConfiguration.documentHighlights) { + providers.push( + languages.registerDocumentHighlightProvider( + languageId, + new languageFeatures.DocumentHighlightAdapter(worker) + ) + ); + } + if (modeConfiguration.links) { + providers.push( + languages.registerLinkProvider(languageId, new languageFeatures.DocumentLinkAdapter(worker)) + ); + } + if (modeConfiguration.documentSymbols) { + providers.push( + languages.registerDocumentSymbolProvider( + languageId, + new languageFeatures.DocumentSymbolAdapter(worker) + ) + ); + } + if (modeConfiguration.rename) { + providers.push( + languages.registerRenameProvider(languageId, new languageFeatures.RenameAdapter(worker)) + ); + } + if (modeConfiguration.foldingRanges) { + providers.push( + languages.registerFoldingRangeProvider( + languageId, + new languageFeatures.FoldingRangeAdapter(worker) + ) + ); + } + if (modeConfiguration.selectionRanges) { + providers.push( + languages.registerSelectionRangeProvider( + languageId, + new languageFeatures.SelectionRangeAdapter(worker) + ) + ); + } + if (modeConfiguration.documentFormattingEdits) { + providers.push( + languages.registerDocumentFormattingEditProvider( + languageId, + new languageFeatures.DocumentFormattingEditProvider(worker) + ) + ); + } + if (modeConfiguration.documentRangeFormattingEdits) { + providers.push( + languages.registerDocumentRangeFormattingEditProvider( + languageId, + new languageFeatures.DocumentRangeFormattingEditProvider(worker) + ) + ); + } + } + + registerProviders(); + + disposables.push(asDisposable(providers)); + + return asDisposable(disposables); +} + +function asDisposable(disposables: IDisposable[]): IDisposable { + return { dispose: () => disposeAll(disposables) }; +} + +function disposeAll(disposables: IDisposable[]) { + while (disposables.length) { + disposables.pop().dispose(); + } +} diff --git a/monaco-html/src/htmlWorker.ts b/monaco-html/src/htmlWorker.ts new file mode 100644 index 00000000..5de8154d --- /dev/null +++ b/monaco-html/src/htmlWorker.ts @@ -0,0 +1,134 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { worker } from './fillers/monaco-editor-core'; +import * as htmlService from 'vscode-html-languageservice'; +import type { Options } from './monaco.contribution'; +import { IHTMLDataProvider } from 'vscode-html-languageservice'; + +export class HTMLWorker { + private _ctx: worker.IWorkerContext; + private _languageService: htmlService.LanguageService; + private _languageSettings: Options; + private _languageId: string; + + constructor(ctx: worker.IWorkerContext, createData: ICreateData) { + this._ctx = ctx; + this._languageSettings = createData.languageSettings; + this._languageId = createData.languageId; + + const data = this._languageSettings.data; + + const useDefaultDataProvider = data?.useDefaultDataProvider; + const customDataProviders: IHTMLDataProvider[] = []; + if (data?.dataProviders) { + for (const id in data.dataProviders) { + customDataProviders.push(htmlService.newHTMLDataProvider(id, data.dataProviders[id])); + } + } + this._languageService = htmlService.getLanguageService({ useDefaultDataProvider, customDataProviders }); + } + + async doComplete( + uri: string, + position: htmlService.Position + ): Promise { + let document = this._getTextDocument(uri); + let htmlDocument = this._languageService.parseHTMLDocument(document); + return Promise.resolve( + this._languageService.doComplete( + document, + position, + htmlDocument, + this._languageSettings && this._languageSettings.suggest + ) + ); + } + async format( + uri: string, + range: htmlService.Range, + options: htmlService.FormattingOptions + ): Promise { + let document = this._getTextDocument(uri); + let formattingOptions = { ...this._languageSettings.format, ...options }; + let textEdits = this._languageService.format(document, range, formattingOptions); + return Promise.resolve(textEdits); + } + async doHover(uri: string, position: htmlService.Position): Promise { + let document = this._getTextDocument(uri); + let htmlDocument = this._languageService.parseHTMLDocument(document); + let hover = this._languageService.doHover(document, position, htmlDocument); + return Promise.resolve(hover); + } + async findDocumentHighlights( + uri: string, + position: htmlService.Position + ): Promise { + let document = this._getTextDocument(uri); + let htmlDocument = this._languageService.parseHTMLDocument(document); + let highlights = this._languageService.findDocumentHighlights(document, position, htmlDocument); + return Promise.resolve(highlights); + } + async findDocumentLinks(uri: string): Promise { + let document = this._getTextDocument(uri); + let links = this._languageService.findDocumentLinks(document, null); + return Promise.resolve(links); + } + async findDocumentSymbols(uri: string): Promise { + let document = this._getTextDocument(uri); + let htmlDocument = this._languageService.parseHTMLDocument(document); + let symbols = this._languageService.findDocumentSymbols(document, htmlDocument); + return Promise.resolve(symbols); + } + async getFoldingRanges( + uri: string, + context?: { rangeLimit?: number } + ): Promise { + let document = this._getTextDocument(uri); + let ranges = this._languageService.getFoldingRanges(document, context); + return Promise.resolve(ranges); + } + async getSelectionRanges( + uri: string, + positions: htmlService.Position[] + ): Promise { + let document = this._getTextDocument(uri); + let ranges = this._languageService.getSelectionRanges(document, positions); + return Promise.resolve(ranges); + } + async doRename( + uri: string, + position: htmlService.Position, + newName: string + ): Promise { + let document = this._getTextDocument(uri); + let htmlDocument = this._languageService.parseHTMLDocument(document); + let renames = this._languageService.doRename(document, position, newName, htmlDocument); + return Promise.resolve(renames); + } + private _getTextDocument(uri: string): htmlService.TextDocument { + let models = this._ctx.getMirrorModels(); + for (let model of models) { + if (model.uri.toString() === uri) { + return htmlService.TextDocument.create( + uri, + this._languageId, + model.version, + model.getValue() + ); + } + } + return null; + } +} + +export interface ICreateData { + languageId: string; + languageSettings: Options; +} + +export function create(ctx: worker.IWorkerContext, createData: ICreateData): HTMLWorker { + return new HTMLWorker(ctx, createData); +} diff --git a/monaco-html/src/languageFeatures.ts b/monaco-html/src/languageFeatures.ts new file mode 100644 index 00000000..e0ca4ce5 --- /dev/null +++ b/monaco-html/src/languageFeatures.ts @@ -0,0 +1,611 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { HTMLWorker } from './htmlWorker'; +import * as htmlService from 'vscode-html-languageservice'; +import { + languages, + editor, + Uri, + Position, + Range, + CancellationToken, + IMarkdownString +} from './fillers/monaco-editor-core'; + +export interface WorkerAccessor { + (...more: Uri[]): Promise; +} + +// --- completion ------ + +function fromPosition(position: Position): htmlService.Position { + if (!position) { + return void 0; + } + return { character: position.column - 1, line: position.lineNumber - 1 }; +} + +function fromRange(range: Range): htmlService.Range { + if (!range) { + return void 0; + } + return { + start: fromPosition(range.getStartPosition()), + end: fromPosition(range.getEndPosition()) + }; +} + +function toRange(range: htmlService.Range): Range { + if (!range) { + return void 0; + } + return new Range( + range.start.line + 1, + range.start.character + 1, + range.end.line + 1, + range.end.character + 1 + ); +} + +function isInsertReplaceEdit(edit: htmlService.TextEdit | htmlService.InsertReplaceEdit): edit is htmlService.InsertReplaceEdit { + return ( + typeof (edit).insert !== 'undefined' && + typeof (edit).replace !== 'undefined' + ); +} + +function toCompletionItemKind(kind: number): languages.CompletionItemKind { + const mItemKind = languages.CompletionItemKind; + + switch (kind) { + case htmlService.CompletionItemKind.Text: + return mItemKind.Text; + case htmlService.CompletionItemKind.Method: + return mItemKind.Method; + case htmlService.CompletionItemKind.Function: + return mItemKind.Function; + case htmlService.CompletionItemKind.Constructor: + return mItemKind.Constructor; + case htmlService.CompletionItemKind.Field: + return mItemKind.Field; + case htmlService.CompletionItemKind.Variable: + return mItemKind.Variable; + case htmlService.CompletionItemKind.Class: + return mItemKind.Class; + case htmlService.CompletionItemKind.Interface: + return mItemKind.Interface; + case htmlService.CompletionItemKind.Module: + return mItemKind.Module; + case htmlService.CompletionItemKind.Property: + return mItemKind.Property; + case htmlService.CompletionItemKind.Unit: + return mItemKind.Unit; + case htmlService.CompletionItemKind.Value: + return mItemKind.Value; + case htmlService.CompletionItemKind.Enum: + return mItemKind.Enum; + case htmlService.CompletionItemKind.Keyword: + return mItemKind.Keyword; + case htmlService.CompletionItemKind.Snippet: + return mItemKind.Snippet; + case htmlService.CompletionItemKind.Color: + return mItemKind.Color; + case htmlService.CompletionItemKind.File: + return mItemKind.File; + case htmlService.CompletionItemKind.Reference: + return mItemKind.Reference; + } + return mItemKind.Property; +} + +function fromCompletionItemKind( + kind: languages.CompletionItemKind +): htmlService.CompletionItemKind { + const mItemKind = languages.CompletionItemKind; + + switch (kind) { + case mItemKind.Text: + return htmlService.CompletionItemKind.Text; + case mItemKind.Method: + return htmlService.CompletionItemKind.Method; + case mItemKind.Function: + return htmlService.CompletionItemKind.Function; + case mItemKind.Constructor: + return htmlService.CompletionItemKind.Constructor; + case mItemKind.Field: + return htmlService.CompletionItemKind.Field; + case mItemKind.Variable: + return htmlService.CompletionItemKind.Variable; + case mItemKind.Class: + return htmlService.CompletionItemKind.Class; + case mItemKind.Interface: + return htmlService.CompletionItemKind.Interface; + case mItemKind.Module: + return htmlService.CompletionItemKind.Module; + case mItemKind.Property: + return htmlService.CompletionItemKind.Property; + case mItemKind.Unit: + return htmlService.CompletionItemKind.Unit; + case mItemKind.Value: + return htmlService.CompletionItemKind.Value; + case mItemKind.Enum: + return htmlService.CompletionItemKind.Enum; + case mItemKind.Keyword: + return htmlService.CompletionItemKind.Keyword; + case mItemKind.Snippet: + return htmlService.CompletionItemKind.Snippet; + case mItemKind.Color: + return htmlService.CompletionItemKind.Color; + case mItemKind.File: + return htmlService.CompletionItemKind.File; + case mItemKind.Reference: + return htmlService.CompletionItemKind.Reference; + } + return htmlService.CompletionItemKind.Property; +} + +function toTextEdit(textEdit: htmlService.TextEdit): editor.ISingleEditOperation { + if (!textEdit) { + return void 0; + } + return { + range: toRange(textEdit.range), + text: textEdit.newText + }; +} + +function toCommand(c: htmlService.Command | undefined): languages.Command { + return c && c.command === 'editor.action.triggerSuggest' ? { id: c.command, title: c.title, arguments: c.arguments } : undefined +} + +export class CompletionAdapter implements languages.CompletionItemProvider { + constructor(private _worker: WorkerAccessor) { } + + public get triggerCharacters(): string[] { + return ['.', ':', '<', '"', '=', '/']; + } + + provideCompletionItems( + model: editor.IReadOnlyModel, + position: Position, + context: languages.CompletionContext, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doComplete(resource.toString(), fromPosition(position)); + }) + .then((info) => { + if (!info) { + return; + } + const wordInfo = model.getWordUntilPosition(position); + const wordRange = new Range( + position.lineNumber, + wordInfo.startColumn, + position.lineNumber, + wordInfo.endColumn + ); + + const items: languages.CompletionItem[] = info.items.map((entry) => { + const item: languages.CompletionItem = { + label: entry.label, + insertText: entry.insertText || entry.label, + sortText: entry.sortText, + filterText: entry.filterText, + documentation: entry.documentation, + command: toCommand(entry.command), + detail: entry.detail, + range: wordRange, + kind: toCompletionItemKind(entry.kind) + }; + if (entry.textEdit) { + if (isInsertReplaceEdit(entry.textEdit)) { + item.range = { + insert: toRange(entry.textEdit.insert), + replace: toRange(entry.textEdit.replace) + }; + } else { + item.range = toRange(entry.textEdit.range); + } + item.insertText = entry.textEdit.newText; + } + if (entry.additionalTextEdits) { + item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit); + } + if (entry.insertTextFormat === htmlService.InsertTextFormat.Snippet) { + item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet; + } + return item; + }); + + return { + isIncomplete: info.isIncomplete, + suggestions: items + }; + }); + } +} + +// --- hover ------ + +function isMarkupContent(thing: any): thing is htmlService.MarkupContent { + return ( + thing && + typeof thing === 'object' && + typeof (thing).kind === 'string' + ); +} + +function toMarkdownString( + entry: htmlService.MarkupContent | htmlService.MarkedString +): IMarkdownString { + if (typeof entry === 'string') { + return { + value: entry + }; + } + if (isMarkupContent(entry)) { + if (entry.kind === 'plaintext') { + return { + value: entry.value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') + }; + } + return { + value: entry.value + }; + } + + return { value: '```' + entry.language + '\n' + entry.value + '\n```\n' }; +} + +function toMarkedStringArray( + contents: htmlService.MarkupContent | htmlService.MarkedString | htmlService.MarkedString[] +): IMarkdownString[] { + if (!contents) { + return void 0; + } + if (Array.isArray(contents)) { + return contents.map(toMarkdownString); + } + return [toMarkdownString(contents)]; +} + +export class HoverAdapter implements languages.HoverProvider { + constructor(private _worker: WorkerAccessor) { } + + provideHover( + model: editor.IReadOnlyModel, + position: Position, + token: CancellationToken + ): Promise { + let resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doHover(resource.toString(), fromPosition(position)); + }) + .then((info) => { + if (!info) { + return; + } + return { + range: toRange(info.range), + contents: toMarkedStringArray(info.contents) + }; + }); + } +} + +// --- document highlights ------ + +function toHighlighKind(kind: htmlService.DocumentHighlightKind): languages.DocumentHighlightKind { + const mKind = languages.DocumentHighlightKind; + + switch (kind) { + case htmlService.DocumentHighlightKind.Read: + return mKind.Read; + case htmlService.DocumentHighlightKind.Write: + return mKind.Write; + case htmlService.DocumentHighlightKind.Text: + return mKind.Text; + } + return mKind.Text; +} + +export class DocumentHighlightAdapter implements languages.DocumentHighlightProvider { + constructor(private _worker: WorkerAccessor) { } + + public provideDocumentHighlights( + model: editor.IReadOnlyModel, + position: Position, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.findDocumentHighlights(resource.toString(), fromPosition(position))) + .then((items) => { + if (!items) { + return; + } + return items.map((item) => ({ + range: toRange(item.range), + kind: toHighlighKind(item.kind) + })); + }); + } +} + +// --- document symbols ------ + +function toSymbolKind(kind: htmlService.SymbolKind): languages.SymbolKind { + let mKind = languages.SymbolKind; + + switch (kind) { + case htmlService.SymbolKind.File: + return mKind.Array; + case htmlService.SymbolKind.Module: + return mKind.Module; + case htmlService.SymbolKind.Namespace: + return mKind.Namespace; + case htmlService.SymbolKind.Package: + return mKind.Package; + case htmlService.SymbolKind.Class: + return mKind.Class; + case htmlService.SymbolKind.Method: + return mKind.Method; + case htmlService.SymbolKind.Property: + return mKind.Property; + case htmlService.SymbolKind.Field: + return mKind.Field; + case htmlService.SymbolKind.Constructor: + return mKind.Constructor; + case htmlService.SymbolKind.Enum: + return mKind.Enum; + case htmlService.SymbolKind.Interface: + return mKind.Interface; + case htmlService.SymbolKind.Function: + return mKind.Function; + case htmlService.SymbolKind.Variable: + return mKind.Variable; + case htmlService.SymbolKind.Constant: + return mKind.Constant; + case htmlService.SymbolKind.String: + return mKind.String; + case htmlService.SymbolKind.Number: + return mKind.Number; + case htmlService.SymbolKind.Boolean: + return mKind.Boolean; + case htmlService.SymbolKind.Array: + return mKind.Array; + } + return mKind.Function; +} + +export class DocumentSymbolAdapter implements languages.DocumentSymbolProvider { + constructor(private _worker: WorkerAccessor) { } + + public provideDocumentSymbols( + model: editor.IReadOnlyModel, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.findDocumentSymbols(resource.toString())) + .then((items) => { + if (!items) { + return; + } + return items.map((item) => ({ + name: item.name, + detail: '', + containerName: item.containerName, + kind: toSymbolKind(item.kind), + tags: [], + range: toRange(item.location.range), + selectionRange: toRange(item.location.range) + })); + }); + } +} + +export class DocumentLinkAdapter implements languages.LinkProvider { + constructor(private _worker: WorkerAccessor) { } + + public provideLinks( + model: editor.IReadOnlyModel, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.findDocumentLinks(resource.toString())) + .then((items) => { + if (!items) { + return; + } + return { + links: items.map((item) => ({ + range: toRange(item.range), + url: item.target + })) + }; + }); + } +} + +function fromFormattingOptions( + options: languages.FormattingOptions +): htmlService.FormattingOptions { + return { + tabSize: options.tabSize, + insertSpaces: options.insertSpaces + }; +} + +export class DocumentFormattingEditProvider implements languages.DocumentFormattingEditProvider { + constructor(private _worker: WorkerAccessor) { } + + public provideDocumentFormattingEdits( + model: editor.IReadOnlyModel, + options: languages.FormattingOptions, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource).then((worker) => { + return worker + .format(resource.toString(), null, fromFormattingOptions(options)) + .then((edits) => { + if (!edits || edits.length === 0) { + return; + } + return edits.map(toTextEdit); + }); + }); + } +} + +export class DocumentRangeFormattingEditProvider + implements languages.DocumentRangeFormattingEditProvider { + constructor(private _worker: WorkerAccessor) { } + + public provideDocumentRangeFormattingEdits( + model: editor.IReadOnlyModel, + range: Range, + options: languages.FormattingOptions, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource).then((worker) => { + return worker + .format(resource.toString(), fromRange(range), fromFormattingOptions(options)) + .then((edits) => { + if (!edits || edits.length === 0) { + return; + } + return edits.map(toTextEdit); + }); + }); + } +} + +export class RenameAdapter implements languages.RenameProvider { + constructor(private _worker: WorkerAccessor) { } + + provideRenameEdits( + model: editor.IReadOnlyModel, + position: Position, + newName: string, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doRename(resource.toString(), fromPosition(position), newName); + }) + .then((edit) => { + return toWorkspaceEdit(edit); + }); + } +} + +function toWorkspaceEdit(edit: htmlService.WorkspaceEdit): languages.WorkspaceEdit { + if (!edit || !edit.changes) { + return void 0; + } + let resourceEdits: languages.WorkspaceTextEdit[] = []; + for (let uri in edit.changes) { + const _uri = Uri.parse(uri); + for (let e of edit.changes[uri]) { + resourceEdits.push({ + resource: _uri, + edit: { + range: toRange(e.range), + text: e.newText + } + }); + } + } + return { + edits: resourceEdits + }; +} + +export class FoldingRangeAdapter implements languages.FoldingRangeProvider { + constructor(private _worker: WorkerAccessor) { } + + public provideFoldingRanges( + model: editor.IReadOnlyModel, + context: languages.FoldingContext, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.getFoldingRanges(resource.toString(), context)) + .then((ranges) => { + if (!ranges) { + return; + } + return ranges.map((range) => { + const result: languages.FoldingRange = { + start: range.startLine + 1, + end: range.endLine + 1 + }; + if (typeof range.kind !== 'undefined') { + result.kind = toFoldingRangeKind(range.kind); + } + return result; + }); + }); + } +} + +function toFoldingRangeKind(kind: htmlService.FoldingRangeKind): languages.FoldingRangeKind { + switch (kind) { + case htmlService.FoldingRangeKind.Comment: + return languages.FoldingRangeKind.Comment; + case htmlService.FoldingRangeKind.Imports: + return languages.FoldingRangeKind.Imports; + case htmlService.FoldingRangeKind.Region: + return languages.FoldingRangeKind.Region; + } +} + +export class SelectionRangeAdapter implements languages.SelectionRangeProvider { + constructor(private _worker: WorkerAccessor) { } + + public provideSelectionRanges( + model: editor.IReadOnlyModel, + positions: Position[], + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.getSelectionRanges(resource.toString(), positions.map(fromPosition))) + .then((selectionRanges) => { + if (!selectionRanges) { + return; + } + return selectionRanges.map((selectionRange) => { + const result: languages.SelectionRange[] = []; + while (selectionRange) { + result.push({ range: toRange(selectionRange.range) }); + selectionRange = selectionRange.parent; + } + return result; + }); + }); + } +} diff --git a/monaco-html/src/monaco.contribution.ts b/monaco-html/src/monaco.contribution.ts new file mode 100644 index 00000000..fcbeccd3 --- /dev/null +++ b/monaco-html/src/monaco.contribution.ts @@ -0,0 +1,316 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as mode from './htmlMode'; +import { languages, Emitter, IEvent, IDisposable } from './fillers/monaco-editor-core'; + +export interface HTMLFormatConfiguration { + readonly tabSize: number; + readonly insertSpaces: boolean; + readonly wrapLineLength: number; + readonly unformatted: string; + readonly contentUnformatted: string; + readonly indentInnerHtml: boolean; + readonly preserveNewLines: boolean; + readonly maxPreserveNewLines: number; + readonly indentHandlebars: boolean; + readonly endWithNewline: boolean; + readonly extraLiners: string; + readonly wrapAttributes: 'auto' | 'force' | 'force-aligned' | 'force-expand-multiline'; +} + +export interface CompletionConfiguration { + readonly [providerId: string]: boolean; +} + +export interface Options { + /** + * If set, comments are tolerated. If set to false, syntax errors will be emitted for comments. + */ + readonly format?: HTMLFormatConfiguration; + /** + * A list of known schemas and/or associations of schemas to file names. + */ + readonly suggest?: CompletionConfiguration; + /** + * Configures the HTML data types known by the HTML langauge service. + */ + readonly data?: HTMLDataConfiguration; +} + +export interface ModeConfiguration { + /** + * Defines whether the built-in completionItemProvider is enabled. + */ + readonly completionItems?: boolean; + + /** + * Defines whether the built-in hoverProvider is enabled. + */ + readonly hovers?: boolean; + + /** + * Defines whether the built-in documentSymbolProvider is enabled. + */ + readonly documentSymbols?: boolean; + + /** + * Defines whether the built-in definitions provider is enabled. + */ + readonly links?: boolean; + + /** + * Defines whether the built-in references provider is enabled. + */ + readonly documentHighlights?: boolean; + + /** + * Defines whether the built-in rename provider is enabled. + */ + readonly rename?: boolean; + + /** + * Defines whether the built-in color provider is enabled. + */ + readonly colors?: boolean; + + /** + * Defines whether the built-in foldingRange provider is enabled. + */ + readonly foldingRanges?: boolean; + + /** + * Defines whether the built-in diagnostic provider is enabled. + */ + readonly diagnostics?: boolean; + + /** + * Defines whether the built-in selection range provider is enabled. + */ + readonly selectionRanges?: boolean; + + /** + * Defines whether the built-in documentFormattingEdit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + + /** + * Defines whether the built-in documentRangeFormattingEdit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; +} + +export interface LanguageServiceDefaults { + readonly languageId: string; + readonly modeConfiguration: ModeConfiguration; + readonly onDidChange: IEvent; + readonly options: Options; + setOptions(options: Options): void; + setModeConfiguration(modeConfiguration: ModeConfiguration): void; +} +// --- HTML configuration and defaults --------- + +class LanguageServiceDefaultsImpl implements LanguageServiceDefaults { + private _onDidChange = new Emitter(); + private _options: Options; + private _modeConfiguration: ModeConfiguration; + private _languageId: string; + + constructor(languageId: string, options: Options, modeConfiguration: ModeConfiguration) { + this._languageId = languageId; + this.setOptions(options); + this.setModeConfiguration(modeConfiguration); + } + + get onDidChange(): IEvent { + return this._onDidChange.event; + } + + get languageId(): string { + return this._languageId; + } + + get options(): Options { + return this._options; + } + + get modeConfiguration(): ModeConfiguration { + return this._modeConfiguration; + } + + setOptions(options: Options): void { + this._options = options || Object.create(null); + this._onDidChange.fire(this); + } + + setModeConfiguration(modeConfiguration: ModeConfiguration): void { + this._modeConfiguration = modeConfiguration || Object.create(null); + this._onDidChange.fire(this); + } +} + +const formatDefaults: Required = { + tabSize: 4, + insertSpaces: false, + wrapLineLength: 120, + unformatted: + 'default": "a, abbr, acronym, b, bdo, big, br, button, cite, code, dfn, em, i, img, input, kbd, label, map, object, q, samp, select, small, span, strong, sub, sup, textarea, tt, var', + contentUnformatted: 'pre', + indentInnerHtml: false, + preserveNewLines: true, + maxPreserveNewLines: null, + indentHandlebars: false, + endWithNewline: false, + extraLiners: 'head, body, /html', + wrapAttributes: 'auto' +}; + +const optionsDefault: Required = { + format: formatDefaults, + suggest: {}, + data: { useDefaultDataProvider: true } +}; + + +function getConfigurationDefault(languageId: string): Required { + return { + completionItems: true, + hovers: true, + documentSymbols: true, + links: true, + documentHighlights: true, + rename: true, + colors: true, + foldingRanges: true, + selectionRanges: true, + diagnostics: languageId === htmlLanguageId, // turned off for Razor and Handlebar + documentFormattingEdits: languageId === htmlLanguageId, // turned off for Razor and Handlebar + documentRangeFormattingEdits: languageId === htmlLanguageId // turned off for Razor and Handlebar + }; +} + +const htmlLanguageId = 'html'; +const handlebarsLanguageId = 'handlebars'; +const razorLanguageId = 'razor'; + +export const htmlLanguageService = registerHTMLLanguageService( + htmlLanguageId, + optionsDefault, + getConfigurationDefault(htmlLanguageId) +); +export const htmlDefaults = htmlLanguageService.defaults; + +export const handlebarLanguageService = registerHTMLLanguageService( + handlebarsLanguageId, + optionsDefault, + getConfigurationDefault(handlebarsLanguageId) +); +export const handlebarDefaults = handlebarLanguageService.defaults; + +export const razorLanguageService = registerHTMLLanguageService( + razorLanguageId, + optionsDefault, + getConfigurationDefault(razorLanguageId) +); +export const razorDefaults = razorLanguageService.defaults; + +// export to the global based API +(languages).html = { htmlDefaults, razorDefaults, handlebarDefaults, htmlLanguageService, handlebarLanguageService, razorLanguageService, registerHTMLLanguageService }; + + +// --- Registration to monaco editor --- + +function getMode(): Promise { + return import('./htmlMode'); +} + +export interface LanguageServiceRegistration extends IDisposable { + readonly defaults: LanguageServiceDefaults; +} + +/** + * Registers a new HTML language service for the languageId. + * Note: 'html', 'handlebar' and 'razor' are registered by default. + * + * Use this method to register additional language ids with a HTML service. + * The language server has to be registered before an editor model is opened. + */ +export function registerHTMLLanguageService( + languageId: string, + options: Options = optionsDefault, + modeConfiguration: ModeConfiguration = getConfigurationDefault(languageId) +): LanguageServiceRegistration { + const defaults = new LanguageServiceDefaultsImpl(languageId, options, modeConfiguration); + let mode: IDisposable | undefined; + + // delay the initalization of the mode until the language is accessed the first time + const onLanguageListener = languages.onLanguage(languageId, async () => { + mode = (await getMode()).setupMode(defaults); + }); + return { + defaults, + dispose() { + onLanguageListener.dispose(); + mode?.dispose(); + mode = undefined; + } + }; +} + + + +export interface HTMLDataConfiguration { + /** + * Defines whether the standard HTML tags and attributes are shown + */ + readonly useDefaultDataProvider?: boolean; + /** + * Provides a set of custom data providers. + */ + readonly dataProviders?: { [providerId: string]: HTMLDataV1 }; +} + +/** + * Custom HTML tags attributes and attribute values + * https://github.com/microsoft/vscode-html-languageservice/blob/main/docs/customData.md + */ +export interface HTMLDataV1 { + readonly version: 1 | 1.1; + readonly tags?: ITagData[]; + readonly globalAttributes?: IAttributeData[]; + readonly valueSets?: IValueSet[]; +} + +export interface IReference { + readonly name: string; + readonly url: string; +} +export interface ITagData { + readonly name: string; + readonly description?: string | MarkupContent; + readonly attributes: IAttributeData[]; + readonly references?: IReference[]; +} +export interface IAttributeData { + readonly name: string; + readonly description?: string | MarkupContent; + readonly valueSet?: string; + readonly values?: IValueData[]; + readonly references?: IReference[]; +} +export interface IValueData { + readonly name: string; + readonly description?: string | MarkupContent; + readonly references?: IReference[]; +} +export interface IValueSet { + readonly name: string; + readonly values: IValueData[]; +} +export interface MarkupContent { + readonly kind: MarkupKind; + readonly value: string; +} +export declare type MarkupKind = 'plaintext' | 'markdown'; \ No newline at end of file diff --git a/monaco-html/src/tsconfig.esm.json b/monaco-html/src/tsconfig.esm.json new file mode 100644 index 00000000..3edf3ca4 --- /dev/null +++ b/monaco-html/src/tsconfig.esm.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "node", + "outDir": "../out/esm", + "declaration": true, + "target": "es5", + "lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"] + } +} diff --git a/monaco-html/src/tsconfig.json b/monaco-html/src/tsconfig.json new file mode 100644 index 00000000..707f714d --- /dev/null +++ b/monaco-html/src/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "amd", + "moduleResolution": "node", + "outDir": "../out/amd", + "declaration": true, + "target": "es5", + "lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"] + } +} diff --git a/monaco-html/src/workerManager.ts b/monaco-html/src/workerManager.ts new file mode 100644 index 00000000..4c7716a8 --- /dev/null +++ b/monaco-html/src/workerManager.ts @@ -0,0 +1,89 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LanguageServiceDefaults } from './monaco.contribution'; +import type { HTMLWorker } from './htmlWorker'; +import { Uri, IDisposable, editor } from './fillers/monaco-editor-core'; + +const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min + +export class WorkerManager { + private _defaults: LanguageServiceDefaults; + private _idleCheckInterval: number; + private _lastUsedTime: number; + private _configChangeListener: IDisposable; + + private _worker: editor.MonacoWebWorker; + private _client: Promise; + + constructor(defaults: LanguageServiceDefaults) { + this._defaults = defaults; + this._worker = null; + this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000); + this._lastUsedTime = 0; + this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker()); + } + + private _stopWorker(): void { + if (this._worker) { + this._worker.dispose(); + this._worker = null; + } + this._client = null; + } + + dispose(): void { + clearInterval(this._idleCheckInterval); + this._configChangeListener.dispose(); + this._stopWorker(); + } + + private _checkIfIdle(): void { + if (!this._worker) { + return; + } + let timePassedSinceLastUsed = Date.now() - this._lastUsedTime; + if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) { + this._stopWorker(); + } + } + + private _getClient(): Promise { + this._lastUsedTime = Date.now(); + + if (!this._client) { + this._worker = editor.createWebWorker({ + // module that exports the create() method and returns a `HTMLWorker` instance + moduleId: 'vs/language/html/htmlWorker', + + // passed in to the create() method + createData: { + languageSettings: this._defaults.options, + languageId: this._defaults.languageId + }, + + label: this._defaults.languageId + }); + + this._client = >this._worker.getProxy(); + } + + return this._client; + } + + getLanguageServiceWorker(...resources: Uri[]): Promise { + let _client: HTMLWorker; + return this._getClient() + .then((client) => { + _client = client; + }) + .then((_) => { + if (this._worker) { + return this._worker.withSyncedResources(resources); + } + }) + .then((_) => _client); + } +} diff --git a/monaco-html/test/index.html b/monaco-html/test/index.html new file mode 100644 index 00000000..8b98c1b6 --- /dev/null +++ b/monaco-html/test/index.html @@ -0,0 +1,75 @@ + + + + + + + + +

Monaco Editor HTML test page

+
+ + + + + + + + + diff --git a/monaco-html/yarn.lock b/monaco-html/yarn.lock new file mode 100644 index 00000000..41bddd00 --- /dev/null +++ b/monaco-html/yarn.lock @@ -0,0 +1,399 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/minimatch@^3.0.3": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" + integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +array-differ@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" + integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +execa@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +get-stream@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +husky@^5.1.3: + version "5.2.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-5.2.0.tgz#fc5e1c2300d34855d47de4753607d00943fc0802" + integrity sha512-AM8T/auHXRBxlrfPVLKP6jt49GCM2Zz47m8G3FOMsLmTv8Dj/fKVWE0Rh2d4Qrvmy131xEsdQnb3OXRib67PGg== + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +monaco-editor-core@0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/monaco-editor-core/-/monaco-editor-core-0.27.0.tgz#2a24d1155d6331f966525e82154a0591e4b179f3" + integrity sha512-x7I0QiIwwvxt1lzYSoQjf1xGjtEPobFx3Zvrj+tWbJbJFsXUy11IJ6TEIZ2yRjEFzuy+vrlbcfASC6lcGg/xhw== + +monaco-languages@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/monaco-languages/-/monaco-languages-2.5.0.tgz#9bef3f59729980ea4375c1e01547e732d4267323" + integrity sha512-nwVv15bM/RJFoW/17CQ9XN8N3pzx+JEX8zNGBIpPrHpuPM47XkPzzh//MiLdEM9eoYf0xUQpbv3ZFbHqtiCu8A== + +monaco-plugin-helpers@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz#d12458eb4a41f54a553226f11134f1f2283d0c20" + integrity sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw== + dependencies: + typescript "^2.7.2" + +mri@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6" + integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ== + +multimatch@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3" + integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ== + dependencies: + "@types/minimatch" "^3.0.3" + array-differ "^3.0.0" + array-union "^2.1.0" + arrify "^2.0.1" + minimatch "^3.0.4" + +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +prettier@^2.2.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" + integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== + +pretty-quick@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.1.tgz#93ca4e2dd38cc4e970e3f54a0ead317a25454688" + integrity sha512-ZYLGiMoV2jcaas3vTJrLvKAYsxDoXQBUn8OSTxkl67Fyov9lyXivJTl0+2WVh+y6EovGcw7Lm5ThYpH+Sh3XxQ== + dependencies: + chalk "^3.0.0" + execa "^4.0.0" + find-up "^4.1.0" + ignore "^5.1.4" + mri "^1.1.5" + multimatch "^4.0.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +requirejs@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.6.tgz#e5093d9601c2829251258c0b9445d4d19fa9e7c9" + integrity sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +source-map-support@~0.5.19: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +terser@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.1.tgz#2dc7a61009b66bb638305cb2a824763b116bf784" + integrity sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg== + dependencies: + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.19" + +typescript@^2.7.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== + +typescript@^4.2.3: + version "4.3.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" + integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== + +vscode-html-languageservice@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-4.0.8.tgz#9429bacce3244dcfcb3a7172903f33b6f418db3b" + integrity sha512-VJ4boG3uOD5Ls0pCvml7ZkHY+f1uDuxr+wR39XrerPr7qQFAu91DRTBuOzBsp6lV3x5Vz2S835AS2ZzLNmezbg== + dependencies: + vscode-languageserver-textdocument "^1.0.1" + vscode-languageserver-types "^3.16.0" + vscode-nls "^5.0.0" + vscode-uri "^3.0.2" + +vscode-languageserver-textdocument@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" + integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== + +vscode-languageserver-types@3.16.0, vscode-languageserver-types@^3.16.0: + version "3.16.0" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== + +vscode-nls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" + integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== + +vscode-uri@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.2.tgz#ecfd1d066cb8ef4c3a208decdbab9a8c23d055d0" + integrity sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/monaco-json/.gitignore b/monaco-json/.gitignore new file mode 100644 index 00000000..d9ef910d --- /dev/null +++ b/monaco-json/.gitignore @@ -0,0 +1,3 @@ +/node_modules/ +/out/ +/release/ diff --git a/monaco-json/.npmignore b/monaco-json/.npmignore new file mode 100644 index 00000000..4262b0f9 --- /dev/null +++ b/monaco-json/.npmignore @@ -0,0 +1,12 @@ +/.vscode/ +/out/ +/scripts/ +/src/ +/test/ +/.gitignore +/.npmignore +/.prettierrc +/.prettierignore +/package-lock.json +/webpack.dev.config.js +/webpack.min.config.js diff --git a/monaco-json/.prettierignore b/monaco-json/.prettierignore new file mode 100644 index 00000000..3c58ccd1 --- /dev/null +++ b/monaco-json/.prettierignore @@ -0,0 +1,2 @@ +/out/ +/release/ diff --git a/monaco-json/.prettierrc b/monaco-json/.prettierrc new file mode 100644 index 00000000..c12f08c5 --- /dev/null +++ b/monaco-json/.prettierrc @@ -0,0 +1,8 @@ +{ + "arrowParens": "always", + "singleQuote": true, + "trailingComma": "none", + "semi": true, + "useTabs": true, + "printWidth": 100 +} diff --git a/monaco-json/.vscode/settings.json b/monaco-json/.vscode/settings.json new file mode 100644 index 00000000..e25fee75 --- /dev/null +++ b/monaco-json/.vscode/settings.json @@ -0,0 +1,9 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.trimTrailingWhitespace": true, + "search.exclude": { + "**/node_modules": true, + "**/release": true, + "**/out": true + } +} diff --git a/monaco-json/LICENSE.md b/monaco-json/LICENSE.md new file mode 100644 index 00000000..5ae193c9 --- /dev/null +++ b/monaco-json/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/monaco-json/README.md b/monaco-json/README.md new file mode 100644 index 00000000..60fa1e16 --- /dev/null +++ b/monaco-json/README.md @@ -0,0 +1,39 @@ +# Monaco JSON + +JSON language plugin for the Monaco Editor. It provides the following features when editing JSON files: + +- Code completion, based on JSON schemas or by looking at similar objects in the same file +- Hovers, based on JSON schemas +- Validation: Syntax errors and schema validation +- Formatting +- Document Symbols +- Syntax highlighting +- Color decorators for all properties matching a schema containing `format: "color-hex"'` (non-standard schema extension) + +Schemas can be provided by configuration. See [here](https://github.com/Microsoft/monaco-json/blob/master/monaco.d.ts) +for the API that the JSON plugin offers to configure the JSON language support. + +Internally the JSON plugin uses the [vscode-json-languageservice](https://github.com/Microsoft/vscode-json-languageservice) +node module, providing the implementation of the features listed above. The same module is also used +in [Visual Studio Code](https://github.com/Microsoft/vscode) to power the JSON editing experience. + +## Issues + +Please file issues concerning `monaco-json` in the [`monaco-editor` repository](https://github.com/Microsoft/monaco-editor/issues). + +## Installing + +This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module. + +## Development + +- `git clone https://github.com/Microsoft/monaco-json` +- `npm install .` +- compile with `npm run compile` +- watch with `npm run watch` +- `npm run prepublishOnly` +- open `$/monaco-json/test/index.html` in your favorite browser. + +## License + +[MIT](https://github.com/Microsoft/monaco-json/blob/master/LICENSE.md) diff --git a/monaco-json/SECURITY.md b/monaco-json/SECURITY.md new file mode 100644 index 00000000..10541931 --- /dev/null +++ b/monaco-json/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + diff --git a/monaco-json/monaco.d.ts b/monaco-json/monaco.d.ts new file mode 100644 index 00000000..0da80d0c --- /dev/null +++ b/monaco-json/monaco.d.ts @@ -0,0 +1,113 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// + +declare namespace monaco.languages.json { + export interface DiagnosticsOptions { + /** + * If set, the validator will be enabled and perform syntax and schema based validation, + * unless `DiagnosticsOptions.schemaValidation` is set to `ignore`. + */ + readonly validate?: boolean; + /** + * If set, comments are tolerated. If set to false, syntax errors will be emitted for comments. + * `DiagnosticsOptions.allowComments` will override this setting. + */ + readonly allowComments?: boolean; + /** + * A list of known schemas and/or associations of schemas to file names. + */ + readonly schemas?: { + /** + * The URI of the schema, which is also the identifier of the schema. + */ + readonly uri: string; + /** + * A list of glob patterns that describe for which file URIs the JSON schema will be used. + * '*' and '**' wildcards are supported. Exclusion patterns start with '!'. + * For example '*.schema.json', 'package.json', '!foo*.schema.json', 'foo/**\/BADRESP.json'. + * A match succeeds when there is at least one pattern matching and last matching pattern does not start with '!'. + */ + readonly fileMatch?: string[]; + /** + * The schema for the given URI. + */ + readonly schema?: any; + }[]; + /** + * If set, the schema service would load schema content on-demand with 'fetch' if available + */ + readonly enableSchemaRequest?: boolean; + /** + * The severity of problems from schema validation. If set to 'ignore', schema validation will be skipped. If not set, 'warning' is used. + */ + readonly schemaValidation?: SeverityLevel; + /** + * The severity of problems that occurred when resolving and loading schemas. If set to 'ignore', schema resolving problems are not reported. If not set, 'warning' is used. + */ + readonly schemaRequest?: SeverityLevel; + /** + * The severity of reported trailing commas. If not set, trailing commas will be reported as errors. + */ + readonly trailingCommas?: SeverityLevel; + /** + * The severity of reported comments. If not set, 'DiagnosticsOptions.allowComments' defines whether comments are ignored or reported as errors. + */ + readonly comments?: SeverityLevel; + } + export type SeverityLevel = 'error' | 'warning' | 'ignore'; + export interface ModeConfiguration { + /** + * Defines whether the built-in documentFormattingEdit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + /** + * Defines whether the built-in documentRangeFormattingEdit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; + /** + * Defines whether the built-in completionItemProvider is enabled. + */ + readonly completionItems?: boolean; + /** + * Defines whether the built-in hoverProvider is enabled. + */ + readonly hovers?: boolean; + /** + * Defines whether the built-in documentSymbolProvider is enabled. + */ + readonly documentSymbols?: boolean; + /** + * Defines whether the built-in tokens provider is enabled. + */ + readonly tokens?: boolean; + /** + * Defines whether the built-in color provider is enabled. + */ + readonly colors?: boolean; + /** + * Defines whether the built-in foldingRange provider is enabled. + */ + readonly foldingRanges?: boolean; + /** + * Defines whether the built-in diagnostic provider is enabled. + */ + readonly diagnostics?: boolean; + /** + * Defines whether the built-in selection range provider is enabled. + */ + readonly selectionRanges?: boolean; + } + export interface LanguageServiceDefaults { + readonly languageId: string; + readonly onDidChange: IEvent; + readonly diagnosticsOptions: DiagnosticsOptions; + readonly modeConfiguration: ModeConfiguration; + setDiagnosticsOptions(options: DiagnosticsOptions): void; + setModeConfiguration(modeConfiguration: ModeConfiguration): void; + } + export const jsonDefaults: LanguageServiceDefaults; +} diff --git a/monaco-json/package-lock.json b/monaco-json/package-lock.json new file mode 100644 index 00000000..6bdf0649 --- /dev/null +++ b/monaco-json/package-lock.json @@ -0,0 +1,504 @@ +{ + "name": "monaco-json", + "version": "3.9.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@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 + }, + "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" + } + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "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" + } + }, + "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 + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "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 + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "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 + }, + "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" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "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 + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "husky": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-5.1.3.tgz", + "integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==", + "dev": true + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "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 + }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "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" + } + }, + "monaco-editor-core": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.30.0.tgz", + "integrity": "sha512-vFJ7BEOCqLv4xWgFW+UheI/PtccHHNht29lNmo79Re1kNhWCBLLb2nThjRMLPO1rd41vX9hhd9C07/iKOk9/jQ==", + "dev": true + }, + "monaco-languages": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-2.11.0.tgz", + "integrity": "sha512-fpeP8XUPejcdoUEMZ5bo4MW8VzEadhrsuyDtT48p2a2PSRT/CXptQm4eGnIfgxf5R95jrCZ0456c5dSEPBuktA==", + "dev": true + }, + "monaco-plugin-helpers": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz", + "integrity": "sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw==", + "dev": true, + "requires": { + "typescript": "^2.7.2" + }, + "dependencies": { + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + } + } + }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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 + }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, + "pretty-quick": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.0.tgz", + "integrity": "sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + } + }, + "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" + } + }, + "requirejs": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", + "dev": true + }, + "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 + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "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 + } + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "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" + } + }, + "terser": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", + "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + } + }, + "typescript": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "dev": true + }, + "vscode-json-languageservice": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.9.tgz", + "integrity": "sha512-kxNHitUy2fCxmP6vAp0SRLrUSuecUYzzxlC+85cC3jJlFHWmvtCJOzikC+kcUnIdls9fQSB8n0yHs8Sl6taxJw==", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-languageserver-textdocument": "^1.0.1", + "vscode-languageserver-types": "^3.16.0", + "vscode-nls": "^5.0.0", + "vscode-uri": "^3.0.2" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.2.tgz", + "integrity": "sha512-T7uPC18+f8mYE4lbVZwb3OSmvwTZm3cuFhrdx9Bn2l11lmp3SvSuSVjy2JtvrghzjAo4G6Trqny2m9XGnFnWVA==", + "dev": true + }, + "vscode-languageserver-types": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", + "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", + "dev": true + }, + "vscode-nls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.0.0.tgz", + "integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==", + "dev": true + }, + "vscode-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz", + "integrity": "sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA==", + "dev": true + }, + "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" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/monaco-json/package.json b/monaco-json/package.json new file mode 100644 index 00000000..4e4f9368 --- /dev/null +++ b/monaco-json/package.json @@ -0,0 +1,43 @@ +{ + "name": "monaco-json", + "version": "3.9.0", + "description": "JSON plugin for the Monaco Editor", + "scripts": { + "compile": "mrmdir ./out && tsc -p ./src/tsconfig.json && tsc -p ./src/tsconfig.esm.json && node ./scripts/dts && prettier --write ./monaco.d.ts", + "watch": "tsc -p ./src --watch", + "prepublishOnly": "mrmdir ./release && npm run compile && node ./scripts/release.js && node ./scripts/bundle && mcopy ./monaco.d.ts ./release/monaco.d.ts && mcopy ./out/esm/monaco.contribution.d.ts ./release/esm/monaco.contribution.d.ts && mcopy ./out/esm/fillers/monaco-editor-core.d.ts ./release/esm/fillers/monaco-editor-core.d.ts", + "install-service-next": "npm install vscode-json-languageservice@next -f -D && npm install vscode-languageserver-types@next -f -D", + "install-service-local": "npm install ../vscode-json-languageservice -f -D && npm install ../vscode-languageserver-node/types -f -D", + "prettier": "prettier --write ." + }, + "author": "Microsoft Corporation", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/monaco-json" + }, + "bugs": { + "url": "https://github.com/Microsoft/monaco-json/issues" + }, + "module": "./release/esm/monaco.contribution.js", + "typings": "./release/esm/monaco.contribution.d.ts", + "devDependencies": { + "husky": "^5.1.3", + "jsonc-parser": "^3.0.0", + "monaco-editor-core": "0.30.0", + "monaco-languages": "2.11.0", + "monaco-plugin-helpers": "^1.0.3", + "prettier": "^2.2.1", + "pretty-quick": "^3.1.0", + "requirejs": "^2.3.6", + "terser": "^5.6.0", + "typescript": "4.2.4", + "vscode-json-languageservice": "4.1.9", + "vscode-uri": "3.0.2" + }, + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } + } +} diff --git a/monaco-json/scripts/bundle.js b/monaco-json/scripts/bundle.js new file mode 100644 index 00000000..e2883148 --- /dev/null +++ b/monaco-json/scripts/bundle.js @@ -0,0 +1,90 @@ +const requirejs = require('requirejs'); +const path = require('path'); +const fs = require('fs'); +const Terser = require('terser'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.resolve(__dirname, '..'); + +const sha1 = helpers.getGitVersion(REPO_ROOT); +const semver = require('../package.json').version; +const headerVersion = semver + '(' + sha1 + ')'; + +const BUNDLED_FILE_HEADER = [ + '/*!-----------------------------------------------------------------------------', + ' * Copyright (c) Microsoft Corporation. All rights reserved.', + ' * monaco-json version: ' + headerVersion, + ' * Released under the MIT license', + ' * https://github.com/Microsoft/monaco-json/blob/master/LICENSE.md', + ' *-----------------------------------------------------------------------------*/', + '' +].join('\n'); + +bundleOne('monaco.contribution'); +bundleOne('jsonMode', ['vs/language/json/monaco.contribution']); +bundleOne('jsonWorker'); + +function bundleOne(moduleId, exclude) { + requirejs.optimize( + { + baseUrl: 'out/amd/', + name: 'vs/language/json/' + moduleId, + out: 'release/dev/' + moduleId + '.js', + exclude: exclude, + paths: { + 'vs/language/json': REPO_ROOT + '/out/amd', + 'vs/language/json/fillers/monaco-editor-core': + REPO_ROOT + '/out/amd/fillers/monaco-editor-core-amd' + }, + optimize: 'none', + packages: [ + { + name: 'vscode-json-languageservice', + location: path.join(REPO_ROOT, 'node_modules/vscode-json-languageservice/lib/umd'), + main: 'jsonLanguageService' + }, + { + name: 'vscode-languageserver-types', + location: path.join(REPO_ROOT, 'node_modules/vscode-languageserver-types/lib/umd'), + main: 'main' + }, + { + name: 'vscode-languageserver-textdocument', + location: path.join(REPO_ROOT, 'node_modules/vscode-languageserver-textdocument/lib/umd'), + main: 'main' + }, + { + name: 'jsonc-parser', + location: path.join(REPO_ROOT, 'node_modules/jsonc-parser/lib/umd'), + main: 'main' + }, + { + name: 'vscode-uri', + location: path.join(REPO_ROOT, 'node_modules/vscode-uri/lib/umd'), + main: 'index' + }, + { + name: 'vscode-nls', + location: path.join(REPO_ROOT, '/out/amd/fillers'), + main: 'vscode-nls' + } + ] + }, + async function (buildResponse) { + const devFilePath = path.join(REPO_ROOT, 'release/dev/' + moduleId + '.js'); + const minFilePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js'); + const fileContents = fs.readFileSync(devFilePath).toString(); + console.log(`Minifying ${devFilePath}...`); + const result = await Terser.minify(fileContents, { + output: { + comments: 'some' + } + }); + console.log(`Done minifying ${devFilePath}.`); + try { + fs.mkdirSync(path.join(REPO_ROOT, 'release/min')); + } catch (err) {} + fs.writeFileSync(minFilePath, BUNDLED_FILE_HEADER + result.code); + } + ); +} diff --git a/monaco-json/scripts/dts.js b/monaco-json/scripts/dts.js new file mode 100644 index 00000000..74764d22 --- /dev/null +++ b/monaco-json/scripts/dts.js @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const path = require('path'); +const fs = require('fs'); + +const REPO_ROOT = path.join(__dirname, '../'); +const SRC_PATH = path.join(REPO_ROOT, 'out/amd/monaco.contribution.d.ts'); +const DST_PATH = path.join(REPO_ROOT, 'monaco.d.ts'); + +const lines = fs + .readFileSync(SRC_PATH) + .toString() + .split(/\r\n|\r|\n/); +let result = [ + `/*---------------------------------------------------------------------------------------------`, + ` * Copyright (c) Microsoft Corporation. All rights reserved.`, + ` * Licensed under the MIT License. See License.txt in the project root for license information.`, + ` *--------------------------------------------------------------------------------------------*/`, + ``, + `/// `, + ``, + `declare namespace monaco.languages.json {` +]; +for (let line of lines) { + if (/^import/.test(line)) { + continue; + } + line = line.replace(/ /g, '\t'); + line = line.replace(/declare /g, ''); + if (line.length > 0) { + line = `\t${line}`; + result.push(line); + } +} +result.push(`}`); +result.push(``); + +fs.writeFileSync(DST_PATH, result.join('\n')); diff --git a/monaco-json/scripts/release.js b/monaco-json/scripts/release.js new file mode 100644 index 00000000..b73abf08 --- /dev/null +++ b/monaco-json/scripts/release.js @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const path = require('path'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.join(__dirname, '../'); + +helpers.packageESM({ + repoRoot: REPO_ROOT, + esmSource: 'out/esm', + esmDestination: 'release/esm', + entryPoints: ['monaco.contribution.js', 'jsonMode.js', 'json.worker.js'], + resolveAlias: { + 'vscode-nls': path.join(REPO_ROOT, 'out/esm/fillers/vscode-nls.js') + }, + resolveSkip: ['monaco-editor-core'], + destinationFolderSimplification: { + node_modules: '_deps', + 'jsonc-parser/lib/esm': 'jsonc-parser', + 'vscode-languageserver-types/lib/esm': 'vscode-languageserver-types', + 'vscode-uri/lib/esm': 'vscode-uri', + 'vscode-json-languageservice/lib/esm': 'vscode-json-languageservice' + } +}); diff --git a/monaco-json/src/fillers/monaco-editor-core-amd.ts b/monaco-json/src/fillers/monaco-editor-core-amd.ts new file mode 100644 index 00000000..59874efb --- /dev/null +++ b/monaco-json/src/fillers/monaco-editor-core-amd.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// Resolves with the global monaco API + +declare var define; + +define([], function () { + return (self).monaco; +}); diff --git a/monaco-json/src/fillers/monaco-editor-core.ts b/monaco-json/src/fillers/monaco-editor-core.ts new file mode 100644 index 00000000..cd996aa7 --- /dev/null +++ b/monaco-json/src/fillers/monaco-editor-core.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export * from 'monaco-editor-core'; diff --git a/monaco-json/src/fillers/vscode-nls.ts b/monaco-json/src/fillers/vscode-nls.ts new file mode 100644 index 00000000..38f7b334 --- /dev/null +++ b/monaco-json/src/fillers/vscode-nls.ts @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface Options { + locale?: string; + cacheLanguageResolution?: boolean; +} +export interface LocalizeInfo { + key: string; + comment: string[]; +} +export interface LocalizeFunc { + (info: LocalizeInfo, message: string, ...args: any[]): string; + (key: string, message: string, ...args: any[]): string; +} +export interface LoadFunc { + (file?: string): LocalizeFunc; +} + +function format(message: string, args: any[]): string { + let result: string; + + if (args.length === 0) { + result = message; + } else { + result = message.replace(/\{(\d+)\}/g, (match, rest) => { + let index = rest[0]; + return typeof args[index] !== 'undefined' ? args[index] : match; + }); + } + return result; +} + +function localize(key: string | LocalizeInfo, message: string, ...args: any[]): string { + return format(message, args); +} + +export function loadMessageBundle(file?: string): LocalizeFunc { + return localize; +} + +export function config(opt?: Options | string): LoadFunc { + return loadMessageBundle; +} diff --git a/monaco-json/src/json.worker.ts b/monaco-json/src/json.worker.ts new file mode 100644 index 00000000..be7295be --- /dev/null +++ b/monaco-json/src/json.worker.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker'; +import { JSONWorker } from './jsonWorker'; + +self.onmessage = () => { + // ignore the first message + worker.initialize((ctx, createData) => { + return new JSONWorker(ctx, createData); + }); +}; diff --git a/monaco-json/src/jsonMode.ts b/monaco-json/src/jsonMode.ts new file mode 100644 index 00000000..7d66f6a0 --- /dev/null +++ b/monaco-json/src/jsonMode.ts @@ -0,0 +1,143 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { WorkerManager } from './workerManager'; +import type { JSONWorker } from './jsonWorker'; +import { LanguageServiceDefaults } from './monaco.contribution'; +import * as languageFeatures from './languageFeatures'; +import { createTokenizationSupport } from './tokenization'; +import { Uri, IDisposable, languages } from './fillers/monaco-editor-core'; + +export function setupMode(defaults: LanguageServiceDefaults): IDisposable { + const disposables: IDisposable[] = []; + const providers: IDisposable[] = []; + + const client = new WorkerManager(defaults); + disposables.push(client); + + const worker: languageFeatures.WorkerAccessor = (...uris: Uri[]): Promise => { + return client.getLanguageServiceWorker(...uris); + }; + + function registerProviders(): void { + const { languageId, modeConfiguration } = defaults; + + disposeAll(providers); + + if (modeConfiguration.documentFormattingEdits) { + providers.push( + languages.registerDocumentFormattingEditProvider( + languageId, + new languageFeatures.DocumentFormattingEditProvider(worker) + ) + ); + } + if (modeConfiguration.documentRangeFormattingEdits) { + providers.push( + languages.registerDocumentRangeFormattingEditProvider( + languageId, + new languageFeatures.DocumentRangeFormattingEditProvider(worker) + ) + ); + } + if (modeConfiguration.completionItems) { + providers.push( + languages.registerCompletionItemProvider( + languageId, + new languageFeatures.CompletionAdapter(worker) + ) + ); + } + if (modeConfiguration.hovers) { + providers.push( + languages.registerHoverProvider(languageId, new languageFeatures.HoverAdapter(worker)) + ); + } + if (modeConfiguration.documentSymbols) { + providers.push( + languages.registerDocumentSymbolProvider( + languageId, + new languageFeatures.DocumentSymbolAdapter(worker) + ) + ); + } + if (modeConfiguration.tokens) { + providers.push(languages.setTokensProvider(languageId, createTokenizationSupport(true))); + } + if (modeConfiguration.colors) { + providers.push( + languages.registerColorProvider( + languageId, + new languageFeatures.DocumentColorAdapter(worker) + ) + ); + } + if (modeConfiguration.foldingRanges) { + providers.push( + languages.registerFoldingRangeProvider( + languageId, + new languageFeatures.FoldingRangeAdapter(worker) + ) + ); + } + if (modeConfiguration.diagnostics) { + providers.push(new languageFeatures.DiagnosticsAdapter(languageId, worker, defaults)); + } + if (modeConfiguration.selectionRanges) { + providers.push( + languages.registerSelectionRangeProvider( + languageId, + new languageFeatures.SelectionRangeAdapter(worker) + ) + ); + } + } + + registerProviders(); + + disposables.push(languages.setLanguageConfiguration(defaults.languageId, richEditConfiguration)); + + let modeConfiguration = defaults.modeConfiguration; + defaults.onDidChange((newDefaults) => { + if (newDefaults.modeConfiguration !== modeConfiguration) { + modeConfiguration = newDefaults.modeConfiguration; + registerProviders(); + } + }); + + disposables.push(asDisposable(providers)); + + return asDisposable(disposables); +} + +function asDisposable(disposables: IDisposable[]): IDisposable { + return { dispose: () => disposeAll(disposables) }; +} + +function disposeAll(disposables: IDisposable[]) { + while (disposables.length) { + disposables.pop().dispose(); + } +} + +const richEditConfiguration: languages.LanguageConfiguration = { + wordPattern: /(-?\d*\.\d\w*)|([^\[\{\]\}\:\"\,\s]+)/g, + + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + + brackets: [ + ['{', '}'], + ['[', ']'] + ], + + autoClosingPairs: [ + { open: '{', close: '}', notIn: ['string'] }, + { open: '[', close: ']', notIn: ['string'] }, + { open: '"', close: '"', notIn: ['string'] } + ] +}; diff --git a/monaco-json/src/jsonWorker.ts b/monaco-json/src/jsonWorker.ts new file mode 100644 index 00000000..781b58e2 --- /dev/null +++ b/monaco-json/src/jsonWorker.ts @@ -0,0 +1,192 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as jsonService from 'vscode-json-languageservice'; +import type { worker } from './fillers/monaco-editor-core'; +import { URI } from 'vscode-uri'; +import { DiagnosticsOptions } from './monaco.contribution'; + +let defaultSchemaRequestService; +if (typeof fetch !== 'undefined') { + defaultSchemaRequestService = function (url) { + return fetch(url).then((response) => response.text()); + }; +} + +export class JSONWorker { + private _ctx: worker.IWorkerContext; + private _languageService: jsonService.LanguageService; + private _languageSettings: DiagnosticsOptions; + private _languageId: string; + + constructor(ctx: worker.IWorkerContext, createData: ICreateData) { + this._ctx = ctx; + this._languageSettings = createData.languageSettings; + this._languageId = createData.languageId; + this._languageService = jsonService.getLanguageService({ + workspaceContext: { + resolveRelativePath: (relativePath: string, resource: string) => { + const base = resource.substr(0, resource.lastIndexOf('/') + 1); + return resolvePath(base, relativePath); + } + }, + schemaRequestService: createData.enableSchemaRequest && defaultSchemaRequestService + }); + this._languageService.configure(this._languageSettings); + } + + async doValidation(uri: string): Promise { + let document = this._getTextDocument(uri); + if (document) { + let jsonDocument = this._languageService.parseJSONDocument(document); + return this._languageService.doValidation(document, jsonDocument, this._languageSettings); + } + return Promise.resolve([]); + } + async doComplete( + uri: string, + position: jsonService.Position + ): Promise { + let document = this._getTextDocument(uri); + let jsonDocument = this._languageService.parseJSONDocument(document); + return this._languageService.doComplete(document, position, jsonDocument); + } + async doResolve(item: jsonService.CompletionItem): Promise { + return this._languageService.doResolve(item); + } + async doHover(uri: string, position: jsonService.Position): Promise { + let document = this._getTextDocument(uri); + let jsonDocument = this._languageService.parseJSONDocument(document); + return this._languageService.doHover(document, position, jsonDocument); + } + async format( + uri: string, + range: jsonService.Range, + options: jsonService.FormattingOptions + ): Promise { + let document = this._getTextDocument(uri); + let textEdits = this._languageService.format(document, range, options); + return Promise.resolve(textEdits); + } + async resetSchema(uri: string): Promise { + return Promise.resolve(this._languageService.resetSchema(uri)); + } + async findDocumentSymbols(uri: string): Promise { + let document = this._getTextDocument(uri); + let jsonDocument = this._languageService.parseJSONDocument(document); + let symbols = this._languageService.findDocumentSymbols(document, jsonDocument); + return Promise.resolve(symbols); + } + async findDocumentColors(uri: string): Promise { + let document = this._getTextDocument(uri); + let jsonDocument = this._languageService.parseJSONDocument(document); + let colorSymbols = this._languageService.findDocumentColors(document, jsonDocument); + return Promise.resolve(colorSymbols); + } + async getColorPresentations( + uri: string, + color: jsonService.Color, + range: jsonService.Range + ): Promise { + let document = this._getTextDocument(uri); + let jsonDocument = this._languageService.parseJSONDocument(document); + let colorPresentations = this._languageService.getColorPresentations( + document, + jsonDocument, + color, + range + ); + return Promise.resolve(colorPresentations); + } + async getFoldingRanges( + uri: string, + context?: { rangeLimit?: number } + ): Promise { + let document = this._getTextDocument(uri); + let ranges = this._languageService.getFoldingRanges(document, context); + return Promise.resolve(ranges); + } + async getSelectionRanges( + uri: string, + positions: jsonService.Position[] + ): Promise { + let document = this._getTextDocument(uri); + let jsonDocument = this._languageService.parseJSONDocument(document); + let ranges = this._languageService.getSelectionRanges(document, positions, jsonDocument); + return Promise.resolve(ranges); + } + private _getTextDocument(uri: string): jsonService.TextDocument { + let models = this._ctx.getMirrorModels(); + for (let model of models) { + if (model.uri.toString() === uri) { + return jsonService.TextDocument.create( + uri, + this._languageId, + model.version, + model.getValue() + ); + } + } + return null; + } +} + +// URI path utilities, will (hopefully) move to vscode-uri + +const Slash = '/'.charCodeAt(0); +const Dot = '.'.charCodeAt(0); + +function isAbsolutePath(path: string) { + return path.charCodeAt(0) === Slash; +} + +function resolvePath(uriString: string, path: string): string { + if (isAbsolutePath(path)) { + const uri = URI.parse(uriString); + const parts = path.split('/'); + return uri.with({ path: normalizePath(parts) }).toString(); + } + return joinPath(uriString, path); +} + +function normalizePath(parts: string[]): string { + const newParts: string[] = []; + for (const part of parts) { + if (part.length === 0 || (part.length === 1 && part.charCodeAt(0) === Dot)) { + // ignore + } else if (part.length === 2 && part.charCodeAt(0) === Dot && part.charCodeAt(1) === Dot) { + newParts.pop(); + } else { + newParts.push(part); + } + } + if (parts.length > 1 && parts[parts.length - 1].length === 0) { + newParts.push(''); + } + let res = newParts.join('/'); + if (parts[0].length === 0) { + res = '/' + res; + } + return res; +} + +function joinPath(uriString: string, ...paths: string[]): string { + const uri = URI.parse(uriString); + const parts = uri.path.split('/'); + for (let path of paths) { + parts.push(...path.split('/')); + } + return uri.with({ path: normalizePath(parts) }).toString(); +} + +export interface ICreateData { + languageId: string; + languageSettings: DiagnosticsOptions; + enableSchemaRequest: boolean; +} + +export function create(ctx: worker.IWorkerContext, createData: ICreateData): JSONWorker { + return new JSONWorker(ctx, createData); +} diff --git a/monaco-json/src/languageFeatures.ts b/monaco-json/src/languageFeatures.ts new file mode 100644 index 00000000..5de634bb --- /dev/null +++ b/monaco-json/src/languageFeatures.ts @@ -0,0 +1,722 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LanguageServiceDefaults } from './monaco.contribution'; +import type { JSONWorker } from './jsonWorker'; +import { + Uri, + Position, + Range, + IRange, + CancellationToken, + IDisposable, + editor, + languages, + MarkerSeverity, + IMarkdownString +} from './fillers/monaco-editor-core'; +import * as jsonService from 'vscode-json-languageservice'; + +export interface WorkerAccessor { + (...more: Uri[]): Promise; +} + +// --- diagnostics --- --- + +export class DiagnosticsAdapter { + private _disposables: IDisposable[] = []; + private _listener: { [uri: string]: IDisposable } = Object.create(null); + + constructor( + private _languageId: string, + private _worker: WorkerAccessor, + defaults: LanguageServiceDefaults + ) { + const onModelAdd = (model: editor.IModel): void => { + let modeId = model.getLanguageId(); + if (modeId !== this._languageId) { + return; + } + + let handle: number; + this._listener[model.uri.toString()] = model.onDidChangeContent(() => { + clearTimeout(handle); + handle = setTimeout(() => this._doValidate(model.uri, modeId), 500); + }); + + this._doValidate(model.uri, modeId); + }; + + const onModelRemoved = (model: editor.IModel): void => { + editor.setModelMarkers(model, this._languageId, []); + let uriStr = model.uri.toString(); + let listener = this._listener[uriStr]; + if (listener) { + listener.dispose(); + delete this._listener[uriStr]; + } + }; + + this._disposables.push(editor.onDidCreateModel(onModelAdd)); + this._disposables.push( + editor.onWillDisposeModel((model) => { + onModelRemoved(model); + this._resetSchema(model.uri); + }) + ); + this._disposables.push( + editor.onDidChangeModelLanguage((event) => { + onModelRemoved(event.model); + onModelAdd(event.model); + this._resetSchema(event.model.uri); + }) + ); + + this._disposables.push( + defaults.onDidChange((_) => { + editor.getModels().forEach((model) => { + if (model.getLanguageId() === this._languageId) { + onModelRemoved(model); + onModelAdd(model); + } + }); + }) + ); + + this._disposables.push({ + dispose: () => { + editor.getModels().forEach(onModelRemoved); + for (let key in this._listener) { + this._listener[key].dispose(); + } + } + }); + + editor.getModels().forEach(onModelAdd); + } + + public dispose(): void { + this._disposables.forEach((d) => d && d.dispose()); + this._disposables = []; + } + + private _resetSchema(resource: Uri): void { + this._worker().then((worker) => { + worker.resetSchema(resource.toString()); + }); + } + + private _doValidate(resource: Uri, languageId: string): void { + this._worker(resource) + .then((worker) => { + return worker.doValidation(resource.toString()).then((diagnostics) => { + const markers = diagnostics.map((d) => toDiagnostics(resource, d)); + let model = editor.getModel(resource); + if (model && model.getLanguageId() === languageId) { + editor.setModelMarkers(model, languageId, markers); + } + }); + }) + .then(undefined, (err) => { + console.error(err); + }); + } +} + +function toSeverity(lsSeverity: number): MarkerSeverity { + switch (lsSeverity) { + case jsonService.DiagnosticSeverity.Error: + return MarkerSeverity.Error; + case jsonService.DiagnosticSeverity.Warning: + return MarkerSeverity.Warning; + case jsonService.DiagnosticSeverity.Information: + return MarkerSeverity.Info; + case jsonService.DiagnosticSeverity.Hint: + return MarkerSeverity.Hint; + default: + return MarkerSeverity.Info; + } +} + +function toDiagnostics(resource: Uri, diag: jsonService.Diagnostic): editor.IMarkerData { + let code = typeof diag.code === 'number' ? String(diag.code) : diag.code; + + return { + severity: toSeverity(diag.severity), + startLineNumber: diag.range.start.line + 1, + startColumn: diag.range.start.character + 1, + endLineNumber: diag.range.end.line + 1, + endColumn: diag.range.end.character + 1, + message: diag.message, + code: code, + source: diag.source + }; +} + +// --- completion ------ + +function fromPosition(position: Position): jsonService.Position { + if (!position) { + return void 0; + } + return { character: position.column - 1, line: position.lineNumber - 1 }; +} + +function fromRange(range: IRange): jsonService.Range { + if (!range) { + return void 0; + } + return { + start: { + line: range.startLineNumber - 1, + character: range.startColumn - 1 + }, + end: { line: range.endLineNumber - 1, character: range.endColumn - 1 } + }; +} +function toRange(range: jsonService.Range): Range { + if (!range) { + return void 0; + } + return new Range( + range.start.line + 1, + range.start.character + 1, + range.end.line + 1, + range.end.character + 1 + ); +} + +interface InsertReplaceEdit { + /** + * The string to be inserted. + */ + newText: string; + /** + * The range if the insert is requested + */ + insert: jsonService.Range; + /** + * The range if the replace is requested. + */ + replace: jsonService.Range; +} + +function isInsertReplaceEdit( + edit: jsonService.TextEdit | InsertReplaceEdit +): edit is InsertReplaceEdit { + return ( + typeof (edit).insert !== 'undefined' && + typeof (edit).replace !== 'undefined' + ); +} + +function toCompletionItemKind(kind: number): languages.CompletionItemKind { + let mItemKind = languages.CompletionItemKind; + + switch (kind) { + case jsonService.CompletionItemKind.Text: + return mItemKind.Text; + case jsonService.CompletionItemKind.Method: + return mItemKind.Method; + case jsonService.CompletionItemKind.Function: + return mItemKind.Function; + case jsonService.CompletionItemKind.Constructor: + return mItemKind.Constructor; + case jsonService.CompletionItemKind.Field: + return mItemKind.Field; + case jsonService.CompletionItemKind.Variable: + return mItemKind.Variable; + case jsonService.CompletionItemKind.Class: + return mItemKind.Class; + case jsonService.CompletionItemKind.Interface: + return mItemKind.Interface; + case jsonService.CompletionItemKind.Module: + return mItemKind.Module; + case jsonService.CompletionItemKind.Property: + return mItemKind.Property; + case jsonService.CompletionItemKind.Unit: + return mItemKind.Unit; + case jsonService.CompletionItemKind.Value: + return mItemKind.Value; + case jsonService.CompletionItemKind.Enum: + return mItemKind.Enum; + case jsonService.CompletionItemKind.Keyword: + return mItemKind.Keyword; + case jsonService.CompletionItemKind.Snippet: + return mItemKind.Snippet; + case jsonService.CompletionItemKind.Color: + return mItemKind.Color; + case jsonService.CompletionItemKind.File: + return mItemKind.File; + case jsonService.CompletionItemKind.Reference: + return mItemKind.Reference; + } + return mItemKind.Property; +} + +function fromCompletionItemKind( + kind: languages.CompletionItemKind +): jsonService.CompletionItemKind { + let mItemKind = languages.CompletionItemKind; + + switch (kind) { + case mItemKind.Text: + return jsonService.CompletionItemKind.Text; + case mItemKind.Method: + return jsonService.CompletionItemKind.Method; + case mItemKind.Function: + return jsonService.CompletionItemKind.Function; + case mItemKind.Constructor: + return jsonService.CompletionItemKind.Constructor; + case mItemKind.Field: + return jsonService.CompletionItemKind.Field; + case mItemKind.Variable: + return jsonService.CompletionItemKind.Variable; + case mItemKind.Class: + return jsonService.CompletionItemKind.Class; + case mItemKind.Interface: + return jsonService.CompletionItemKind.Interface; + case mItemKind.Module: + return jsonService.CompletionItemKind.Module; + case mItemKind.Property: + return jsonService.CompletionItemKind.Property; + case mItemKind.Unit: + return jsonService.CompletionItemKind.Unit; + case mItemKind.Value: + return jsonService.CompletionItemKind.Value; + case mItemKind.Enum: + return jsonService.CompletionItemKind.Enum; + case mItemKind.Keyword: + return jsonService.CompletionItemKind.Keyword; + case mItemKind.Snippet: + return jsonService.CompletionItemKind.Snippet; + case mItemKind.Color: + return jsonService.CompletionItemKind.Color; + case mItemKind.File: + return jsonService.CompletionItemKind.File; + case mItemKind.Reference: + return jsonService.CompletionItemKind.Reference; + } + return jsonService.CompletionItemKind.Property; +} + +function toTextEdit(textEdit: jsonService.TextEdit): editor.ISingleEditOperation { + if (!textEdit) { + return void 0; + } + return { + range: toRange(textEdit.range), + text: textEdit.newText + }; + +} + +function toCommand(c: jsonService.Command | undefined): languages.Command { + return c && c.command === 'editor.action.triggerSuggest' ? { id: c.command, title: c.title, arguments: c.arguments } : undefined +} + +export class CompletionAdapter implements languages.CompletionItemProvider { + constructor(private _worker: WorkerAccessor) {} + + public get triggerCharacters(): string[] { + return [' ', ':', '"']; + } + + provideCompletionItems( + model: editor.IReadOnlyModel, + position: Position, + context: languages.CompletionContext, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doComplete(resource.toString(), fromPosition(position)); + }) + .then((info) => { + if (!info) { + return; + } + const wordInfo = model.getWordUntilPosition(position); + const wordRange = new Range( + position.lineNumber, + wordInfo.startColumn, + position.lineNumber, + wordInfo.endColumn + ); + + let items: languages.CompletionItem[] = info.items.map((entry) => { + let item: languages.CompletionItem = { + label: entry.label, + insertText: entry.insertText || entry.label, + sortText: entry.sortText, + filterText: entry.filterText, + documentation: entry.documentation, + detail: entry.detail, + command: toCommand(entry.command), + range: wordRange, + kind: toCompletionItemKind(entry.kind) + }; + if (entry.textEdit) { + if (isInsertReplaceEdit(entry.textEdit)) { + item.range = { + insert: toRange(entry.textEdit.insert), + replace: toRange(entry.textEdit.replace) + }; + } else { + item.range = toRange(entry.textEdit.range); + } + item.insertText = entry.textEdit.newText; + } + if (entry.additionalTextEdits) { + item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit); + } + if (entry.insertTextFormat === jsonService.InsertTextFormat.Snippet) { + item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet; + } + return item; + }); + + return { + isIncomplete: info.isIncomplete, + suggestions: items + }; + }); + } +} + +function isMarkupContent(thing: any): thing is jsonService.MarkupContent { + return ( + thing && + typeof thing === 'object' && + typeof (thing).kind === 'string' + ); +} + +function toMarkdownString( + entry: jsonService.MarkupContent | jsonService.MarkedString +): IMarkdownString { + if (typeof entry === 'string') { + return { + value: entry + }; + } + if (isMarkupContent(entry)) { + if (entry.kind === 'plaintext') { + return { + value: entry.value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&') + }; + } + return { + value: entry.value + }; + } + + return { value: '```' + entry.language + '\n' + entry.value + '\n```\n' }; +} + +function toMarkedStringArray( + contents: jsonService.MarkupContent | jsonService.MarkedString | jsonService.MarkedString[] +): IMarkdownString[] { + if (!contents) { + return void 0; + } + if (Array.isArray(contents)) { + return contents.map(toMarkdownString); + } + return [toMarkdownString(contents)]; +} + +// --- hover ------ + +export class HoverAdapter implements languages.HoverProvider { + constructor(private _worker: WorkerAccessor) {} + + provideHover( + model: editor.IReadOnlyModel, + position: Position, + token: CancellationToken + ): Promise { + let resource = model.uri; + + return this._worker(resource) + .then((worker) => { + return worker.doHover(resource.toString(), fromPosition(position)); + }) + .then((info) => { + if (!info) { + return; + } + return { + range: toRange(info.range), + contents: toMarkedStringArray(info.contents) + }; + }); + } +} + +// --- definition ------ + +function toLocation(location: jsonService.Location): languages.Location { + return { + uri: Uri.parse(location.uri), + range: toRange(location.range) + }; +} + +// --- document symbols ------ + +function toSymbolKind(kind: jsonService.SymbolKind): languages.SymbolKind { + let mKind = languages.SymbolKind; + + switch (kind) { + case jsonService.SymbolKind.File: + return mKind.Array; + case jsonService.SymbolKind.Module: + return mKind.Module; + case jsonService.SymbolKind.Namespace: + return mKind.Namespace; + case jsonService.SymbolKind.Package: + return mKind.Package; + case jsonService.SymbolKind.Class: + return mKind.Class; + case jsonService.SymbolKind.Method: + return mKind.Method; + case jsonService.SymbolKind.Property: + return mKind.Property; + case jsonService.SymbolKind.Field: + return mKind.Field; + case jsonService.SymbolKind.Constructor: + return mKind.Constructor; + case jsonService.SymbolKind.Enum: + return mKind.Enum; + case jsonService.SymbolKind.Interface: + return mKind.Interface; + case jsonService.SymbolKind.Function: + return mKind.Function; + case jsonService.SymbolKind.Variable: + return mKind.Variable; + case jsonService.SymbolKind.Constant: + return mKind.Constant; + case jsonService.SymbolKind.String: + return mKind.String; + case jsonService.SymbolKind.Number: + return mKind.Number; + case jsonService.SymbolKind.Boolean: + return mKind.Boolean; + case jsonService.SymbolKind.Array: + return mKind.Array; + } + return mKind.Function; +} + +export class DocumentSymbolAdapter implements languages.DocumentSymbolProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideDocumentSymbols( + model: editor.IReadOnlyModel, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.findDocumentSymbols(resource.toString())) + .then((items) => { + if (!items) { + return; + } + return items.map((item) => ({ + name: item.name, + detail: '', + containerName: item.containerName, + kind: toSymbolKind(item.kind), + range: toRange(item.location.range), + selectionRange: toRange(item.location.range), + tags: [] + })); + }); + } +} + +function fromFormattingOptions( + options: languages.FormattingOptions +): jsonService.FormattingOptions { + return { + tabSize: options.tabSize, + insertSpaces: options.insertSpaces + }; +} + +export class DocumentFormattingEditProvider implements languages.DocumentFormattingEditProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideDocumentFormattingEdits( + model: editor.IReadOnlyModel, + options: languages.FormattingOptions, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource).then((worker) => { + return worker + .format(resource.toString(), null, fromFormattingOptions(options)) + .then((edits) => { + if (!edits || edits.length === 0) { + return; + } + return edits.map(toTextEdit); + }); + }); + } +} + +export class DocumentRangeFormattingEditProvider + implements languages.DocumentRangeFormattingEditProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideDocumentRangeFormattingEdits( + model: editor.IReadOnlyModel, + range: Range, + options: languages.FormattingOptions, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource).then((worker) => { + return worker + .format(resource.toString(), fromRange(range), fromFormattingOptions(options)) + .then((edits) => { + if (!edits || edits.length === 0) { + return; + } + return edits.map(toTextEdit); + }); + }); + } +} + +export class DocumentColorAdapter implements languages.DocumentColorProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideDocumentColors( + model: editor.IReadOnlyModel, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.findDocumentColors(resource.toString())) + .then((infos) => { + if (!infos) { + return; + } + return infos.map((item) => ({ + color: item.color, + range: toRange(item.range) + })); + }); + } + + public provideColorPresentations( + model: editor.IReadOnlyModel, + info: languages.IColorInformation, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => + worker.getColorPresentations(resource.toString(), info.color, fromRange(info.range)) + ) + .then((presentations) => { + if (!presentations) { + return; + } + return presentations.map((presentation) => { + let item: languages.IColorPresentation = { + label: presentation.label + }; + if (presentation.textEdit) { + item.textEdit = toTextEdit(presentation.textEdit); + } + if (presentation.additionalTextEdits) { + item.additionalTextEdits = presentation.additionalTextEdits.map(toTextEdit); + } + return item; + }); + }); + } +} + +export class FoldingRangeAdapter implements languages.FoldingRangeProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideFoldingRanges( + model: editor.IReadOnlyModel, + context: languages.FoldingContext, + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.getFoldingRanges(resource.toString(), context)) + .then((ranges) => { + if (!ranges) { + return; + } + return ranges.map((range) => { + let result: languages.FoldingRange = { + start: range.startLine + 1, + end: range.endLine + 1 + }; + if (typeof range.kind !== 'undefined') { + result.kind = toFoldingRangeKind(range.kind); + } + return result; + }); + }); + } +} + +function toFoldingRangeKind(kind: jsonService.FoldingRangeKind): languages.FoldingRangeKind { + switch (kind) { + case jsonService.FoldingRangeKind.Comment: + return languages.FoldingRangeKind.Comment; + case jsonService.FoldingRangeKind.Imports: + return languages.FoldingRangeKind.Imports; + case jsonService.FoldingRangeKind.Region: + return languages.FoldingRangeKind.Region; + } + return void 0; +} + +export class SelectionRangeAdapter implements languages.SelectionRangeProvider { + constructor(private _worker: WorkerAccessor) {} + + public provideSelectionRanges( + model: editor.IReadOnlyModel, + positions: Position[], + token: CancellationToken + ): Promise { + const resource = model.uri; + + return this._worker(resource) + .then((worker) => worker.getSelectionRanges(resource.toString(), positions.map(fromPosition))) + .then((selectionRanges) => { + if (!selectionRanges) { + return; + } + return selectionRanges.map((selectionRange) => { + const result: languages.SelectionRange[] = []; + while (selectionRange) { + result.push({ range: toRange(selectionRange.range) }); + selectionRange = selectionRange.parent; + } + return result; + }); + }); + } +} diff --git a/monaco-json/src/monaco.contribution.ts b/monaco-json/src/monaco.contribution.ts new file mode 100644 index 00000000..7e9d65e3 --- /dev/null +++ b/monaco-json/src/monaco.contribution.ts @@ -0,0 +1,218 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as mode from './jsonMode'; +import { Emitter, IEvent, languages } from './fillers/monaco-editor-core'; + +// --- JSON configuration and defaults --------- + +export interface DiagnosticsOptions { + /** + * If set, the validator will be enabled and perform syntax and schema based validation, + * unless `DiagnosticsOptions.schemaValidation` is set to `ignore`. + */ + readonly validate?: boolean; + /** + * If set, comments are tolerated. If set to false, syntax errors will be emitted for comments. + * `DiagnosticsOptions.allowComments` will override this setting. + */ + readonly allowComments?: boolean; + /** + * A list of known schemas and/or associations of schemas to file names. + */ + readonly schemas?: { + /** + * The URI of the schema, which is also the identifier of the schema. + */ + readonly uri: string; + /** + * A list of glob patterns that describe for which file URIs the JSON schema will be used. + * '*' and '**' wildcards are supported. Exclusion patterns start with '!'. + * For example '*.schema.json', 'package.json', '!foo*.schema.json', 'foo/**\/BADRESP.json'. + * A match succeeds when there is at least one pattern matching and last matching pattern does not start with '!'. + */ + readonly fileMatch?: string[]; + /** + * The schema for the given URI. + */ + readonly schema?: any; + }[]; + /** + * If set, the schema service would load schema content on-demand with 'fetch' if available + */ + readonly enableSchemaRequest?: boolean; + /** + * The severity of problems from schema validation. If set to 'ignore', schema validation will be skipped. If not set, 'warning' is used. + */ + readonly schemaValidation?: SeverityLevel; + /** + * The severity of problems that occurred when resolving and loading schemas. If set to 'ignore', schema resolving problems are not reported. If not set, 'warning' is used. + */ + readonly schemaRequest?: SeverityLevel; + /** + * The severity of reported trailing commas. If not set, trailing commas will be reported as errors. + */ + readonly trailingCommas?: SeverityLevel; + /** + * The severity of reported comments. If not set, 'DiagnosticsOptions.allowComments' defines whether comments are ignored or reported as errors. + */ + readonly comments?: SeverityLevel; +} + +export declare type SeverityLevel = 'error' | 'warning' | 'ignore'; + +export interface ModeConfiguration { + /** + * Defines whether the built-in documentFormattingEdit provider is enabled. + */ + readonly documentFormattingEdits?: boolean; + + /** + * Defines whether the built-in documentRangeFormattingEdit provider is enabled. + */ + readonly documentRangeFormattingEdits?: boolean; + + /** + * Defines whether the built-in completionItemProvider is enabled. + */ + readonly completionItems?: boolean; + + /** + * Defines whether the built-in hoverProvider is enabled. + */ + readonly hovers?: boolean; + + /** + * Defines whether the built-in documentSymbolProvider is enabled. + */ + readonly documentSymbols?: boolean; + + /** + * Defines whether the built-in tokens provider is enabled. + */ + readonly tokens?: boolean; + + /** + * Defines whether the built-in color provider is enabled. + */ + readonly colors?: boolean; + + /** + * Defines whether the built-in foldingRange provider is enabled. + */ + readonly foldingRanges?: boolean; + + /** + * Defines whether the built-in diagnostic provider is enabled. + */ + readonly diagnostics?: boolean; + + /** + * Defines whether the built-in selection range provider is enabled. + */ + readonly selectionRanges?: boolean; +} + +export interface LanguageServiceDefaults { + readonly languageId: string; + readonly onDidChange: IEvent; + readonly diagnosticsOptions: DiagnosticsOptions; + readonly modeConfiguration: ModeConfiguration; + setDiagnosticsOptions(options: DiagnosticsOptions): void; + setModeConfiguration(modeConfiguration: ModeConfiguration): void; +} + +class LanguageServiceDefaultsImpl implements LanguageServiceDefaults { + private _onDidChange = new Emitter(); + private _diagnosticsOptions: DiagnosticsOptions; + private _modeConfiguration: ModeConfiguration; + private _languageId: string; + + constructor( + languageId: string, + diagnosticsOptions: DiagnosticsOptions, + modeConfiguration: ModeConfiguration + ) { + this._languageId = languageId; + this.setDiagnosticsOptions(diagnosticsOptions); + this.setModeConfiguration(modeConfiguration); + } + + get onDidChange(): IEvent { + return this._onDidChange.event; + } + + get languageId(): string { + return this._languageId; + } + + get modeConfiguration(): ModeConfiguration { + return this._modeConfiguration; + } + + get diagnosticsOptions(): DiagnosticsOptions { + return this._diagnosticsOptions; + } + + setDiagnosticsOptions(options: DiagnosticsOptions): void { + this._diagnosticsOptions = options || Object.create(null); + this._onDidChange.fire(this); + } + + setModeConfiguration(modeConfiguration: ModeConfiguration): void { + this._modeConfiguration = modeConfiguration || Object.create(null); + this._onDidChange.fire(this); + } +} + +const diagnosticDefault: Required = { + validate: true, + allowComments: true, + schemas: [], + enableSchemaRequest: false, + schemaRequest: 'warning', + schemaValidation: 'warning', + comments: 'error', + trailingCommas: 'error' +}; + +const modeConfigurationDefault: Required = { + documentFormattingEdits: true, + documentRangeFormattingEdits: true, + completionItems: true, + hovers: true, + documentSymbols: true, + tokens: true, + colors: true, + foldingRanges: true, + diagnostics: true, + selectionRanges: true +}; + +export const jsonDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( + 'json', + diagnosticDefault, + modeConfigurationDefault +); + +// export to the global based API +(languages).json = { jsonDefaults }; + +// --- Registration to monaco editor --- + +function getMode(): Promise { + return import('./jsonMode'); +} + +languages.register({ + id: 'json', + extensions: ['.json', '.bowerrc', '.jshintrc', '.jscsrc', '.eslintrc', '.babelrc', '.har'], + aliases: ['JSON', 'json'], + mimetypes: ['application/json'] +}); + +languages.onLanguage('json', () => { + getMode().then((mode) => mode.setupMode(jsonDefaults)); +}); diff --git a/monaco-json/src/tokenization.ts b/monaco-json/src/tokenization.ts new file mode 100644 index 00000000..942cb784 --- /dev/null +++ b/monaco-json/src/tokenization.ts @@ -0,0 +1,260 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as json from 'jsonc-parser'; +import { languages } from './fillers/monaco-editor-core'; + +export function createTokenizationSupport(supportComments: boolean): languages.TokensProvider { + return { + getInitialState: () => new JSONState(null, null, false, null), + tokenize: (line, state, offsetDelta?, stopAtOffset?) => + tokenize(supportComments, line, state, offsetDelta, stopAtOffset) + }; +} + +export const TOKEN_DELIM_OBJECT = 'delimiter.bracket.json'; +export const TOKEN_DELIM_ARRAY = 'delimiter.array.json'; +export const TOKEN_DELIM_COLON = 'delimiter.colon.json'; +export const TOKEN_DELIM_COMMA = 'delimiter.comma.json'; +export const TOKEN_VALUE_BOOLEAN = 'keyword.json'; +export const TOKEN_VALUE_NULL = 'keyword.json'; +export const TOKEN_VALUE_STRING = 'string.value.json'; +export const TOKEN_VALUE_NUMBER = 'number.json'; +export const TOKEN_PROPERTY_NAME = 'string.key.json'; +export const TOKEN_COMMENT_BLOCK = 'comment.block.json'; +export const TOKEN_COMMENT_LINE = 'comment.line.json'; + +const enum JSONParent { + Object = 0, + Array = 1 +} + +class ParentsStack { + constructor( + public readonly parent: ParentsStack | null, + public readonly type: JSONParent + ) {} + + public static pop(parents: ParentsStack | null): ParentsStack | null { + if (parents) { + return parents.parent; + } + return null; + } + + public static push( + parents: ParentsStack | null, + type: JSONParent + ): ParentsStack { + return new ParentsStack(parents, type); + } + + public static equals( + a: ParentsStack | null, + b: ParentsStack | null + ): boolean { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + while (a && b) { + if (a === b) { + return true; + } + if (a.type !== b.type) { + return false; + } + a = a.parent; + b = b.parent; + } + return true; + } +} + +class JSONState implements languages.IState { + private _state: languages.IState; + + public scanError: json.ScanError; + public lastWasColon: boolean; + public parents: ParentsStack | null; + + constructor( + state: languages.IState, + scanError: json.ScanError, + lastWasColon: boolean, + parents: ParentsStack | null + ) { + this._state = state; + this.scanError = scanError; + this.lastWasColon = lastWasColon; + this.parents = parents; + } + + public clone(): JSONState { + return new JSONState( + this._state, + this.scanError, + this.lastWasColon, + this.parents + ); + } + + public equals(other: languages.IState): boolean { + if (other === this) { + return true; + } + if (!other || !(other instanceof JSONState)) { + return false; + } + return ( + this.scanError === other.scanError && + this.lastWasColon === other.lastWasColon && + ParentsStack.equals(this.parents, other.parents) + ); + } + + public getStateData(): languages.IState { + return this._state; + } + + public setStateData(state: languages.IState): void { + this._state = state; + } +} + +function tokenize( + comments: boolean, + line: string, + state: JSONState, + offsetDelta: number = 0, + stopAtOffset?: number +): languages.ILineTokens { + // handle multiline strings and block comments + let numberOfInsertedCharacters = 0; + let adjustOffset = false; + + switch (state.scanError) { + case json.ScanError.UnexpectedEndOfString: + line = '"' + line; + numberOfInsertedCharacters = 1; + break; + case json.ScanError.UnexpectedEndOfComment: + line = '/*' + line; + numberOfInsertedCharacters = 2; + break; + } + + const scanner = json.createScanner(line); + let lastWasColon = state.lastWasColon; + let parents = state.parents; + + const ret: languages.ILineTokens = { + tokens: [], + endState: state.clone() + }; + + while (true) { + let offset = offsetDelta + scanner.getPosition(); + let type = ''; + + const kind = scanner.scan(); + if (kind === json.SyntaxKind.EOF) { + break; + } + + // Check that the scanner has advanced + if (offset === offsetDelta + scanner.getPosition()) { + throw new Error( + 'Scanner did not advance, next 3 characters are: ' + line.substr(scanner.getPosition(), 3) + ); + } + + // In case we inserted /* or " character, we need to + // adjust the offset of all tokens (except the first) + if (adjustOffset) { + offset -= numberOfInsertedCharacters; + } + adjustOffset = numberOfInsertedCharacters > 0; + + // brackets and type + switch (kind) { + case json.SyntaxKind.OpenBraceToken: + parents = ParentsStack.push(parents, JSONParent.Object); + type = TOKEN_DELIM_OBJECT; + lastWasColon = false; + break; + case json.SyntaxKind.CloseBraceToken: + parents = ParentsStack.pop(parents); + type = TOKEN_DELIM_OBJECT; + lastWasColon = false; + break; + case json.SyntaxKind.OpenBracketToken: + parents = ParentsStack.push(parents, JSONParent.Array); + type = TOKEN_DELIM_ARRAY; + lastWasColon = false; + break; + case json.SyntaxKind.CloseBracketToken: + parents = ParentsStack.pop(parents); + type = TOKEN_DELIM_ARRAY; + lastWasColon = false; + break; + case json.SyntaxKind.ColonToken: + type = TOKEN_DELIM_COLON; + lastWasColon = true; + break; + case json.SyntaxKind.CommaToken: + type = TOKEN_DELIM_COMMA; + lastWasColon = false; + break; + case json.SyntaxKind.TrueKeyword: + case json.SyntaxKind.FalseKeyword: + type = TOKEN_VALUE_BOOLEAN; + lastWasColon = false; + break; + case json.SyntaxKind.NullKeyword: + type = TOKEN_VALUE_NULL; + lastWasColon = false; + break; + case json.SyntaxKind.StringLiteral: + const currentParent = parents ? parents.type : JSONParent.Object; + const inArray = currentParent === JSONParent.Array; + type = + lastWasColon || inArray ? TOKEN_VALUE_STRING : TOKEN_PROPERTY_NAME; + lastWasColon = false; + break; + case json.SyntaxKind.NumericLiteral: + type = TOKEN_VALUE_NUMBER; + lastWasColon = false; + break; + } + + // comments, iff enabled + if (comments) { + switch (kind) { + case json.SyntaxKind.LineCommentTrivia: + type = TOKEN_COMMENT_LINE; + break; + case json.SyntaxKind.BlockCommentTrivia: + type = TOKEN_COMMENT_BLOCK; + break; + } + } + + ret.endState = new JSONState( + state.getStateData(), + scanner.getTokenError(), + lastWasColon, + parents + ); + ret.tokens.push({ + startIndex: offset, + scopes: type + }); + } + + return ret; +} diff --git a/monaco-json/src/tsconfig.esm.json b/monaco-json/src/tsconfig.esm.json new file mode 100644 index 00000000..b97a230f --- /dev/null +++ b/monaco-json/src/tsconfig.esm.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "declaration": true, + "module": "esnext", + "moduleResolution": "node", + "outDir": "../out/esm", + "target": "es5", + "lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"] + } +} diff --git a/monaco-json/src/tsconfig.json b/monaco-json/src/tsconfig.json new file mode 100644 index 00000000..707f714d --- /dev/null +++ b/monaco-json/src/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "amd", + "moduleResolution": "node", + "outDir": "../out/amd", + "declaration": true, + "target": "es5", + "lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"] + } +} diff --git a/monaco-json/src/workerManager.ts b/monaco-json/src/workerManager.ts new file mode 100644 index 00000000..c4fd2661 --- /dev/null +++ b/monaco-json/src/workerManager.ts @@ -0,0 +1,88 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LanguageServiceDefaults } from './monaco.contribution'; +import type { JSONWorker } from './jsonWorker'; +import { IDisposable, Uri, editor } from './fillers/monaco-editor-core'; + +const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min + +export class WorkerManager { + private _defaults: LanguageServiceDefaults; + private _idleCheckInterval: number; + private _lastUsedTime: number; + private _configChangeListener: IDisposable; + + private _worker: editor.MonacoWebWorker; + private _client: Promise; + + constructor(defaults: LanguageServiceDefaults) { + this._defaults = defaults; + this._worker = null; + this._idleCheckInterval = setInterval(() => this._checkIfIdle(), 30 * 1000); + this._lastUsedTime = 0; + this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker()); + } + + private _stopWorker(): void { + if (this._worker) { + this._worker.dispose(); + this._worker = null; + } + this._client = null; + } + + dispose(): void { + clearInterval(this._idleCheckInterval); + this._configChangeListener.dispose(); + this._stopWorker(); + } + + private _checkIfIdle(): void { + if (!this._worker) { + return; + } + let timePassedSinceLastUsed = Date.now() - this._lastUsedTime; + if (timePassedSinceLastUsed > STOP_WHEN_IDLE_FOR) { + this._stopWorker(); + } + } + + private _getClient(): Promise { + this._lastUsedTime = Date.now(); + + if (!this._client) { + this._worker = editor.createWebWorker({ + // module that exports the create() method and returns a `JSONWorker` instance + moduleId: 'vs/language/json/jsonWorker', + + label: this._defaults.languageId, + + // passed in to the create() method + createData: { + languageSettings: this._defaults.diagnosticsOptions, + languageId: this._defaults.languageId, + enableSchemaRequest: this._defaults.diagnosticsOptions.enableSchemaRequest + } + }); + + this._client = >(this._worker.getProxy()); + } + + return this._client; + } + + getLanguageServiceWorker(...resources: Uri[]): Promise { + let _client: JSONWorker; + return this._getClient() + .then((client) => { + _client = client; + }) + .then((_) => { + return this._worker.withSyncedResources(resources); + }) + .then((_) => _client); + } +} diff --git a/monaco-json/test/index.html b/monaco-json/test/index.html new file mode 100644 index 00000000..90fedaba --- /dev/null +++ b/monaco-json/test/index.html @@ -0,0 +1,120 @@ + + + + + + + + +

Monaco Editor JSON test page

+
+ + + + + + + + + diff --git a/monaco-languages/.editorconfig b/monaco-languages/.editorconfig new file mode 100644 index 00000000..b4180a87 --- /dev/null +++ b/monaco-languages/.editorconfig @@ -0,0 +1,16 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Tab indentation +[*] +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true + +# The indent size used in the `package.json` file cannot be changed +# https://github.com/npm/npm/pull/3180#issuecomment-16336516 +[{*.yml,*.yaml,package.json}] +indent_style = space +indent_size = 2 diff --git a/monaco-languages/.github/workflows/ci.yml b/monaco-languages/.github/workflows/ci.yml new file mode 100644 index 00000000..43519669 --- /dev/null +++ b/monaco-languages/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI + +on: [push, pull_request] + +jobs: + ci: + name: CI + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v2 + with: + node-version: 12 + + - name: npm install + run: npm install + + - name: Compile + run: npm run compile + + - name: Test + run: npm test diff --git a/monaco-languages/.gitignore b/monaco-languages/.gitignore new file mode 100644 index 00000000..e6fdec5e --- /dev/null +++ b/monaco-languages/.gitignore @@ -0,0 +1,5 @@ +/.idea/ +/*.iml +/node_modules/ +/out/ +/release/ diff --git a/monaco-languages/.npmignore b/monaco-languages/.npmignore new file mode 100644 index 00000000..9f8410b6 --- /dev/null +++ b/monaco-languages/.npmignore @@ -0,0 +1,15 @@ +/.vscode/ +/out/ +/release/**/*.test.js +/release/**/test/ +/scripts/ +/src/ +/test/ +/gulpfile.js +/tsconfig.json +/.npmignore +/.prettierrc +/.prettierignore +/.travis.yml +/.editorconfig +/azure-pipelines.yml diff --git a/monaco-languages/.prettierignore b/monaco-languages/.prettierignore new file mode 100644 index 00000000..3c58ccd1 --- /dev/null +++ b/monaco-languages/.prettierignore @@ -0,0 +1,2 @@ +/out/ +/release/ diff --git a/monaco-languages/.prettierrc b/monaco-languages/.prettierrc new file mode 100644 index 00000000..c12f08c5 --- /dev/null +++ b/monaco-languages/.prettierrc @@ -0,0 +1,8 @@ +{ + "arrowParens": "always", + "singleQuote": true, + "trailingComma": "none", + "semi": true, + "useTabs": true, + "printWidth": 100 +} diff --git a/monaco-languages/.vscode/launch.json b/monaco-languages/.vscode/launch.json new file mode 100644 index 00000000..cf0b7bfe --- /dev/null +++ b/monaco-languages/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Unit Tests", + "type": "node", + "request": "launch", + "program": "./test/all.js", + "stopOnEntry": false, + "args": [ + // "--grep", + // "typescript" + ], + "cwd": "${workspaceRoot}", + "preLaunchTask": null, + "runtimeExecutable": null, + "runtimeArgs": ["--nolazy"], + "env": { + "NODE_ENV": "development" + }, + "console": "internalConsole", + "sourceMaps": false, + "outDir": null + } + ] +} diff --git a/monaco-languages/.vscode/settings.json b/monaco-languages/.vscode/settings.json new file mode 100644 index 00000000..01aeb218 --- /dev/null +++ b/monaco-languages/.vscode/settings.json @@ -0,0 +1,14 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "search.exclude": { + "**/node_modules": true, + "**/release": true, + "**/out": true + }, + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "editor.tabSize": 4, + "editor.insertSpaces": false, + "editor.detectIndentation": false, + "typescript.tsdk": "./node_modules/typescript/lib" +} diff --git a/monaco-languages/LICENSE.md b/monaco-languages/LICENSE.md new file mode 100644 index 00000000..5ae193c9 --- /dev/null +++ b/monaco-languages/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/monaco-languages/README.md b/monaco-languages/README.md new file mode 100644 index 00000000..91a9a92c --- /dev/null +++ b/monaco-languages/README.md @@ -0,0 +1,39 @@ +# Monaco Languages [![Build Status](https://dev.azure.com/ms/monaco-languages/_apis/build/status/microsoft.monaco-languages?branchName=master)](https://dev.azure.com/ms/monaco-languages/_build/latest?definitionId=140&branchName=master) + +Colorization and configuration supports for multiple languages for the Monaco Editor: + +![monaco-languages](https://cloud.githubusercontent.com/assets/5047891/15938606/1fd4bac6-2e74-11e6-8839-d455da8bc8a7.gif) + +## Issues + +Please file issues concerning `monaco-languages` in the [`monaco-editor`-repository](https://github.com/Microsoft/monaco-editor/issues). + +## Installing + +This npm module is bundled and distributed in the [monaco-editor](https://www.npmjs.com/package/monaco-editor) npm module. + +## Dev: cheat sheet + +- initial setup with `npm install .` +- compile with `npm run watch` +- test with `npm run test` +- bundle with `npm run prepublishOnly` + +## Dev: Adding a new language + +- create `$/src/myLang/myLang.contribution.ts` +- create `$/src/myLang/myLang.ts` +- create `$/src/myLang/myLang.test.ts` +- edit `$/src/monaco.contribution.ts` and register your new language + +```js +import './myLang/myLang.contribution'; +``` + +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +## License + +[MIT](https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md) diff --git a/monaco-languages/SECURITY.md b/monaco-languages/SECURITY.md new file mode 100644 index 00000000..6143e6b1 --- /dev/null +++ b/monaco-languages/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + diff --git a/monaco-languages/ThirdPartyNotices.txt b/monaco-languages/ThirdPartyNotices.txt new file mode 100644 index 00000000..91701413 --- /dev/null +++ b/monaco-languages/ThirdPartyNotices.txt @@ -0,0 +1,34 @@ +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +This project incorporates components from the projects listed below. The original copyright notices and the licenses +under which Microsoft received such components are set forth below. Microsoft reserves all rights not expressly granted +herein, whether by implication, estoppel or otherwise. + + + + +%% vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift) +========================================= +The MIT License (MIT) + +Copyright (c) 2015 David Owens II + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +========================================= +END OF vscode-swift NOTICES AND INFORMATION diff --git a/monaco-languages/package-lock.json b/monaco-languages/package-lock.json new file mode 100644 index 00000000..539811b3 --- /dev/null +++ b/monaco-languages/package-lock.json @@ -0,0 +1,1927 @@ +{ + "name": "monaco-languages", + "version": "2.11.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", + "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "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" + } + }, + "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" + } + }, + "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 + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "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" + } + } + } + }, + "@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/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "@types/node": { + "version": "16.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz", + "integrity": "sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/tape": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.13.2.tgz", + "integrity": "sha512-V1ez/RtYRGN9cNYApw5xf27DpMkTB0033X6a2i3KUmKhSojBfbWN0i3EgZxboUG96WJLHLdOyZ01aiZwVW5aSA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "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-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": "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" + } + }, + "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" + } + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "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" + } + }, + "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 + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "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" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "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 + }, + "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" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "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 + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "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" + } + }, + "cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "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 + } + } + }, + "data-urls": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.1.tgz", + "integrity": "sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^10.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true + }, + "whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true + }, + "whatwg-url": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", + "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", + "dev": true, + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } + } + }, + "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" + } + }, + "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 + }, + "deep-equal": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.5.tgz", + "integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "es-get-iterator": "^1.1.1", + "get-intrinsic": "^1.0.1", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.1.1", + "isarray": "^2.0.5", + "object-is": "^1.1.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "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" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "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 + }, + "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 + } + } + }, + "dotignore": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz", + "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "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.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "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-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + } + }, + "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" + } + }, + "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" + } + }, + "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 + }, + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "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 + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "find-versions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", + "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", + "dev": true, + "requires": { + "semver-regex": "^3.1.2" + } + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "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" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + }, + "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-dynamic-import": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-dynamic-import/-/has-dynamic-import-2.0.0.tgz", + "integrity": "sha512-GYPi/aZmACJVrVfEhP1rNUFmtCuK+SQ96mn8Bs7mXiGZRAJiI4VjaMmjj4uuvW8qaF085uWJvyJk9UNYUIYn0A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "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 + }, + "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 + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "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" + } + }, + "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" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "husky": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", + "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^7.0.0", + "find-versions": "^4.0.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^5.0.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + } + }, + "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": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "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" + } + }, + "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.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "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.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.7.0.tgz", + "integrity": "sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "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-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "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.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "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" + } + }, + "is-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0" + } + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, + "is-weakref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz", + "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-weakset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==", + "dev": true + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "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 + }, + "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 + }, + "jsdom": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-17.0.0.tgz", + "integrity": "sha512-MUq4XdqwtNurZDVeKScENMPHnkgmdIvMzZ1r1NSwHkDuaqI6BouPjr+17COo4/19oLNnmdpFDPOHVpgIZmZ+VA==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.4.1", + "acorn-globals": "^6.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.0", + "decimal.js": "^10.3.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^4.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": "^9.0.0", + "ws": "^8.0.0", + "xml-name-validator": "^3.0.0" + } + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "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" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mime-db": { + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", + "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", + "dev": true + }, + "mime-types": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", + "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "dev": true, + "requires": { + "mime-db": "1.50.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "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": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "monaco-editor-core": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.30.0.tgz", + "integrity": "sha512-vFJ7BEOCqLv4xWgFW+UheI/PtccHHNht29lNmo79Re1kNhWCBLLb2nThjRMLPO1rd41vX9hhd9C07/iKOk9/jQ==", + "dev": true + }, + "monaco-plugin-helpers": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz", + "integrity": "sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw==", + "dev": true, + "requires": { + "typescript": "^2.7.2" + }, + "dependencies": { + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + } + } + }, + "mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true + }, + "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 + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.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-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "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" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "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" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "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" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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-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 + }, + "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-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.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-quick": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.1.tgz", + "integrity": "sha512-ZYLGiMoV2jcaas3vTJrLvKAYsxDoXQBUn8OSTxkl67Fyov9lyXivJTl0+2WVh+y6EovGcw7Lm5ThYpH+Sh3XxQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "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" + } + }, + "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 + }, + "regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "requirejs": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", + "dev": true + }, + "resolve": { + "version": "2.0.0-next.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", + "integrity": "sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "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 + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "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" + } + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "semver-regex": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz", + "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==", + "dev": true + }, + "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 + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", + "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "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 + }, + "source-map-support": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", + "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "string.prototype.trim": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz", + "integrity": "sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.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" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "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" + } + }, + "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 + }, + "tape": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/tape/-/tape-5.3.1.tgz", + "integrity": "sha512-Mj3h+/dgfI2xct4kTpzqZaRxhhglXcMg//xGTbB0AQisfiOYa6ZBNQIgv46xi1MqbgthuNLSS1SAySDZsb7MMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "deep-equal": "^2.0.5", + "defined": "^1.0.0", + "dotignore": "^0.1.2", + "for-each": "^0.3.3", + "get-package-type": "^0.1.0", + "glob": "^7.1.7", + "has": "^1.0.3", + "has-dynamic-import": "^2.0.0", + "inherits": "^2.0.4", + "is-regex": "^1.1.4", + "minimist": "^1.2.5", + "object-inspect": "^1.11.0", + "object-is": "^1.1.5", + "object.assign": "^4.1.2", + "resolve": "^2.0.0-next.3", + "resumer": "^0.0.0", + "string.prototype.trim": "^1.2.4", + "through": "^2.3.8" + } + }, + "terser": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", + "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "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" + } + }, + "typescript": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", + "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==", + "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" + } + }, + "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 + }, + "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" + } + }, + "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-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": "9.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-9.1.0.tgz", + "integrity": "sha512-CQ0UcrPHyomtlOCot1TL77WyMIm/bCwrJ2D6AOKGwEczU9EpyoqAokfqrf/MioU9kHcMsmJZcg1egXix2KYEsA==", + "dev": true, + "requires": { + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.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" + } + } + } + }, + "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" + } + }, + "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" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, + "which-typed-array": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", + "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.7" + } + }, + "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 + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "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 + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/monaco-languages/package.json b/monaco-languages/package.json new file mode 100644 index 00000000..58fd25d9 --- /dev/null +++ b/monaco-languages/package.json @@ -0,0 +1,41 @@ +{ + "name": "monaco-languages", + "version": "2.11.1", + "description": "Bundle of many languages for the Monaco Editor.", + "scripts": { + "compile": "mrmdir ./out && tsc -p ./src/tsconfig.json && tsc -p ./src/tsconfig.esm.json", + "watch": "tsc -p ./src --watch", + "watch-esm": "tsc -p ./src/tsconfig.esm.json --watch", + "test": "node ./test/all.js", + "prepublishOnly": "mrmdir ./release && npm run compile && node ./scripts/release.js && node ./scripts/bundle", + "prettier": "prettier --write ." + }, + "author": "Microsoft Corporation", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/monaco-languages" + }, + "bugs": { + "url": "https://github.com/Microsoft/monaco-languages/issues" + }, + "devDependencies": { + "@types/tape": "^4.13.2", + "glob": "^7.2.0", + "husky": "^4.3.8", + "jsdom": "^17.0.0", + "monaco-editor-core": "0.30.0", + "monaco-plugin-helpers": "^1.0.3", + "prettier": "^2.4.1", + "pretty-quick": "^3.1.1", + "requirejs": "^2.3.6", + "tape": "^5.3.1", + "terser": "^5.9.0", + "typescript": "4.4.3" + }, + "husky": { + "hooks": { + "pre-commit": "pretty-quick --staged" + } + } +} diff --git a/monaco-languages/scripts/bundle.js b/monaco-languages/scripts/bundle.js new file mode 100644 index 00000000..a02c3348 --- /dev/null +++ b/monaco-languages/scripts/bundle.js @@ -0,0 +1,72 @@ +const requirejs = require('requirejs'); +const path = require('path'); +const fs = require('fs'); +const terser = require('terser'); +const glob = require('glob'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.resolve(__dirname, '..'); + +const sha1 = helpers.getGitVersion(REPO_ROOT); +const semver = require('../package.json').version; +const headerVersion = semver + '(' + sha1 + ')'; + +const BUNDLED_FILE_HEADER = [ + '/*!-----------------------------------------------------------------------------', + ' * Copyright (c) Microsoft Corporation. All rights reserved.', + ' * monaco-languages version: ' + headerVersion, + ' * Released under the MIT license', + ' * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md', + ' *-----------------------------------------------------------------------------*/', + '' +].join('\n'); + +bundleOne('monaco.contribution'); +glob('out/amd/*/*.contribution.js', { cwd: path.dirname(__dirname) }, function (err, files) { + if (err) { + console.log(err); + return; + } + files.forEach(function (file) { + file = file.replace(/\.contribution\.js$/, ''); + file = file.replace(/out[/\\]amd[/\\]/, ''); + bundleOne(file, ['vs/basic-languages/monaco.contribution']); + }); +}); + +function bundleOne(moduleId, exclude) { + requirejs.optimize( + { + baseUrl: 'out/amd/', + name: 'vs/basic-languages/' + moduleId, + out: 'release/dev/' + moduleId + '.js', + exclude: exclude, + paths: { + 'vs/basic-languages': REPO_ROOT + '/out/amd', + 'vs/basic-languages/fillers/monaco-editor-core': + REPO_ROOT + '/out/amd/fillers/monaco-editor-core-amd' + }, + optimize: 'none' + }, + async function (buildResponse) { + const devFilePath = path.join(REPO_ROOT, 'release/dev/' + moduleId + '.js'); + const minFilePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js'); + const fileContents = fs.readFileSync(devFilePath).toString(); + console.log(); + console.log(`Minifying ${devFilePath}...`); + const result = await terser.minify(fileContents, { + output: { + comments: 'some' + } + }); + console.log(`Done minifying ${devFilePath}.`); + try { + fs.mkdirSync(path.join(REPO_ROOT, 'release/min')); + } catch (err) {} + try { + fs.mkdirSync(path.dirname(minFilePath)); + } catch (err) {} + fs.writeFileSync(minFilePath, BUNDLED_FILE_HEADER + result.code); + } + ); +} diff --git a/monaco-languages/scripts/release.js b/monaco-languages/scripts/release.js new file mode 100644 index 00000000..1b681166 --- /dev/null +++ b/monaco-languages/scripts/release.js @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const path = require('path'); +const helpers = require('monaco-plugin-helpers'); + +const REPO_ROOT = path.join(__dirname, '../'); + +helpers.packageESM({ + repoRoot: REPO_ROOT, + esmSource: 'out/esm', + esmDestination: 'release/esm', + entryPoints: ['monaco.contribution.js'], + resolveSkip: ['monaco-editor-core'] +}); diff --git a/monaco-languages/src/_.contribution.ts b/monaco-languages/src/_.contribution.ts new file mode 100644 index 00000000..41092f88 --- /dev/null +++ b/monaco-languages/src/_.contribution.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { languages } from './fillers/monaco-editor-core'; + +interface ILang extends languages.ILanguageExtensionPoint { + loader: () => Promise; +} + +interface ILangImpl { + conf: languages.LanguageConfiguration; + language: languages.IMonarchLanguage; +} + +const languageDefinitions: { [languageId: string]: ILang } = {}; +const lazyLanguageLoaders: { [languageId: string]: LazyLanguageLoader } = {}; + +class LazyLanguageLoader { + public static getOrCreate(languageId: string): LazyLanguageLoader { + if (!lazyLanguageLoaders[languageId]) { + lazyLanguageLoaders[languageId] = new LazyLanguageLoader(languageId); + } + return lazyLanguageLoaders[languageId]; + } + + private readonly _languageId: string; + private _loadingTriggered: boolean; + private _lazyLoadPromise: Promise; + private _lazyLoadPromiseResolve!: (value: ILangImpl) => void; + private _lazyLoadPromiseReject!: (err: any) => void; + + constructor(languageId: string) { + this._languageId = languageId; + this._loadingTriggered = false; + this._lazyLoadPromise = new Promise((resolve, reject) => { + this._lazyLoadPromiseResolve = resolve; + this._lazyLoadPromiseReject = reject; + }); + } + + public whenLoaded(): Promise { + return this._lazyLoadPromise; + } + + public load(): Promise { + if (!this._loadingTriggered) { + this._loadingTriggered = true; + languageDefinitions[this._languageId].loader().then( + (mod) => this._lazyLoadPromiseResolve(mod), + (err) => this._lazyLoadPromiseReject(err) + ); + } + return this._lazyLoadPromise; + } +} + +export function loadLanguage(languageId: string): Promise { + return LazyLanguageLoader.getOrCreate(languageId).load(); +} + +export function registerLanguage(def: ILang): void { + const languageId = def.id; + + languageDefinitions[languageId] = def; + languages.register(def); + + const lazyLanguageLoader = LazyLanguageLoader.getOrCreate(languageId); + languages.setMonarchTokensProvider( + languageId, + lazyLanguageLoader.whenLoaded().then((mod) => mod.language) + ); + languages.onLanguage(languageId, () => { + lazyLanguageLoader.load().then((mod) => { + languages.setLanguageConfiguration(languageId, mod.conf); + }); + }); +} diff --git a/monaco-languages/src/abap/abap.contribution.ts b/monaco-languages/src/abap/abap.contribution.ts new file mode 100644 index 00000000..c515f9d2 --- /dev/null +++ b/monaco-languages/src/abap/abap.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'abap', + extensions: ['.abap'], + aliases: ['abap', 'ABAP'], + loader: () => import('./abap') +}); diff --git a/monaco-languages/src/abap/abap.test.ts b/monaco-languages/src/abap/abap.test.ts new file mode 100644 index 00000000..7c5db1dc --- /dev/null +++ b/monaco-languages/src/abap/abap.test.ts @@ -0,0 +1,360 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('abap', [ + [ + { + line: '* comment', + tokens: [{ startIndex: 0, type: 'comment.abap' }] + } + ], + [ + { + line: ' " comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'comment.abap' } + ] + } + ], + [ + { + line: 'write hello.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.abap' }, + { startIndex: 11, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'IF 2 = 3.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.abap' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'key.abap' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.abap' }, + { startIndex: 8, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: "'hello'", + tokens: [{ startIndex: 0, type: 'string.abap' }] + } + ], + [ + { + line: '|hello|', + tokens: [{ startIndex: 0, type: 'string.abap' }] + } + ], + [ + { + line: 'write: hello, world.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 5, type: 'delimiter.abap' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.abap' }, + { startIndex: 12, type: 'delimiter.abap' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.abap' }, + { startIndex: 19, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'method_call( param ).', + tokens: [ + { startIndex: 0, type: 'identifier.abap' }, + { startIndex: 11, type: 'delimiter.parenthesis.abap' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.abap' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'delimiter.parenthesis.abap' }, + { startIndex: 20, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: "'he'' llo'", + tokens: [{ startIndex: 0, type: 'string.abap' }] + } + ], + [ + { + line: '|hel\\|lo|', + tokens: [{ startIndex: 0, type: 'string.abap' }] + } + ], + [ + { + line: 'FIELD-SYMBOLS .', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.abap' }, + { startIndex: 19, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'IF foo IS NOT INITIAL.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'identifier.abap' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'keyword.abap' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'keyword.abap' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.abap' }, + { startIndex: 21, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'WRITE `moo`.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'string.abap' }, + { startIndex: 11, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'FORM foo.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.abap' }, + { startIndex: 8, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'moo = CONV #( 1 ).', + tokens: [ + { startIndex: 0, type: 'identifier.abap' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'key.abap' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.abap' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'key.abap' }, + { startIndex: 12, type: 'delimiter.parenthesis.abap' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.abap' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.parenthesis.abap' }, + { startIndex: 17, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'WRITE foo ##pragma.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.abap' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'comment.abap' }, + { startIndex: 18, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'SELECT * FROM foo02 INTO @foo.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'key.abap' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.abap' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.abap' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'keyword.abap' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'identifier.abap' }, + { startIndex: 29, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'li = lines( itab ).', + tokens: [ + { startIndex: 0, type: 'identifier.abap' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'key.abap' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'keyword.abap' }, + { startIndex: 10, type: 'delimiter.parenthesis.abap' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'identifier.abap' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.parenthesis.abap' }, + { startIndex: 18, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: "foo = 'bar' && 'baz'.", + tokens: [ + { startIndex: 0, type: 'identifier.abap' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'key.abap' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'string.abap' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'key.abap' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'string.abap' }, + { startIndex: 20, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'DATA num TYPE n.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.abap' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.abap' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'type.abap' }, + { startIndex: 15, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'CLASS-METHODS class_constructor.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'type.abap' }, + { startIndex: 31, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'super->constructor( ).', + tokens: [ + { startIndex: 0, type: 'type.abap' }, + { startIndex: 5, type: 'tag.abap' }, + { startIndex: 7, type: 'type.abap' }, + { startIndex: 18, type: 'delimiter.parenthesis.abap' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'delimiter.parenthesis.abap' }, + { startIndex: 21, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'foo->my_method( ).', + tokens: [ + { startIndex: 0, type: 'identifier.abap' }, + { startIndex: 3, type: 'tag.abap' }, + { startIndex: 5, type: 'identifier.abap' }, + { startIndex: 14, type: 'delimiter.parenthesis.abap' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.parenthesis.abap' }, + { startIndex: 17, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'foo=>const_bar.', + tokens: [ + { startIndex: 0, type: 'identifier.abap' }, + { startIndex: 3, type: 'tag.abap' }, + { startIndex: 5, type: 'identifier.abap' }, + { startIndex: 14, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'foo-bar+42(42).', + tokens: [ + { startIndex: 0, type: 'identifier.abap' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.abap' }, + { startIndex: 10, type: 'delimiter.parenthesis.abap' }, + { startIndex: 11, type: 'number.abap' }, + { startIndex: 13, type: 'delimiter.parenthesis.abap' }, + { startIndex: 14, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: "@EndUserText.label: 'hallo'", + tokens: [ + { startIndex: 0, type: 'annotation.abap' }, + { startIndex: 12, type: 'delimiter.abap' }, + { startIndex: 13, type: 'identifier.abap' }, + { startIndex: 18, type: 'delimiter.abap' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'string.abap' } + ] + } + ], + [ + { + line: 'IF foo = abap_true.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'identifier.abap' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'key.abap' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'type.abap' }, + { startIndex: 18, type: 'delimiter.abap' } + ] + } + ], + [ + { + line: 'LOOP AT screen.', + tokens: [ + { startIndex: 0, type: 'keyword.abap' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'keyword.abap' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'type.abap' }, + { startIndex: 14, type: 'delimiter.abap' } + ] + } + ] +]); diff --git a/monaco-languages/src/abap/abap.ts b/monaco-languages/src/abap/abap.ts new file mode 100644 index 00000000..092d9aea --- /dev/null +++ b/monaco-languages/src/abap/abap.ts @@ -0,0 +1,1398 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------------------------- + * ABAP Language + * + * Based on SAP ABAP Application Server 7.55 + * + * Definition: + * https://github.com/microsoft/monaco-languages/blob/master/src/abap/abap.ts + * + * Reference: + * https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm?file=abenabap_words.htm + * https://help.sap.com/doc/abapdocu_755_index_htm/7.55/en-US/index.htm?file=abenabap_index.htm + * + * Playground: + * https://microsoft.github.io/monaco-editor/monarch.html + * + * Themes: + * https://github.com/Microsoft/vscode/blob/master/src/vs/editor/standalone/common/themes.ts + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '*' + }, + brackets: [ + ['[', ']'], + ['(', ')'] + ] +}; + +export const language = { + defaultToken: 'invalid', + ignoreCase: true, + tokenPostfix: '.abap', + + keywords: [ + 'abap-source', + 'abbreviated', + 'abstract', + 'accept', + 'accepting', + 'according', + 'activation', + 'actual', + 'add', + 'add-corresponding', + 'adjacent', + 'after', + 'alias', + 'aliases', + 'align', + 'all', + 'allocate', + 'alpha', + 'analysis', + 'analyzer', + 'and', // also an operator + 'append', + 'appendage', + 'appending', + 'application', + 'archive', + 'area', + 'arithmetic', + 'as', + 'ascending', + 'aspect', + 'assert', + 'assign', + 'assigned', + 'assigning', + 'association', + 'asynchronous', + 'at', + 'attributes', + 'authority', + 'authority-check', + 'avg', + 'back', + 'background', + 'backup', + 'backward', + 'badi', + 'base', + 'before', + 'begin', + 'between', // also an operator + 'big', + 'binary', + 'bintohex', + 'bit', + 'black', + 'blank', + 'blanks', + 'blob', + 'block', + 'blocks', + 'blue', + 'bound', + 'boundaries', + 'bounds', + 'boxed', + 'break-point', + 'buffer', + 'by', + 'bypassing', + 'byte', + 'byte-order', + 'call', + 'calling', + 'case', + 'cast', + 'casting', + 'catch', + 'center', + 'centered', + 'chain', + 'chain-input', + 'chain-request', + 'change', + 'changing', + 'channels', + 'character', + 'char-to-hex', + 'check', + 'checkbox', + 'ci_', + 'circular', + 'class', + 'class-coding', + 'class-data', + 'class-events', + 'class-methods', + 'class-pool', + 'cleanup', + 'clear', + 'client', + 'clob', + 'clock', + 'close', + 'coalesce', + 'code', + 'coding', + 'col_background', + 'col_group', + 'col_heading', + 'col_key', + 'col_negative', + 'col_normal', + 'col_positive', + 'col_total', + 'collect', + 'color', + 'column', + 'columns', + 'comment', + 'comments', + 'commit', + 'common', + 'communication', + 'comparing', + 'component', + 'components', + 'compression', + 'compute', + 'concat', + 'concat_with_space', + 'concatenate', + 'cond', + 'condense', // also a built-in + 'condition', + 'connect', + 'connection', + 'constants', + 'context', + 'contexts', + 'continue', + 'control', + 'controls', + 'conv', + 'conversion', + 'convert', + 'copies', + 'copy', + 'corresponding', + 'country', + 'cover', + 'cpi', + 'create', + 'creating', + 'critical', + 'currency', + 'currency_conversion', + 'current', + 'cursor', + 'cursor-selection', + 'customer', + 'customer-function', + 'dangerous', + 'data', + 'database', + 'datainfo', + 'dataset', + 'date', + 'dats_add_days', + 'dats_add_months', + 'dats_days_between', + 'dats_is_valid', + 'daylight', + 'dd/mm/yy', + 'dd/mm/yyyy', + 'ddmmyy', + 'deallocate', + 'decimal_shift', + 'decimals', + 'declarations', + 'deep', + 'default', + 'deferred', + 'define', + 'defining', + 'definition', + 'delete', + 'deleting', + 'demand', + 'department', + 'descending', + 'describe', + 'destination', + 'detail', + 'dialog', + 'directory', + 'disconnect', + 'display', + 'display-mode', + 'distinct', + 'divide', + 'divide-corresponding', + 'division', + 'do', + 'dummy', + 'duplicate', + 'duplicates', + 'duration', + 'during', + 'dynamic', + 'dynpro', + 'edit', + 'editor-call', + 'else', + 'elseif', + 'empty', + 'enabled', + 'enabling', + 'encoding', + 'end', + 'endat', + 'endcase', + 'endcatch', + 'endchain', + 'endclass', + 'enddo', + 'endenhancement', + 'end-enhancement-section', + 'endexec', + 'endform', + 'endfunction', + 'endian', + 'endif', + 'ending', + 'endinterface', + 'end-lines', + 'endloop', + 'endmethod', + 'endmodule', + 'end-of-definition', + 'end-of-editing', + 'end-of-file', + 'end-of-page', + 'end-of-selection', + 'endon', + 'endprovide', + 'endselect', + 'end-test-injection', + 'end-test-seam', + 'endtry', + 'endwhile', + 'endwith', + 'engineering', + 'enhancement', + 'enhancement-point', + 'enhancements', + 'enhancement-section', + 'entries', + 'entry', + 'enum', + 'environment', + 'equiv', // also an operator + 'errormessage', + 'errors', + 'escaping', + 'event', + 'events', + 'exact', + 'except', + 'exception', + 'exceptions', + 'exception-table', + 'exclude', + 'excluding', + 'exec', + 'execute', + 'exists', + 'exit', + 'exit-command', + 'expand', + 'expanding', + 'expiration', + 'explicit', + 'exponent', + 'export', + 'exporting', + 'extend', + 'extended', + 'extension', + 'extract', + 'fail', + 'fetch', + 'field', + 'field-groups', + 'fields', + 'field-symbol', + 'field-symbols', + 'file', + 'filter', + 'filters', + 'filter-table', + 'final', + 'find', // also a built-in + 'first', + 'first-line', + 'fixed-point', + 'fkeq', + 'fkge', + 'flush', + 'font', + 'for', + 'form', + 'format', + 'forward', + 'found', + 'frame', + 'frames', + 'free', + 'friends', + 'from', + 'function', + 'functionality', + 'function-pool', + 'further', + 'gaps', + 'generate', + 'get', + 'giving', + 'gkeq', + 'gkge', + 'global', + 'grant', + 'green', + 'group', + 'groups', + 'handle', + 'handler', + 'harmless', + 'hashed', // also a table type + 'having', + 'hdb', + 'header', + 'headers', + 'heading', + 'head-lines', + 'help-id', + 'help-request', + 'hextobin', + 'hide', + 'high', + 'hint', + 'hold', + 'hotspot', + 'icon', + 'id', + 'identification', + 'identifier', + 'ids', + 'if', + 'ignore', + 'ignoring', + 'immediately', + 'implementation', + 'implementations', + 'implemented', + 'implicit', + 'import', + 'importing', + 'in', // also an operator + 'inactive', + 'incl', + 'include', + 'includes', + 'including', + 'increment', + 'index', // also a table type + 'index-line', + 'infotypes', + 'inheriting', + 'init', + 'initial', + 'initialization', + 'inner', + 'inout', + 'input', + 'insert', // also a built-in + 'instance', + 'instances', + 'instr', + 'intensified', + 'interface', + 'interface-pool', + 'interfaces', + 'internal', + 'intervals', + 'into', + 'inverse', + 'inverted-date', + 'is', + 'iso', + 'job', + 'join', + 'keep', + 'keeping', + 'kernel', + 'key', + 'keys', + 'keywords', + 'kind', + 'language', + 'last', + 'late', + 'layout', + 'leading', + 'leave', + 'left', + 'left-justified', + 'leftplus', + 'leftspace', + 'legacy', + 'length', + 'let', + 'level', + 'levels', + 'like', + 'line', + 'lines', // also a built-in + 'line-count', + 'linefeed', + 'line-selection', + 'line-size', + 'list', + 'listbox', + 'list-processing', + 'little', + 'llang', + 'load', + 'load-of-program', + 'lob', + 'local', + 'locale', + 'locator', + 'logfile', + 'logical', + 'log-point', + 'long', + 'loop', + 'low', + 'lower', + 'lpad', + 'lpi', + 'ltrim', + 'mail', + 'main', + 'major-id', + 'mapping', + 'margin', + 'mark', + 'mask', + 'match', // also a built-in + 'matchcode', + 'max', + 'maximum', + 'medium', + 'members', + 'memory', + 'mesh', + 'message', + 'message-id', + 'messages', + 'messaging', + 'method', + 'methods', + 'min', + 'minimum', + 'minor-id', + 'mm/dd/yy', + 'mm/dd/yyyy', + 'mmddyy', + 'mode', + 'modif', + 'modifier', + 'modify', + 'module', + 'move', + 'move-corresponding', + 'multiply', + 'multiply-corresponding', + 'name', + 'nametab', + 'native', + 'nested', + 'nesting', + 'new', + 'new-line', + 'new-page', + 'new-section', + 'next', + 'no', + 'no-display', + 'no-extension', + 'no-gap', + 'no-gaps', + 'no-grouping', + 'no-heading', + 'no-scrolling', + 'no-sign', + 'no-title', + 'no-topofpage', + 'no-zero', + 'node', + 'nodes', + 'non-unicode', + 'non-unique', + 'not', // also an operator + 'null', + 'number', + 'object', // also a data type + 'objects', + 'obligatory', + 'occurrence', + 'occurrences', + 'occurs', + 'of', + 'off', + 'offset', + 'ole', + 'on', + 'only', + 'open', + 'option', + 'optional', + 'options', + 'or', // also an operator + 'order', + 'other', + 'others', + 'out', + 'outer', + 'output', + 'output-length', + 'overflow', + 'overlay', + 'pack', + 'package', + 'pad', + 'padding', + 'page', + 'pages', + 'parameter', + 'parameters', + 'parameter-table', + 'part', + 'partially', + 'pattern', + 'percentage', + 'perform', + 'performing', + 'person', + 'pf1', + 'pf10', + 'pf11', + 'pf12', + 'pf13', + 'pf14', + 'pf15', + 'pf2', + 'pf3', + 'pf4', + 'pf5', + 'pf6', + 'pf7', + 'pf8', + 'pf9', + 'pf-status', + 'pink', + 'places', + 'pool', + 'pos_high', + 'pos_low', + 'position', + 'pragmas', + 'precompiled', + 'preferred', + 'preserving', + 'primary', + 'print', + 'print-control', + 'priority', + 'private', + 'procedure', + 'process', + 'program', + 'property', + 'protected', + 'provide', + 'public', + 'push', + 'pushbutton', + 'put', + 'queue-only', + 'quickinfo', + 'radiobutton', + 'raise', + 'raising', + 'range', + 'ranges', + 'read', + 'reader', + 'read-only', + 'receive', + 'received', + 'receiver', + 'receiving', + 'red', + 'redefinition', + 'reduce', + 'reduced', + 'ref', + 'reference', + 'refresh', + 'regex', + 'reject', + 'remote', + 'renaming', + 'replace', // also a built-in + 'replacement', + 'replacing', + 'report', + 'request', + 'requested', + 'reserve', + 'reset', + 'resolution', + 'respecting', + 'responsible', + 'result', + 'results', + 'resumable', + 'resume', + 'retry', + 'return', + 'returncode', + 'returning', + 'returns', + 'right', + 'right-justified', + 'rightplus', + 'rightspace', + 'risk', + 'rmc_communication_failure', + 'rmc_invalid_status', + 'rmc_system_failure', + 'role', + 'rollback', + 'rows', + 'rpad', + 'rtrim', + 'run', + 'sap', + 'sap-spool', + 'saving', + 'scale_preserving', + 'scale_preserving_scientific', + 'scan', + 'scientific', + 'scientific_with_leading_zero', + 'scroll', + 'scroll-boundary', + 'scrolling', + 'search', + 'secondary', + 'seconds', + 'section', + 'select', + 'selection', + 'selections', + 'selection-screen', + 'selection-set', + 'selection-sets', + 'selection-table', + 'select-options', + 'send', + 'separate', + 'separated', + 'set', + 'shared', + 'shift', + 'short', + 'shortdump-id', + 'sign_as_postfix', + 'single', + 'size', + 'skip', + 'skipping', + 'smart', + 'some', + 'sort', + 'sortable', + 'sorted', // also a table type + 'source', + 'specified', + 'split', + 'spool', + 'spots', + 'sql', + 'sqlscript', + 'stable', + 'stamp', + 'standard', // also a table type + 'starting', + 'start-of-editing', + 'start-of-selection', + 'state', + 'statement', + 'statements', + 'static', + 'statics', + 'statusinfo', + 'step-loop', + 'stop', + 'structure', + 'structures', + 'style', + 'subkey', + 'submatches', + 'submit', + 'subroutine', + 'subscreen', + 'subtract', + 'subtract-corresponding', + 'suffix', + 'sum', + 'summary', + 'summing', + 'supplied', + 'supply', + 'suppress', + 'switch', + 'switchstates', + 'symbol', + 'syncpoints', + 'syntax', + 'syntax-check', + 'syntax-trace', + 'system-call', + 'system-exceptions', + 'system-exit', + 'tab', + 'tabbed', + 'table', + 'tables', + 'tableview', + 'tabstrip', + 'target', + 'task', + 'tasks', + 'test', + 'testing', + 'test-injection', + 'test-seam', + 'text', + 'textpool', + 'then', + 'throw', + 'time', + 'times', + 'timestamp', + 'timezone', + 'tims_is_valid', + 'title', + 'titlebar', + 'title-lines', + 'to', + 'tokenization', + 'tokens', + 'top-lines', + 'top-of-page', + 'trace-file', + 'trace-table', + 'trailing', + 'transaction', + 'transfer', + 'transformation', + 'translate', // also a built-in + 'transporting', + 'trmac', + 'truncate', + 'truncation', + 'try', + 'tstmp_add_seconds', + 'tstmp_current_utctimestamp', + 'tstmp_is_valid', + 'tstmp_seconds_between', + 'type', + 'type-pool', + 'type-pools', + 'types', + 'uline', + 'unassign', + 'under', + 'unicode', + 'union', + 'unique', + 'unit_conversion', + 'unix', + 'unpack', + 'until', + 'unwind', + 'up', + 'update', + 'upper', + 'user', + 'user-command', + 'using', + 'utf-8', + 'valid', + 'value', + 'value-request', + 'values', + 'vary', + 'varying', + 'verification-message', + 'version', + 'via', + 'view', + 'visible', + 'wait', + 'warning', + 'when', + 'whenever', + 'where', + 'while', + 'width', + 'window', + 'windows', + 'with', + 'with-heading', + 'without', + 'with-title', + 'word', + 'work', + 'write', + 'writer', + 'xml', + 'xsd', + 'yellow', + 'yes', + 'yymmdd', + 'zero', + 'zone', + // since 7.55: + 'abap_system_timezone', + 'abap_user_timezone', + 'access', + 'action', + 'adabas', + 'adjust_numbers', + 'allow_precision_loss', + 'allowed', + 'amdp', + 'applicationuser', + 'as_geo_json', + 'as400', + 'associations', + 'balance', + 'behavior', + 'breakup', + 'bulk', + 'cds', + 'cds_client', + 'check_before_save', + 'child', + 'clients', + 'corr', + 'corr_spearman', + 'cross', + 'cycles', + 'datn_add_days', + 'datn_add_months', + 'datn_days_between', + 'dats_from_datn', + 'dats_tims_to_tstmp', + 'dats_to_datn', + 'db2', + 'db6', + 'ddl', + 'dense_rank', + 'depth', + 'deterministic', + 'discarding', + 'entities', + 'entity', + 'error', + 'failed', + 'finalize', + 'first_value', + 'fltp_to_dec', + 'following', + 'fractional', + 'full', + 'graph', + 'grouping', + 'hierarchy', + 'hierarchy_ancestors', + 'hierarchy_ancestors_aggregate', + 'hierarchy_descendants', + 'hierarchy_descendants_aggregate', + 'hierarchy_siblings', + 'incremental', + 'indicators', + 'lag', + 'last_value', + 'lead', + 'leaves', + 'like_regexpr', + 'link', + 'locale_sap', + 'lock', + 'locks', + 'many', + 'mapped', + 'matched', + 'measures', + 'median', + 'mssqlnt', + 'multiple', + 'nodetype', + 'ntile', + 'nulls', + 'occurrences_regexpr', + 'one', + 'operations', + 'oracle', + 'orphans', + 'over', + 'parent', + 'parents', + 'partition', + 'pcre', + 'period', + 'pfcg_mapping', + 'preceding', + 'privileged', + 'product', + 'projection', + 'rank', + 'redirected', + 'replace_regexpr', + 'reported', + 'response', + 'responses', + 'root', + 'row', + 'row_number', + 'sap_system_date', + 'save', + 'schema', + 'session', + 'sets', + 'shortdump', + 'siblings', + 'spantree', + 'start', + 'stddev', + 'string_agg', + 'subtotal', + 'sybase', + 'tims_from_timn', + 'tims_to_timn', + 'to_blob', + 'to_clob', + 'total', + 'trace-entry', + 'tstmp_to_dats', + 'tstmp_to_dst', + 'tstmp_to_tims', + 'tstmpl_from_utcl', + 'tstmpl_to_utcl', + 'unbounded', + 'utcl_add_seconds', + 'utcl_current', + 'utcl_seconds_between', + 'uuid', + 'var', + 'verbatim' + ], + + // + // Built-in Functions + // + // Functions that are also statements have been moved to keywords + // + builtinFunctions: [ + 'abs', + 'acos', + 'asin', + 'atan', + 'bit-set', + 'boolc', + 'boolx', + 'ceil', + 'char_off', + 'charlen', + 'cmax', + 'cmin', + 'concat_lines_of', + // 'condense', // moved to keywords + 'contains', + 'contains_any_not_of', + 'contains_any_of', + 'cos', + 'cosh', + 'count', + 'count_any_not_of', + 'count_any_of', + 'dbmaxlen', + 'distance', + 'escape', + 'exp', + // 'find', // moved to keywords + 'find_any_not_of', + 'find_any_of', + 'find_end', + 'floor', + 'frac', + 'from_mixed', + // 'insert', // moved to keywords + 'ipow', + 'line_exists', + 'line_index', + // 'lines', // moved to keywords + 'log', + 'log10', + // 'match', // moved to keywords + 'matches', + 'nmax', + 'nmin', + 'numofchar', + 'repeat', + // 'replace', // moved to keywords + 'rescale', + 'reverse', + 'round', + 'segment', + 'shift_left', + 'shift_right', + 'sign', + 'sin', + 'sinh', + 'sqrt', + 'strlen', + 'substring', + 'substring_after', + 'substring_before', + 'substring_from', + 'substring_to', + 'tan', + 'tanh', + 'to_lower', + 'to_mixed', + 'to_upper', + // 'translate', // moved to keywords + 'trunc', + 'utclong_add', // since 7.54 + 'utclong_current', // since 7.54 + 'utclong_diff', // since 7.54 + 'xsdbool', + 'xstrlen' + ], + + // + // Data Types + // + // Data types that are also part of statements have been moved to keywords + // + typeKeywords: [ + // built-in abap types + 'b', + 'c', + 'd', + 'decfloat16', + 'decfloat34', + 'f', + 'i', + 'int8', // since 7.54 + 'n', + 'p', + 's', + 'string', + 't', + 'utclong', // since 7.54 + 'x', + 'xstring', + // generic data types + 'any', + 'clike', + 'csequence', + 'decfloat', + // 'object', // moved to keywords + 'numeric', + 'simple', + 'xsequence', + // ddic/sql data types + 'accp', + 'char', + 'clnt', + 'cuky', + 'curr', + 'datn', // since 7.55 + 'dats', + 'd16d', // since 7.55 + 'd16n', // since 7.55 + 'd16r', // since 7.55 + 'd34d', // since 7.55 + 'd34n', // since 7.55 + 'd34r', // since 7.55 + 'dec', + 'df16_dec', + 'df16_raw', + 'df34_dec', + 'df34_raw', + 'fltp', + 'geom_ewkb', // since 7.55 + 'int1', + 'int2', + 'int4', + 'lang', + 'lchr', + 'lraw', + 'numc', + 'quan', + 'raw', + 'rawstring', + 'sstring', + 'timn', // since 7.55 + 'tims', + 'unit', + 'utcl', // since 7.55 + // ddic data types (obsolete) + 'df16_scl', + 'df34_scl', + 'prec', + 'varc', + // special data types and constants + 'abap_bool', + 'abap_false', + 'abap_true', + 'abap_undefined', + 'me', + 'screen', + 'space', + 'super', + 'sy', + 'syst', + 'table_line', + // obsolete data object + '*sys*' + ], + + builtinMethods: ['class_constructor', 'constructor'], + + derivedTypes: [ + '%CID', + '%CID_REF', + '%CONTROL', + '%DATA', + '%ELEMENT', + '%FAIL', + '%KEY', + '%MSG', + '%PARAM', + '%PID', + '%PID_ASSOC', + '%PID_PARENT', + '%_HINTS' + ], + + cdsLanguage: [ + '@AbapAnnotation', + '@AbapCatalog', + '@AccessControl', + '@API', + '@ClientDependent', + '@ClientHandling', + '@CompatibilityContract', + '@DataAging', + '@EndUserText', + '@Environment', + '@LanguageDependency', + '@MappingRole', + '@Metadata', + '@MetadataExtension', + '@ObjectModel', + '@Scope', + '@Semantics', + '$EXTENSION', + '$SELF' + ], + + selectors: ['->', '->*', '=>', '~', '~*'], + + // + // Operators + // + // Operators that can be part of statements have been moved to keywords + // + operators: [ + // arithmetic operators + ' +', + ' -', + '/', + '*', + '**', + 'div', + 'mod', + // assignment operators + '=', + '#', + '@', + '+=', + '-=', + '*=', + '/=', + '**=', + '&&=', + // casting operator + '?=', + // concat operators + '&', + '&&', + // bit operators + 'bit-and', + 'bit-not', + 'bit-or', + 'bit-xor', + 'm', + 'o', + 'z', + // boolean operators + // 'and', // moved to keywords + // 'equiv', // moved to keywords + // 'not', // moved to keywords + // 'or', // moved to keywords + // comparison operators + '<', + ' >', // todo: separate from -> and => + '<=', + '>=', + '<>', + '><', // obsolete + '=<', // obsolete + '=>', // obsolete + // 'between', // moved to keywords + 'bt', + 'byte-ca', + 'byte-cn', + 'byte-co', + 'byte-cs', + 'byte-na', + 'byte-ns', + 'ca', + 'cn', + 'co', + 'cp', + 'cs', + 'eq', // obsolete + 'ge', // obsolete + 'gt', // obsolete + // 'in', // moved to keywords + 'le', // obsolete + 'lt', // obsolete + 'na', + 'nb', + 'ne', // obsolete + 'np', + 'ns', + // cds + '*/', + '*:', + '--', + '/*', + '//' + ], + + symbols: /[=>))*/, // exclude '->' selector + { + cases: { + '@typeKeywords': 'type', + '@keywords': 'keyword', + '@cdsLanguage': 'annotation', + '@derivedTypes': 'type', + '@builtinFunctions': 'type', + '@builtinMethods': 'type', + '@operators': 'key', + '@default': 'identifier' + } + } + ], + + [/<[\w]+>/, 'identifier'], // field symbols + + [/##[\w|_]+/, 'comment'], // pragmas + + { include: '@whitespace' }, + + [/[:,.]/, 'delimiter'], + + [/[{}()\[\]]/, '@brackets'], + + [ + /@symbols/, + { + cases: { + '@selectors': 'tag', + '@operators': 'key', + '@default': '' + } + } + ], + + [/'/, { token: 'string', bracket: '@open', next: '@stringquote' }], + [/`/, { token: 'string', bracket: '@open', next: '@stringping' }], + [/\|/, { token: 'string', bracket: '@open', next: '@stringtemplate' }], + + [/\d+/, 'number'] + ], + + stringtemplate: [ + [/[^\\\|]+/, 'string'], + [/\\\|/, 'string'], + [/\|/, { token: 'string', bracket: '@close', next: '@pop' }] + ], + + stringping: [ + [/[^\\`]+/, 'string'], + [/`/, { token: 'string', bracket: '@close', next: '@pop' }] + ], + + stringquote: [ + [/[^\\']+/, 'string'], + [/'/, { token: 'string', bracket: '@close', next: '@pop' }] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/^\*.*$/, 'comment'], + [/\".*$/, 'comment'] + ] + } +}; diff --git a/monaco-languages/src/apex/apex.contribution.ts b/monaco-languages/src/apex/apex.contribution.ts new file mode 100644 index 00000000..58e86d59 --- /dev/null +++ b/monaco-languages/src/apex/apex.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'apex', + extensions: ['.cls'], + aliases: ['Apex', 'apex'], + mimetypes: ['text/x-apex-source', 'text/x-apex'], + loader: () => import('./apex') +}); diff --git a/monaco-languages/src/apex/apex.test.ts b/monaco-languages/src/apex/apex.test.ts new file mode 100644 index 00000000..a683d991 --- /dev/null +++ b/monaco-languages/src/apex/apex.test.ts @@ -0,0 +1,700 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('apex', [ + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.apex' } + ] + } + ], + + // Broken nested tokens due to invalid comment tokenization + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.apex' }, + { startIndex: 1, type: 'identifier.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.apex' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.apex' }, + { startIndex: 5, type: 'delimiter.apex' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.apex' } + ] + } + ], + + [ + { + line: 'int x = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.int.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.apex' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.apex' }, + { startIndex: 9, type: 'delimiter.apex' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.apex' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + } + ], + + [ + { + line: 'int x = /* a simple comment */ 1;', + tokens: [ + { startIndex: 0, type: 'keyword.int.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.apex' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.apex' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.apex' }, + { startIndex: 32, type: 'delimiter.apex' } + ] + } + ], + + [ + { + line: 'int x = /* comment */ 1; */', + tokens: [ + { startIndex: 0, type: 'keyword.int.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.apex' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.apex' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.apex' }, + { startIndex: 23, type: 'delimiter.apex' }, + { startIndex: 24, type: '' } + ] + } + ], + + [ + { + line: 'x = /**/;', + tokens: [ + { startIndex: 0, type: 'identifier.apex' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.apex' }, + { startIndex: 8, type: 'delimiter.apex' } + ] + } + ], + + [ + { + line: 'x = /*/;', + tokens: [ + { startIndex: 0, type: 'identifier.apex' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.apex' } + ] + } + ], + + // Comments - range comment, multiple lines + [ + { + line: '/* start of multiline comment', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + }, + { + line: 'a comment between without a star', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + }, + { + line: 'end of multiline comment*/', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + } + ], + + [ + { + line: 'int x = /* start a comment', + tokens: [ + { startIndex: 0, type: 'keyword.int.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.apex' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.apex' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.apex' }] + }, + { + line: 'and end it */ 2;', + tokens: [ + { startIndex: 0, type: 'comment.apex' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.apex' }, + { startIndex: 15, type: 'delimiter.apex' } + ] + } + ], + + // Comments - apex doc, multiple lines + [ + { + line: '/** start of Apex Doc', + tokens: [{ startIndex: 0, type: 'comment.doc.apex' }] + }, + { + line: 'a comment between without a star', + tokens: [{ startIndex: 0, type: 'comment.doc.apex' }] + }, + { + line: 'end of multiline comment*/', + tokens: [{ startIndex: 0, type: 'comment.doc.apex' }] + } + ], + + // Keywords + [ + { + line: 'package test; class Program { static void main(String[] args) {} } }', + tokens: [ + { startIndex: 0, type: 'keyword.package.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.apex' }, + { startIndex: 12, type: 'delimiter.apex' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.class.apex' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'type.identifier.apex' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.curly.apex' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'keyword.static.apex' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'keyword.void.apex' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'identifier.apex' }, + { startIndex: 46, type: 'delimiter.parenthesis.apex' }, + { startIndex: 47, type: 'type.identifier.apex' }, + { startIndex: 53, type: 'delimiter.square.apex' }, + { startIndex: 55, type: '' }, + { startIndex: 56, type: 'identifier.apex' }, + { startIndex: 60, type: 'delimiter.parenthesis.apex' }, + { startIndex: 61, type: '' }, + { startIndex: 62, type: 'delimiter.curly.apex' }, + { startIndex: 64, type: '' }, + { startIndex: 65, type: 'delimiter.curly.apex' }, + { startIndex: 66, type: '' }, + { startIndex: 67, type: 'delimiter.curly.apex' } + ] + } + ], + + // Keywords with case variations + [ + { + line: 'Package test; CLASS Program { Static void main(String[] args) {} } }', + tokens: [ + { startIndex: 0, type: 'keyword.Package.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.apex' }, + { startIndex: 12, type: 'delimiter.apex' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.CLASS.apex' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'type.identifier.apex' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.curly.apex' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'keyword.Static.apex' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'keyword.void.apex' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'identifier.apex' }, + { startIndex: 46, type: 'delimiter.parenthesis.apex' }, + { startIndex: 47, type: 'type.identifier.apex' }, + { startIndex: 53, type: 'delimiter.square.apex' }, + { startIndex: 55, type: '' }, + { startIndex: 56, type: 'identifier.apex' }, + { startIndex: 60, type: 'delimiter.parenthesis.apex' }, + { startIndex: 61, type: '' }, + { startIndex: 62, type: 'delimiter.curly.apex' }, + { startIndex: 64, type: '' }, + { startIndex: 65, type: 'delimiter.curly.apex' }, + { startIndex: 66, type: '' }, + { startIndex: 67, type: 'delimiter.curly.apex' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.apex' }] + } + ], + + [ + { + line: '0.10', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '0x', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '10e3', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '10f', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5e-3', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5E-3', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5F', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5f', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5D', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23.5d', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '1.72E3D', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '1.72E3d', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '1.72E-3d', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '1.72e3D', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '1.72e3d', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '1.72e-3d', + tokens: [{ startIndex: 0, type: 'number.float.apex' }] + } + ], + + [ + { + line: '23L', + tokens: [{ startIndex: 0, type: 'number.apex' }] + } + ], + + [ + { + line: '23l', + tokens: [{ startIndex: 0, type: 'number.apex' }] + } + ], + + [ + { + line: '0_52', + tokens: [{ startIndex: 0, type: 'number.apex' }] + } + ], + + [ + { + line: '5_2', + tokens: [{ startIndex: 0, type: 'number.apex' }] + } + ], + + [ + { + line: '5_______2', + tokens: [{ startIndex: 0, type: 'number.apex' }] + } + ], + + [ + { + line: '3_.1415F', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: 'identifier.apex' }, + { startIndex: 2, type: 'delimiter.apex' }, + { startIndex: 3, type: 'number.float.apex' } + ] + } + ], + + [ + { + line: '3._1415F', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: 'delimiter.apex' }, + { startIndex: 2, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '999_99_9999_L', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 11, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '52_', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 2, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '0_x52', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '0x_52', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: 'identifier.apex' } + ] + } + ], + + [ + { + line: '23.5L', + tokens: [ + { startIndex: 0, type: 'number.float.apex' }, + { startIndex: 4, type: 'type.identifier.apex' } + ] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: 'delimiter.apex' }, + { startIndex: 2, type: 'number.apex' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 3, type: 'delimiter.apex' }, + { startIndex: 4, type: 'number.apex' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.apex' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.apex' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.apex' } + ] + } + ], + + // single line Strings + [ + { + line: 'String s = "I\'m an Apex String";', + tokens: [ + { startIndex: 0, type: 'type.identifier.apex' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.apex' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.apex' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.apex' }, + { startIndex: 31, type: 'delimiter.apex' } + ] + } + ], + + [ + { + line: 'String s = "concatenated" + " String" ;', + tokens: [ + { startIndex: 0, type: 'type.identifier.apex' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.apex' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.apex' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.apex' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'delimiter.apex' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'string.apex' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'delimiter.apex' } + ] + } + ], + + [ + { + line: '"quote in a string"', + tokens: [{ startIndex: 0, type: 'string.apex' }] + } + ], + + [ + { + line: '"escaping \\"quotes\\" is cool"', + tokens: [ + { startIndex: 0, type: 'string.apex' }, + { startIndex: 10, type: 'string.escape.apex' }, + { startIndex: 12, type: 'string.apex' }, + { startIndex: 18, type: 'string.escape.apex' }, + { startIndex: 20, type: 'string.apex' } + ] + } + ], + + [ + { + line: '"\\"', + tokens: [{ startIndex: 0, type: 'string.invalid.apex' }] + } + ], + + // Annotations + [ + { + line: '@', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: '@Override', + tokens: [{ startIndex: 0, type: 'annotation.apex' }] + } + ], + + [ + { + line: '@SuppressWarnings(value = "aString")', + tokens: [ + { startIndex: 0, type: 'annotation.apex' }, + { startIndex: 17, type: 'delimiter.parenthesis.apex' }, + { startIndex: 18, type: 'identifier.apex' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'delimiter.apex' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'string.apex' }, + { startIndex: 35, type: 'delimiter.parenthesis.apex' } + ] + } + ], + + [ + { + line: '@ AnnotationWithKeywordAfter private', + tokens: [ + { startIndex: 0, type: 'annotation.apex' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'keyword.private.apex' } + ] + } + ] +]); diff --git a/monaco-languages/src/apex/apex.ts b/monaco-languages/src/apex/apex.ts new file mode 100644 index 00000000..6b30c8f2 --- /dev/null +++ b/monaco-languages/src/apex/apex.ts @@ -0,0 +1,356 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + // the default separators except `@$` + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: '<', close: '>' } + ], + folding: { + markers: { + start: new RegExp('^\\s*//\\s*(?:(?:#?region\\b)|(?:))') + } + } +}; + +const keywords = [ + 'abstract', + 'activate', + 'and', + 'any', + 'array', + 'as', + 'asc', + 'assert', + 'autonomous', + 'begin', + 'bigdecimal', + 'blob', + 'boolean', + 'break', + 'bulk', + 'by', + 'case', + 'cast', + 'catch', + 'char', + 'class', + 'collect', + 'commit', + 'const', + 'continue', + 'convertcurrency', + 'decimal', + 'default', + 'delete', + 'desc', + 'do', + 'double', + 'else', + 'end', + 'enum', + 'exception', + 'exit', + 'export', + 'extends', + 'false', + 'final', + 'finally', + 'float', + 'for', + 'from', + 'future', + 'get', + 'global', + 'goto', + 'group', + 'having', + 'hint', + 'if', + 'implements', + 'import', + 'in', + 'inner', + 'insert', + 'instanceof', + 'int', + 'interface', + 'into', + 'join', + 'last_90_days', + 'last_month', + 'last_n_days', + 'last_week', + 'like', + 'limit', + 'list', + 'long', + 'loop', + 'map', + 'merge', + 'native', + 'new', + 'next_90_days', + 'next_month', + 'next_n_days', + 'next_week', + 'not', + 'null', + 'nulls', + 'number', + 'object', + 'of', + 'on', + 'or', + 'outer', + 'override', + 'package', + 'parallel', + 'pragma', + 'private', + 'protected', + 'public', + 'retrieve', + 'return', + 'returning', + 'rollback', + 'savepoint', + 'search', + 'select', + 'set', + 'short', + 'sort', + 'stat', + 'static', + 'strictfp', + 'super', + 'switch', + 'synchronized', + 'system', + 'testmethod', + 'then', + 'this', + 'this_month', + 'this_week', + 'throw', + 'throws', + 'today', + 'tolabel', + 'tomorrow', + 'transaction', + 'transient', + 'trigger', + 'true', + 'try', + 'type', + 'undelete', + 'update', + 'upsert', + 'using', + 'virtual', + 'void', + 'volatile', + 'webservice', + 'when', + 'where', + 'while', + 'yesterday' +]; + +// create case variations of the keywords - apex is case insensitive, but we can't make the highlighter case insensitive +// because we use a heuristic to assume that identifiers starting with an upper case letter are types. +const uppercaseFirstLetter = (lowercase: string) => + lowercase.charAt(0).toUpperCase() + lowercase.substr(1); + +let keywordsWithCaseVariations: string[] = []; +keywords.forEach((lowercase) => { + keywordsWithCaseVariations.push(lowercase); + keywordsWithCaseVariations.push(lowercase.toUpperCase()); + keywordsWithCaseVariations.push(uppercaseFirstLetter(lowercase)); +}); + +export const language = { + defaultToken: '', + tokenPostfix: '.apex', + + keywords: keywordsWithCaseVariations, + + operators: [ + '=', + '>', + '<', + '!', + '~', + '?', + ':', + '==', + '<=', + '>=', + '!=', + '&&', + '||', + '++', + '--', + '+', + '-', + '*', + '/', + '&', + '|', + '^', + '%', + '<<', + '>>', + '>>>', + '+=', + '-=', + '*=', + '/=', + '&=', + '|=', + '^=', + '%=', + '<<=', + '>>=', + '>>>=' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // @ annotations. + [/@\s*[a-zA-Z_\$][\w\$]*/, 'annotation'], + + // numbers + [/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/(@digits)[fFdD]/, 'number.float'], + [/(@digits)[lL]?/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/'([^'\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, 'string', '@string."'], + [/'/, 'string', "@string.'"], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@apexdoc'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + // [/\/\*/, 'comment', '@push' ], // nested comment not allowed :-( + // [/\/\*/, 'comment.invalid' ], // this breaks block comments in the shape of /* //*/ + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + //Identical copy of comment above, except for the addition of .doc + apexdoc: [ + [/[^\/*]+/, 'comment.doc'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'] + ], + + string: [ + [/[^\\"']+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [ + /["']/, + { + cases: { + '$#==$S2': { token: 'string', next: '@pop' }, + '@default': 'string' + } + } + ] + ] + } +}; diff --git a/monaco-languages/src/azcli/azcli.contribution.ts b/monaco-languages/src/azcli/azcli.contribution.ts new file mode 100644 index 00000000..b0f5bcc1 --- /dev/null +++ b/monaco-languages/src/azcli/azcli.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'azcli', + extensions: ['.azcli'], + aliases: ['Azure CLI', 'azcli'], + loader: () => import('./azcli') +}); diff --git a/monaco-languages/src/azcli/azcli.test.ts b/monaco-languages/src/azcli/azcli.test.ts new file mode 100644 index 00000000..cf34ecfd --- /dev/null +++ b/monaco-languages/src/azcli/azcli.test.ts @@ -0,0 +1,172 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization as actualTestTokenization, ITestItem } from '../test/testRunner'; + +function testTokenization(_language: string | string[], tests: ITestItem[][]): void { + tests = tests.map((t) => { + return t.map((t) => { + return { + line: t.line.replace(/\n/g, ' '), + tokens: t.tokens + }; + }); + }); + actualTestTokenization(_language, tests); +} + +testTokenization('azcli', [ + // Comment single line + [ + { + line: '#', + tokens: [{ startIndex: 0, type: 'comment.azcli' }] + } + ], + [ + { + line: '# az find -q secret', + tokens: [{ startIndex: 0, type: 'comment.azcli' }] + } + ], + [ + { + line: ' # az find -q secret', + tokens: [ + { startIndex: 0, type: 'keyword.azcli' }, + { startIndex: 4, type: 'comment.azcli' } + ] + } + ], + [ + { + line: '#az find -q secret', + tokens: [{ startIndex: 0, type: 'comment.azcli' }] + } + ], + + // Other cases + [ + { + line: 'az find -q secret', + tokens: [ + { startIndex: 0, type: 'keyword.azcli' }, + { startIndex: 7, type: 'key.identifier.azcli' }, + { startIndex: 11, type: 'string.azcli' } + ] + } + ], + [ + { + line: '', + tokens: [] + } + ], + [ + { + line: ' ', + tokens: [{ startIndex: 0, type: 'keyword.azcli' }] + } + ], + [ + { + line: '--assignee', + tokens: [{ startIndex: 0, type: 'key.identifier.azcli' }] + } + ], + [ + { + line: ' --service-principal', + tokens: [ + { startIndex: 0, type: 'keyword.azcli' }, + { startIndex: 3, type: 'key.identifier.azcli' } + ] + } + ], + [ + { + line: 'az ad sp create-for-rb --name ServicePrincipalName --password PASSWORD', + tokens: [ + { startIndex: 0, type: 'keyword.azcli' }, + { startIndex: 23, type: 'key.identifier.azcli' }, + { startIndex: 31, type: 'string.azcli' }, + { startIndex: 52, type: 'key.identifier.azcli' }, + { startIndex: 63, type: 'string.azcli' } + ] + } + ], + [ + { + line: '--name!~`"$%^&*(|/.,-=+', + tokens: [{ startIndex: 0, type: 'key.identifier.azcli' }] + } + ], + [ + { + line: '--name#some comment', + tokens: [ + { startIndex: 0, type: 'key.identifier.azcli' }, + { startIndex: 6, type: 'comment.azcli' } + ] + } + ], + [ + { + line: '--query osPro ``````', + tokens: [ + { startIndex: 0, type: 'key.identifier.azcli' }, + { startIndex: 8, type: 'string.azcli' } + ] + } + ], + [ + { + line: 'az ad sp create-for-rbac', + tokens: [{ startIndex: 0, type: 'keyword.azcli' }] + } + ], + [ + { + line: '123456789', + tokens: [{ startIndex: 0, type: 'keyword.azcli' }] + } + ], + [ + { + line: '- abc', + tokens: [ + { startIndex: 0, type: 'key.identifier.azcli' }, + { startIndex: 2, type: 'string.azcli' } + ] + } + ], + [ + { + line: '- @!$()', + tokens: [ + { startIndex: 0, type: 'key.identifier.azcli' }, + { startIndex: 2, type: 'string.azcli' } + ] + } + ], + [ + { + line: '""', + tokens: [{ startIndex: 0, type: 'keyword.azcli' }] + } + ], + [ + { + line: '// some text', + tokens: [{ startIndex: 0, type: 'keyword.azcli' }] + } + ], + [ + { + line: `'APP_ID'`, + tokens: [{ startIndex: 0, type: 'keyword.azcli' }] + } + ] +]); diff --git a/monaco-languages/src/azcli/azcli.ts b/monaco-languages/src/azcli/azcli.ts new file mode 100644 index 00000000..b527a411 --- /dev/null +++ b/monaco-languages/src/azcli/azcli.ts @@ -0,0 +1,77 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '#' + } +}; + +export const language = { + defaultToken: 'keyword', + ignoreCase: true, + tokenPostfix: '.azcli', + + str: /[^#\s]/, + + tokenizer: { + root: [ + { include: '@comment' }, + [ + /\s-+@str*\s*/, + { + cases: { + '@eos': { token: 'key.identifier', next: '@popall' }, + '@default': { token: 'key.identifier', next: '@type' } + } + } + ], + [ + /^-+@str*\s*/, + { + cases: { + '@eos': { token: 'key.identifier', next: '@popall' }, + '@default': { token: 'key.identifier', next: '@type' } + } + } + ] + ], + + type: [ + { include: '@comment' }, + [ + /-+@str*\s*/, + { + cases: { + '@eos': { token: 'key.identifier', next: '@popall' }, + '@default': 'key.identifier' + } + } + ], + [ + /@str+\s*/, + { + cases: { + '@eos': { token: 'string', next: '@popall' }, + '@default': 'string' + } + } + ] + ], + + comment: [ + [ + /#.*$/, + { + cases: { + '@eos': { token: 'comment', next: '@popall' } + } + } + ] + ] + } +}; diff --git a/monaco-languages/src/bat/bat.contribution.ts b/monaco-languages/src/bat/bat.contribution.ts new file mode 100644 index 00000000..bc9cdd1f --- /dev/null +++ b/monaco-languages/src/bat/bat.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'bat', + extensions: ['.bat', '.cmd'], + aliases: ['Batch', 'bat'], + loader: () => import('./bat') +}); diff --git a/monaco-languages/src/bat/bat.test.ts b/monaco-languages/src/bat/bat.test.ts new file mode 100644 index 00000000..e3f4afa2 --- /dev/null +++ b/monaco-languages/src/bat/bat.test.ts @@ -0,0 +1,397 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('bat', [ + // Keywords + [ + { + line: '@echo off title Selfhost', + tokens: [ + { startIndex: 0, type: 'keyword.bat' }, + { startIndex: 1, type: 'keyword.echo.bat' }, + { startIndex: 5, type: '' }, + { startIndex: 10, type: 'keyword.title.bat' }, + { startIndex: 15, type: '' } + ] + } + ], + + // Comments - single line + [ + { + line: 'REM', + tokens: [{ startIndex: 0, type: 'comment.bat' }] + } + ], + + [ + { + line: ' REM a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.bat' } + ] + } + ], + + [ + { + line: 'REM a comment', + tokens: [{ startIndex: 0, type: 'comment.bat' }] + } + ], + + [ + { + line: 'REMnot a comment', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + // number + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.bat' }] + } + ], + + [ + { + line: '0.0', + tokens: [{ startIndex: 0, type: 'number.float.bat' }] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.bat' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.bat' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.bat' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.bat' }] + } + ], + + [ + { + line: '1.72e-3', + tokens: [{ startIndex: 0, type: 'number.float.bat' }] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.bat' }, + { startIndex: 1, type: 'delimiter.bat' }, + { startIndex: 2, type: 'number.bat' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.bat' }, + { startIndex: 3, type: 'delimiter.bat' }, + { startIndex: 4, type: 'number.bat' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.bat' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.bat' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.bat' } + ] + } + ], + + // Strings + [ + { + line: 'set s = "string"', + tokens: [ + { startIndex: 0, type: 'keyword.set.bat' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.bat' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.bat' } + ] + } + ], + + [ + { + line: '"use strict";', + tokens: [ + { startIndex: 0, type: 'string.bat' }, + { startIndex: 12, type: 'delimiter.bat' } + ] + } + ], + + // Tags + [ + { + line: 'setlocal endlocal', + tokens: [ + { startIndex: 0, type: 'keyword.tag-setlocal.bat' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.tag-setlocal.bat' } + ] + } + ], + + [ + { + line: 'setlocal ENDLOCAL', + tokens: [ + { startIndex: 0, type: 'keyword.tag-setlocal.bat' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.tag-setlocal.bat' } + ] + } + ], + + [ + { + line: 'SETLOCAL endlocal', + tokens: [ + { startIndex: 0, type: 'keyword.tag-setlocal.bat' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.tag-setlocal.bat' } + ] + } + ], + + [ + { + line: 'setlocal setlocal endlocal', + tokens: [ + { startIndex: 0, type: 'keyword.tag-setlocal.bat' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.tag-setlocal.bat' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'keyword.tag-setlocal.bat' } + ] + } + ], + + // Monarch generated + [ + { + line: 'rem asdf', + tokens: [{ startIndex: 0, type: 'comment.bat' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'REM', + tokens: [{ startIndex: 0, type: 'comment.bat' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'REMOVED not a comment really', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'keyword.not.bat' }, + { startIndex: 11, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'echo cool', + tokens: [ + { startIndex: 0, type: 'keyword.echo.bat' }, + { startIndex: 4, type: '' } + ] + }, + { + line: '@echo off', + tokens: [ + { startIndex: 0, type: 'keyword.bat' }, + { startIndex: 1, type: 'keyword.echo.bat' }, + { startIndex: 5, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'setlocAL', + tokens: [{ startIndex: 0, type: 'keyword.tag-setlocal.bat' }] + }, + { + line: ' asdf', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' asdf', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: 'endLocaL', + tokens: [{ startIndex: 0, type: 'keyword.tag-setlocal.bat' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'call', + tokens: [{ startIndex: 0, type: 'keyword.call.bat' }] + }, + { + line: '', + tokens: [] + }, + { + line: ':MyLabel', + tokens: [{ startIndex: 0, type: 'metatag.bat' }] + }, + { + line: 'some command', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: '%sdfsdf% ', + tokens: [ + { startIndex: 0, type: 'variable.bat' }, + { startIndex: 8, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'this is "a string %sdf% asdf"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'string.bat' }, + { startIndex: 18, type: 'variable.bat' }, + { startIndex: 23, type: 'string.bat' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '', + tokens: [] + }, + { + line: 'FOR %%A IN (1 2 3) DO (', + tokens: [ + { startIndex: 0, type: 'keyword.for.bat' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'variable.bat' }, + { startIndex: 7, type: '' }, + { startIndex: 11, type: 'delimiter.parenthesis.bat' }, + { startIndex: 12, type: 'number.bat' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.bat' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'number.bat' }, + { startIndex: 17, type: 'delimiter.parenthesis.bat' }, + { startIndex: 18, type: '' }, + { startIndex: 22, type: 'delimiter.parenthesis.bat' } + ] + }, + { + line: ' SET VAR1=%VAR1%%%A', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.set.bat' }, + { startIndex: 4, type: '' }, + { startIndex: 9, type: 'delimiter.bat' }, + { startIndex: 10, type: 'variable.bat' } + ] + }, + { + line: ' SET VAR2=%VAR2%%%A', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.set.bat' }, + { startIndex: 4, type: '' }, + { startIndex: 9, type: 'delimiter.bat' }, + { startIndex: 10, type: 'variable.bat' } + ] + }, + { + line: " use 'string %%a asdf asdf'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'string.bat' }, + { startIndex: 13, type: 'variable.bat' }, + { startIndex: 16, type: 'string.bat' } + ] + }, + { + line: ' non terminated "string %%aaa sdf', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 16, type: 'string.bat' }, + { startIndex: 24, type: 'variable.bat' }, + { startIndex: 29, type: 'string.bat' } + ] + }, + { + line: ' this shold NOT BE red', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 12, type: 'keyword.not.bat' }, + { startIndex: 15, type: '' } + ] + }, + { + line: ')', + tokens: [{ startIndex: 0, type: 'delimiter.parenthesis.bat' }] + } + ] +]); diff --git a/monaco-languages/src/bat/bat.ts b/monaco-languages/src/bat/bat.ts new file mode 100644 index 00000000..0b7969dd --- /dev/null +++ b/monaco-languages/src/bat/bat.ts @@ -0,0 +1,121 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: 'REM' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' } + ], + surroundingPairs: [ + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' } + ], + folding: { + markers: { + start: new RegExp('^\\s*(::\\s*|REM\\s+)#region'), + end: new RegExp('^\\s*(::\\s*|REM\\s+)#endregion') + } + } +}; + +export const language = { + defaultToken: '', + ignoreCase: true, + tokenPostfix: '.bat', + + brackets: [ + { token: 'delimiter.bracket', open: '{', close: '}' }, + { token: 'delimiter.parenthesis', open: '(', close: ')' }, + { token: 'delimiter.square', open: '[', close: ']' } + ], + + keywords: + /call|defined|echo|errorlevel|exist|for|goto|if|pause|set|shift|start|title|not|pushd|popd/, + + // we include these common regular expressions + symbols: /[=> import('./bicep') +}); diff --git a/monaco-languages/src/bicep/bicep.test.ts b/monaco-languages/src/bicep/bicep.test.ts new file mode 100644 index 00000000..feb0cf34 --- /dev/null +++ b/monaco-languages/src/bicep/bicep.test.ts @@ -0,0 +1,1063 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/* To generate an initial baseline from a .bicep file, uncomment: + +import { testTokenization } from '../test/testRunner'; +import { readFileSync } from 'fs'; + +const lines = readFileSync('/Users/ant/Code/bicep/src/monarch/test/baselines/basic.bicep', { encoding: 'utf-8' }).split(/\r?\n/); + +testTokenization('bicep', [ + lines.map(line => ({ + line, + tokens: [], + })) +]); +*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('bicep', [ + [ + // https://github.com/Azure/bicep/blob/bc9fc9ce09d1d8da21144d84db01655e042e74bf/src/monarch/test/baselines/comments.bicep + { + line: '', + tokens: [] + }, + { + line: "resource test 'Microsoft.AAD/domainServices@2021-03-01' = {", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'string.quote.bicep' }, + { startIndex: 15, type: 'string.bicep' }, + { startIndex: 55, type: '' } + ] + }, + { + line: " name: 'asdfsdf'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'string.quote.bicep' }, + { startIndex: 9, type: 'string.bicep' } + ] + }, + { + line: ' // this is a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'comment.bicep' } + ] + }, + { + line: ' properties: {/*comment*/', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 12, type: '' }, + { startIndex: 15, type: 'comment.bicep' } + ] + }, + { + line: " domainConfigurationType/*comment*/:/*comment*/'as//notacomment!d/* also not a comment */fsdf'// test!/*", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 27, type: 'comment.bicep' }, + { startIndex: 38, type: '' }, + { startIndex: 39, type: 'comment.bicep' }, + { startIndex: 50, type: 'string.quote.bicep' }, + { startIndex: 51, type: 'string.bicep' }, + { startIndex: 97, type: 'comment.bicep' } + ] + }, + { + line: ' /* multi', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.bicep' } + ] + }, + { + line: ' line', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: ' comment */ domainName: /*', + tokens: [ + { startIndex: 0, type: 'comment.bicep' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'identifier.bicep' }, + { startIndex: 25, type: '' }, + { startIndex: 27, type: 'comment.bicep' } + ] + }, + { + line: " asdf*/'test'", + tokens: [ + { startIndex: 0, type: 'comment.bicep' }, + { startIndex: 10, type: 'string.quote.bicep' }, + { startIndex: 11, type: 'string.bicep' } + ] + }, + { + line: ' // comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.bicep' } + ] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + } + ], + [ + // https://github.com/Azure/bicep/blob/bc9fc9ce09d1d8da21144d84db01655e042e74bf/src/monarch/test/baselines/basic.bicep + { + line: '// test', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '/* test 2 */', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: "targetScope = 'resourceGroup'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 11, type: '' }, + { startIndex: 14, type: 'string.quote.bicep' }, + { startIndex: 15, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: "resource avcsdd 'Microsoft.Cache/redis@2020-06-01' = { // line comment", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'string.quote.bicep' }, + { startIndex: 17, type: 'string.bicep' }, + { startIndex: 50, type: '' }, + { startIndex: 55, type: 'comment.bicep' } + ] + }, + { + line: " name: 'def' /* block", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'string.quote.bicep' }, + { startIndex: 9, type: 'string.bicep' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'comment.bicep' } + ] + }, + { + line: ' comment */', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: " location: 'somewhere'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 10, type: '' }, + { startIndex: 12, type: 'string.quote.bicep' }, + { startIndex: 13, type: 'string.bicep' } + ] + }, + { + line: ' properties: {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 12, type: '' } + ] + }, + { + line: ' sku: {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 7, type: '' } + ] + }, + { + line: ' capacity: 123', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'identifier.bicep' }, + { startIndex: 14, type: '' }, + { startIndex: 16, type: 'number.bicep' } + ] + }, + { + line: " family: 'C'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'identifier.bicep' }, + { startIndex: 12, type: '' }, + { startIndex: 14, type: 'string.quote.bicep' }, + { startIndex: 15, type: 'string.bicep' } + ] + }, + { + line: " name: 'Basic'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'identifier.bicep' }, + { startIndex: 10, type: '' }, + { startIndex: 12, type: 'string.quote.bicep' }, + { startIndex: 13, type: 'string.bicep' } + ] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'var secretsObject = {', + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 17, type: '' } + ] + }, + { + line: ' secrets: [', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 9, type: '' } + ] + }, + { + line: " 'abc'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'string.quote.bicep' }, + { startIndex: 5, type: 'string.bicep' } + ] + }, + { + line: " 'def'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'string.quote.bicep' }, + { startIndex: 5, type: 'string.bicep' } + ] + }, + { + line: ' ]', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: "var parent = 'abc'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 10, type: '' }, + { startIndex: 13, type: 'string.quote.bicep' }, + { startIndex: 14, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: "resource secrets0 'Microsoft.KeyVault/vaults/secrets@2018-02-14' = {", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.quote.bicep' }, + { startIndex: 19, type: 'string.bicep' }, + { startIndex: 64, type: '' } + ] + }, + { + line: " name: '${parent}/child'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'string.quote.bicep' }, + { startIndex: 9, type: 'delimiter.bracket.bicep' }, + { startIndex: 11, type: 'identifier.bicep' }, + { startIndex: 17, type: 'delimiter.bracket.bicep' }, + { startIndex: 18, type: 'string.bicep' } + ] + }, + { + line: ' properties: {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 12, type: '' } + ] + }, + { + line: ' attributes: {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 14, type: '' } + ] + }, + { + line: ' enabled: true', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'identifier.bicep' }, + { startIndex: 13, type: '' }, + { startIndex: 15, type: 'keyword.bicep' } + ] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: "resource secrets1 'Microsoft.KeyVault/vaults/secrets@2018-02-14' = if (secrets0.id == '') {", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.quote.bicep' }, + { startIndex: 19, type: 'string.bicep' }, + { startIndex: 64, type: '' }, + { startIndex: 67, type: 'keyword.bicep' }, + { startIndex: 69, type: '' }, + { startIndex: 71, type: 'identifier.bicep' }, + { startIndex: 79, type: '' }, + { startIndex: 80, type: 'identifier.bicep' }, + { startIndex: 82, type: '' }, + { startIndex: 86, type: 'string.quote.bicep' }, + { startIndex: 87, type: 'string.bicep' }, + { startIndex: 88, type: '' } + ] + }, + { + line: " name: '${parent}/child1'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'string.quote.bicep' }, + { startIndex: 9, type: 'delimiter.bracket.bicep' }, + { startIndex: 11, type: 'identifier.bicep' }, + { startIndex: 17, type: 'delimiter.bracket.bicep' }, + { startIndex: 18, type: 'string.bicep' } + ] + }, + { + line: ' properties: {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 12, type: '' } + ] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: "resource secrets2 'Microsoft.KeyVault/vaults/secrets@2018-02-14' = [for secret in secretsObject.secrets: {", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.quote.bicep' }, + { startIndex: 19, type: 'string.bicep' }, + { startIndex: 64, type: '' }, + { startIndex: 68, type: 'keyword.bicep' }, + { startIndex: 71, type: '' }, + { startIndex: 72, type: 'identifier.bicep' }, + { startIndex: 78, type: '' }, + { startIndex: 79, type: 'keyword.bicep' }, + { startIndex: 81, type: '' }, + { startIndex: 82, type: 'identifier.bicep' }, + { startIndex: 95, type: '' }, + { startIndex: 96, type: 'identifier.bicep' }, + { startIndex: 103, type: '' } + ] + }, + { + line: " name: 'asdfsd/forloop'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'string.quote.bicep' }, + { startIndex: 9, type: 'string.bicep' } + ] + }, + { + line: ' properties: {}', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 12, type: '' } + ] + }, + { + line: '}]', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: "resource secrets3 'Microsoft.KeyVault/vaults/secrets@2018-02-14' = [for secret in secretsObject.secrets: {", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.quote.bicep' }, + { startIndex: 19, type: 'string.bicep' }, + { startIndex: 64, type: '' }, + { startIndex: 68, type: 'keyword.bicep' }, + { startIndex: 71, type: '' }, + { startIndex: 72, type: 'identifier.bicep' }, + { startIndex: 78, type: '' }, + { startIndex: 79, type: 'keyword.bicep' }, + { startIndex: 81, type: '' }, + { startIndex: 82, type: 'identifier.bicep' }, + { startIndex: 95, type: '' }, + { startIndex: 96, type: 'identifier.bicep' }, + { startIndex: 103, type: '' } + ] + }, + { + line: " name: 'jk${true}asdf${23}.\\${SDF${secretsObject['secrets'][1]}'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'string.quote.bicep' }, + { startIndex: 9, type: 'string.bicep' }, + { startIndex: 11, type: 'delimiter.bracket.bicep' }, + { startIndex: 13, type: 'keyword.bicep' }, + { startIndex: 17, type: 'delimiter.bracket.bicep' }, + { startIndex: 18, type: 'string.bicep' }, + { startIndex: 22, type: 'delimiter.bracket.bicep' }, + { startIndex: 24, type: 'number.bicep' }, + { startIndex: 26, type: 'delimiter.bracket.bicep' }, + { startIndex: 27, type: 'string.bicep' }, + { startIndex: 28, type: 'string.escape.bicep' }, + { startIndex: 31, type: 'string.bicep' }, + { startIndex: 34, type: 'delimiter.bracket.bicep' }, + { startIndex: 36, type: 'identifier.bicep' }, + { startIndex: 49, type: '' }, + { startIndex: 50, type: 'string.quote.bicep' }, + { startIndex: 51, type: 'string.bicep' }, + { startIndex: 59, type: '' }, + { startIndex: 61, type: 'number.bicep' }, + { startIndex: 62, type: '' }, + { startIndex: 63, type: 'delimiter.bracket.bicep' }, + { startIndex: 64, type: 'string.bicep' } + ] + }, + { + line: ' properties: {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 12, type: '' } + ] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '}]', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: "resource secrets4 'Microsoft.KeyVault/vaults/secrets@2018-02-14' = [for secret in secretsObject.secrets: if (true) {", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.quote.bicep' }, + { startIndex: 19, type: 'string.bicep' }, + { startIndex: 64, type: '' }, + { startIndex: 68, type: 'keyword.bicep' }, + { startIndex: 71, type: '' }, + { startIndex: 72, type: 'identifier.bicep' }, + { startIndex: 78, type: '' }, + { startIndex: 79, type: 'keyword.bicep' }, + { startIndex: 81, type: '' }, + { startIndex: 82, type: 'identifier.bicep' }, + { startIndex: 95, type: '' }, + { startIndex: 96, type: 'identifier.bicep' }, + { startIndex: 103, type: '' }, + { startIndex: 105, type: 'keyword.bicep' }, + { startIndex: 107, type: '' }, + { startIndex: 109, type: 'keyword.bicep' }, + { startIndex: 113, type: '' } + ] + }, + { + line: " 'name': 'test'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 10, type: 'string.quote.bicep' }, + { startIndex: 11, type: 'string.bicep' } + ] + }, + { + line: ' properties:{', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 12, type: '' } + ] + }, + { + line: ' }', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '}]', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: "resource virtualNetwork 'Microsoft.Network/virtualNetworks@2020-08-01' existing = {", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'string.quote.bicep' }, + { startIndex: 25, type: 'string.bicep' }, + { startIndex: 70, type: '' }, + { startIndex: 71, type: 'keyword.bicep' }, + { startIndex: 79, type: '' } + ] + }, + { + line: " name: 'myVnet'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'string.quote.bicep' }, + { startIndex: 9, type: 'string.bicep' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: "var multi = ''''''", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 9, type: '' }, + { startIndex: 12, type: 'string.quote.bicep' } + ] + }, + { + line: "var multi2 = '''", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 10, type: '' }, + { startIndex: 13, type: 'string.quote.bicep' } + ] + }, + { + line: ' hello!', + tokens: [{ startIndex: 0, type: 'string.bicep' }] + }, + { + line: "'''", + tokens: [{ startIndex: 0, type: 'string.quote.bicep' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'var func = resourceGroup().location', + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 8, type: '' }, + { startIndex: 11, type: 'identifier.bicep' }, + { startIndex: 24, type: '' }, + { startIndex: 27, type: 'identifier.bicep' } + ] + }, + { + line: "var func2 = reference('Microsoft.KeyVault/vaults/secrets', func)", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 9, type: '' }, + { startIndex: 12, type: 'identifier.bicep' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'string.quote.bicep' }, + { startIndex: 23, type: 'string.bicep' }, + { startIndex: 57, type: '' }, + { startIndex: 59, type: 'identifier.bicep' }, + { startIndex: 63, type: '' } + ] + }, + { + line: 'var func3 = union({', + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 9, type: '' }, + { startIndex: 12, type: 'identifier.bicep' }, + { startIndex: 17, type: '' } + ] + }, + { + line: " 'abc': resourceGroup().id", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 7, type: '' }, + { startIndex: 9, type: 'identifier.bicep' }, + { startIndex: 22, type: '' }, + { startIndex: 25, type: 'identifier.bicep' } + ] + }, + { + line: '}, {', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: " 'def': 'test'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 7, type: '' }, + { startIndex: 9, type: 'string.quote.bicep' }, + { startIndex: 10, type: 'string.bicep' } + ] + }, + { + line: '})', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: '@allowed([', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'identifier.bicep' }, + { startIndex: 8, type: '' } + ] + }, + { + line: " 'hello!'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' } + ] + }, + { + line: " 'hi!'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' } + ] + }, + { + line: '])', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '@secure()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'identifier.bicep' }, + { startIndex: 7, type: '' } + ] + }, + { + line: "param secureParam string = 'hello!'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.bicep' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'identifier.bicep' }, + { startIndex: 24, type: '' }, + { startIndex: 27, type: 'string.quote.bicep' }, + { startIndex: 28, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: "var emojis = '💪😊😈🍕☕'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 10, type: '' }, + { startIndex: 13, type: 'string.quote.bicep' }, + { startIndex: 14, type: 'string.bicep' } + ] + }, + { + line: "var ninjaCat = '🐱‍👤'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 12, type: '' }, + { startIndex: 15, type: 'string.quote.bicep' }, + { startIndex: 16, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '/* block */', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '', + tokens: [] + }, + { + line: '/*', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '朝辞白帝彩云间', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '千里江陵一日还', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '两岸猿声啼不住', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '轻舟已过万重山', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '*/', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: '', + tokens: [] + }, + { + line: '// greek letters in comment: Π π Φ φ plus emoji 😎', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: 'var variousAlphabets = {', + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 20, type: '' } + ] + }, + { + line: " 'α': 'α'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 5, type: '' }, + { startIndex: 7, type: 'string.quote.bicep' }, + { startIndex: 8, type: 'string.bicep' } + ] + }, + { + line: " 'Ωω': [", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 6, type: '' } + ] + }, + { + line: " 'Θμ'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'string.quote.bicep' }, + { startIndex: 5, type: 'string.bicep' } + ] + }, + { + line: ' ]', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: " 'ążźćłóę': 'Cześć!'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 11, type: '' }, + { startIndex: 13, type: 'string.quote.bicep' }, + { startIndex: 14, type: 'string.bicep' } + ] + }, + { + line: " 'áéóúñü': '¡Hola!'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 10, type: '' }, + { startIndex: 12, type: 'string.quote.bicep' }, + { startIndex: 13, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: " '二头肌': '二头肌'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.quote.bicep' }, + { startIndex: 3, type: 'string.bicep' }, + { startIndex: 7, type: '' }, + { startIndex: 9, type: 'string.quote.bicep' }, + { startIndex: 10, type: 'string.bicep' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: "output concatUnicodeStrings string = concat('Θμ', '二头肌', 'α')", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.bicep' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'identifier.bicep' }, + { startIndex: 34, type: '' }, + { startIndex: 37, type: 'identifier.bicep' }, + { startIndex: 43, type: '' }, + { startIndex: 44, type: 'string.quote.bicep' }, + { startIndex: 45, type: 'string.bicep' }, + { startIndex: 48, type: '' }, + { startIndex: 50, type: 'string.quote.bicep' }, + { startIndex: 51, type: 'string.bicep' }, + { startIndex: 55, type: '' }, + { startIndex: 57, type: 'string.quote.bicep' }, + { startIndex: 58, type: 'string.bicep' }, + { startIndex: 60, type: '' } + ] + }, + { + line: "output interpolateUnicodeStrings string = 'Θμ二${emojis}头肌${ninjaCat}α'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.bicep' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'identifier.bicep' }, + { startIndex: 39, type: '' }, + { startIndex: 42, type: 'string.quote.bicep' }, + { startIndex: 43, type: 'string.bicep' }, + { startIndex: 46, type: 'delimiter.bracket.bicep' }, + { startIndex: 48, type: 'identifier.bicep' }, + { startIndex: 54, type: 'delimiter.bracket.bicep' }, + { startIndex: 55, type: 'string.bicep' }, + { startIndex: 57, type: 'delimiter.bracket.bicep' }, + { startIndex: 59, type: 'identifier.bicep' }, + { startIndex: 67, type: 'delimiter.bracket.bicep' }, + { startIndex: 68, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '// all of these should produce the same string', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: "var surrogate_char = '𐐷'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 18, type: '' }, + { startIndex: 26, type: 'string.quote.bicep' }, + { startIndex: 27, type: 'string.bicep' } + ] + }, + { + line: "var surrogate_codepoint = '\\u{10437}'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 23, type: '' }, + { startIndex: 26, type: 'string.quote.bicep' }, + { startIndex: 27, type: 'string.escape.bicep' }, + { startIndex: 36, type: 'string.bicep' } + ] + }, + { + line: "var surrogate_pairs = '\\u{D801}\\u{DC37}'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 19, type: '' }, + { startIndex: 26, type: 'string.quote.bicep' }, + { startIndex: 27, type: 'string.escape.bicep' }, + { startIndex: 43, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '// ascii escapes', + tokens: [{ startIndex: 0, type: 'comment.bicep' }] + }, + { + line: "var hello = '❆ Hello\\u{20}World\\u{21} ❁'", + tokens: [ + { startIndex: 0, type: 'keyword.bicep' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.bicep' }, + { startIndex: 9, type: '' }, + { startIndex: 12, type: 'string.quote.bicep' }, + { startIndex: 13, type: 'string.bicep' }, + { startIndex: 20, type: 'string.escape.bicep' }, + { startIndex: 26, type: 'string.bicep' }, + { startIndex: 31, type: 'string.escape.bicep' }, + { startIndex: 37, type: 'string.bicep' } + ] + }, + { + line: '', + tokens: [] + } + ] +]); diff --git a/monaco-languages/src/bicep/bicep.ts b/monaco-languages/src/bicep/bicep.ts new file mode 100644 index 00000000..4c0094c3 --- /dev/null +++ b/monaco-languages/src/bicep/bicep.ts @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import type { languages } from '../fillers/monaco-editor-core'; + +const bounded = (text: string) => `\\b${text}\\b`; + +const identifierStart = '[_a-zA-Z]'; +const identifierContinue = '[_a-zA-Z0-9]'; +const identifier = bounded(`${identifierStart}${identifierContinue}*`); + +const keywords = [ + 'targetScope', + 'resource', + 'module', + 'param', + 'var', + 'output', + 'for', + 'in', + 'if', + 'existing' +]; + +const namedLiterals = ['true', 'false', 'null']; + +const nonCommentWs = `[ \\t\\r\\n]`; + +const numericLiteral = `[0-9]+`; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'" }, + { open: "'''", close: "'''" } + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: "'''", close: "'''", notIn: ['string', 'comment'] } + ], + autoCloseBefore: ":.,=}])' \n\t", + indentationRules: { + increaseIndentPattern: new RegExp( + '^((?!\\/\\/).)*(\\{[^}"\'`]*|\\([^)"\'`]*|\\[[^\\]"\'`]*)$' + ), + decreaseIndentPattern: new RegExp('^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$') + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.bicep', + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' } + ], + + symbols: /[=> import('./cameligo') +}); diff --git a/monaco-languages/src/cameligo/cameligo.test.ts b/monaco-languages/src/cameligo/cameligo.test.ts new file mode 100644 index 00000000..2e48ecf4 --- /dev/null +++ b/monaco-languages/src/cameligo/cameligo.test.ts @@ -0,0 +1,144 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('cameligo', [ + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: 'white.cameligo' }, + { startIndex: 4, type: 'comment.cameligo' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + } + ], + + // Comments - multi line (single line) + [ + { + line: '(**)', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + } + ], + + [ + { + line: ' (* a comment *)', + tokens: [ + { startIndex: 0, type: 'white.cameligo' }, + { startIndex: 4, type: 'comment.cameligo' } + ] + } + ], + + [ + { + line: '(* a comment *)', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + } + ], + + [ + { + line: '(*sticky comment*)', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + } + ], + + // Comments - multi line (multi line) + [ + { + line: '(* start of multiline comment ', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + }, + { + line: 'a comment between curly', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + }, + { + line: 'end of multiline comment*)', + tokens: [{ startIndex: 0, type: 'comment.cameligo' }] + } + ], + + // Keywords + [ + { + line: 'let check if Current.amount', + tokens: [ + { startIndex: 0, type: 'keyword.let.cameligo' }, + { startIndex: 3, type: 'white.cameligo' }, + { startIndex: 4, type: 'identifier.cameligo' }, + { startIndex: 9, type: 'white.cameligo' }, + { startIndex: 10, type: 'keyword.if.cameligo' }, + { startIndex: 12, type: 'white.cameligo' }, + { startIndex: 13, type: 'keyword.current.cameligo' }, + { startIndex: 20, type: 'delimiter.cameligo' }, + { startIndex: 21, type: 'identifier.cameligo' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.cameligo' }] + } + ], + [ + { + line: '0;', + tokens: [ + { startIndex: 0, type: 'number.cameligo' }, + { startIndex: 1, type: 'delimiter.cameligo' } + ] + } + ], + [ + { + line: '2.4', + tokens: [{ startIndex: 0, type: 'number.float.cameligo' }] + } + ], + [ + { + line: '2.4;', + tokens: [ + { startIndex: 0, type: 'number.float.cameligo' }, + { startIndex: 3, type: 'delimiter.cameligo' } + ] + } + ], + [ + { + line: '$123FF', + tokens: [{ startIndex: 0, type: 'number.hex.cameligo' }] + } + ] +]); diff --git a/monaco-languages/src/cameligo/cameligo.ts b/monaco-languages/src/cameligo/cameligo.ts new file mode 100644 index 00000000..b4fdd1ac --- /dev/null +++ b/monaco-languages/src/cameligo/cameligo.ts @@ -0,0 +1,193 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['(*', '*)'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'], + ['<', '>'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: "'", close: "'" }, + { open: '"', close: '"' }, + { open: '(*', close: '*)' } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: "'", close: "'" }, + { open: '"', close: '"' }, + { open: '(*', close: '*)' } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.cameligo', + ignoreCase: true, + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + keywords: [ + 'abs', + 'assert', + 'block', + 'Bytes', + 'case', + 'Crypto', + 'Current', + 'else', + 'failwith', + 'false', + 'for', + 'fun', + 'if', + 'in', + 'let', + 'let%entry', + 'let%init', + 'List', + 'list', + 'Map', + 'map', + 'match', + 'match%nat', + 'mod', + 'not', + 'operation', + 'Operation', + 'of', + 'record', + 'Set', + 'set', + 'sender', + 'skip', + 'source', + 'String', + 'then', + 'to', + 'true', + 'type', + 'with' + ], + + typeKeywords: ['int', 'unit', 'string', 'tz', 'nat', 'bool'], + + operators: [ + '=', + '>', + '<', + '<=', + '>=', + '<>', + ':', + ':=', + 'and', + 'mod', + 'or', + '+', + '-', + '*', + '/', + '@', + '&', + '^', + '%', + '->', + '<-', + '&&', + '||' + ], + + // we include these common regular expressions + symbols: /[=><:@\^&|+\-*\/\^%]+/, + + // The main tokenizer for our languages + tokenizer: { + root: [ + // identifiers and keywords + [ + /[a-zA-Z_][\w]*/, + { + cases: { + '@keywords': { token: 'keyword.$0' }, + '@default': 'identifier' + } + } + ], + + // whitespace + { include: '@whitespace' }, + + // delimiters and operators + [/[{}()\[\]]/, '@brackets'], + [/[<>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], + [/\$[0-9a-fA-F]{1,16}/, 'number.hex'], + [/\d+/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/'([^'\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/'/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/'/, 'string.invalid'], + [/\#\d+/, 'string'] + ], + /* */ + + comment: [ + [/[^\(\*]+/, 'comment'], + //[/\(\*/, 'comment', '@push' ], // nested comment not allowed :-( + [/\*\)/, 'comment', '@pop'], + [/\(\*/, 'comment'] + ], + + string: [ + [/[^\\']+/, 'string'], + [/\\./, 'string.escape.invalid'], + [/'/, { token: 'string.quote', bracket: '@close', next: '@pop' }] + ], + + whitespace: [ + [/[ \t\r\n]+/, 'white'], + [/\(\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ] + } +}; diff --git a/monaco-languages/src/clojure/clojure.contribution.ts b/monaco-languages/src/clojure/clojure.contribution.ts new file mode 100644 index 00000000..139424ba --- /dev/null +++ b/monaco-languages/src/clojure/clojure.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'clojure', + extensions: ['.clj', '.cljs', '.cljc', '.edn'], + aliases: ['clojure', 'Clojure'], + loader: () => import('./clojure') +}); diff --git a/monaco-languages/src/clojure/clojure.test.ts b/monaco-languages/src/clojure/clojure.test.ts new file mode 100644 index 00000000..4046eeb3 --- /dev/null +++ b/monaco-languages/src/clojure/clojure.test.ts @@ -0,0 +1,943 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ITestItem, testTokenization } from '../test/testRunner'; + +const specialForms = [ + '.', + 'catch', + 'def', + 'do', + 'if', + 'monitor-enter', + 'monitor-exit', + 'new', + 'quote', + 'recur', + 'set!', + 'throw', + 'try', + 'var' +]; + +const coreSymbols = [ + '*', + "*'", + '*1', + '*2', + '*3', + '*agent*', + '*allow-unresolved-vars*', + '*assert*', + '*clojure-version*', + '*command-line-args*', + '*compile-files*', + '*compile-path*', + '*compiler-options*', + '*data-readers*', + '*default-data-reader-fn*', + '*e', + '*err*', + '*file*', + '*flush-on-newline*', + '*fn-loader*', + '*in*', + '*math-context*', + '*ns*', + '*out*', + '*print-dup*', + '*print-length*', + '*print-level*', + '*print-meta*', + '*print-namespace-maps*', + '*print-readably*', + '*read-eval*', + '*reader-resolver*', + '*source-path*', + '*suppress-read*', + '*unchecked-math*', + '*use-context-classloader*', + '*verbose-defrecords*', + '*warn-on-reflection*', + '+', + "+'", + '-', + "-'", + '->', + '->>', + '->ArrayChunk', + '->Eduction', + '->Vec', + '->VecNode', + '->VecSeq', + '-cache-protocol-fn', + '-reset-methods', + '..', + '/', + '<', + '<=', + '=', + '==', + '>', + '>=', + 'EMPTY-NODE', + 'Inst', + 'StackTraceElement->vec', + 'Throwable->map', + 'accessor', + 'aclone', + 'add-classpath', + 'add-watch', + 'agent', + 'agent-error', + 'agent-errors', + 'aget', + 'alength', + 'alias', + 'all-ns', + 'alter', + 'alter-meta!', + 'alter-var-root', + 'amap', + 'ancestors', + 'and', + 'any?', + 'apply', + 'areduce', + 'array-map', + 'as->', + 'aset', + 'aset-boolean', + 'aset-byte', + 'aset-char', + 'aset-double', + 'aset-float', + 'aset-int', + 'aset-long', + 'aset-short', + 'assert', + 'assoc', + 'assoc!', + 'assoc-in', + 'associative?', + 'atom', + 'await', + 'await-for', + 'await1', + 'bases', + 'bean', + 'bigdec', + 'bigint', + 'biginteger', + 'binding', + 'bit-and', + 'bit-and-not', + 'bit-clear', + 'bit-flip', + 'bit-not', + 'bit-or', + 'bit-set', + 'bit-shift-left', + 'bit-shift-right', + 'bit-test', + 'bit-xor', + 'boolean', + 'boolean-array', + 'boolean?', + 'booleans', + 'bound-fn', + 'bound-fn*', + 'bound?', + 'bounded-count', + 'butlast', + 'byte', + 'byte-array', + 'bytes', + 'bytes?', + 'case', + 'cast', + 'cat', + 'char', + 'char-array', + 'char-escape-string', + 'char-name-string', + 'char?', + 'chars', + 'chunk', + 'chunk-append', + 'chunk-buffer', + 'chunk-cons', + 'chunk-first', + 'chunk-next', + 'chunk-rest', + 'chunked-seq?', + 'class', + 'class?', + 'clear-agent-errors', + 'clojure-version', + 'coll?', + 'comment', + 'commute', + 'comp', + 'comparator', + 'compare', + 'compare-and-set!', + 'compile', + 'complement', + 'completing', + 'concat', + 'cond', + 'cond->', + 'cond->>', + 'condp', + 'conj', + 'conj!', + 'cons', + 'constantly', + 'construct-proxy', + 'contains?', + 'count', + 'counted?', + 'create-ns', + 'create-struct', + 'cycle', + 'dec', + "dec'", + 'decimal?', + 'declare', + 'dedupe', + 'default-data-readers', + 'definline', + 'definterface', + 'defmacro', + 'defmethod', + 'defmulti', + 'defn', + 'defn-', + 'defonce', + 'defprotocol', + 'defrecord', + 'defstruct', + 'deftype', + 'delay', + 'delay?', + 'deliver', + 'denominator', + 'deref', + 'derive', + 'descendants', + 'destructure', + 'disj', + 'disj!', + 'dissoc', + 'dissoc!', + 'distinct', + 'distinct?', + 'doall', + 'dorun', + 'doseq', + 'dosync', + 'dotimes', + 'doto', + 'double', + 'double-array', + 'double?', + 'doubles', + 'drop', + 'drop-last', + 'drop-while', + 'eduction', + 'empty', + 'empty?', + 'ensure', + 'ensure-reduced', + 'enumeration-seq', + 'error-handler', + 'error-mode', + 'eval', + 'even?', + 'every-pred', + 'every?', + 'ex-data', + 'ex-info', + 'extend', + 'extend-protocol', + 'extend-type', + 'extenders', + 'extends?', + 'false?', + 'ffirst', + 'file-seq', + 'filter', + 'filterv', + 'find', + 'find-keyword', + 'find-ns', + 'find-protocol-impl', + 'find-protocol-method', + 'find-var', + 'first', + 'flatten', + 'float', + 'float-array', + 'float?', + 'floats', + 'flush', + 'fn', + 'fn?', + 'fnext', + 'fnil', + 'for', + 'force', + 'format', + 'frequencies', + 'future', + 'future-call', + 'future-cancel', + 'future-cancelled?', + 'future-done?', + 'future?', + 'gen-class', + 'gen-interface', + 'gensym', + 'get', + 'get-in', + 'get-method', + 'get-proxy-class', + 'get-thread-bindings', + 'get-validator', + 'group-by', + 'halt-when', + 'hash', + 'hash-combine', + 'hash-map', + 'hash-ordered-coll', + 'hash-set', + 'hash-unordered-coll', + 'ident?', + 'identical?', + 'identity', + 'if-let', + 'if-not', + 'if-some', + 'ifn?', + 'import', + 'in-ns', + 'inc', + "inc'", + 'indexed?', + 'init-proxy', + 'inst-ms', + 'inst-ms*', + 'inst?', + 'instance?', + 'int', + 'int-array', + 'int?', + 'integer?', + 'interleave', + 'intern', + 'interpose', + 'into', + 'into-array', + 'ints', + 'io!', + 'isa?', + 'iterate', + 'iterator-seq', + 'juxt', + 'keep', + 'keep-indexed', + 'key', + 'keys', + 'keyword', + 'keyword?', + 'last', + 'lazy-cat', + 'lazy-seq', + 'let', + 'letfn', + 'line-seq', + 'list', + 'list*', + 'list?', + 'load', + 'load-file', + 'load-reader', + 'load-string', + 'loaded-libs', + 'locking', + 'long', + 'long-array', + 'longs', + 'loop', + 'macroexpand', + 'macroexpand-1', + 'make-array', + 'make-hierarchy', + 'map', + 'map-entry?', + 'map-indexed', + 'map?', + 'mapcat', + 'mapv', + 'max', + 'max-key', + 'memfn', + 'memoize', + 'merge', + 'merge-with', + 'meta', + 'method-sig', + 'methods', + 'min', + 'min-key', + 'mix-collection-hash', + 'mod', + 'munge', + 'name', + 'namespace', + 'namespace-munge', + 'nat-int?', + 'neg-int?', + 'neg?', + 'newline', + 'next', + 'nfirst', + 'nil?', + 'nnext', + 'not', + 'not-any?', + 'not-empty', + 'not-every?', + 'not=', + 'ns', + 'ns-aliases', + 'ns-imports', + 'ns-interns', + 'ns-map', + 'ns-name', + 'ns-publics', + 'ns-refers', + 'ns-resolve', + 'ns-unalias', + 'ns-unmap', + 'nth', + 'nthnext', + 'nthrest', + 'num', + 'number?', + 'numerator', + 'object-array', + 'odd?', + 'or', + 'parents', + 'partial', + 'partition', + 'partition-all', + 'partition-by', + 'pcalls', + 'peek', + 'persistent!', + 'pmap', + 'pop', + 'pop!', + 'pop-thread-bindings', + 'pos-int?', + 'pos?', + 'pr', + 'pr-str', + 'prefer-method', + 'prefers', + 'primitives-classnames', + 'print', + 'print-ctor', + 'print-dup', + 'print-method', + 'print-simple', + 'print-str', + 'printf', + 'println', + 'println-str', + 'prn', + 'prn-str', + 'promise', + 'proxy', + 'proxy-call-with-super', + 'proxy-mappings', + 'proxy-name', + 'proxy-super', + 'push-thread-bindings', + 'pvalues', + 'qualified-ident?', + 'qualified-keyword?', + 'qualified-symbol?', + 'quot', + 'rand', + 'rand-int', + 'rand-nth', + 'random-sample', + 'range', + 'ratio?', + 'rational?', + 'rationalize', + 're-find', + 're-groups', + 're-matcher', + 're-matches', + 're-pattern', + 're-seq', + 'read', + 'read-line', + 'read-string', + 'reader-conditional', + 'reader-conditional?', + 'realized?', + 'record?', + 'reduce', + 'reduce-kv', + 'reduced', + 'reduced?', + 'reductions', + 'ref', + 'ref-history-count', + 'ref-max-history', + 'ref-min-history', + 'ref-set', + 'refer', + 'refer-clojure', + 'reify', + 'release-pending-sends', + 'rem', + 'remove', + 'remove-all-methods', + 'remove-method', + 'remove-ns', + 'remove-watch', + 'repeat', + 'repeatedly', + 'replace', + 'replicate', + 'require', + 'reset!', + 'reset-meta!', + 'reset-vals!', + 'resolve', + 'rest', + 'restart-agent', + 'resultset-seq', + 'reverse', + 'reversible?', + 'rseq', + 'rsubseq', + 'run!', + 'satisfies?', + 'second', + 'select-keys', + 'send', + 'send-off', + 'send-via', + 'seq', + 'seq?', + 'seqable?', + 'seque', + 'sequence', + 'sequential?', + 'set', + 'set-agent-send-executor!', + 'set-agent-send-off-executor!', + 'set-error-handler!', + 'set-error-mode!', + 'set-validator!', + 'set?', + 'short', + 'short-array', + 'shorts', + 'shuffle', + 'shutdown-agents', + 'simple-ident?', + 'simple-keyword?', + 'simple-symbol?', + 'slurp', + 'some', + 'some->', + 'some->>', + 'some-fn', + 'some?', + 'sort', + 'sort-by', + 'sorted-map', + 'sorted-map-by', + 'sorted-set', + 'sorted-set-by', + 'sorted?', + 'special-symbol?', + 'spit', + 'split-at', + 'split-with', + 'str', + 'string?', + 'struct', + 'struct-map', + 'subs', + 'subseq', + 'subvec', + 'supers', + 'swap!', + 'swap-vals!', + 'symbol', + 'symbol?', + 'sync', + 'tagged-literal', + 'tagged-literal?', + 'take', + 'take-last', + 'take-nth', + 'take-while', + 'test', + 'the-ns', + 'thread-bound?', + 'time', + 'to-array', + 'to-array-2d', + 'trampoline', + 'transduce', + 'transient', + 'tree-seq', + 'true?', + 'type', + 'unchecked-add', + 'unchecked-add-int', + 'unchecked-byte', + 'unchecked-char', + 'unchecked-dec', + 'unchecked-dec-int', + 'unchecked-divide-int', + 'unchecked-double', + 'unchecked-float', + 'unchecked-inc', + 'unchecked-inc-int', + 'unchecked-int', + 'unchecked-long', + 'unchecked-multiply', + 'unchecked-multiply-int', + 'unchecked-negate', + 'unchecked-negate-int', + 'unchecked-remainder-int', + 'unchecked-short', + 'unchecked-subtract', + 'unchecked-subtract-int', + 'underive', + 'unquote', + 'unquote-splicing', + 'unreduced', + 'unsigned-bit-shift-right', + 'update', + 'update-in', + 'update-proxy', + 'uri?', + 'use', + 'uuid?', + 'val', + 'vals', + 'var-get', + 'var-set', + 'var?', + 'vary-meta', + 'vec', + 'vector', + 'vector-of', + 'vector?', + 'volatile!', + 'volatile?', + 'vreset!', + 'vswap!', + 'when', + 'when-first', + 'when-let', + 'when-not', + 'when-some', + 'while', + 'with-bindings', + 'with-bindings*', + 'with-in-str', + 'with-loading-context', + 'with-local-vars', + 'with-meta', + 'with-open', + 'with-out-str', + 'with-precision', + 'with-redefs', + 'with-redefs-fn', + 'xml-seq', + 'zero?', + 'zipmap' +]; + +function createTestCases(specialForms: string[], type: string): ITestItem[] { + const testCases = []; + + for (const specialForm of specialForms) { + testCases.push({ + line: `${specialForm}`, + tokens: [{ startIndex: 0, type: `${type}.clj` }] + }); + } + + return testCases; +} + +testTokenization('clojure', [ + // special forms + createTestCases(specialForms, 'keyword'), + + // core symbols + createTestCases(coreSymbols, 'keyword'), + + // atoms + createTestCases(['false', 'nil', 'true'], 'constant'), + + // keywords + createTestCases([':foo', '::bar', ':foo/bar', ':foo.bar/baz'], 'constant'), + + // numbers + createTestCases( + [ + '42', + '+42', + '-421', + '42N', + '+42N', + '-42N', + '0.42', + '+0.42', + '-0.42', + '42M', + '+42M', + '-42M', + '42.42M', + '+42.42M', + '-42.42M', + '1/42', + '+1/42', + '-1/42', + '0x42af', + '+0x42af', + '-0x42af', + '0x42AF', + '+0x42AF', + '-0x42AF', + '1e2', + '1e+2', + '1e-2', + '+1e2', + '+1e+2', + '+1e-2', + '-1e2', + '-1e+2', + '-1e-2', + '-1.0e2', + '-0.1e+2', + '-1.01e-2', + '1E2', + '1E+2', + '1E-2', + '+1E2', + '+1E+2', + '+1E-2', + '-1E2', + '-1E+2', + '-1E-2', + '-1.0E2', + '-0.1E+2', + '-1.01E-2', + '2r101010', + '+2r101010', + '-2r101010', + '2r101010', + '+2r101010', + '-2r101010', + '8r52', + '+8r52', + '-8r52', + '36rhello', + '+36rhello', + '-36rhello', + '36rz', + '+36rz', + '-36rz', + '36rZ', + '+36rZ', + '-36rZ' + ], + 'number' + ), + + // characters + createTestCases( + [ + '\\1', + '\\a', + '\\#', + '\\\\', + '\\"', + '\\(', + '\\A', + '\\backspace', + '\\formfeed', + '\\newline', + '\\space', + '\\return', + '\\tab', + '\\o123', + '\\u1000', + '\\uAaAa', + '\\u9F9F' + ], + 'string' + ), + + // strings + [ + { + line: '"I\'m a little teapot."', + tokens: [{ startIndex: 0, type: 'string.clj' }] + }, + { + line: '"I\'m a \\"little\\" teapot."', + tokens: [ + { startIndex: 0, type: 'string.clj' }, + { startIndex: 7, type: 'string.escape.clj' }, + { startIndex: 9, type: 'string.clj' }, + { startIndex: 15, type: 'string.escape.clj' }, + { startIndex: 17, type: 'string.clj' } + ] + } + ], + + // multi-line strings + [ + { + line: '"I\'m', + tokens: [{ startIndex: 0, type: 'string.clj' }] + }, + { + line: '\\"a little\\"', + tokens: [ + { startIndex: 0, type: 'string.escape.clj' }, + { startIndex: 2, type: 'string.clj' }, + { startIndex: 10, type: 'string.escape.clj' } + ] + }, + { + line: 'teapot."', + tokens: [{ startIndex: 0, type: 'string.clj' }] + } + ], + + // strings with other escapes in them (\" \' \\ \b \f \n \r \t) + [ + { + line: '"the escape \\" \\\' \\\\ \\b \\f \\n \\r \\t characters"', + tokens: [ + { startIndex: 0, type: 'string.clj' }, + { startIndex: 12, type: 'string.escape.clj' }, + { startIndex: 14, type: 'string.clj' }, + { startIndex: 15, type: 'string.escape.clj' }, + { startIndex: 17, type: 'string.clj' }, + { startIndex: 18, type: 'string.escape.clj' }, + { startIndex: 20, type: 'string.clj' }, + { startIndex: 21, type: 'string.escape.clj' }, + { startIndex: 23, type: 'string.clj' }, + { startIndex: 24, type: 'string.escape.clj' }, + { startIndex: 26, type: 'string.clj' }, + { startIndex: 27, type: 'string.escape.clj' }, + { startIndex: 29, type: 'string.clj' }, + { startIndex: 30, type: 'string.escape.clj' }, + { startIndex: 32, type: 'string.clj' }, + { startIndex: 33, type: 'string.escape.clj' }, + { startIndex: 35, type: 'string.clj' } + ] + } + ], + + // comments + createTestCases(['; this is an in-line comment.', ';; this is a line comment.'], 'comment'), + + // `comment` + [ + { + line: '(comment)', + tokens: [{ startIndex: 0, type: 'comment.clj' }] + }, + { + line: 'foo :bar 42', + tokens: [ + { startIndex: 0, type: 'identifier.clj' }, + { startIndex: 3, type: 'white.clj' }, + { startIndex: 4, type: 'constant.clj' }, + { startIndex: 8, type: 'white.clj' }, + { startIndex: 9, type: 'number.clj' } + ] + }, + { + line: '(comment (foo [bar :baz 1 "qux"]))', + tokens: [{ startIndex: 0, type: 'comment.clj' }] + }, + { + line: '(comments foo bar)', + tokens: [ + { startIndex: 0, type: 'delimiter.parenthesis.clj' }, + { startIndex: 1, type: 'identifier.clj' }, + { startIndex: 9, type: 'white.clj' }, + { startIndex: 10, type: 'identifier.clj' }, + { startIndex: 13, type: 'white.clj' }, + { startIndex: 14, type: 'identifier.clj' }, + { startIndex: 17, type: 'delimiter.parenthesis.clj' } + ] + }, + { + line: '(comment6 foo bar)', + tokens: [ + { startIndex: 0, type: 'delimiter.parenthesis.clj' }, + { startIndex: 1, type: 'identifier.clj' }, + { startIndex: 9, type: 'white.clj' }, + { startIndex: 10, type: 'identifier.clj' }, + { startIndex: 13, type: 'white.clj' }, + { startIndex: 14, type: 'identifier.clj' }, + { startIndex: 17, type: 'delimiter.parenthesis.clj' } + ] + }, + { + line: '(comment foo', + tokens: [{ startIndex: 0, type: 'comment.clj' }] + }, + { + line: 'foo', + tokens: [{ startIndex: 0, type: 'comment.clj' }] + } + ], + + // reader macro characters + createTestCases(['#', '@', '^', '`', '~', "'"], 'meta'), + + // treat comma as whitespace + [ + { + line: ', foo, :bar, "one", 2, ', + tokens: [ + { startIndex: 0, type: 'white.clj' }, + { startIndex: 2, type: 'identifier.clj' }, + { startIndex: 5, type: 'white.clj' }, + { startIndex: 7, type: 'constant.clj' }, + { startIndex: 11, type: 'white.clj' }, + { startIndex: 13, type: 'string.clj' }, + { startIndex: 18, type: 'white.clj' }, + { startIndex: 20, type: 'number.clj' }, + { startIndex: 21, type: 'white.clj' } + ] + } + ] +]); diff --git a/monaco-languages/src/clojure/clojure.ts b/monaco-languages/src/clojure/clojure.ts new file mode 100644 index 00000000..1eaa55f9 --- /dev/null +++ b/monaco-languages/src/clojure/clojure.ts @@ -0,0 +1,792 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: ';;' + }, + + brackets: [ + ['[', ']'], + ['(', ')'], + ['{', '}'] + ], + + autoClosingPairs: [ + { open: '[', close: ']' }, + { open: '"', close: '"' }, + { open: '(', close: ')' }, + { open: '{', close: '}' } + ], + + surroundingPairs: [ + { open: '[', close: ']' }, + { open: '"', close: '"' }, + { open: '(', close: ')' }, + { open: '{', close: '}' } + ] +}; + +export const language = { + defaultToken: '', + ignoreCase: true, + tokenPostfix: '.clj', + + brackets: [ + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '{', close: '}', token: 'delimiter.curly' } + ], + + constants: ['true', 'false', 'nil'], + + // delimiters: /[\\\[\]\s"#'(),;@^`{}~]|$/, + + numbers: + /^(?:[+\-]?\d+(?:(?:N|(?:[eE][+\-]?\d+))|(?:\.?\d*(?:M|(?:[eE][+\-]?\d+))?)|\/\d+|[xX][0-9a-fA-F]+|r[0-9a-zA-Z]+)?(?=[\\\[\]\s"#'(),;@^`{}~]|$))/, + + characters: + /^(?:\\(?:backspace|formfeed|newline|return|space|tab|o[0-7]{3}|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{4}|.)?(?=[\\\[\]\s"(),;@^`{}~]|$))/, + + escapes: /^\\(?:["'\\bfnrt]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, + + // simple-namespace := /^[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*/ + // simple-symbol := /^(?:\/|[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*)/ + // qualified-symbol := ((<.>)*)? + qualifiedSymbols: + /^(?:(?:[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*(?:\.[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*)*\/)?(?:\/|[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*)*(?=[\\\[\]\s"(),;@^`{}~]|$))/, + + specialForms: [ + '.', + 'catch', + 'def', + 'do', + 'if', + 'monitor-enter', + 'monitor-exit', + 'new', + 'quote', + 'recur', + 'set!', + 'throw', + 'try', + 'var' + ], + + coreSymbols: [ + '*', + "*'", + '*1', + '*2', + '*3', + '*agent*', + '*allow-unresolved-vars*', + '*assert*', + '*clojure-version*', + '*command-line-args*', + '*compile-files*', + '*compile-path*', + '*compiler-options*', + '*data-readers*', + '*default-data-reader-fn*', + '*e', + '*err*', + '*file*', + '*flush-on-newline*', + '*fn-loader*', + '*in*', + '*math-context*', + '*ns*', + '*out*', + '*print-dup*', + '*print-length*', + '*print-level*', + '*print-meta*', + '*print-namespace-maps*', + '*print-readably*', + '*read-eval*', + '*reader-resolver*', + '*source-path*', + '*suppress-read*', + '*unchecked-math*', + '*use-context-classloader*', + '*verbose-defrecords*', + '*warn-on-reflection*', + '+', + "+'", + '-', + "-'", + '->', + '->>', + '->ArrayChunk', + '->Eduction', + '->Vec', + '->VecNode', + '->VecSeq', + '-cache-protocol-fn', + '-reset-methods', + '..', + '/', + '<', + '<=', + '=', + '==', + '>', + '>=', + 'EMPTY-NODE', + 'Inst', + 'StackTraceElement->vec', + 'Throwable->map', + 'accessor', + 'aclone', + 'add-classpath', + 'add-watch', + 'agent', + 'agent-error', + 'agent-errors', + 'aget', + 'alength', + 'alias', + 'all-ns', + 'alter', + 'alter-meta!', + 'alter-var-root', + 'amap', + 'ancestors', + 'and', + 'any?', + 'apply', + 'areduce', + 'array-map', + 'as->', + 'aset', + 'aset-boolean', + 'aset-byte', + 'aset-char', + 'aset-double', + 'aset-float', + 'aset-int', + 'aset-long', + 'aset-short', + 'assert', + 'assoc', + 'assoc!', + 'assoc-in', + 'associative?', + 'atom', + 'await', + 'await-for', + 'await1', + 'bases', + 'bean', + 'bigdec', + 'bigint', + 'biginteger', + 'binding', + 'bit-and', + 'bit-and-not', + 'bit-clear', + 'bit-flip', + 'bit-not', + 'bit-or', + 'bit-set', + 'bit-shift-left', + 'bit-shift-right', + 'bit-test', + 'bit-xor', + 'boolean', + 'boolean-array', + 'boolean?', + 'booleans', + 'bound-fn', + 'bound-fn*', + 'bound?', + 'bounded-count', + 'butlast', + 'byte', + 'byte-array', + 'bytes', + 'bytes?', + 'case', + 'cast', + 'cat', + 'char', + 'char-array', + 'char-escape-string', + 'char-name-string', + 'char?', + 'chars', + 'chunk', + 'chunk-append', + 'chunk-buffer', + 'chunk-cons', + 'chunk-first', + 'chunk-next', + 'chunk-rest', + 'chunked-seq?', + 'class', + 'class?', + 'clear-agent-errors', + 'clojure-version', + 'coll?', + 'comment', + 'commute', + 'comp', + 'comparator', + 'compare', + 'compare-and-set!', + 'compile', + 'complement', + 'completing', + 'concat', + 'cond', + 'cond->', + 'cond->>', + 'condp', + 'conj', + 'conj!', + 'cons', + 'constantly', + 'construct-proxy', + 'contains?', + 'count', + 'counted?', + 'create-ns', + 'create-struct', + 'cycle', + 'dec', + "dec'", + 'decimal?', + 'declare', + 'dedupe', + 'default-data-readers', + 'definline', + 'definterface', + 'defmacro', + 'defmethod', + 'defmulti', + 'defn', + 'defn-', + 'defonce', + 'defprotocol', + 'defrecord', + 'defstruct', + 'deftype', + 'delay', + 'delay?', + 'deliver', + 'denominator', + 'deref', + 'derive', + 'descendants', + 'destructure', + 'disj', + 'disj!', + 'dissoc', + 'dissoc!', + 'distinct', + 'distinct?', + 'doall', + 'dorun', + 'doseq', + 'dosync', + 'dotimes', + 'doto', + 'double', + 'double-array', + 'double?', + 'doubles', + 'drop', + 'drop-last', + 'drop-while', + 'eduction', + 'empty', + 'empty?', + 'ensure', + 'ensure-reduced', + 'enumeration-seq', + 'error-handler', + 'error-mode', + 'eval', + 'even?', + 'every-pred', + 'every?', + 'ex-data', + 'ex-info', + 'extend', + 'extend-protocol', + 'extend-type', + 'extenders', + 'extends?', + 'false?', + 'ffirst', + 'file-seq', + 'filter', + 'filterv', + 'find', + 'find-keyword', + 'find-ns', + 'find-protocol-impl', + 'find-protocol-method', + 'find-var', + 'first', + 'flatten', + 'float', + 'float-array', + 'float?', + 'floats', + 'flush', + 'fn', + 'fn?', + 'fnext', + 'fnil', + 'for', + 'force', + 'format', + 'frequencies', + 'future', + 'future-call', + 'future-cancel', + 'future-cancelled?', + 'future-done?', + 'future?', + 'gen-class', + 'gen-interface', + 'gensym', + 'get', + 'get-in', + 'get-method', + 'get-proxy-class', + 'get-thread-bindings', + 'get-validator', + 'group-by', + 'halt-when', + 'hash', + 'hash-combine', + 'hash-map', + 'hash-ordered-coll', + 'hash-set', + 'hash-unordered-coll', + 'ident?', + 'identical?', + 'identity', + 'if-let', + 'if-not', + 'if-some', + 'ifn?', + 'import', + 'in-ns', + 'inc', + "inc'", + 'indexed?', + 'init-proxy', + 'inst-ms', + 'inst-ms*', + 'inst?', + 'instance?', + 'int', + 'int-array', + 'int?', + 'integer?', + 'interleave', + 'intern', + 'interpose', + 'into', + 'into-array', + 'ints', + 'io!', + 'isa?', + 'iterate', + 'iterator-seq', + 'juxt', + 'keep', + 'keep-indexed', + 'key', + 'keys', + 'keyword', + 'keyword?', + 'last', + 'lazy-cat', + 'lazy-seq', + 'let', + 'letfn', + 'line-seq', + 'list', + 'list*', + 'list?', + 'load', + 'load-file', + 'load-reader', + 'load-string', + 'loaded-libs', + 'locking', + 'long', + 'long-array', + 'longs', + 'loop', + 'macroexpand', + 'macroexpand-1', + 'make-array', + 'make-hierarchy', + 'map', + 'map-entry?', + 'map-indexed', + 'map?', + 'mapcat', + 'mapv', + 'max', + 'max-key', + 'memfn', + 'memoize', + 'merge', + 'merge-with', + 'meta', + 'method-sig', + 'methods', + 'min', + 'min-key', + 'mix-collection-hash', + 'mod', + 'munge', + 'name', + 'namespace', + 'namespace-munge', + 'nat-int?', + 'neg-int?', + 'neg?', + 'newline', + 'next', + 'nfirst', + 'nil?', + 'nnext', + 'not', + 'not-any?', + 'not-empty', + 'not-every?', + 'not=', + 'ns', + 'ns-aliases', + 'ns-imports', + 'ns-interns', + 'ns-map', + 'ns-name', + 'ns-publics', + 'ns-refers', + 'ns-resolve', + 'ns-unalias', + 'ns-unmap', + 'nth', + 'nthnext', + 'nthrest', + 'num', + 'number?', + 'numerator', + 'object-array', + 'odd?', + 'or', + 'parents', + 'partial', + 'partition', + 'partition-all', + 'partition-by', + 'pcalls', + 'peek', + 'persistent!', + 'pmap', + 'pop', + 'pop!', + 'pop-thread-bindings', + 'pos-int?', + 'pos?', + 'pr', + 'pr-str', + 'prefer-method', + 'prefers', + 'primitives-classnames', + 'print', + 'print-ctor', + 'print-dup', + 'print-method', + 'print-simple', + 'print-str', + 'printf', + 'println', + 'println-str', + 'prn', + 'prn-str', + 'promise', + 'proxy', + 'proxy-call-with-super', + 'proxy-mappings', + 'proxy-name', + 'proxy-super', + 'push-thread-bindings', + 'pvalues', + 'qualified-ident?', + 'qualified-keyword?', + 'qualified-symbol?', + 'quot', + 'rand', + 'rand-int', + 'rand-nth', + 'random-sample', + 'range', + 'ratio?', + 'rational?', + 'rationalize', + 're-find', + 're-groups', + 're-matcher', + 're-matches', + 're-pattern', + 're-seq', + 'read', + 'read-line', + 'read-string', + 'reader-conditional', + 'reader-conditional?', + 'realized?', + 'record?', + 'reduce', + 'reduce-kv', + 'reduced', + 'reduced?', + 'reductions', + 'ref', + 'ref-history-count', + 'ref-max-history', + 'ref-min-history', + 'ref-set', + 'refer', + 'refer-clojure', + 'reify', + 'release-pending-sends', + 'rem', + 'remove', + 'remove-all-methods', + 'remove-method', + 'remove-ns', + 'remove-watch', + 'repeat', + 'repeatedly', + 'replace', + 'replicate', + 'require', + 'reset!', + 'reset-meta!', + 'reset-vals!', + 'resolve', + 'rest', + 'restart-agent', + 'resultset-seq', + 'reverse', + 'reversible?', + 'rseq', + 'rsubseq', + 'run!', + 'satisfies?', + 'second', + 'select-keys', + 'send', + 'send-off', + 'send-via', + 'seq', + 'seq?', + 'seqable?', + 'seque', + 'sequence', + 'sequential?', + 'set', + 'set-agent-send-executor!', + 'set-agent-send-off-executor!', + 'set-error-handler!', + 'set-error-mode!', + 'set-validator!', + 'set?', + 'short', + 'short-array', + 'shorts', + 'shuffle', + 'shutdown-agents', + 'simple-ident?', + 'simple-keyword?', + 'simple-symbol?', + 'slurp', + 'some', + 'some->', + 'some->>', + 'some-fn', + 'some?', + 'sort', + 'sort-by', + 'sorted-map', + 'sorted-map-by', + 'sorted-set', + 'sorted-set-by', + 'sorted?', + 'special-symbol?', + 'spit', + 'split-at', + 'split-with', + 'str', + 'string?', + 'struct', + 'struct-map', + 'subs', + 'subseq', + 'subvec', + 'supers', + 'swap!', + 'swap-vals!', + 'symbol', + 'symbol?', + 'sync', + 'tagged-literal', + 'tagged-literal?', + 'take', + 'take-last', + 'take-nth', + 'take-while', + 'test', + 'the-ns', + 'thread-bound?', + 'time', + 'to-array', + 'to-array-2d', + 'trampoline', + 'transduce', + 'transient', + 'tree-seq', + 'true?', + 'type', + 'unchecked-add', + 'unchecked-add-int', + 'unchecked-byte', + 'unchecked-char', + 'unchecked-dec', + 'unchecked-dec-int', + 'unchecked-divide-int', + 'unchecked-double', + 'unchecked-float', + 'unchecked-inc', + 'unchecked-inc-int', + 'unchecked-int', + 'unchecked-long', + 'unchecked-multiply', + 'unchecked-multiply-int', + 'unchecked-negate', + 'unchecked-negate-int', + 'unchecked-remainder-int', + 'unchecked-short', + 'unchecked-subtract', + 'unchecked-subtract-int', + 'underive', + 'unquote', + 'unquote-splicing', + 'unreduced', + 'unsigned-bit-shift-right', + 'update', + 'update-in', + 'update-proxy', + 'uri?', + 'use', + 'uuid?', + 'val', + 'vals', + 'var-get', + 'var-set', + 'var?', + 'vary-meta', + 'vec', + 'vector', + 'vector-of', + 'vector?', + 'volatile!', + 'volatile?', + 'vreset!', + 'vswap!', + 'when', + 'when-first', + 'when-let', + 'when-not', + 'when-some', + 'while', + 'with-bindings', + 'with-bindings*', + 'with-in-str', + 'with-loading-context', + 'with-local-vars', + 'with-meta', + 'with-open', + 'with-out-str', + 'with-precision', + 'with-redefs', + 'with-redefs-fn', + 'xml-seq', + 'zero?', + 'zipmap' + ], + + tokenizer: { + root: [ + // whitespaces and comments + { include: '@whitespace' }, + + // numbers + [/@numbers/, 'number'], + + // characters + [/@characters/, 'string'], + + // strings + { include: '@string' }, + + // brackets + [/[()\[\]{}]/, '@brackets'], + + // regular expressions + [/\/#"(?:\.|(?:")|[^"\n])*"\/g/, 'regexp'], + + // reader macro characters + [/[#'@^`~]/, 'meta'], + + // symbols + [ + /@qualifiedSymbols/, + { + cases: { + '^:.+$': 'constant', // Clojure keywords (e.g., `:foo/bar`) + '@specialForms': 'keyword', + '@coreSymbols': 'keyword', + '@constants': 'constant', + '@default': 'identifier' + } + } + ] + ], + + whitespace: [ + [/[\s,]+/, 'white'], + [/;.*$/, 'comment'], + [/\(comment\b/, 'comment', '@comment'] + ], + + comment: [ + [/\(/, 'comment', '@push'], + [/\)/, 'comment', '@pop'], + [/[^()]/, 'comment'] + ], + + string: [[/"/, 'string', '@multiLineString']], + + multiLineString: [ + [/"/, 'string', '@popall'], + [/@escapes/, 'string.escape'], + [/./, 'string'] + ] + } +}; diff --git a/monaco-languages/src/coffee/coffee.contribution.ts b/monaco-languages/src/coffee/coffee.contribution.ts new file mode 100644 index 00000000..6af9a015 --- /dev/null +++ b/monaco-languages/src/coffee/coffee.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'coffeescript', + extensions: ['.coffee'], + aliases: ['CoffeeScript', 'coffeescript', 'coffee'], + mimetypes: ['text/x-coffeescript', 'text/coffeescript'], + loader: () => import('./coffee') +}); diff --git a/monaco-languages/src/coffee/coffee.test.ts b/monaco-languages/src/coffee/coffee.test.ts new file mode 100644 index 00000000..4008060c --- /dev/null +++ b/monaco-languages/src/coffee/coffee.test.ts @@ -0,0 +1,2363 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('coffeescript', [ + // Comments + [ + { + line: '#', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + } + ], + + [ + { + line: ' # a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.coffee' } + ] + } + ], + + [ + { + line: '# a comment', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + } + ], + + [ + { + line: '#sticky comment', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + } + ], + + [ + { + line: 'x = 1 # my comment # is a nice one', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'comment.coffee' } + ] + } + ], + + [ + { + line: 'x = 1e #is a exponent number', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.float.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.coffee' } + ] + } + ], + + [ + { + line: 'x = 0x1F #is a hex number', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.hex.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'comment.coffee' } + ] + } + ], + + // Keywords + [ + { + line: 'new x = switch()', + tokens: [ + { startIndex: 0, type: 'keyword.new.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'keyword.switch.coffee' }, + { startIndex: 14, type: 'delimiter.parenthesis.coffee' } + ] + } + ], + + [ + { + line: '@test [do]', + tokens: [ + { startIndex: 0, type: 'variable.predefined.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.square.coffee' }, + { startIndex: 7, type: 'keyword.do.coffee' }, + { startIndex: 9, type: 'delimiter.square.coffee' } + ] + } + ], + + [ + { + line: 'this do', + tokens: [ + { startIndex: 0, type: 'variable.predefined.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'keyword.do.coffee' } + ] + } + ], + + [ + { + line: ' new ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.new.coffee' }, + { startIndex: 7, type: '' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '### a simple comment ###', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + } + ], + + [ + { + line: 'new x = ### a simple comment ### 1', + tokens: [ + { startIndex: 0, type: 'keyword.new.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.coffee' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'number.coffee' } + ] + } + ], + + [ + { + line: 'new x = ### comment ### 1 ###', + tokens: [ + { startIndex: 0, type: 'keyword.new.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.coffee' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'number.coffee' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'comment.coffee' } + ] + } + ], + + [ + { + line: 'x = ######s', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.coffee' }, + { startIndex: 10, type: '' } + ] + } + ], + + [ + { + line: 'x = ###/', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.coffee' } + ] + } + ], + + // Comments - range comment, multi lines + [ + { + line: '### a multiline comment', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'can actually span', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'multiple lines ###', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + } + ], + + [ + { + line: 'new x = ### start a comment', + tokens: [ + { startIndex: 0, type: 'keyword.new.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.coffee' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'and end it ### new a = 2;', + tokens: [ + { startIndex: 0, type: 'comment.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'keyword.new.coffee' }, + { startIndex: 18, type: '' }, + { startIndex: 21, type: 'delimiter.coffee' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'number.coffee' }, + { startIndex: 24, type: '' } + ] + } + ], + + // Block Strings + [ + { + line: "b('''asdads''')", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 2, type: 'string.coffee' }, + { startIndex: 14, type: 'delimiter.parenthesis.coffee' } + ] + } + ], + + [ + { + line: 'foo(""" var i = \'foo\'; """)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 4, type: 'string.coffee' }, + { startIndex: 26, type: 'delimiter.parenthesis.coffee' } + ] + } + ], + + // Strings + [ + { + line: "for a = 'a';", + tokens: [ + { startIndex: 0, type: 'keyword.for.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.coffee' }, + { startIndex: 11, type: '' } + ] + } + ], + + [ + { + line: '"use strict";', + tokens: [ + { startIndex: 0, type: 'string.coffee' }, + { startIndex: 12, type: '' } + ] + } + ], + + [ + { + line: 'b = a + " \'cool\' "', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.coffee' } + ] + } + ], + + [ + { + line: '"escaping \\"quotes\\" is cool"', + tokens: [ + { startIndex: 0, type: 'string.coffee' }, + { startIndex: 10, type: 'string.escape.coffee' }, + { startIndex: 12, type: 'string.coffee' }, + { startIndex: 18, type: 'string.escape.coffee' }, + { startIndex: 20, type: 'string.coffee' } + ] + } + ], + + [ + { + line: "'''", + tokens: [{ startIndex: 0, type: 'string.coffee' }] + } + ], + + [ + { + line: "'\\''", + tokens: [ + { startIndex: 0, type: 'string.coffee' }, + { startIndex: 1, type: 'string.escape.coffee' }, + { startIndex: 3, type: 'string.coffee' } + ] + } + ], + + [ + { + line: "'be careful \\not to escape'", + tokens: [ + { startIndex: 0, type: 'string.coffee' }, + { startIndex: 12, type: 'string.escape.coffee' }, + { startIndex: 14, type: 'string.coffee' } + ] + } + ], + + // Strings - multiline + [ + { + line: "'a multiline string", + tokens: [{ startIndex: 0, type: 'string.coffee' }] + }, + { + line: 'second line', + tokens: [{ startIndex: 0, type: 'string.coffee' }] + } + ], + + // Strings - with nested code + [ + { + line: '"for a = \'a\'; #{ new } works"', + tokens: [ + { startIndex: 0, type: 'string.coffee' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'keyword.new.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'string.coffee' } + ] + } + ], + + [ + { + line: '"a comment with nested code #{ 2 / 3 } works"', + tokens: [ + { startIndex: 0, type: 'string.coffee' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.coffee' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'delimiter.coffee' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'number.coffee' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'string.coffee' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.coffee' }] + } + ], + + [ + { + line: ' 0', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'number.coffee' } + ] + } + ], + + [ + { + line: ' 0 ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'number.coffee' }, + { startIndex: 2, type: '' } + ] + } + ], + + [ + { + line: '0 ', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 1, type: '' } + ] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 1, type: 'delimiter.coffee' }, + { startIndex: 2, type: 'number.coffee' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 3, type: 'delimiter.coffee' }, + { startIndex: 4, type: 'number.coffee' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.coffee' } + ] + } + ], + + [ + { + line: '0123', + tokens: [{ startIndex: 0, type: 'number.octal.coffee' }] + } + ], + + [ + { + line: '01239', + tokens: [{ startIndex: 0, type: 'number.coffee' }] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.coffee' }] + } + ], + + [ + { + line: '[1,2,3]', + tokens: [ + { startIndex: 0, type: 'delimiter.square.coffee' }, + { startIndex: 1, type: 'number.coffee' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: 'number.coffee' }, + { startIndex: 4, type: 'delimiter.coffee' }, + { startIndex: 5, type: 'number.coffee' }, + { startIndex: 6, type: 'delimiter.square.coffee' } + ] + } + ], + + [ + { + line: 'foo(123);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 4, type: 'number.coffee' }, + { startIndex: 7, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 8, type: '' } + ] + } + ], + + [ + { + line: '(a:(b:[]))', + tokens: [ + { startIndex: 0, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: 'delimiter.square.coffee' }, + { startIndex: 8, type: 'delimiter.parenthesis.coffee' } + ] + } + ], + + [ + { + line: "x = '[{()}]'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.coffee' } + ] + } + ], + + // Regular Expressions + [ + { + line: '#', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + } + ], + + [ + { + line: '/ /', + tokens: [{ startIndex: 0, type: 'regexp.coffee' }] + } + ], + + [ + { + line: '/abc\\/asd/', + tokens: [{ startIndex: 0, type: 'regexp.coffee' }] + } + ], + + [ + { + line: 'new r = /sweet"regular exp" \\/ cool/;', + tokens: [ + { startIndex: 0, type: 'keyword.new.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'regexp.coffee' }, + { startIndex: 36, type: '' } + ] + } + ], + + [ + { + line: '5 / 3;', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.coffee' }, + { startIndex: 5, type: '' } + ] + } + ], + + // Regex - range regex, multi lines + [ + { + line: '/// a multiline regex', + tokens: [{ startIndex: 0, type: 'regexp.coffee' }] + }, + { + line: 'can actually span', + tokens: [{ startIndex: 0, type: 'regexp.coffee' }] + }, + { + line: 'multiplelines with # comments', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 19, type: 'comment.coffee' } + ] + }, + { + line: 'multiple lines ///', + tokens: [{ startIndex: 0, type: 'regexp.coffee' }] + } + ], + + // Regex - multi lines followed by #comment + [ + { + line: '///', + tokens: [{ startIndex: 0, type: 'regexp.coffee' }] + }, + { + line: '#comment', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + } + ], + + // Advanced regular expressions + [ + { + line: '1 / 2; # comment', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 7, type: 'comment.coffee' } + ] + } + ], + + [ + { + line: '1 / 2 / x / b;', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 10, type: 'delimiter.coffee' }, + { startIndex: 11, type: '' } + ] + } + ], + + [ + { + line: 'a /ads/ b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' } + ] + } + ], + + [ + { + line: "x = /foo/.test('')", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'regexp.coffee' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 14, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 15, type: 'string.coffee' }, + { startIndex: 17, type: 'delimiter.parenthesis.coffee' } + ] + } + ], + + [ + { + line: 'x = 1 + f(2 / 3, /foo/)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 9, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 10, type: 'number.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.coffee' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.coffee' }, + { startIndex: 15, type: 'delimiter.coffee' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'regexp.coffee' }, + { startIndex: 22, type: 'delimiter.parenthesis.coffee' } + ] + } + ], + + [ + { + line: '1/(2/3)/2/3;', + tokens: [ + { startIndex: 0, type: 'number.coffee' }, + { startIndex: 1, type: 'delimiter.coffee' }, + { startIndex: 2, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 3, type: 'number.coffee' }, + { startIndex: 4, type: 'delimiter.coffee' }, + { startIndex: 5, type: 'number.coffee' }, + { startIndex: 6, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: 'number.coffee' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: 'number.coffee' }, + { startIndex: 11, type: '' } + ] + } + ], + + [ + { + line: '{ key: 123 }', + tokens: [ + { startIndex: 0, type: 'delimiter.curly.coffee' }, + { startIndex: 1, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.curly.coffee' } + ] + } + ], + + [ + { + line: '[1,2,3]', + tokens: [ + { startIndex: 0, type: 'delimiter.square.coffee' }, + { startIndex: 1, type: 'number.coffee' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: 'number.coffee' }, + { startIndex: 4, type: 'delimiter.coffee' }, + { startIndex: 5, type: 'number.coffee' }, + { startIndex: 6, type: 'delimiter.square.coffee' } + ] + } + ], + + [ + { + line: 'foo(123);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 4, type: 'number.coffee' }, + { startIndex: 7, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 8, type: '' } + ] + } + ], + + [ + { + line: '{a:{b:[]}}', + tokens: [ + { startIndex: 0, type: 'delimiter.curly.coffee' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: 'delimiter.curly.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: 'delimiter.square.coffee' }, + { startIndex: 8, type: 'delimiter.curly.coffee' } + ] + } + ], + + [ + { + line: "x = '[{()}]'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.coffee' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.coffee' } + ] + } + ], + + // syntax highligting issue with {} - bug 16176 + [ + { + line: '"/api/v2/course/#{ $stateParams.courseId }/grading/student/#{$stateParams.studentId}",', + tokens: [ + { startIndex: 0, type: 'string.coffee' }, + { startIndex: 18, type: '' }, + { startIndex: 31, type: 'delimiter.coffee' }, + { startIndex: 32, type: '' }, + { startIndex: 41, type: 'string.coffee' }, + { startIndex: 61, type: '' }, + { startIndex: 73, type: 'delimiter.coffee' }, + { startIndex: 74, type: '' }, + { startIndex: 83, type: 'string.coffee' }, + { startIndex: 85, type: 'delimiter.coffee' } + ] + } + ], + + // Generated from sample + [ + { + line: '# Assignment:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'number = 42', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'number.coffee' } + ] + }, + { + line: 'opposite = true', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.true.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Conditions:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'number = -42 if opposite', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: 'number.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'keyword.if.coffee' }, + { startIndex: 15, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Functions:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'square = (x) -> x * x', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.coffee' }, + { startIndex: 15, type: '' }, + { startIndex: 18, type: 'delimiter.coffee' }, + { startIndex: 19, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Arrays:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'list = [1, 2, 3, 4, 5]', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.square.coffee' }, + { startIndex: 8, type: 'number.coffee' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'number.coffee' }, + { startIndex: 12, type: 'delimiter.coffee' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.coffee' }, + { startIndex: 15, type: 'delimiter.coffee' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'number.coffee' }, + { startIndex: 18, type: 'delimiter.coffee' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'number.coffee' }, + { startIndex: 21, type: 'delimiter.square.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Objects:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'math =', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' } + ] + }, + { + line: ' root: Math.sqrt', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 14, type: 'delimiter.coffee' }, + { startIndex: 15, type: '' } + ] + }, + { + line: ' square: square', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' } + ] + }, + { + line: ' cube: (x) -> x * square x', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 10, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'delimiter.coffee' }, + { startIndex: 16, type: '' }, + { startIndex: 19, type: 'delimiter.coffee' }, + { startIndex: 20, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Splats:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'race = (winner, runners...) ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 14, type: 'delimiter.coffee' }, + { startIndex: 15, type: '' }, + { startIndex: 23, type: 'delimiter.coffee' }, + { startIndex: 26, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.coffee' } + ] + }, + { + line: ' print winner, runners', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 14, type: 'delimiter.coffee' }, + { startIndex: 15, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Existence:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'alert "I knew it!" if elvis?', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'string.coffee' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'keyword.if.coffee' }, + { startIndex: 21, type: '' }, + { startIndex: 27, type: 'delimiter.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Array comprehensions:', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'cubes = (math.cube num for num in list)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 13, type: 'delimiter.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 23, type: 'keyword.for.coffee' }, + { startIndex: 26, type: '' }, + { startIndex: 31, type: 'keyword.in.coffee' }, + { startIndex: 33, type: '' }, + { startIndex: 38, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'fill = (container, liquid = "coffee") ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 17, type: 'delimiter.coffee' }, + { startIndex: 18, type: '' }, + { startIndex: 26, type: 'delimiter.coffee' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'string.coffee' }, + { startIndex: 36, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'delimiter.coffee' } + ] + }, + { + line: ' "Filling the #{container} with #{liquid}..."', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.coffee' }, + { startIndex: 17, type: '' }, + { startIndex: 26, type: 'string.coffee' }, + { startIndex: 35, type: '' }, + { startIndex: 41, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'ong = ["do", "re", "mi", "fa", "so"]', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'delimiter.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.square.coffee' }, + { startIndex: 7, type: 'string.coffee' }, + { startIndex: 11, type: 'delimiter.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'string.coffee' }, + { startIndex: 17, type: 'delimiter.coffee' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'string.coffee' }, + { startIndex: 23, type: 'delimiter.coffee' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'string.coffee' }, + { startIndex: 29, type: 'delimiter.coffee' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'string.coffee' }, + { startIndex: 35, type: 'delimiter.square.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'singers = {Jagger: "Rock", Elvis: "Roll"}', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.curly.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 17, type: 'delimiter.coffee' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'string.coffee' }, + { startIndex: 25, type: 'delimiter.coffee' }, + { startIndex: 26, type: '' }, + { startIndex: 32, type: 'delimiter.coffee' }, + { startIndex: 33, type: '' }, + { startIndex: 34, type: 'string.coffee' }, + { startIndex: 40, type: 'delimiter.curly.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'bitlist = [', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.square.coffee' } + ] + }, + { + line: ' 1, 0, 1', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'number.coffee' }, + { startIndex: 3, type: 'delimiter.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'number.coffee' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.coffee' } + ] + }, + { + line: ' 0, 0, 1', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'number.coffee' }, + { startIndex: 3, type: 'delimiter.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'number.coffee' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.coffee' } + ] + }, + { + line: ' 1, 1, 0', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'number.coffee' }, + { startIndex: 3, type: 'delimiter.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'number.coffee' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.coffee' } + ] + }, + { + line: ']', + tokens: [{ startIndex: 0, type: 'delimiter.square.coffee' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'kids =', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' } + ] + }, + { + line: ' brother:', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' } + ] + }, + { + line: ' name: "Max"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'string.coffee' } + ] + }, + { + line: ' age: 11', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 10, type: 'number.coffee' } + ] + }, + { + line: ' sister:', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' } + ] + }, + { + line: ' name: "Ida"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'string.coffee' } + ] + }, + { + line: ' age: 9', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 10, type: 'number.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: "$('.account').attr class: 'active'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 2, type: 'string.coffee' }, + { startIndex: 12, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 13, type: 'delimiter.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 19, type: 'keyword.class.coffee' }, + { startIndex: 24, type: 'delimiter.coffee' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'string.coffee' } + ] + }, + { + line: 'log object.class', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 10, type: 'delimiter.coffee' }, + { startIndex: 11, type: 'keyword.class.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'outer = 1', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.coffee' } + ] + }, + { + line: 'changeNumbers = ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 14, type: 'delimiter.coffee' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.coffee' } + ] + }, + { + line: 'inner = -1', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: 'number.coffee' } + ] + }, + { + line: 'outer = 10', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.coffee' } + ] + }, + { + line: 'inner = changeNumbers()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 21, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'mood = greatlyImproved if singing', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 23, type: 'keyword.if.coffee' }, + { startIndex: 25, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'if happy and knowsIt', + tokens: [ + { startIndex: 0, type: 'keyword.if.coffee' }, + { startIndex: 2, type: '' }, + { startIndex: 9, type: 'keyword.and.coffee' }, + { startIndex: 12, type: '' } + ] + }, + { + line: ' clapsHands()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 12, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: ' chaChaCha()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 11, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: 'else', + tokens: [{ startIndex: 0, type: 'keyword.else.coffee' }] + }, + { + line: ' showIt()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'date = if friday then sue else jill', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'keyword.if.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 17, type: 'keyword.then.coffee' }, + { startIndex: 21, type: '' }, + { startIndex: 26, type: 'keyword.else.coffee' }, + { startIndex: 30, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'options or= defaults', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'keyword.or.coffee' }, + { startIndex: 10, type: 'delimiter.coffee' }, + { startIndex: 11, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Eat lunch.', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: "eat food for food in ['toast', 'cheese', 'wine']", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'keyword.for.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 18, type: 'keyword.in.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.square.coffee' }, + { startIndex: 22, type: 'string.coffee' }, + { startIndex: 29, type: 'delimiter.coffee' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'string.coffee' }, + { startIndex: 39, type: 'delimiter.coffee' }, + { startIndex: 40, type: '' }, + { startIndex: 41, type: 'string.coffee' }, + { startIndex: 47, type: 'delimiter.square.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Fine five course dining.', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: "courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.square.coffee' }, + { startIndex: 11, type: 'string.coffee' }, + { startIndex: 19, type: 'delimiter.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'string.coffee' }, + { startIndex: 29, type: 'delimiter.coffee' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'string.coffee' }, + { startIndex: 41, type: 'delimiter.coffee' }, + { startIndex: 42, type: '' }, + { startIndex: 43, type: 'string.coffee' }, + { startIndex: 50, type: 'delimiter.coffee' }, + { startIndex: 51, type: '' }, + { startIndex: 52, type: 'string.coffee' }, + { startIndex: 58, type: 'delimiter.square.coffee' } + ] + }, + { + line: 'menu i + 1, dish for dish, i in courses', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'number.coffee' }, + { startIndex: 10, type: 'delimiter.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 17, type: 'keyword.for.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 25, type: 'delimiter.coffee' }, + { startIndex: 26, type: '' }, + { startIndex: 29, type: 'keyword.in.coffee' }, + { startIndex: 31, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Health conscious meal.', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: "foods = ['broccoli', 'spinach', 'chocolate']", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.square.coffee' }, + { startIndex: 9, type: 'string.coffee' }, + { startIndex: 19, type: 'delimiter.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'string.coffee' }, + { startIndex: 30, type: 'delimiter.coffee' }, + { startIndex: 31, type: '' }, + { startIndex: 32, type: 'string.coffee' }, + { startIndex: 43, type: 'delimiter.square.coffee' } + ] + }, + { + line: "eat food for food in foods when food isnt 'chocolate'", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'keyword.for.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 18, type: 'keyword.in.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 27, type: 'keyword.when.coffee' }, + { startIndex: 31, type: '' }, + { startIndex: 37, type: 'keyword.isnt.coffee' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'countdown = (num for num in [10..1])', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 10, type: 'delimiter.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 13, type: '' }, + { startIndex: 17, type: 'keyword.for.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 25, type: 'keyword.in.coffee' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.square.coffee' }, + { startIndex: 29, type: 'number.coffee' }, + { startIndex: 31, type: 'delimiter.coffee' }, + { startIndex: 33, type: 'number.coffee' }, + { startIndex: 34, type: 'delimiter.square.coffee' }, + { startIndex: 35, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'yearsOld = max: 10, ida: 9, tim: 11', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 14, type: 'delimiter.coffee' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'number.coffee' }, + { startIndex: 18, type: 'delimiter.coffee' }, + { startIndex: 19, type: '' }, + { startIndex: 23, type: 'delimiter.coffee' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'number.coffee' }, + { startIndex: 26, type: 'delimiter.coffee' }, + { startIndex: 27, type: '' }, + { startIndex: 31, type: 'delimiter.coffee' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'number.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'ages = for child, age of yearsOld', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'keyword.for.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 16, type: 'delimiter.coffee' }, + { startIndex: 17, type: '' }, + { startIndex: 22, type: 'keyword.of.coffee' }, + { startIndex: 24, type: '' } + ] + }, + { + line: ' "#{child} is #{age}"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 10, type: 'string.coffee' }, + { startIndex: 17, type: '' }, + { startIndex: 20, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Econ 101', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'if this.studyingEconomics', + tokens: [ + { startIndex: 0, type: 'keyword.if.coffee' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'variable.predefined.coffee' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' } + ] + }, + { + line: ' buy() while supply > demand', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 9, type: 'keyword.while.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 22, type: 'delimiter.coffee' }, + { startIndex: 23, type: '' } + ] + }, + { + line: ' sell() until supply > demand', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.until.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 22, type: 'delimiter.coffee' }, + { startIndex: 23, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Nursery Rhyme', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'num = 6', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'delimiter.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'number.coffee' } + ] + }, + { + line: 'lyrics = while num -= 1', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.while.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 19, type: 'delimiter.coffee' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.coffee' } + ] + }, + { + line: ' "#{num} little monkeys, jumping on the bed.', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 8, type: 'string.coffee' } + ] + }, + { + line: ' One fell out and bumped his head."', + tokens: [{ startIndex: 0, type: 'string.coffee' }] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '# Everything is an Expression (at least, as much as possible)', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'grade = (student) ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 16, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'delimiter.coffee' } + ] + }, + { + line: ' if student.excellentWork', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.if.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 12, type: 'delimiter.coffee' }, + { startIndex: 13, type: '' } + ] + }, + { + line: ' "A+"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'string.coffee' } + ] + }, + { + line: ' else if student.okayStuff', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.else.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'keyword.if.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 17, type: 'delimiter.coffee' }, + { startIndex: 18, type: '' } + ] + }, + { + line: ' if student.triedHard then "B" else "B-"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.if.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 14, type: 'delimiter.coffee' }, + { startIndex: 15, type: '' }, + { startIndex: 25, type: 'keyword.then.coffee' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'string.coffee' }, + { startIndex: 33, type: '' }, + { startIndex: 34, type: 'keyword.else.coffee' }, + { startIndex: 38, type: '' }, + { startIndex: 39, type: 'string.coffee' } + ] + }, + { + line: ' else', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.else.coffee' } + ] + }, + { + line: ' "C"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'eldest = if 24 > 21 then "Liz" else "Ike"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.if.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'number.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.coffee' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'number.coffee' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'keyword.then.coffee' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'string.coffee' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'keyword.else.coffee' }, + { startIndex: 35, type: '' }, + { startIndex: 36, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '#Classes, Inheritance and Super', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'class Animal', + tokens: [ + { startIndex: 0, type: 'keyword.class.coffee' }, + { startIndex: 5, type: '' } + ] + }, + { + line: ' constructor: (@name) ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 13, type: 'delimiter.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 16, type: 'variable.predefined.coffee' }, + { startIndex: 21, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: ' move: (meters) ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 15, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.coffee' } + ] + }, + { + line: ' alert @name + " moved #{meters}m."', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 10, type: 'variable.predefined.coffee' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.coffee' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.coffee' }, + { startIndex: 28, type: '' }, + { startIndex: 34, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'class Snake extends Animal', + tokens: [ + { startIndex: 0, type: 'keyword.class.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 12, type: 'keyword.extends.coffee' }, + { startIndex: 19, type: '' } + ] + }, + { + line: ' move: ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' } + ] + }, + { + line: ' alert "Slithering..."', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 10, type: 'string.coffee' } + ] + }, + { + line: ' super 5', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.super.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'number.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'class Horse extends Animal', + tokens: [ + { startIndex: 0, type: 'keyword.class.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 12, type: 'keyword.extends.coffee' }, + { startIndex: 19, type: '' } + ] + }, + { + line: ' move: ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'delimiter.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' } + ] + }, + { + line: ' alert "Galloping..."', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 10, type: 'string.coffee' } + ] + }, + { + line: ' super 45', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.super.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'number.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'sam = new Snake "Sammy the Python"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'delimiter.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.new.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 16, type: 'string.coffee' } + ] + }, + { + line: 'tom = new Horse "Tommy the Palomino"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'delimiter.coffee' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.new.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 16, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'sam.move()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: 'tom.move()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.coffee' }, + { startIndex: 4, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '#Function binding', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'Account = (customer, cart) ->', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 19, type: 'delimiter.coffee' }, + { startIndex: 20, type: '' }, + { startIndex: 25, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'delimiter.coffee' } + ] + }, + { + line: ' @customer = customer', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.predefined.coffee' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.coffee' }, + { startIndex: 13, type: '' } + ] + }, + { + line: ' @cart = cart', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.predefined.coffee' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.coffee' }, + { startIndex: 9, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: " $('.shopping_cart').bind 'click', (event) =>", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 4, type: 'string.coffee' }, + { startIndex: 20, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 21, type: 'delimiter.coffee' }, + { startIndex: 22, type: '' }, + { startIndex: 27, type: 'string.coffee' }, + { startIndex: 34, type: 'delimiter.coffee' }, + { startIndex: 35, type: '' }, + { startIndex: 36, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 37, type: '' }, + { startIndex: 42, type: 'delimiter.parenthesis.coffee' }, + { startIndex: 43, type: '' }, + { startIndex: 44, type: 'delimiter.coffee' } + ] + }, + { + line: ' @customer.purchase @cart', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'variable.predefined.coffee' }, + { startIndex: 13, type: 'delimiter.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 23, type: 'variable.predefined.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '#Switch/When/Else ', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'switch day', + tokens: [ + { startIndex: 0, type: 'keyword.switch.coffee' }, + { startIndex: 6, type: '' } + ] + }, + { + line: ' when "Mon" then go work', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.when.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'keyword.then.coffee' }, + { startIndex: 17, type: '' } + ] + }, + { + line: ' when "Tue" then go relax', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.when.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'keyword.then.coffee' }, + { startIndex: 17, type: '' } + ] + }, + { + line: ' when "Thu" then go iceFishing', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.when.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'keyword.then.coffee' }, + { startIndex: 17, type: '' } + ] + }, + { + line: ' when "Fri", "Sat"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.when.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.coffee' }, + { startIndex: 12, type: 'delimiter.coffee' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'string.coffee' } + ] + }, + { + line: ' if day is bingoDay', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.if.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 11, type: 'keyword.is.coffee' }, + { startIndex: 13, type: '' } + ] + }, + { + line: ' go bingo', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' go dancing', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' when "Sun" then go church', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.when.coffee' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.coffee' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'keyword.then.coffee' }, + { startIndex: 17, type: '' } + ] + }, + { + line: ' else go work', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.else.coffee' }, + { startIndex: 6, type: '' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '#Try/Catch/Finally', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'try', + tokens: [{ startIndex: 0, type: 'keyword.try.coffee' }] + }, + { + line: ' allHellBreaksLoose()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 20, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: ' catsAndDogsLivingTogether()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 27, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: 'catch error', + tokens: [ + { startIndex: 0, type: 'keyword.catch.coffee' }, + { startIndex: 5, type: '' } + ] + }, + { + line: ' print error', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: 'finally', + tokens: [{ startIndex: 0, type: 'keyword.finally.coffee' }] + }, + { + line: ' cleanUp()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.parenthesis.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '#String Interpolation and Block Comments', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'author = "Wittgenstein"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'string.coffee' } + ] + }, + { + line: 'quote = "A picture is a fact. -- #{ author }"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 7, type: 'delimiter.coffee' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'string.coffee' }, + { startIndex: 36, type: '' }, + { startIndex: 44, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'sentence = "#{ 22 / 7 } is a decent approximation of p"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.coffee' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'number.coffee' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'delimiter.coffee' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'number.coffee' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'string.coffee' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'mobyDick = "Call me Ishmael. Some years ago --', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.coffee' } + ] + }, + { + line: ' never mind how long precisely -- having little', + tokens: [{ startIndex: 0, type: 'string.coffee' }] + }, + { + line: ' or no money in my purse, and nothing particular', + tokens: [{ startIndex: 0, type: 'string.coffee' }] + }, + { + line: ' to interest me on shore, I thought I would sail', + tokens: [{ startIndex: 0, type: 'string.coffee' }] + }, + { + line: ' about a little and see the watery part of the', + tokens: [{ startIndex: 0, type: 'string.coffee' }] + }, + { + line: ' world..."', + tokens: [{ startIndex: 0, type: 'string.coffee' }] + }, + { + line: '', + tokens: [] + }, + { + line: '#Extended Regular Expressions', + tokens: [{ startIndex: 0, type: 'comment.coffee' }] + }, + { + line: 'OPERATOR = /// ^ (', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 9, type: 'delimiter.coffee' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'regexp.coffee' } + ] + }, + { + line: ' ?: [-=]> # function', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 23, type: 'comment.coffee' } + ] + }, + { + line: ' | [-+*/%<>&|^!?=]= # compound assign / compare', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 23, type: 'comment.coffee' } + ] + }, + { + line: ' | >>>=? # zero-fill right shift', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 23, type: 'comment.coffee' } + ] + }, + { + line: ' | ([-+:])\\1 # doubles', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 23, type: 'comment.coffee' } + ] + }, + { + line: ' | ([&|<>])\\2=? # logic / shift', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 23, type: 'comment.coffee' } + ] + }, + { + line: ' | \\?\\. # soak access', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 23, type: 'comment.coffee' } + ] + }, + { + line: ' | \\.{2,3} # range or splat', + tokens: [ + { startIndex: 0, type: 'regexp.coffee' }, + { startIndex: 23, type: 'comment.coffee' } + ] + }, + { + line: ') ///', + tokens: [{ startIndex: 0, type: 'regexp.coffee' }] + }, + { + line: '', + tokens: [] + } + ] +]); diff --git a/monaco-languages/src/coffee/coffee.ts b/monaco-languages/src/coffee/coffee.ts new file mode 100644 index 00000000..0994a23f --- /dev/null +++ b/monaco-languages/src/coffee/coffee.ts @@ -0,0 +1,258 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\@\#%\^\&\*\(\)\=\$\-\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + comments: { + blockComment: ['###', '###'], + lineComment: '#' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + folding: { + markers: { + start: new RegExp('^\\s*#region\\b'), + end: new RegExp('^\\s*#endregion\\b') + } + } +}; + +export const language = { + defaultToken: '', + ignoreCase: true, + tokenPostfix: '.coffee', + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' } + ], + + regEx: /\/(?!\/\/)(?:[^\/\\]|\\.)*\/[igm]*/, + + keywords: [ + 'and', + 'or', + 'is', + 'isnt', + 'not', + 'on', + 'yes', + '@', + 'no', + 'off', + 'true', + 'false', + 'null', + 'this', + 'new', + 'delete', + 'typeof', + 'in', + 'instanceof', + 'return', + 'throw', + 'break', + 'continue', + 'debugger', + 'if', + 'else', + 'switch', + 'for', + 'while', + 'do', + 'try', + 'catch', + 'finally', + 'class', + 'extends', + 'super', + 'undefined', + 'then', + 'unless', + 'until', + 'loop', + 'of', + 'by', + 'when' + ], + + // we include these common regular expressions + symbols: /[=> import('./cpp') +}); +registerLanguage({ + id: 'cpp', + extensions: ['.cpp', '.cc', '.cxx', '.hpp', '.hh', '.hxx'], + aliases: ['C++', 'Cpp', 'cpp'], + loader: () => import('./cpp') +}); diff --git a/monaco-languages/src/cpp/cpp.test.ts b/monaco-languages/src/cpp/cpp.test.ts new file mode 100644 index 00000000..b776103f --- /dev/null +++ b/monaco-languages/src/cpp/cpp.test.ts @@ -0,0 +1,979 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('cpp', [ + // Keywords + [ + { + line: 'int _tmain(int argc, _TCHAR* argv[])', + tokens: [ + { startIndex: 0, type: 'keyword.int.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cpp' }, + { startIndex: 10, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 11, type: 'keyword.int.cpp' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'identifier.cpp' }, + { startIndex: 19, type: 'delimiter.cpp' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'identifier.cpp' }, + { startIndex: 27, type: 'delimiter.cpp' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'identifier.cpp' }, + { startIndex: 33, type: 'delimiter.square.cpp' }, + { startIndex: 35, type: 'delimiter.parenthesis.cpp' } + ] + } + ], + + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.cpp' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.cpp' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.cpp' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.cpp' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.cpp' }, + { startIndex: 1, type: 'identifier.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.cpp' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.cpp' } + ] + } + ], + + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.cpp' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.cpp' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.cpp' }, + { startIndex: 5, type: 'delimiter.cpp' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.cpp' } + ] + } + ], + + [ + { + line: 'int x = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.int.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.cpp' }, + { startIndex: 9, type: 'delimiter.cpp' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.cpp' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.cpp' }] + } + ], + + [ + { + line: 'int x = /* a simple comment */ 1;', + tokens: [ + { startIndex: 0, type: 'keyword.int.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.cpp' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.cpp' }, + { startIndex: 32, type: 'delimiter.cpp' } + ] + } + ], + + [ + { + line: 'int x = /* comment */ 1; */', + tokens: [ + { startIndex: 0, type: 'keyword.int.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.cpp' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.cpp' }, + { startIndex: 23, type: 'delimiter.cpp' }, + { startIndex: 24, type: '' } + ] + } + ], + + [ + { + line: 'x = /**/;', + tokens: [ + { startIndex: 0, type: 'identifier.cpp' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.cpp' }, + { startIndex: 8, type: 'delimiter.cpp' } + ] + } + ], + + [ + { + line: 'x = /*/;', + tokens: [ + { startIndex: 0, type: 'identifier.cpp' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.cpp' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: '12l', + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: '34U', + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: '55LL', + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: '34ul', + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: '55llU', + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: "5'5llU", + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: "100'000'000", + tokens: [{ startIndex: 0, type: 'number.cpp' }] + } + ], + + [ + { + line: "0x100'aafllU", + tokens: [{ startIndex: 0, type: 'number.hex.cpp' }] + } + ], + + [ + { + line: "0342'325", + tokens: [{ startIndex: 0, type: 'number.octal.cpp' }] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.cpp' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '23.5F', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '23.5f', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72E3F', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72E3f', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72e3F', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72e3f', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '23.5L', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '23.5l', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72E3L', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72E3l', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72e3L', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '1.72e3l', + tokens: [{ startIndex: 0, type: 'number.float.cpp' }] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.cpp' }, + { startIndex: 1, type: 'delimiter.cpp' }, + { startIndex: 2, type: 'number.cpp' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.cpp' }, + { startIndex: 3, type: 'delimiter.cpp' }, + { startIndex: 4, type: 'number.cpp' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.cpp' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.cpp' } + ] + } + ], + + // Monarch Generated + [ + { + line: '#include', + tokens: [ + { startIndex: 0, type: 'keyword.directive.include.cpp' }, + { startIndex: 8, type: 'keyword.directive.include.begin.cpp' }, + { startIndex: 9, type: 'string.include.identifier.cpp' }, + { startIndex: 17, type: 'keyword.directive.include.end.cpp' } + ] + }, + { + line: '#include "/path/to/my/file.h"', + tokens: [ + { startIndex: 0, type: 'keyword.directive.include.cpp' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.directive.include.begin.cpp' }, + { startIndex: 10, type: 'string.include.identifier.cpp' }, + { startIndex: 28, type: 'keyword.directive.include.end.cpp' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '#ifdef VAR', + tokens: [ + { startIndex: 0, type: 'keyword.directive.cpp' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.cpp' } + ] + }, + { + line: '#define SUM(A,B) (A) + (B)', + tokens: [ + { startIndex: 0, type: 'keyword.directive.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.cpp' }, + { startIndex: 11, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 12, type: 'identifier.cpp' }, + { startIndex: 13, type: 'delimiter.cpp' }, + { startIndex: 14, type: 'identifier.cpp' }, + { startIndex: 15, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 18, type: 'identifier.cpp' }, + { startIndex: 19, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.cpp' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 24, type: 'identifier.cpp' }, + { startIndex: 25, type: 'delimiter.parenthesis.cpp' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'int main(int argc, char** argv)', + tokens: [ + { startIndex: 0, type: 'keyword.int.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cpp' }, + { startIndex: 8, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 9, type: 'keyword.int.cpp' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.cpp' }, + { startIndex: 17, type: 'delimiter.cpp' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'keyword.char.cpp' }, + { startIndex: 23, type: '' }, + { startIndex: 26, type: 'identifier.cpp' }, + { startIndex: 30, type: 'delimiter.parenthesis.cpp' } + ] + }, + { + line: '{', + tokens: [{ startIndex: 0, type: 'delimiter.curly.cpp' }] + }, + { + line: ' return 0;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.return.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.cpp' }, + { startIndex: 9, type: 'delimiter.cpp' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.cpp' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'namespace TestSpace', + tokens: [ + { startIndex: 0, type: 'keyword.namespace.cpp' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.cpp' } + ] + }, + { + line: '{', + tokens: [{ startIndex: 0, type: 'delimiter.curly.cpp' }] + }, + { + line: ' using Asdf.CDE;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.using.cpp' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.cpp' }, + { startIndex: 11, type: 'delimiter.cpp' }, + { startIndex: 12, type: 'identifier.cpp' }, + { startIndex: 15, type: 'delimiter.cpp' } + ] + }, + { + line: ' template ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.template.cpp' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.angle.cpp' }, + { startIndex: 11, type: 'keyword.typename.cpp' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'identifier.cpp' }, + { startIndex: 21, type: 'delimiter.angle.cpp' } + ] + }, + { + line: ' class CoolClass : protected BaseClass', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.class.cpp' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.cpp' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.cpp' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'keyword.protected.cpp' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'identifier.cpp' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.cpp' } + ] + }, + { + line: ' private:', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.private.cpp' }, + { startIndex: 9, type: 'delimiter.cpp' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' static T field;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.static.cpp' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.cpp' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'identifier.cpp' }, + { startIndex: 16, type: 'delimiter.cpp' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' public:', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.public.cpp' }, + { startIndex: 8, type: 'delimiter.cpp' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' [[deprecated]]', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'annotation.cpp' } + ] + }, + { + line: ' foo method() const override', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.cpp' }, + { startIndex: 12, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'keyword.const.cpp' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'keyword.override.cpp' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.cpp' } + ] + }, + { + line: ' auto s = new Bar();', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.auto.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.cpp' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.cpp' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'keyword.new.cpp' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'identifier.cpp' }, + { startIndex: 19, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 21, type: 'delimiter.cpp' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' if (s.field) {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.if.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 7, type: 'identifier.cpp' }, + { startIndex: 8, type: 'delimiter.cpp' }, + { startIndex: 9, type: 'identifier.cpp' }, + { startIndex: 14, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.curly.cpp' } + ] + }, + { + line: ' for(const auto & b : s.field) {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.for.cpp' }, + { startIndex: 7, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 8, type: 'keyword.const.cpp' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.auto.cpp' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'delimiter.cpp' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'identifier.cpp' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.cpp' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'identifier.cpp' }, + { startIndex: 26, type: 'delimiter.cpp' }, + { startIndex: 27, type: 'identifier.cpp' }, + { startIndex: 32, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 33, type: '' }, + { startIndex: 34, type: 'delimiter.curly.cpp' } + ] + }, + { + line: ' break;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'keyword.break.cpp' }, + { startIndex: 10, type: 'delimiter.cpp' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'delimiter.curly.cpp' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.curly.cpp' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.cpp' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' std::string s = "hello wordld\\n";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 7, type: 'identifier.cpp' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.cpp' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.cpp' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.cpp' }, + { startIndex: 31, type: 'string.escape.cpp' }, + { startIndex: 33, type: 'string.cpp' }, + { startIndex: 34, type: 'delimiter.cpp' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: " int number = 123'123'123Ull;", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.int.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.cpp' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.cpp' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'number.cpp' }, + { startIndex: 29, type: 'delimiter.cpp' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.cpp' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.cpp' }] + }, + { + line: '', + tokens: [] + }, + { + line: '#endif', + tokens: [{ startIndex: 0, type: 'keyword.directive.cpp' }] + }, + { + line: '# ifdef VAR', + tokens: [ + { startIndex: 0, type: 'keyword.directive.cpp' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'identifier.cpp' } + ] + }, + { + line: '# define SUM(A,B) (A) + (B)', + tokens: [ + { startIndex: 0, type: 'keyword.directive.cpp' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.cpp' }, + { startIndex: 12, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 13, type: 'identifier.cpp' }, + { startIndex: 14, type: 'delimiter.cpp' }, + { startIndex: 15, type: 'identifier.cpp' }, + { startIndex: 16, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 19, type: 'identifier.cpp' }, + { startIndex: 20, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'delimiter.cpp' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 25, type: 'identifier.cpp' }, + { startIndex: 26, type: 'delimiter.parenthesis.cpp' } + ] + }, + { + line: 'uR"V0G0N(abc)V0G0N"def', + tokens: [ + { startIndex: 0, type: 'string.raw.begin.cpp' }, + { startIndex: 9, type: 'string.raw.cpp' }, + { startIndex: 12, type: 'string.raw.end.cpp' }, + { startIndex: 19, type: 'identifier.cpp' } + ] + } + ], + + // https://github.com/microsoft/monaco-editor/issues/1951 + [ + { + line: 'auto sv = R"({ "message": "Hello World" })""\\n"sv;', + tokens: [ + { startIndex: 0, type: 'keyword.auto.cpp' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.cpp' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'string.raw.begin.cpp' }, + { startIndex: 13, type: 'string.raw.cpp' }, + { startIndex: 41, type: 'string.raw.end.cpp' }, + { startIndex: 43, type: 'string.cpp' }, + { startIndex: 44, type: 'string.escape.cpp' }, + { startIndex: 46, type: 'string.cpp' }, + { startIndex: 47, type: 'identifier.cpp' }, + { startIndex: 49, type: 'delimiter.cpp' } + ] + }, + { + line: ' // This is a comment, not a string', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.cpp' } + ] + } + ], + + // Annotations + [ + { + line: '[[nodiscard]]', + tokens: [{ startIndex: 0, type: 'annotation.cpp' }] + } + ], + [ + { + // Example from http://eel.is/c++draft/dcl.attr + line: '[[using CC: opt(1), debug]]', + tokens: [ + { startIndex: 0, type: 'annotation.cpp' }, // [[ + { startIndex: 2, type: 'keyword.cpp' }, // using + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'annotation.cpp' }, // CC + { startIndex: 10, type: 'delimiter.cpp' }, // colon + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'annotation.cpp' }, // opt + { startIndex: 15, type: 'delimiter.parenthesis.cpp' }, // ( + { startIndex: 16, type: 'annotation.cpp' }, // 1 + { startIndex: 17, type: 'delimiter.parenthesis.cpp' }, // ) + { startIndex: 18, type: 'delimiter.cpp' }, // , + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'annotation.cpp' } // debug]] + ] + } + ], + [ + // Multiline and comments. + { + line: '[[nodiscard /*commented*/', + tokens: [ + { startIndex: 0, type: 'annotation.cpp' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'comment.cpp' } + ] + }, + { + line: ']] int i;', + tokens: [ + { startIndex: 0, type: 'annotation.cpp' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'keyword.int.cpp' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.cpp' }, + { startIndex: 8, type: 'delimiter.cpp' } + ] + } + ], + [ + // We don't support newlines between annotation square brackets, but we do support other whitespace. + { + line: '[ [nodiscard] ]', + tokens: [{ startIndex: 0, type: 'annotation.cpp' }] + } + ], + + // Preprocessor directives with whitespace inamongst the characters, + // and crucially checking with whitespace before the initial #. + [ + { + line: ' # if defined(SOMETHING)', + tokens: [ + { startIndex: 0, type: 'keyword.directive.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.cpp' }, + { startIndex: 13, type: 'delimiter.parenthesis.cpp' }, + { startIndex: 14, type: 'identifier.cpp' }, + { startIndex: 23, type: 'delimiter.parenthesis.cpp' } + ] + }, + { + line: ' #include ', + tokens: [ + { startIndex: 0, type: 'keyword.directive.include.cpp' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'keyword.directive.include.begin.cpp' }, + { startIndex: 18, type: 'string.include.identifier.cpp' }, + { startIndex: 22, type: 'keyword.directive.include.end.cpp' } + ] + }, + { + line: ' # include ', + tokens: [ + { startIndex: 0, type: 'keyword.directive.include.cpp' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'keyword.directive.include.begin.cpp' }, + { startIndex: 18, type: 'string.include.identifier.cpp' }, + { startIndex: 22, type: 'keyword.directive.include.end.cpp' } + ] + } + ], + + [ + // microsoft/monaco-editor#2497 : comment continuation highlighting + { + line: '// this is a comment \\', + tokens: [{ startIndex: 0, type: 'comment.cpp' }] + }, + { + line: 'this is still a comment', + tokens: [{ startIndex: 0, type: 'comment.cpp' }] + }, + { + line: 'int x = 1;', + tokens: [ + { startIndex: 0, type: 'keyword.int.cpp' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cpp' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.cpp' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.cpp' }, + { startIndex: 9, type: 'delimiter.cpp' } + ] + } + ] +]); diff --git a/monaco-languages/src/cpp/cpp.ts b/monaco-languages/src/cpp/cpp.ts new file mode 100644 index 00000000..6b4eef50 --- /dev/null +++ b/monaco-languages/src/cpp/cpp.ts @@ -0,0 +1,428 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '[', close: ']' }, + { open: '{', close: '}' }, + { open: '(', close: ')' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + folding: { + markers: { + start: new RegExp('^\\s*#pragma\\s+region\\b'), + end: new RegExp('^\\s*#pragma\\s+endregion\\b') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.cpp', + + brackets: [ + { token: 'delimiter.curly', open: '{', close: '}' }, + { token: 'delimiter.parenthesis', open: '(', close: ')' }, + { token: 'delimiter.square', open: '[', close: ']' }, + { token: 'delimiter.angle', open: '<', close: '>' } + ], + + keywords: [ + 'abstract', + 'amp', + 'array', + 'auto', + 'bool', + 'break', + 'case', + 'catch', + 'char', + 'class', + 'const', + 'constexpr', + 'const_cast', + 'continue', + 'cpu', + 'decltype', + 'default', + 'delegate', + 'delete', + 'do', + 'double', + 'dynamic_cast', + 'each', + 'else', + 'enum', + 'event', + 'explicit', + 'export', + 'extern', + 'false', + 'final', + 'finally', + 'float', + 'for', + 'friend', + 'gcnew', + 'generic', + 'goto', + 'if', + 'in', + 'initonly', + 'inline', + 'int', + 'interface', + 'interior_ptr', + 'internal', + 'literal', + 'long', + 'mutable', + 'namespace', + 'new', + 'noexcept', + 'nullptr', + '__nullptr', + 'operator', + 'override', + 'partial', + 'pascal', + 'pin_ptr', + 'private', + 'property', + 'protected', + 'public', + 'ref', + 'register', + 'reinterpret_cast', + 'restrict', + 'return', + 'safe_cast', + 'sealed', + 'short', + 'signed', + 'sizeof', + 'static', + 'static_assert', + 'static_cast', + 'struct', + 'switch', + 'template', + 'this', + 'thread_local', + 'throw', + 'tile_static', + 'true', + 'try', + 'typedef', + 'typeid', + 'typename', + 'union', + 'unsigned', + 'using', + 'virtual', + 'void', + 'volatile', + 'wchar_t', + 'where', + 'while', + + '_asm', // reserved word with one underscores + '_based', + '_cdecl', + '_declspec', + '_fastcall', + '_if_exists', + '_if_not_exists', + '_inline', + '_multiple_inheritance', + '_pascal', + '_single_inheritance', + '_stdcall', + '_virtual_inheritance', + '_w64', + + '__abstract', // reserved word with two underscores + '__alignof', + '__asm', + '__assume', + '__based', + '__box', + '__builtin_alignof', + '__cdecl', + '__clrcall', + '__declspec', + '__delegate', + '__event', + '__except', + '__fastcall', + '__finally', + '__forceinline', + '__gc', + '__hook', + '__identifier', + '__if_exists', + '__if_not_exists', + '__inline', + '__int128', + '__int16', + '__int32', + '__int64', + '__int8', + '__interface', + '__leave', + '__m128', + '__m128d', + '__m128i', + '__m256', + '__m256d', + '__m256i', + '__m64', + '__multiple_inheritance', + '__newslot', + '__nogc', + '__noop', + '__nounwind', + '__novtordisp', + '__pascal', + '__pin', + '__pragma', + '__property', + '__ptr32', + '__ptr64', + '__raise', + '__restrict', + '__resume', + '__sealed', + '__single_inheritance', + '__stdcall', + '__super', + '__thiscall', + '__try', + '__try_cast', + '__typeof', + '__unaligned', + '__unhook', + '__uuidof', + '__value', + '__virtual_inheritance', + '__w64', + '__wchar_t' + ], + + operators: [ + '=', + '>', + '<', + '!', + '~', + '?', + ':', + '==', + '<=', + '>=', + '!=', + '&&', + '||', + '++', + '--', + '+', + '-', + '*', + '/', + '&', + '|', + '^', + '%', + '<<', + '>>', + '>>>', + '+=', + '-=', + '*=', + '/=', + '&=', + '|=', + '^=', + '%=', + '<<=', + '>>=', + '>>>=' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'], + [/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/, 'number.float'], + [/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, 'number.hex'], + [/0[0-7']*[0-7](@integersuffix)/, 'number.octal'], + [/0[bB][0-1']*[0-1](@integersuffix)/, 'number.binary'], + [/\d[\d']*\d(@integersuffix)/, 'number'], + [/\d(@integersuffix)/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@doccomment'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*\\$/, 'comment', '@linecomment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + //For use with continuous line comments + linecomment: [ + [/.*[^\\]$/, 'comment', '@pop'], + [/[^]+/, 'comment'] + ], + + //Identical copy of comment above, except for the addition of .doc + doccomment: [ + [/[^\/*]+/, 'comment.doc'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'] + ], + + raw: [ + [ + /(.*)(\))(?:([^ ()\\\t"]*))(\")/, + { + cases: { + '$3==$S2': [ + 'string.raw', + 'string.raw.end', + 'string.raw.end', + { token: 'string.raw.end', next: '@pop' } + ], + '@default': ['string.raw', 'string.raw', 'string.raw', 'string.raw'] + } + } + ], + [/.*/, 'string.raw'] + ], + + annotation: [ + { include: '@whitespace' }, + [/using|alignas/, 'keyword'], + [/[a-zA-Z0-9_]+/, 'annotation'], + [/[,:]/, 'delimiter'], + [/[()]/, '@brackets'], + [/\]\s*\]/, { token: 'annotation', next: '@pop' }] + ], + + include: [ + [ + /(\s*)(<)([^<>]*)(>)/, + [ + '', + 'keyword.directive.include.begin', + 'string.include.identifier', + { token: 'keyword.directive.include.end', next: '@pop' } + ] + ], + [ + /(\s*)(")([^"]*)(")/, + [ + '', + 'keyword.directive.include.begin', + 'string.include.identifier', + { token: 'keyword.directive.include.end', next: '@pop' } + ] + ] + ] + } +}; diff --git a/monaco-languages/src/csharp/csharp.contribution.ts b/monaco-languages/src/csharp/csharp.contribution.ts new file mode 100644 index 00000000..06e44f0d --- /dev/null +++ b/monaco-languages/src/csharp/csharp.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'csharp', + extensions: ['.cs', '.csx', '.cake'], + aliases: ['C#', 'csharp'], + loader: () => import('./csharp') +}); diff --git a/monaco-languages/src/csharp/csharp.test.ts b/monaco-languages/src/csharp/csharp.test.ts new file mode 100644 index 00000000..9b1aaae7 --- /dev/null +++ b/monaco-languages/src/csharp/csharp.test.ts @@ -0,0 +1,976 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('csharp', [ + // Generated from sample + [ + { + line: 'using System;', + tokens: [ + { startIndex: 0, type: 'keyword.using.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'namespace.cs' }, + { startIndex: 12, type: 'delimiter.cs' } + ] + }, + { + line: 'using System.Collections.Generic;', + tokens: [ + { startIndex: 0, type: 'keyword.using.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'namespace.cs' }, + { startIndex: 12, type: 'delimiter.cs' }, + { startIndex: 13, type: 'namespace.cs' }, + { startIndex: 24, type: 'delimiter.cs' }, + { startIndex: 25, type: 'namespace.cs' }, + { startIndex: 32, type: 'delimiter.cs' } + ] + }, + { + line: 'using System.Diagnostics;', + tokens: [ + { startIndex: 0, type: 'keyword.using.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'namespace.cs' }, + { startIndex: 12, type: 'delimiter.cs' }, + { startIndex: 13, type: 'namespace.cs' }, + { startIndex: 24, type: 'delimiter.cs' } + ] + }, + { + line: 'using System.Linq;', + tokens: [ + { startIndex: 0, type: 'keyword.using.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'namespace.cs' }, + { startIndex: 12, type: 'delimiter.cs' }, + { startIndex: 13, type: 'namespace.cs' }, + { startIndex: 17, type: 'delimiter.cs' } + ] + }, + { + line: 'using System.Text;', + tokens: [ + { startIndex: 0, type: 'keyword.using.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'namespace.cs' }, + { startIndex: 12, type: 'delimiter.cs' }, + { startIndex: 13, type: 'namespace.cs' }, + { startIndex: 17, type: 'delimiter.cs' } + ] + }, + { + line: 'using System.Threading.Tasks;', + tokens: [ + { startIndex: 0, type: 'keyword.using.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'namespace.cs' }, + { startIndex: 12, type: 'delimiter.cs' }, + { startIndex: 13, type: 'namespace.cs' }, + { startIndex: 22, type: 'delimiter.cs' }, + { startIndex: 23, type: 'namespace.cs' }, + { startIndex: 28, type: 'delimiter.cs' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'namespace VS', + tokens: [ + { startIndex: 0, type: 'keyword.namespace.cs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'namespace.cs' } + ] + }, + { + line: '{', + tokens: [{ startIndex: 0, type: 'delimiter.curly.cs' }] + }, + { + line: ' class Program', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.class.cs' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.cs' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' static void Main(string[] args)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.static.cs' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.void.cs' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.cs' }, + { startIndex: 18, type: 'delimiter.parenthesis.cs' }, + { startIndex: 19, type: 'keyword.string.cs' }, + { startIndex: 25, type: 'delimiter.square.cs' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'identifier.cs' }, + { startIndex: 32, type: 'delimiter.parenthesis.cs' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' ProcessStartInfo si = new ProcessStartInfo();', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'identifier.cs' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'identifier.cs' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.cs' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'keyword.new.cs' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'identifier.cs' }, + { startIndex: 45, type: 'delimiter.parenthesis.cs' }, + { startIndex: 47, type: 'delimiter.cs' } + ] + }, + { + line: ' float load= 3.2e02f;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.float.cs' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.cs' }, + { startIndex: 13, type: 'delimiter.cs' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'number.float.cs' }, + { startIndex: 22, type: 'delimiter.cs' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: ' si.FileName = @"tools\\\\node.exe";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'identifier.cs' }, + { startIndex: 5, type: 'delimiter.cs' }, + { startIndex: 6, type: 'identifier.cs' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.cs' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'string.quote.cs' }, + { startIndex: 19, type: 'string.cs' }, + { startIndex: 34, type: 'string.quote.cs' }, + { startIndex: 35, type: 'delimiter.cs' } + ] + }, + { + line: ' si.Arguments = "tools\\\\simpl3server.js";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'identifier.cs' }, + { startIndex: 5, type: 'delimiter.cs' }, + { startIndex: 6, type: 'identifier.cs' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.cs' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'string.quote.cs' }, + { startIndex: 19, type: 'string.cs' }, + { startIndex: 24, type: 'string.escape.cs' }, + { startIndex: 26, type: 'string.cs' }, + { startIndex: 41, type: 'string.quote.cs' }, + { startIndex: 42, type: 'delimiter.cs' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' string someString = $"hello{outside+variable}the string again {{ escaped";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.string.cs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.cs' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.cs' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'string.quote.cs' }, + { startIndex: 25, type: 'string.cs' }, + { startIndex: 30, type: 'string.quote.cs' }, + { startIndex: 31, type: 'identifier.cs' }, + { startIndex: 38, type: 'delimiter.cs' }, + { startIndex: 39, type: 'identifier.cs' }, + { startIndex: 47, type: 'string.quote.cs' }, + { startIndex: 48, type: 'string.cs' }, + { startIndex: 65, type: 'string.escape.cs' }, + { startIndex: 67, type: 'string.cs' }, + { startIndex: 75, type: 'string.quote.cs' }, + { startIndex: 76, type: 'delimiter.cs' } + ] + }, + { + line: ' var @string = 5;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.var.cs' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.cs' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.cs' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'number.cs' }, + { startIndex: 18, type: 'delimiter.cs' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' if (x == 4)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.if.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.parenthesis.cs' }, + { startIndex: 7, type: 'identifier.cs' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.cs' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'number.cs' }, + { startIndex: 13, type: 'delimiter.parenthesis.cs' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' for (int i = 4; i<10; i++)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.for.cs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.cs' }, + { startIndex: 9, type: 'keyword.int.cs' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.cs' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.cs' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'number.cs' }, + { startIndex: 18, type: 'delimiter.cs' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'identifier.cs' }, + { startIndex: 21, type: 'delimiter.angle.cs' }, + { startIndex: 22, type: 'number.cs' }, + { startIndex: 24, type: 'delimiter.cs' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'identifier.cs' }, + { startIndex: 27, type: 'delimiter.cs' }, + { startIndex: 29, type: 'delimiter.parenthesis.cs' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' var d = i;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'keyword.var.cs' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.cs' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.cs' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.cs' }, + { startIndex: 14, type: 'delimiter.cs' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' else', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.else.cs' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' return;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.return.cs' }, + { startIndex: 10, type: 'delimiter.cs' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: ' Process.Start(si);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'identifier.cs' }, + { startIndex: 10, type: 'delimiter.cs' }, + { startIndex: 11, type: 'identifier.cs' }, + { startIndex: 16, type: 'delimiter.parenthesis.cs' }, + { startIndex: 17, type: 'identifier.cs' }, + { startIndex: 19, type: 'delimiter.parenthesis.cs' }, + { startIndex: 20, type: 'delimiter.cs' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.cs' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.cs' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.cs' }] + }, + { + line: '', + tokens: [] + }, + { + line: '#pragma region /MapLayer/*Image* /// ', + tokens: [{ startIndex: 0, type: 'namespace.cpp.cs' }] + }, + { + line: 'namespace ShouldNotBeAComment {}', + tokens: [ + { startIndex: 0, type: 'keyword.namespace.cs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'namespace.cs' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'delimiter.curly.cs' } + ] + }, + { + line: '#pragma endregion Region_1', + tokens: [{ startIndex: 0, type: 'namespace.cpp.cs' }] + } + ], + + // Keywords + [ + { + line: 'namespace VS { class Program { static void Main(string[] args) {} } }', + tokens: [ + { startIndex: 0, type: 'keyword.namespace.cs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'namespace.cs' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.curly.cs' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'keyword.class.cs' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'identifier.cs' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'delimiter.curly.cs' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'keyword.static.cs' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'keyword.void.cs' }, + { startIndex: 42, type: '' }, + { startIndex: 43, type: 'identifier.cs' }, + { startIndex: 47, type: 'delimiter.parenthesis.cs' }, + { startIndex: 48, type: 'keyword.string.cs' }, + { startIndex: 54, type: 'delimiter.square.cs' }, + { startIndex: 56, type: '' }, + { startIndex: 57, type: 'identifier.cs' }, + { startIndex: 61, type: 'delimiter.parenthesis.cs' }, + { startIndex: 62, type: '' }, + { startIndex: 63, type: 'delimiter.curly.cs' }, + { startIndex: 65, type: '' }, + { startIndex: 66, type: 'delimiter.curly.cs' }, + { startIndex: 67, type: '' }, + { startIndex: 68, type: 'delimiter.curly.cs' } + ] + } + ], + + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.cs' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.cs' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.cs' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.cs' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.cs' }, + { startIndex: 1, type: 'identifier.cs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.cs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.cs' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.cs' }, + { startIndex: 5, type: 'delimiter.cs' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.cs' } + ] + } + ], + + [ + { + line: 'var x = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.var.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.cs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.cs' }, + { startIndex: 9, type: 'delimiter.cs' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.cs' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.cs' }] + } + ], + + [ + { + line: 'var x = /* a simple comment */ 1;', + tokens: [ + { startIndex: 0, type: 'keyword.var.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.cs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.cs' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.cs' }, + { startIndex: 32, type: 'delimiter.cs' } + ] + } + ], + + [ + { + line: 'var x = /* comment */ 1; */', + tokens: [ + { startIndex: 0, type: 'keyword.var.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.cs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.cs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.cs' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.cs' }, + { startIndex: 23, type: 'delimiter.cs' }, + { startIndex: 24, type: '' } + ] + } + ], + + [ + { + line: 'x = /**/;', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.cs' }, + { startIndex: 8, type: 'delimiter.cs' } + ] + } + ], + + [ + { + line: 'x = /*/;', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.cs' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.cs' }] + } + ], + + [ + { + line: '123_456', + tokens: [{ startIndex: 0, type: 'number.cs' }] + } + ], + + [ + { + line: '0x', + tokens: [ + { startIndex: 0, type: 'number.cs' }, + { startIndex: 1, type: 'identifier.cs' } + ] + } + ], + + [ + { + line: '0b', + tokens: [ + { startIndex: 0, type: 'number.cs' }, + { startIndex: 1, type: 'identifier.cs' } + ] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.cs' }] + } + ], + + [ + { + line: '0x123_456', + tokens: [{ startIndex: 0, type: 'number.hex.cs' }] + } + ], + + [ + { + line: '0b101', + tokens: [{ startIndex: 0, type: 'number.hex.cs' }] + } + ], + + [ + { + line: '0b1010_0001', + tokens: [{ startIndex: 0, type: 'number.hex.cs' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1_23.5', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '23.5F', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '23.5f', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '2_3.5f', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72E3F', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72E3f', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72e3F', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72e3f', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '23.5D', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '456_123.5D', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '23.5d', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72E3D', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72E3d', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.720_123E3d', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72e3D', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '1.72e3d', + tokens: [{ startIndex: 0, type: 'number.float.cs' }] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.cs' }, + { startIndex: 1, type: 'delimiter.cs' }, + { startIndex: 2, type: 'number.cs' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.cs' }, + { startIndex: 3, type: 'delimiter.cs' }, + { startIndex: 4, type: 'number.cs' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.cs' } + ] + } + ], + + // Strings + [ + { + line: 'x = "string";', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.quote.cs' }, + { startIndex: 5, type: 'string.cs' }, + { startIndex: 11, type: 'string.quote.cs' }, + { startIndex: 12, type: 'delimiter.cs' } + ] + } + ], + + [ + { + line: 'x = "stri\\"ng";', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.quote.cs' }, + { startIndex: 5, type: 'string.cs' }, + { startIndex: 9, type: 'string.escape.cs' }, + { startIndex: 11, type: 'string.cs' }, + { startIndex: 13, type: 'string.quote.cs' }, + { startIndex: 14, type: 'delimiter.cs' } + ] + } + ], + + // Verbatim Strings + [ + { + line: 'x = @"verbatimstring";', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.quote.cs' }, + { startIndex: 6, type: 'string.cs' }, + { startIndex: 20, type: 'string.quote.cs' }, + { startIndex: 21, type: 'delimiter.cs' } + ] + } + ], + + [ + { + line: 'x = @"verbatim""string";', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.quote.cs' }, + { startIndex: 6, type: 'string.cs' }, + { startIndex: 14, type: 'string.escape.cs' }, + { startIndex: 16, type: 'string.cs' }, + { startIndex: 22, type: 'string.quote.cs' }, + { startIndex: 23, type: 'delimiter.cs' } + ] + } + ], + + [ + { + line: 'x = @"verbatim\\string\\";', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.quote.cs' }, + { startIndex: 6, type: 'string.cs' }, + { startIndex: 22, type: 'string.quote.cs' }, + { startIndex: 23, type: 'delimiter.cs' } + ] + } + ], + + [ + { + line: 'x = @"verbatim', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.quote.cs' }, + { startIndex: 6, type: 'string.cs' } + ] + }, + { + line: 'string";', + tokens: [ + { startIndex: 0, type: 'string.cs' }, + { startIndex: 6, type: 'string.quote.cs' }, + { startIndex: 7, type: 'delimiter.cs' } + ] + } + ], + + [ + { + line: 'x = $@"verbatim {interpolated} string{{}}"" ";', + tokens: [ + { startIndex: 0, type: 'identifier.cs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.cs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.quote.cs' }, + { startIndex: 7, type: 'string.cs' }, + { startIndex: 16, type: 'string.quote.cs' }, + { startIndex: 17, type: 'identifier.cs' }, + { startIndex: 29, type: 'string.quote.cs' }, + { startIndex: 30, type: 'string.cs' }, + { startIndex: 37, type: 'string.escape.cs' }, + { startIndex: 39, type: 'string.cs' }, + { startIndex: 41, type: 'string.escape.cs' }, + { startIndex: 43, type: 'string.cs' }, + { startIndex: 44, type: 'string.quote.cs' }, + { startIndex: 45, type: 'delimiter.cs' } + ] + } + ] +]); diff --git a/monaco-languages/src/csharp/csharp.ts b/monaco-languages/src/csharp/csharp.ts new file mode 100644 index 00000000..3b2e3e73 --- /dev/null +++ b/monaco-languages/src/csharp/csharp.ts @@ -0,0 +1,352 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\#\$\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: "'", close: "'" }, + { open: '"', close: '"' } + ], + folding: { + markers: { + start: new RegExp('^\\s*#region\\b'), + end: new RegExp('^\\s*#endregion\\b') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.cs', + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + keywords: [ + 'extern', + 'alias', + 'using', + 'bool', + 'decimal', + 'sbyte', + 'byte', + 'short', + 'ushort', + 'int', + 'uint', + 'long', + 'ulong', + 'char', + 'float', + 'double', + 'object', + 'dynamic', + 'string', + 'assembly', + 'is', + 'as', + 'ref', + 'out', + 'this', + 'base', + 'new', + 'typeof', + 'void', + 'checked', + 'unchecked', + 'default', + 'delegate', + 'var', + 'const', + 'if', + 'else', + 'switch', + 'case', + 'while', + 'do', + 'for', + 'foreach', + 'in', + 'break', + 'continue', + 'goto', + 'return', + 'throw', + 'try', + 'catch', + 'finally', + 'lock', + 'yield', + 'from', + 'let', + 'where', + 'join', + 'on', + 'equals', + 'into', + 'orderby', + 'ascending', + 'descending', + 'select', + 'group', + 'by', + 'namespace', + 'partial', + 'class', + 'field', + 'event', + 'method', + 'param', + 'public', + 'protected', + 'internal', + 'private', + 'abstract', + 'sealed', + 'static', + 'struct', + 'readonly', + 'volatile', + 'virtual', + 'override', + 'params', + 'get', + 'set', + 'add', + 'remove', + 'operator', + 'true', + 'false', + 'implicit', + 'explicit', + 'interface', + 'enum', + 'null', + 'async', + 'await', + 'fixed', + 'sizeof', + 'stackalloc', + 'unsafe', + 'nameof', + 'when' + ], + + namespaceFollows: ['namespace', 'using'], + + parenFollows: ['if', 'for', 'while', 'switch', 'foreach', 'using', 'catch', 'when'], + + operators: [ + '=', + '??', + '||', + '&&', + '|', + '^', + '&', + '==', + '!=', + '<=', + '>=', + '<<', + '+', + '-', + '*', + '/', + '%', + '!', + '~', + '++', + '--', + '+=', + '-=', + '*=', + '/=', + '%=', + '&=', + '|=', + '^=', + '<<=', + '>>=', + '>>', + '=>' + ], + + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [/[0-9_]*\.[0-9_]+([eE][\-+]?\d+)?[fFdD]?/, 'number.float'], + [/0[xX][0-9a-fA-F_]+/, 'number.hex'], + [/0[bB][01_]+/, 'number.hex'], // binary: use same theme style as hex + [/[0-9_]+/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, { token: 'string.quote', next: '@string' }], + [/\$\@"/, { token: 'string.quote', next: '@litinterpstring' }], + [/\@"/, { token: 'string.quote', next: '@litstring' }], + [/\$"/, { token: 'string.quote', next: '@interpolatedstring' }], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + qualified: [ + [ + /[a-zA-Z_][\w]*/, + { + cases: { + '@keywords': { token: 'keyword.$0' }, + '@default': 'identifier' + } + } + ], + [/\./, 'delimiter'], + ['', '', '@pop'] + ], + + namespace: [ + { include: '@whitespace' }, + [/[A-Z]\w*/, 'namespace'], + [/[\.=]/, 'delimiter'], + ['', '', '@pop'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + // [/\/\*/, 'comment', '@push' ], // no nested comments :-( + ['\\*/', 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, { token: 'string.quote', next: '@pop' }] + ], + + litstring: [ + [/[^"]+/, 'string'], + [/""/, 'string.escape'], + [/"/, { token: 'string.quote', next: '@pop' }] + ], + + litinterpstring: [ + [/[^"{]+/, 'string'], + [/""/, 'string.escape'], + [/{{/, 'string.escape'], + [/}}/, 'string.escape'], + [/{/, { token: 'string.quote', next: 'root.litinterpstring' }], + [/"/, { token: 'string.quote', next: '@pop' }] + ], + + interpolatedstring: [ + [/[^\\"{]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/{{/, 'string.escape'], + [/}}/, 'string.escape'], + [/{/, { token: 'string.quote', next: 'root.interpolatedstring' }], + [/"/, { token: 'string.quote', next: '@pop' }] + ], + + whitespace: [ + [/^[ \t\v\f]*#((r)|(load))(?=\s)/, 'directive.csx'], + [/^[ \t\v\f]*#\w.*$/, 'namespace.cpp'], + [/[ \t\v\f\r\n]+/, ''], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ] + } +}; diff --git a/monaco-languages/src/csp/csp.contribution.ts b/monaco-languages/src/csp/csp.contribution.ts new file mode 100644 index 00000000..59a7be78 --- /dev/null +++ b/monaco-languages/src/csp/csp.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'csp', + extensions: [], + aliases: ['CSP', 'csp'], + loader: () => import('./csp') +}); diff --git a/monaco-languages/src/csp/csp.test.ts b/monaco-languages/src/csp/csp.test.ts new file mode 100644 index 00000000..318769d8 --- /dev/null +++ b/monaco-languages/src/csp/csp.test.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('csp', []); diff --git a/monaco-languages/src/csp/csp.ts b/monaco-languages/src/csp/csp.ts new file mode 100644 index 00000000..e93be69d --- /dev/null +++ b/monaco-languages/src/csp/csp.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + brackets: [], + autoClosingPairs: [], + surroundingPairs: [] +}; + +export const language = { + // Set defaultToken to invalid to see what you do not tokenize yet + // defaultToken: 'invalid', + keywords: [], + typeKeywords: [], + tokenPostfix: '.csp', + operators: [], + symbols: /[=> import('./css') +}); diff --git a/monaco-languages/src/css/css.test.ts b/monaco-languages/src/css/css.test.ts new file mode 100644 index 00000000..1c072f71 --- /dev/null +++ b/monaco-languages/src/css/css.test.ts @@ -0,0 +1,591 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('css', [ + // Skip whitespace + [ + { + line: ' body', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'tag.css' } + ] + } + ], + + // CSS rule + // body { + // margin: 0; + // padding: 3em 6em; + // font-family: tahoma, arial, sans-serif; + // text-decoration: none !important; + // color: #000 + // } + [ + { + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' margin: 0;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'attribute.value.number.css' }, + { startIndex: 11, type: 'delimiter.css' } + ] + }, + { + line: ' padding: 3em 6em;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'attribute.value.number.css' }, + { startIndex: 12, type: 'attribute.value.unit.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.value.number.css' }, + { startIndex: 16, type: 'attribute.value.unit.css' }, + { startIndex: 18, type: 'delimiter.css' } + ] + }, + { + line: ' font-family: tahoma, arial, sans-serif;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.value.css' }, + { startIndex: 21, type: 'delimiter.css' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'attribute.value.css' }, + { startIndex: 28, type: 'delimiter.css' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'attribute.value.css' }, + { startIndex: 40, type: 'delimiter.css' } + ] + }, + { + line: ' text-decoration: none !important;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'attribute.value.css' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'keyword.css' }, + { startIndex: 34, type: 'delimiter.css' } + ] + }, + { + line: ' color: #000', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'attribute.value.hex.css' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' } + ] + } + ], + + // CSS units and numbers + [ + { + line: '* { padding: 3em -9pt -0.5px; }', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'attribute.name.css' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.value.number.css' }, + { startIndex: 14, type: 'attribute.value.unit.css' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'attribute.value.number.css' }, + { startIndex: 19, type: 'attribute.value.unit.css' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'attribute.value.number.css' }, + { startIndex: 26, type: 'attribute.value.unit.css' }, + { startIndex: 28, type: 'delimiter.css' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'delimiter.bracket.css' } + ] + } + ], + + // CSS unfinished unit and numbers + [ + { + line: '* { padding: -', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'attribute.name.css' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.css' } + ] + } + ], + + // CSS single line comment + // h1 /*comment*/ p { + [ + { + line: 'h1 /*comment*/ p {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'comment.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'tag.css' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.bracket.css' } + ] + } + ], + + // CSS multi line comment + // h1 /*com + // ment*/ p { + [ + { + line: 'h1 /*com', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'comment.css' } + ] + }, + { + line: 'ment*/ p', + tokens: [ + { startIndex: 0, type: 'comment.css' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'tag.css' } + ] + } + ], + + // CSS ID rule + [ + { + line: '#myID {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.bracket.css' } + ] + } + ], + + // CSS Class rules + [ + { + line: '.myID {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.bracket.css' } + ] + } + ], + + // CSS @import etc + [ + { + line: '@import url("something.css");', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.value.css' }, + { startIndex: 11, type: 'delimiter.parenthesis.css' }, + { startIndex: 12, type: 'string.css' }, + { startIndex: 27, type: 'delimiter.parenthesis.css' }, + { startIndex: 28, type: 'delimiter.css' } + ] + } + ], + + // CSS multi-line string with an escaped newline + // body { + // content: 'con\ + // tent'; + [ + { + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' content: "con\\', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.css' } + ] + }, + { + line: 'tent";', + tokens: [ + { startIndex: 0, type: 'string.css' }, + { startIndex: 5, type: 'delimiter.css' } + ] + } + ], + + // CSS empty string value + // body { + // content: ''; + [ + { + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' content: "";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.css' }, + { startIndex: 13, type: 'delimiter.css' } + ] + } + ], + + // CSS font face + // @font-face { + // font-family: 'Opificio'; + // } + [ + { + line: '@font-face {', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' font-family: "Opificio";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'string.css' }, + { startIndex: 25, type: 'delimiter.css' } + ] + } + ], + + // CSS string with escaped quotes + // 's\"tr' + [ + { + line: '"s\\"tr" ', + tokens: [ + { startIndex: 0, type: 'string.css' }, + { startIndex: 7, type: '' } + ] + } + ], + + // CSS key frame animation syntax + //@-webkit-keyframes infinite-spinning { + // from { + // -webkit-transform: rotate(0deg); + // } + // to { + // -webkit-transform: rotate(360deg); + // } + //} + [ + { + line: '@-webkit-keyframes infinite-spinning {', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'attribute.value.css' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' from {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.value.css' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' -webkit-transform: rotate(0deg);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'attribute.value.css' }, + { startIndex: 28, type: 'attribute.value.number.css' }, + { startIndex: 29, type: 'attribute.value.unit.css' }, + { startIndex: 32, type: 'attribute.value.css' }, + { startIndex: 33, type: 'delimiter.css' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' to {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.value.css' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.bracket.css' } + ] + }, + { + line: ' -webkit-transform: rotate(360deg);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.css' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'attribute.value.css' }, + { startIndex: 28, type: 'attribute.value.number.css' }, + { startIndex: 31, type: 'attribute.value.unit.css' }, + { startIndex: 34, type: 'attribute.value.css' }, + { startIndex: 35, type: 'delimiter.css' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.bracket.css' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.bracket.css' }] + } + ], + + // CSS @import related coloring bug 9553 + // @import url('something.css'); + // .rule1{} + // .rule2{} + [ + { + line: '@import url("something.css");', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.value.css' }, + { startIndex: 11, type: 'delimiter.parenthesis.css' }, + { startIndex: 12, type: 'string.css' }, + { startIndex: 27, type: 'delimiter.parenthesis.css' }, + { startIndex: 28, type: 'delimiter.css' } + ] + }, + { + line: '.rule1{}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 6, type: 'delimiter.bracket.css' } + ] + }, + { + line: '.rule2{}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 6, type: 'delimiter.bracket.css' } + ] + } + ], + + // Triple quotes - bug #9870 + [ + { + line: '"""', + tokens: [{ startIndex: 0, type: 'string.css' }] + } + ], + + [ + { + line: '""""', + tokens: [{ startIndex: 0, type: 'string.css' }] + } + ], + + [ + { + line: '"""""', + tokens: [{ startIndex: 0, type: 'string.css' }] + } + ], + + // import statement - bug #10308 + // @import url('something.css');@import url('something.css'); + [ + { + line: '@import url("something.css");@import url("something.css");', + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.value.css' }, + { startIndex: 11, type: 'delimiter.parenthesis.css' }, + { startIndex: 12, type: 'string.css' }, + { startIndex: 27, type: 'delimiter.parenthesis.css' }, + { startIndex: 28, type: 'delimiter.css' }, + { startIndex: 29, type: 'keyword.css' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'attribute.value.css' }, + { startIndex: 40, type: 'delimiter.parenthesis.css' }, + { startIndex: 41, type: 'string.css' }, + { startIndex: 56, type: 'delimiter.parenthesis.css' }, + { startIndex: 57, type: 'delimiter.css' } + ] + } + ], + + // !important - bug #9578 + // .a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;} + [ + { + line: '.a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 2, type: 'delimiter.bracket.css' }, + { startIndex: 3, type: 'attribute.name.css' }, + { startIndex: 14, type: 'attribute.value.hex.css' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'keyword.css' }, + { startIndex: 32, type: 'delimiter.bracket.css' }, + { startIndex: 33, type: 'tag.css' }, + { startIndex: 35, type: 'delimiter.bracket.css' }, + { startIndex: 36, type: 'attribute.name.css' }, + { startIndex: 48, type: 'string.css' }, + { startIndex: 64, type: 'delimiter.css' }, + { startIndex: 65, type: '' }, + { startIndex: 66, type: 'attribute.value.css' }, + { startIndex: 75, type: 'delimiter.css' }, + { startIndex: 76, type: 'attribute.name.css' }, + { startIndex: 83, type: 'attribute.value.number.css' }, + { startIndex: 85, type: 'attribute.value.unit.css' }, + { startIndex: 87, type: 'delimiter.css' }, + { startIndex: 88, type: 'delimiter.bracket.css' } + ] + } + ], + + // base64-encoded data uris - bug #9580 + //.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom} + [ + { + line: '.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.bracket.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name.css' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'attribute.value.hex.css' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'attribute.value.css' }, + { startIndex: 28, type: 'delimiter.parenthesis.css' }, + { startIndex: 29, type: 'string.css' }, + { startIndex: 215, type: 'delimiter.parenthesis.css' }, + { startIndex: 216, type: '' }, + { startIndex: 217, type: 'attribute.value.css' }, + { startIndex: 225, type: '' }, + { startIndex: 226, type: 'attribute.value.css' }, + { startIndex: 232, type: 'delimiter.bracket.css' } + ] + } + ], + + // /a colorization is incorrect in url - bug #9581 + //.a{background:url(/a.jpg)} + [ + { + line: '.a{background:url(/a.jpg)}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 2, type: 'delimiter.bracket.css' }, + { startIndex: 3, type: 'attribute.name.css' }, + { startIndex: 14, type: 'attribute.value.css' }, + { startIndex: 17, type: 'delimiter.parenthesis.css' }, + { startIndex: 18, type: 'string.css' }, + { startIndex: 24, type: 'delimiter.parenthesis.css' }, + { startIndex: 25, type: 'delimiter.bracket.css' } + ] + } + ], + + // Bracket Matching + [ + { + line: 'p{}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 1, type: 'delimiter.bracket.css' } + ] + } + ], + + [ + { + line: 'p:nth() {}', + tokens: [ + { startIndex: 0, type: 'tag.css' }, + { startIndex: 5, type: '' }, + { startIndex: 8, type: 'delimiter.bracket.css' } + ] + } + ], + + [ + { + line: "@import 'https://example.com/test.css';", + tokens: [ + { startIndex: 0, type: 'keyword.css' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.css' }, + { startIndex: 38, type: 'delimiter.css' } + ] + } + ] +]); diff --git a/monaco-languages/src/css/css.ts b/monaco-languages/src/css/css.ts new file mode 100644 index 00000000..72c7bd16 --- /dev/null +++ b/monaco-languages/src/css/css.ts @@ -0,0 +1,221 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + wordPattern: /(#?-?\d*\.\d\w*%?)|((::|[@#.!:])?[\w-?]+%?)|::|[@#.!:]/g, + + comments: { + blockComment: ['/*', '*/'] + }, + + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + + autoClosingPairs: [ + { open: '{', close: '}', notIn: ['string', 'comment'] }, + { open: '[', close: ']', notIn: ['string', 'comment'] }, + { open: '(', close: ')', notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] }, + { open: "'", close: "'", notIn: ['string', 'comment'] } + ], + + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + folding: { + markers: { + start: new RegExp('^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/'), + end: new RegExp('^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.css', + + ws: '[ \t\n\r\f]*', // whitespaces (referenced in several rules) + identifier: + '-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*', + + brackets: [ + { open: '{', close: '}', token: 'delimiter.bracket' }, + { open: '[', close: ']', token: 'delimiter.bracket' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + tokenizer: { + root: [{ include: '@selector' }], + + selector: [ + { include: '@comments' }, + { include: '@import' }, + { include: '@strings' }, + [ + '[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', + { token: 'keyword', next: '@keyframedeclaration' } + ], + ['[@](page|content|font-face|-moz-document)', { token: 'keyword' }], + ['[@](charset|namespace)', { token: 'keyword', next: '@declarationbody' }], + [ + '(url-prefix)(\\()', + ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] + ], + [ + '(url)(\\()', + ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] + ], + { include: '@selectorname' }, + ['[\\*]', 'tag'], // selector symbols + ['[>\\+,]', 'delimiter'], // selector operators + ['\\[', { token: 'delimiter.bracket', next: '@selectorattribute' }], + ['{', { token: 'delimiter.bracket', next: '@selectorbody' }] + ], + + selectorbody: [ + { include: '@comments' }, + ['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', 'attribute.name', '@rulevalue'], // rule definition: to distinguish from a nested selector check for whitespace, number or a semicolon + ['}', { token: 'delimiter.bracket', next: '@pop' }] + ], + + selectorname: [ + ['(\\.|#(?=[^{])|%|(@identifier)|:)+', 'tag'] // selector (.foo, div, ...) + ], + + selectorattribute: [ + { include: '@term' }, + [']', { token: 'delimiter.bracket', next: '@pop' }] + ], + + term: [ + { include: '@comments' }, + [ + '(url-prefix)(\\()', + ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] + ], + [ + '(url)(\\()', + ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] + ], + { include: '@functioninvocation' }, + { include: '@numbers' }, + { include: '@name' }, + { include: '@strings' }, + ['([<>=\\+\\-\\*\\/\\^\\|\\~,])', 'delimiter'], + [',', 'delimiter'] + ], + + rulevalue: [ + { include: '@comments' }, + { include: '@strings' }, + { include: '@term' }, + ['!important', 'keyword'], + [';', 'delimiter', '@pop'], + ['(?=})', { token: '', next: '@pop' }] // missing semicolon + ], + + warndebug: [['[@](warn|debug)', { token: 'keyword', next: '@declarationbody' }]], + + import: [['[@](import)', { token: 'keyword', next: '@declarationbody' }]], + + urldeclaration: [ + { include: '@strings' }, + ['[^)\r\n]+', 'string'], + ['\\)', { token: 'delimiter.parenthesis', next: '@pop' }] + ], + + parenthizedterm: [ + { include: '@term' }, + ['\\)', { token: 'delimiter.parenthesis', next: '@pop' }] + ], + + declarationbody: [ + { include: '@term' }, + [';', 'delimiter', '@pop'], + ['(?=})', { token: '', next: '@pop' }] // missing semicolon + ], + + comments: [ + ['\\/\\*', 'comment', '@comment'], + ['\\/\\/+.*', 'comment'] + ], + + comment: [ + ['\\*\\/', 'comment', '@pop'], + [/[^*/]+/, 'comment'], + [/./, 'comment'] + ], + + name: [['@identifier', 'attribute.value']], + + numbers: [ + [ + '-?(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', + { token: 'attribute.value.number', next: '@units' } + ], + ['#[0-9a-fA-F_]+(?!\\w)', 'attribute.value.hex'] + ], + + units: [ + [ + '(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?', + 'attribute.value.unit', + '@pop' + ] + ], + + keyframedeclaration: [ + ['@identifier', 'attribute.value'], + ['{', { token: 'delimiter.bracket', switchTo: '@keyframebody' }] + ], + + keyframebody: [ + { include: '@term' }, + ['{', { token: 'delimiter.bracket', next: '@selectorbody' }], + ['}', { token: 'delimiter.bracket', next: '@pop' }] + ], + + functioninvocation: [ + ['@identifier\\(', { token: 'attribute.value', next: '@functionarguments' }] + ], + + functionarguments: [ + ['\\$@identifier@ws:', 'attribute.name'], + ['[,]', 'delimiter'], + { include: '@term' }, + ['\\)', { token: 'attribute.value', next: '@pop' }] + ], + + strings: [ + ['~?"', { token: 'string', next: '@stringenddoublequote' }], + ["~?'", { token: 'string', next: '@stringendquote' }] + ], + + stringenddoublequote: [ + ['\\\\.', 'string'], + ['"', { token: 'string', next: '@pop' }], + [/[^\\"]+/, 'string'], + ['.', 'string'] + ], + + stringendquote: [ + ['\\\\.', 'string'], + ["'", { token: 'string', next: '@pop' }], + [/[^\\']+/, 'string'], + ['.', 'string'] + ] + } +}; diff --git a/monaco-languages/src/dart/dart.contribution.ts b/monaco-languages/src/dart/dart.contribution.ts new file mode 100644 index 00000000..7b3cff5e --- /dev/null +++ b/monaco-languages/src/dart/dart.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'dart', + extensions: ['.dart'], + aliases: ['Dart', 'dart'], + mimetypes: ['text/x-dart-source', 'text/x-dart'], + loader: () => import('./dart') +}); diff --git a/monaco-languages/src/dart/dart.test.ts b/monaco-languages/src/dart/dart.test.ts new file mode 100644 index 00000000..14e822e4 --- /dev/null +++ b/monaco-languages/src/dart/dart.test.ts @@ -0,0 +1,558 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('dart', [ + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.dart' } + ] + } + ], + + // Broken nested tokens due to invalid comment tokenization + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.dart' }, + { startIndex: 1, type: 'identifier.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.dart' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.dart' }, + { startIndex: 5, type: 'delimiter.dart' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.dart' } + ] + } + ], + + [ + { + line: 'var x = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.dart' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.dart' }, + { startIndex: 9, type: 'delimiter.dart' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.dart' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + } + ], + + [ + { + line: 'var x = /* a simple comment */ 1;', + tokens: [ + { startIndex: 0, type: 'keyword.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.dart' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.dart' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.dart' }, + { startIndex: 32, type: 'delimiter.dart' } + ] + } + ], + + [ + { + line: 'var x = /* comment */ 1; */', + tokens: [ + { startIndex: 0, type: 'keyword.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.dart' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.dart' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.dart' }, + { startIndex: 23, type: 'delimiter.dart' }, + { startIndex: 24, type: '' } + ] + } + ], + + [ + { + line: 'x = /**/;', + tokens: [ + { startIndex: 0, type: 'identifier.dart' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.dart' }, + { startIndex: 8, type: 'delimiter.dart' } + ] + } + ], + + [ + { + line: 'x = /*/;', + tokens: [ + { startIndex: 0, type: 'identifier.dart' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.dart' } + ] + } + ], + + // Comments - range comment, multiple lines + [ + { + line: '/* start of multiline comment', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + }, + { + line: 'a comment between without a star', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + }, + { + line: 'end of multiline comment*/', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + } + ], + + [ + { + line: 'var x = /* start a comment', + tokens: [ + { startIndex: 0, type: 'keyword.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.dart' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.dart' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.dart' }] + }, + { + line: 'and end it */ 2;', + tokens: [ + { startIndex: 0, type: 'comment.dart' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.dart' }, + { startIndex: 15, type: 'delimiter.dart' } + ] + } + ], + + // Keywords + [ + { + line: 'var x = function() { };', + tokens: [ + { startIndex: 0, type: 'keyword.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.dart' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.dart' }, + { startIndex: 16, type: 'delimiter.parenthesis.dart' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'delimiter.bracket.dart' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.bracket.dart' }, + { startIndex: 22, type: 'delimiter.dart' } + ] + } + ], + + [ + { + line: ' var ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.dart' }, + { startIndex: 7, type: '' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.dart' }] + } + ], + + [ + { + line: '0.10', + tokens: [{ startIndex: 0, type: 'number.float.dart' }] + } + ], + + [ + { + line: '0x', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 1, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.dart' }] + } + ], + + [ + { + line: '0x5_2', + tokens: [{ startIndex: 0, type: 'number.hex.dart' }] + } + ], + [ + { + line: '0b1010_0101', + tokens: [{ startIndex: 0, type: 'number.binary.dart' }] + } + ], + + [ + { + line: '0B001', + tokens: [{ startIndex: 0, type: 'number.binary.dart' }] + } + ], + + [ + { + line: '10e3', + tokens: [{ startIndex: 0, type: 'number.float.dart' }] + } + ], + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.dart' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.dart' }] + } + ], + + [ + { + line: '23.5e-3', + tokens: [{ startIndex: 0, type: 'number.float.dart' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.dart' }] + } + ], + + [ + { + line: '23.5E-3', + tokens: [{ startIndex: 0, type: 'number.float.dart' }] + } + ], + + [ + { + line: '0_52', + tokens: [{ startIndex: 0, type: 'number.dart' }] + } + ], + + [ + { + line: '5_2', + tokens: [{ startIndex: 0, type: 'number.dart' }] + } + ], + + [ + { + line: '5_______2', + tokens: [{ startIndex: 0, type: 'number.dart' }] + } + ], + [ + { + line: '3._1415F', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 1, type: 'delimiter.dart' }, + { startIndex: 2, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '999_99_9999_L', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 11, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '52_', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 2, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '0_x52', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 1, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '0x_52', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 1, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '0x52_', + tokens: [ + { startIndex: 0, type: 'number.hex.dart' }, + { startIndex: 4, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '052_', + tokens: [ + { startIndex: 0, type: 'number.octal.dart' }, + { startIndex: 3, type: 'identifier.dart' } + ] + } + ], + + [ + { + line: '23.5L', + tokens: [ + { startIndex: 0, type: 'number.float.dart' }, + { startIndex: 4, type: 'type.identifier.dart' } + ] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 1, type: 'delimiter.dart' }, + { startIndex: 2, type: 'number.dart' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 3, type: 'delimiter.dart' }, + { startIndex: 4, type: 'number.dart' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.dart' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.dart' } + ] + } + ], + + // Strings + [ + { + line: "var s = 's';", + tokens: [ + { startIndex: 0, type: 'keyword.dart' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.dart' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.dart' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.dart' }, + { startIndex: 11, type: 'delimiter.dart' } + ] + } + ], + + [ + { + line: 'String s = "concatenated" + " String" ;', + tokens: [ + { startIndex: 0, type: 'type.identifier.dart' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.dart' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.dart' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.dart' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'delimiter.dart' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'string.dart' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'delimiter.dart' } + ] + } + ], + + [ + { + line: '"quote in a string"', + tokens: [{ startIndex: 0, type: 'string.dart' }] + } + ], + + [ + { + line: '"escaping \\"quotes\\" is cool"', + tokens: [ + { startIndex: 0, type: 'string.dart' }, + { startIndex: 10, type: 'string.escape.dart' }, + { startIndex: 12, type: 'string.dart' }, + { startIndex: 18, type: 'string.escape.dart' }, + { startIndex: 20, type: 'string.dart' } + ] + } + ], + + [ + { + line: '"\\"', + tokens: [{ startIndex: 0, type: 'string.invalid.dart' }] + } + ], + + // Annotations + [ + { + line: '@', + tokens: [{ startIndex: 0, type: 'invalid.dart' }] + } + ], + + [ + { + line: '@Override', + tokens: [{ startIndex: 0, type: 'annotation.dart' }] + } + ] +]); diff --git a/monaco-languages/src/dart/dart.ts b/monaco-languages/src/dart/dart.ts new file mode 100644 index 00000000..cced4048 --- /dev/null +++ b/monaco-languages/src/dart/dart.ts @@ -0,0 +1,308 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string'] }, + { open: '`', close: '`', notIn: ['string', 'comment'] }, + { open: '/**', close: ' */', notIn: ['string'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + + { open: '<', close: '>' }, + { open: "'", close: "'" }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: '`', close: '`' } + ], + folding: { + markers: { + start: /^\s*\s*#?region\b/, + end: /^\s*\s*#?endregion\b/ + } + } +}; + +export const language = { + defaultToken: 'invalid', + tokenPostfix: '.dart', + + keywords: [ + 'abstract', + 'dynamic', + 'implements', + 'show', + 'as', + 'else', + 'import', + 'static', + 'assert', + 'enum', + 'in', + 'super', + 'async', + 'export', + 'interface', + 'switch', + 'await', + 'extends', + 'is', + 'sync', + 'break', + 'external', + 'library', + 'this', + 'case', + 'factory', + 'mixin', + 'throw', + 'catch', + 'false', + 'new', + 'true', + 'class', + 'final', + 'null', + 'try', + 'const', + 'finally', + 'on', + 'typedef', + 'continue', + 'for', + 'operator', + 'var', + 'covariant', + 'Function', + 'part', + 'void', + 'default', + 'get', + 'rethrow', + 'while', + 'deferred', + 'hide', + 'return', + 'with', + 'do', + 'if', + 'set', + 'yield' + ], + typeKeywords: ['int', 'double', 'String', 'bool'], + + operators: [ + '+', + '-', + '*', + '/', + '~/', + '%', + '++', + '--', + '==', + '!=', + '>', + '<', + '>=', + '<=', + '=', + '-=', + '/=', + '%=', + '>>=', + '^=', + '+=', + '*=', + '~/=', + '<<=', + '&=', + '!=', + '||', + '&&', + '&', + '|', + '^', + '~', + '<<', + '>>', + '!', + '>>>', + '??', + '?', + ':', + '|=' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [/!(?=([^=]|$))/, 'delimiter'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [/(@digits)[eE]([\-+]?(@digits))?/, 'number.float'], + [/(@digits)\.(@digits)([eE][\-+]?(@digits))?/, 'number.float'], + [/0[xX](@hexdigits)n?/, 'number.hex'], + [/0[oO]?(@octaldigits)n?/, 'number.octal'], + [/0[bB](@binarydigits)n?/, 'number.binary'], + [/(@digits)n?/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/'([^'\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, 'string', '@string_double'], + [/'/, 'string', '@string_single'] + + // [/[a-zA-Z]+/, "variable"] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@jsdoc'], + [/\/\*/, 'comment', '@comment'], + [/\/\/\/.*$/, 'comment.doc'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + jsdoc: [ + [/[^\/*]+/, 'comment.doc'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'] + ], + + // We match regular expression quite precisely + regexp: [ + [ + /(\{)(\d+(?:,\d*)?)(\})/, + ['regexp.escape.control', 'regexp.escape.control', 'regexp.escape.control'] + ], + [ + /(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/, + ['regexp.escape.control', { token: 'regexp.escape.control', next: '@regexrange' }] + ], + [/(\()(\?:|\?=|\?!)/, ['regexp.escape.control', 'regexp.escape.control']], + [/[()]/, 'regexp.escape.control'], + [/@regexpctl/, 'regexp.escape.control'], + [/[^\\\/]/, 'regexp'], + [/@regexpesc/, 'regexp.escape'], + [/\\\./, 'regexp.invalid'], + [ + /(\/)([gimsuy]*)/, + [{ token: 'regexp', bracket: '@close', next: '@pop' }, 'keyword.other'] + ] + ], + + regexrange: [ + [/-/, 'regexp.escape.control'], + [/\^/, 'regexp.invalid'], + [/@regexpesc/, 'regexp.escape'], + [/[^\]]/, 'regexp'], + [ + /\]/, + { + token: 'regexp.escape.control', + next: '@pop', + bracket: '@close' + } + ] + ], + + string_double: [ + [/[^\\"\$]+/, 'string'], + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'], + [/\$\w+/, 'identifier'] + ], + + string_single: [ + [/[^\\'\$]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/'/, 'string', '@pop'], + [/\$\w+/, 'identifier'] + ] + } +}; diff --git a/monaco-languages/src/dockerfile/dockerfile.contribution.ts b/monaco-languages/src/dockerfile/dockerfile.contribution.ts new file mode 100644 index 00000000..51c73e3d --- /dev/null +++ b/monaco-languages/src/dockerfile/dockerfile.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'dockerfile', + extensions: ['.dockerfile'], + filenames: ['Dockerfile'], + aliases: ['Dockerfile'], + loader: () => import('./dockerfile') +}); diff --git a/monaco-languages/src/dockerfile/dockerfile.test.ts b/monaco-languages/src/dockerfile/dockerfile.test.ts new file mode 100644 index 00000000..fb7c8251 --- /dev/null +++ b/monaco-languages/src/dockerfile/dockerfile.test.ts @@ -0,0 +1,238 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('dockerfile', [ + // All + [ + { + line: 'FROM mono:3.12', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 4, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'ENV KRE_FEED https://www.myget.org/F/aspnetvnext/api/v2', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'variable.dockerfile' }, + { startIndex: 12, type: '' } + ] + }, + { + line: 'ENV KRE_USER_HOME /opt/kre', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'variable.dockerfile' }, + { startIndex: 17, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'RUN apt-get -qq update && apt-get -qqy install unzip ', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'ONBUILD RUN curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/kvminstall.sh | sh', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'keyword.dockerfile' }, + { startIndex: 11, type: '' } + ] + }, + { + line: 'ONBUILD RUN bash -c "source $KRE_USER_HOME/kvm/kvm.sh \\', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'keyword.dockerfile' }, + { startIndex: 11, type: '' }, + { startIndex: 20, type: 'string.dockerfile' }, + { startIndex: 28, type: 'variable.dockerfile' }, + { startIndex: 42, type: 'string.dockerfile' } + ] + }, + { + line: ' && kvm install latest -a default \\', + tokens: [{ startIndex: 0, type: 'string.dockerfile' }] + }, + { + line: ' && kvm alias default | xargs -i ln -s $KRE_USER_HOME/packages/{} $KRE_USER_HOME/packages/default"', + tokens: [ + { startIndex: 0, type: 'string.dockerfile' }, + { startIndex: 42, type: 'variable.dockerfile' }, + { startIndex: 56, type: 'string.dockerfile' }, + { startIndex: 69, type: 'variable.dockerfile' }, + { startIndex: 83, type: 'string.dockerfile' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Install libuv for Kestrel from source code (binary is not in wheezy and one in jessie is still too old)', + tokens: [{ startIndex: 0, type: 'comment.dockerfile' }] + }, + { + line: 'RUN apt-get -qqy install \\', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' } + ] + }, + { + line: ' autoconf \\', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' automake \\', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' build-essential \\', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' libtool ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: 'RUN LIBUV_VERSION=1.0.0-rc2 \\', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' } + ] + }, + { + line: ' && curl -sSL https://github.com/joyent/libuv/archive/v${LIBUV_VERSION}.tar.gz | tar zxfv - -C /usr/local/src \\', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 58, type: 'variable.dockerfile' }, + { startIndex: 74, type: '' } + ] + }, + { + line: ' && cd /usr/local/src/libuv-$LIBUV_VERSION \\', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 31, type: 'variable.dockerfile' }, + { startIndex: 45, type: '' } + ] + }, + { + line: ' && sh autogen.sh && ./configure && make && make install \\', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' && rm -rf /usr/local/src/libuv-$LIBUV_VERSION \\', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 35, type: 'variable.dockerfile' }, + { startIndex: 49, type: '' } + ] + }, + { + line: ' && ldconfig', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'ENV PATH $PATH:$KRE_USER_HOME/packages/default/bin', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'variable.dockerfile' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'variable.dockerfile' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'variable.dockerfile' }, + { startIndex: 29, type: '' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Extra things to test', + tokens: [{ startIndex: 0, type: 'comment.dockerfile' }] + }, + { + line: 'RUN echo "string at end"', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' }, + { startIndex: 9, type: 'string.dockerfile' } + ] + }, + { + line: "RUN echo must work 'some str' and some more", + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' }, + { startIndex: 19, type: 'string.dockerfile' }, + { startIndex: 29, type: '' } + ] + }, + { + line: 'RUN echo hi this is # not a comment', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' } + ] + }, + { + line: "RUN echo 'String with ${VAR} and another $one here'", + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' }, + { startIndex: 9, type: 'string.dockerfile' }, + { startIndex: 22, type: 'variable.dockerfile' }, + { startIndex: 28, type: 'string.dockerfile' }, + { startIndex: 41, type: 'variable.dockerfile' }, + { startIndex: 45, type: 'string.dockerfile' } + ] + } + ], + [ + { + line: "RUN \\'e\\'", + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' } + ] + }, + { + line: 'RUN echo hi this is # not a comment', + tokens: [ + { startIndex: 0, type: 'keyword.dockerfile' }, + { startIndex: 3, type: '' } + ] + } + ] +]); diff --git a/monaco-languages/src/dockerfile/dockerfile.ts b/monaco-languages/src/dockerfile/dockerfile.ts new file mode 100644 index 00000000..ed59327b --- /dev/null +++ b/monaco-languages/src/dockerfile/dockerfile.ts @@ -0,0 +1,145 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.dockerfile', + + variable: /\${?[\w]+}?/, + + tokenizer: { + root: [ + { include: '@whitespace' }, + { include: '@comment' }, + + [/(ONBUILD)(\s+)/, ['keyword', '']], + [/(ENV)(\s+)([\w]+)/, ['keyword', '', { token: 'variable', next: '@arguments' }]], + [ + /(FROM|MAINTAINER|RUN|EXPOSE|ENV|ADD|ARG|VOLUME|LABEL|USER|WORKDIR|COPY|CMD|STOPSIGNAL|SHELL|HEALTHCHECK|ENTRYPOINT)/, + { token: 'keyword', next: '@arguments' } + ] + ], + + arguments: [ + { include: '@whitespace' }, + { include: '@strings' }, + + [ + /(@variable)/, + { + cases: { + '@eos': { token: 'variable', next: '@popall' }, + '@default': 'variable' + } + } + ], + [ + /\\/, + { + cases: { + '@eos': '', + '@default': '' + } + } + ], + [ + /./, + { + cases: { + '@eos': { token: '', next: '@popall' }, + '@default': '' + } + } + ] + ], + + // Deal with white space, including comments + whitespace: [ + [ + /\s+/, + { + cases: { + '@eos': { token: '', next: '@popall' }, + '@default': '' + } + } + ] + ], + + comment: [[/(^#.*$)/, 'comment', '@popall']], + + // Recognize strings, including those broken across lines with \ (but not without) + strings: [ + [/\\'$/, '', '@popall'], // \' leaves @arguments at eol + [/\\'/, ''], // \' is not a string + [/'$/, 'string', '@popall'], + [/'/, 'string', '@stringBody'], + [/"$/, 'string', '@popall'], + [/"/, 'string', '@dblStringBody'] + ], + stringBody: [ + [ + /[^\\\$']/, + { + cases: { + '@eos': { token: 'string', next: '@popall' }, + '@default': 'string' + } + } + ], + + [/\\./, 'string.escape'], + [/'$/, 'string', '@popall'], + [/'/, 'string', '@pop'], + [/(@variable)/, 'variable'], + + [/\\$/, 'string'], + [/$/, 'string', '@popall'] + ], + dblStringBody: [ + [ + /[^\\\$"]/, + { + cases: { + '@eos': { token: 'string', next: '@popall' }, + '@default': 'string' + } + } + ], + + [/\\./, 'string.escape'], + [/"$/, 'string', '@popall'], + [/"/, 'string', '@pop'], + [/(@variable)/, 'variable'], + + [/\\$/, 'string'], + [/$/, 'string', '@popall'] + ] + } +}; diff --git a/monaco-languages/src/ecl/ecl.contribution.ts b/monaco-languages/src/ecl/ecl.contribution.ts new file mode 100644 index 00000000..dfa4ed90 --- /dev/null +++ b/monaco-languages/src/ecl/ecl.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'ecl', + extensions: ['.ecl'], + aliases: ['ECL', 'Ecl', 'ecl'], + loader: () => import('./ecl') +}); diff --git a/monaco-languages/src/ecl/ecl.test.ts b/monaco-languages/src/ecl/ecl.test.ts new file mode 100644 index 00000000..d2bbaed1 --- /dev/null +++ b/monaco-languages/src/ecl/ecl.test.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('ecl', []); diff --git a/monaco-languages/src/ecl/ecl.ts b/monaco-languages/src/ecl/ecl.ts new file mode 100644 index 00000000..a1061738 --- /dev/null +++ b/monaco-languages/src/ecl/ecl.ts @@ -0,0 +1,481 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: "'", close: "'" }, + { open: '"', close: '"' } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.ecl', + ignoreCase: true, + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + pounds: [ + 'append', + 'break', + 'declare', + 'demangle', + 'end', + 'for', + 'getdatatype', + 'if', + 'inmodule', + 'loop', + 'mangle', + 'onwarning', + 'option', + 'set', + 'stored', + 'uniquename' + ].join('|'), + + keywords: [ + '__compressed__', + 'after', + 'all', + 'and', + 'any', + 'as', + 'atmost', + 'before', + 'beginc', + 'best', + 'between', + 'case', + 'cluster', + 'compressed', + 'compression', + 'const', + 'counter', + 'csv', + 'default', + 'descend', + 'embed', + 'encoding', + 'encrypt', + 'end', + 'endc', + 'endembed', + 'endmacro', + 'enum', + 'escape', + 'except', + 'exclusive', + 'expire', + 'export', + 'extend', + 'fail', + 'few', + 'fileposition', + 'first', + 'flat', + 'forward', + 'from', + 'full', + 'function', + 'functionmacro', + 'group', + 'grouped', + 'heading', + 'hole', + 'ifblock', + 'import', + 'in', + 'inner', + 'interface', + 'internal', + 'joined', + 'keep', + 'keyed', + 'last', + 'left', + 'limit', + 'linkcounted', + 'literal', + 'little_endian', + 'load', + 'local', + 'locale', + 'lookup', + 'lzw', + 'macro', + 'many', + 'maxcount', + 'maxlength', + 'min skew', + 'module', + 'mofn', + 'multiple', + 'named', + 'namespace', + 'nocase', + 'noroot', + 'noscan', + 'nosort', + 'not', + 'noxpath', + 'of', + 'onfail', + 'only', + 'opt', + 'or', + 'outer', + 'overwrite', + 'packed', + 'partition', + 'penalty', + 'physicallength', + 'pipe', + 'prefetch', + 'quote', + 'record', + 'repeat', + 'retry', + 'return', + 'right', + 'right1', + 'right2', + 'rows', + 'rowset', + 'scan', + 'scope', + 'self', + 'separator', + 'service', + 'shared', + 'skew', + 'skip', + 'smart', + 'soapaction', + 'sql', + 'stable', + 'store', + 'terminator', + 'thor', + 'threshold', + 'timelimit', + 'timeout', + 'token', + 'transform', + 'trim', + 'type', + 'unicodeorder', + 'unordered', + 'unsorted', + 'unstable', + 'update', + 'use', + 'validate', + 'virtual', + 'whole', + 'width', + 'wild', + 'within', + 'wnotrim', + 'xml', + 'xpath' + ], + + functions: [ + 'abs', + 'acos', + 'aggregate', + 'allnodes', + 'apply', + 'ascii', + 'asin', + 'assert', + 'asstring', + 'atan', + 'atan2', + 'ave', + 'build', + 'buildindex', + 'case', + 'catch', + 'choose', + 'choosen', + 'choosesets', + 'clustersize', + 'combine', + 'correlation', + 'cos', + 'cosh', + 'count', + 'covariance', + 'cron', + 'dataset', + 'dedup', + 'define', + 'denormalize', + 'dictionary', + 'distribute', + 'distributed', + 'distribution', + 'ebcdic', + 'enth', + 'error', + 'evaluate', + 'event', + 'eventextra', + 'eventname', + 'exists', + 'exp', + 'fail', + 'failcode', + 'failmessage', + 'fetch', + 'fromunicode', + 'fromxml', + 'getenv', + 'getisvalid', + 'global', + 'graph', + 'group', + 'hash', + 'hash32', + 'hash64', + 'hashcrc', + 'hashmd5', + 'having', + 'httpcall', + 'httpheader', + 'if', + 'iff', + 'index', + 'intformat', + 'isvalid', + 'iterate', + 'join', + 'keydiff', + 'keypatch', + 'keyunicode', + 'length', + 'library', + 'limit', + 'ln', + 'loadxml', + 'local', + 'log', + 'loop', + 'map', + 'matched', + 'matchlength', + 'matchposition', + 'matchtext', + 'matchunicode', + 'max', + 'merge', + 'mergejoin', + 'min', + 'nofold', + 'nolocal', + 'nonempty', + 'normalize', + 'nothor', + 'notify', + 'output', + 'parallel', + 'parse', + 'pipe', + 'power', + 'preload', + 'process', + 'project', + 'pull', + 'random', + 'range', + 'rank', + 'ranked', + 'realformat', + 'recordof', + 'regexfind', + 'regexreplace', + 'regroup', + 'rejected', + 'rollup', + 'round', + 'roundup', + 'row', + 'rowdiff', + 'sample', + 'sequential', + 'set', + 'sin', + 'sinh', + 'sizeof', + 'soapcall', + 'sort', + 'sorted', + 'sqrt', + 'stepped', + 'stored', + 'sum', + 'table', + 'tan', + 'tanh', + 'thisnode', + 'topn', + 'tounicode', + 'toxml', + 'transfer', + 'transform', + 'trim', + 'truncate', + 'typeof', + 'ungroup', + 'unicodeorder', + 'variance', + 'wait', + 'which', + 'workunit', + 'xmldecode', + 'xmlencode', + 'xmltext', + 'xmlunicode' + ], + + typesint: ['integer', 'unsigned'].join('|'), + + typesnum: ['data', 'qstring', 'string', 'unicode', 'utf8', 'varstring', 'varunicode'], + + typesone: [ + 'ascii', + 'big_endian', + 'boolean', + 'data', + 'decimal', + 'ebcdic', + 'grouped', + 'integer', + 'linkcounted', + 'pattern', + 'qstring', + 'real', + 'record', + 'rule', + 'set of', + 'streamed', + 'string', + 'token', + 'udecimal', + 'unicode', + 'unsigned', + 'utf8', + 'varstring', + 'varunicode' + ].join('|'), + + operators: ['+', '-', '/', ':=', '<', '<>', '=', '>', '\\', 'and', 'in', 'not', 'or'], + + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [/[0-9_]*\.[0-9_]+([eE][\-+]?\d+)?/, 'number.float'], + [/0[xX][0-9a-fA-F_]+/, 'number.hex'], + [/0[bB][01]+/, 'number.hex'], // binary: use same theme style as hex + [/[0-9_]+/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], + [/"/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\v\f\r\n]+/, ''], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + string: [ + [/[^\\']+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/'/, 'string', '@pop'] + ] + } +}; diff --git a/monaco-languages/src/elixir/elixir.contribution.ts b/monaco-languages/src/elixir/elixir.contribution.ts new file mode 100644 index 00000000..aaeafa94 --- /dev/null +++ b/monaco-languages/src/elixir/elixir.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'elixir', + extensions: ['.ex', '.exs'], + aliases: ['Elixir', 'elixir', 'ex'], + loader: () => import('./elixir') +}); diff --git a/monaco-languages/src/elixir/elixir.test.ts b/monaco-languages/src/elixir/elixir.test.ts new file mode 100644 index 00000000..a6e9d26f --- /dev/null +++ b/monaco-languages/src/elixir/elixir.test.ts @@ -0,0 +1,376 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('elixir', [ + // Keywords - module definition + [ + { + line: 'defmodule Foo do end', + tokens: [ + { startIndex: 0, type: 'keyword.declaration.elixir' }, + { startIndex: 9, type: 'white.elixir' }, + { startIndex: 10, type: 'type.identifier.elixir' }, + { startIndex: 13, type: 'white.elixir' }, + { startIndex: 14, type: 'keyword.elixir' }, + { startIndex: 16, type: 'white.elixir' }, + { startIndex: 17, type: 'keyword.elixir' } + ] + } + ], + // Keywords - function definition + [ + { + line: 'def foo(x) do end', + tokens: [ + { startIndex: 0, type: 'keyword.declaration.elixir' }, + { startIndex: 3, type: 'white.elixir' }, + { startIndex: 4, type: 'function.elixir' }, + { startIndex: 7, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 8, type: 'identifier.elixir' }, + { startIndex: 9, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 10, type: 'white.elixir' }, + { startIndex: 11, type: 'keyword.elixir' }, + { startIndex: 13, type: 'white.elixir' }, + { startIndex: 14, type: 'keyword.elixir' } + ] + } + ], + // Keywords - macro + [ + { + line: 'defmacro mac(name) do quote do def unquote(name)() do nil end end end', + tokens: [ + { startIndex: 0, type: 'keyword.declaration.elixir' }, + { startIndex: 8, type: 'white.elixir' }, + { startIndex: 9, type: 'function.elixir' }, + { startIndex: 12, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 13, type: 'identifier.elixir' }, + { startIndex: 17, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 18, type: 'white.elixir' }, + { startIndex: 19, type: 'keyword.elixir' }, + { startIndex: 21, type: 'white.elixir' }, + { startIndex: 22, type: 'keyword.elixir' }, + { startIndex: 27, type: 'white.elixir' }, + { startIndex: 28, type: 'keyword.elixir' }, + { startIndex: 30, type: 'white.elixir' }, + { startIndex: 31, type: 'keyword.declaration.elixir' }, + { startIndex: 34, type: 'white.elixir' }, + { startIndex: 35, type: 'keyword.elixir' }, + { startIndex: 42, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 43, type: 'identifier.elixir' }, + { startIndex: 47, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 50, type: 'white.elixir' }, + { startIndex: 51, type: 'keyword.elixir' }, + { startIndex: 53, type: 'white.elixir' }, + { startIndex: 54, type: 'constant.language.elixir' }, + { startIndex: 57, type: 'white.elixir' }, + { startIndex: 58, type: 'keyword.elixir' }, + { startIndex: 61, type: 'white.elixir' }, + { startIndex: 62, type: 'keyword.elixir' }, + { startIndex: 65, type: 'white.elixir' }, + { startIndex: 66, type: 'keyword.elixir' } + ] + } + ], + // Comments + [ + { + line: 'nil # comment', + tokens: [ + { startIndex: 0, type: 'constant.language.elixir' }, + { startIndex: 3, type: 'white.elixir' }, + { startIndex: 4, type: 'comment.punctuation.elixir' }, + { startIndex: 5, type: 'comment.elixir' } + ] + } + ], + // Keyword list shorthand + [ + { + line: '["key": value]', + tokens: [ + { startIndex: 0, type: 'delimiter.square.elixir' }, + { startIndex: 1, type: 'constant.delimiter.elixir' }, + { startIndex: 2, type: 'constant.elixir' }, + { startIndex: 5, type: 'constant.delimiter.elixir' }, + { startIndex: 7, type: 'white.elixir' }, + { startIndex: 8, type: 'identifier.elixir' }, + { startIndex: 13, type: 'delimiter.square.elixir' } + ] + } + ], + // Numbers + [ + { + line: '[1,1.23,1.23e-10,0xab,0o171,0b01001]', + tokens: [ + { startIndex: 0, type: 'delimiter.square.elixir' }, + { startIndex: 1, type: 'number.elixir' }, + { startIndex: 2, type: 'punctuation.elixir' }, + { startIndex: 3, type: 'number.float.elixir' }, + { startIndex: 7, type: 'punctuation.elixir' }, + { startIndex: 8, type: 'number.float.elixir' }, + { startIndex: 16, type: 'punctuation.elixir' }, + { startIndex: 17, type: 'number.hex.elixir' }, + { startIndex: 21, type: 'punctuation.elixir' }, + { startIndex: 22, type: 'number.octal.elixir' }, + { startIndex: 27, type: 'punctuation.elixir' }, + { startIndex: 28, type: 'number.binary.elixir' }, + { startIndex: 35, type: 'delimiter.square.elixir' } + ] + } + ], + // Unused bindings + [ + { + line: 'def foo(_x) do _y = 1 end', + tokens: [ + { startIndex: 0, type: 'keyword.declaration.elixir' }, + { startIndex: 3, type: 'white.elixir' }, + { startIndex: 4, type: 'function.elixir' }, + { startIndex: 7, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 8, type: 'comment.unused.elixir' }, + { startIndex: 10, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 11, type: 'white.elixir' }, + { startIndex: 12, type: 'keyword.elixir' }, + { startIndex: 14, type: 'white.elixir' }, + { startIndex: 15, type: 'comment.unused.elixir' }, + { startIndex: 17, type: 'white.elixir' }, + { startIndex: 18, type: 'operator.elixir' }, + { startIndex: 19, type: 'white.elixir' }, + { startIndex: 20, type: 'number.elixir' }, + { startIndex: 21, type: 'white.elixir' }, + { startIndex: 22, type: 'keyword.elixir' } + ] + } + ], + // Function calls + [ + { + line: 'foo(x)', + tokens: [ + { startIndex: 0, type: 'function.call.elixir' }, + { startIndex: 3, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 4, type: 'identifier.elixir' }, + { startIndex: 5, type: 'delimiter.parenthesis.elixir' } + ] + } + ], + [ + { + line: 'foo.()', + tokens: [ + { startIndex: 0, type: 'function.call.elixir' }, + { startIndex: 3, type: 'operator.elixir' }, + { startIndex: 4, type: 'delimiter.parenthesis.elixir' } + ] + } + ], + [ + { + line: 'Mod.foo()', + tokens: [ + { startIndex: 0, type: 'type.identifier.elixir' }, + { startIndex: 3, type: 'operator.elixir' }, + { startIndex: 4, type: 'function.call.elixir' }, + { startIndex: 7, type: 'delimiter.parenthesis.elixir' } + ] + } + ], + // Function call (Erlang module) + [ + { + line: ':mo.foo()', + tokens: [ + { startIndex: 0, type: 'constant.punctuation.elixir' }, + { startIndex: 1, type: 'constant.elixir' }, + { startIndex: 3, type: 'operator.elixir' }, + { startIndex: 4, type: 'function.call.elixir' }, + { startIndex: 7, type: 'delimiter.parenthesis.elixir' } + ] + } + ], + // Function call (pipe) + [ + { + line: '1 |> abs()', + tokens: [ + { startIndex: 0, type: 'number.elixir' }, + { startIndex: 1, type: 'white.elixir' }, + { startIndex: 2, type: 'operator.elixir' }, + { startIndex: 4, type: 'white.elixir' }, + { startIndex: 5, type: 'function.call.elixir' }, + { startIndex: 8, type: 'delimiter.parenthesis.elixir' } + ] + } + ], + // Function reference + [ + { + line: '&max(&1,&2)', + tokens: [ + { startIndex: 0, type: 'operator.elixir' }, + { startIndex: 1, type: 'function.call.elixir' }, + { startIndex: 4, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 5, type: 'operator.elixir' }, + { startIndex: 7, type: 'punctuation.elixir' }, + { startIndex: 8, type: 'operator.elixir' }, + { startIndex: 10, type: 'delimiter.parenthesis.elixir' } + ] + } + ], + // Strings + [ + { + line: '"foo"', + tokens: [ + { startIndex: 0, type: 'string.delimiter.elixir' }, + { startIndex: 1, type: 'string.elixir' }, + { startIndex: 4, type: 'string.delimiter.elixir' } + ] + } + ], + [ + { + line: '"foo \\u0065\\u0301 #{1}"', + tokens: [ + { startIndex: 0, type: 'string.delimiter.elixir' }, + { startIndex: 1, type: 'string.elixir' }, + { startIndex: 5, type: 'constant.character.escape.elixir' }, + { startIndex: 17, type: 'string.elixir' }, + { startIndex: 18, type: 'delimiter.bracket.embed.elixir' }, + { startIndex: 20, type: 'number.elixir' }, + { startIndex: 21, type: 'delimiter.bracket.embed.elixir' }, + { startIndex: 22, type: 'string.delimiter.elixir' } + ] + } + ], + [ + { + line: '"""heredoc"""', + tokens: [ + { startIndex: 0, type: 'string.delimiter.elixir' }, + { startIndex: 3, type: 'string.elixir' }, + { startIndex: 10, type: 'string.delimiter.elixir' } + ] + } + ], + // Atom strings + [ + { + line: ':"atom"', + tokens: [ + { startIndex: 0, type: 'constant.delimiter.elixir' }, + { startIndex: 2, type: 'constant.elixir' }, + { startIndex: 6, type: 'constant.delimiter.elixir' } + ] + } + ], + // Sigils (string) + [ + { + line: '~s{foo}', + tokens: [ + { startIndex: 0, type: 'string.delimiter.elixir' }, + { startIndex: 3, type: 'string.elixir' }, + { startIndex: 6, type: 'string.delimiter.elixir' } + ] + } + ], + // Sigils (regexp) + [ + { + line: '~r/foo/', + tokens: [ + { startIndex: 0, type: 'regexp.delimiter.elixir' }, + { startIndex: 3, type: 'regexp.elixir' }, + { startIndex: 6, type: 'regexp.delimiter.elixir' } + ] + } + ], + // Sigils (other) + [ + { + line: '~D/foo/', + tokens: [ + { startIndex: 0, type: 'sigil.delimiter.elixir' }, + { startIndex: 3, type: 'sigil.elixir' }, + { startIndex: 6, type: 'sigil.delimiter.elixir' } + ] + } + ], + // Sigils (no interpolation) + [ + { + line: '~W/foo#{1}/', + tokens: [ + { startIndex: 0, type: 'sigil.delimiter.elixir' }, + { startIndex: 3, type: 'sigil.elixir' }, + { startIndex: 10, type: 'sigil.delimiter.elixir' } + ] + } + ], + // Module attributes + [ + { + line: '@attr 1', + tokens: [ + { startIndex: 0, type: 'variable.elixir' }, + { startIndex: 5, type: 'white.elixir' }, + { startIndex: 6, type: 'number.elixir' } + ] + } + ], + // Module attributes (docs) + [ + { + line: '@doc "foo"', + tokens: [{ startIndex: 0, type: 'comment.block.documentation.elixir' }] + } + ], + // Operator definition + [ + { + line: 'def a ~> b, do: max(a,b)', + tokens: [ + { startIndex: 0, type: 'keyword.declaration.elixir' }, + { startIndex: 3, type: 'white.elixir' }, + { startIndex: 4, type: 'identifier.elixir' }, + { startIndex: 5, type: 'white.elixir' }, + { startIndex: 6, type: 'operator.elixir' }, + { startIndex: 8, type: 'white.elixir' }, + { startIndex: 9, type: 'identifier.elixir' }, + { startIndex: 10, type: 'punctuation.elixir' }, + { startIndex: 11, type: 'white.elixir' }, + { startIndex: 12, type: 'constant.elixir' }, + { startIndex: 14, type: 'constant.punctuation.elixir' }, + { startIndex: 15, type: 'white.elixir' }, + { startIndex: 16, type: 'function.call.elixir' }, + { startIndex: 19, type: 'delimiter.parenthesis.elixir' }, + { startIndex: 20, type: 'identifier.elixir' }, + { startIndex: 21, type: 'punctuation.elixir' }, + { startIndex: 22, type: 'identifier.elixir' }, + { startIndex: 23, type: 'delimiter.parenthesis.elixir' } + ] + } + ], + // Constants + [ + { + line: '[true,false,nil]', + tokens: [ + { startIndex: 0, type: 'delimiter.square.elixir' }, + { startIndex: 1, type: 'constant.language.elixir' }, + { startIndex: 5, type: 'punctuation.elixir' }, + { startIndex: 6, type: 'constant.language.elixir' }, + { startIndex: 11, type: 'punctuation.elixir' }, + { startIndex: 12, type: 'constant.language.elixir' }, + { startIndex: 15, type: 'delimiter.square.elixir' } + ] + } + ] +]); diff --git a/monaco-languages/src/elixir/elixir.ts b/monaco-languages/src/elixir/elixir.ts new file mode 100644 index 00000000..f73b350a --- /dev/null +++ b/monaco-languages/src/elixir/elixir.ts @@ -0,0 +1,632 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '#' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: "'", close: "'" }, + { open: '"', close: '"' } + ], + autoClosingPairs: [ + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['comment'] }, + { open: '"""', close: '"""' }, + { open: '`', close: '`', notIn: ['string', 'comment'] }, + { open: '(', close: ')' }, + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '<<', close: '>>' } + ], + indentationRules: { + increaseIndentPattern: /^\s*(after|else|catch|rescue|fn|[^#]*(do|<\-|\->|\{|\[|\=))\s*$/, + decreaseIndentPattern: /^\s*((\}|\])\s*$|(after|else|catch|rescue|end)\b)/ + } +}; + +/** + * A Monarch lexer for the Elixir language. + * + * References: + * + * * Monarch documentation - https://microsoft.github.io/monaco-editor/monarch.html + * * Elixir lexer - https://github.com/elixir-makeup/makeup_elixir/blob/master/lib/makeup/lexers/elixir_lexer.ex + * * TextMate lexer (elixir-tmbundle) - https://github.com/elixir-editors/elixir-tmbundle/blob/master/Syntaxes/Elixir.tmLanguage + * * TextMate lexer (vscode-elixir-ls) - https://github.com/elixir-lsp/vscode-elixir-ls/blob/master/syntaxes/elixir.json + */ +export const language = { + defaultToken: 'source', + tokenPostfix: '.elixir', + + brackets: [ + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '<<', close: '>>', token: 'delimiter.angle.special' } + ], + + // Below are lists/regexps to which we reference later. + + declarationKeywords: [ + 'def', + 'defp', + 'defn', + 'defnp', + 'defguard', + 'defguardp', + 'defmacro', + 'defmacrop', + 'defdelegate', + 'defcallback', + 'defmacrocallback', + 'defmodule', + 'defprotocol', + 'defexception', + 'defimpl', + 'defstruct' + ], + operatorKeywords: ['and', 'in', 'not', 'or', 'when'], + namespaceKeywords: ['alias', 'import', 'require', 'use'], + otherKeywords: [ + 'after', + 'case', + 'catch', + 'cond', + 'do', + 'else', + 'end', + 'fn', + 'for', + 'if', + 'quote', + 'raise', + 'receive', + 'rescue', + 'super', + 'throw', + 'try', + 'unless', + 'unquote_splicing', + 'unquote', + 'with' + ], + constants: ['true', 'false', 'nil'], + nameBuiltin: ['__MODULE__', '__DIR__', '__ENV__', '__CALLER__', '__STACKTRACE__'], + + // Matches any of the operator names: + // <<< >>> ||| &&& ^^^ ~~~ === !== ~>> <~> |~> <|> == != <= >= && || \\ <> ++ -- |> =~ -> <- ~> <~ :: .. = < > + - * / | . ^ & ! + operator: + /-[->]?|!={0,2}|\*|\/|\\\\|&{1,3}|\.\.?|\^(?:\^\^)?|\+\+?|<(?:-|<<|=|>|\|>|~>?)?|=~|={1,3}|>(?:=|>>)?|\|~>|\|>|\|{1,3}|~>>?|~~~|::/, + + // See https://hexdocs.pm/elixir/syntax-reference.html#variables + variableName: /[a-z_][a-zA-Z0-9_]*[?!]?/, + + // See https://hexdocs.pm/elixir/syntax-reference.html#atoms + atomName: /[a-zA-Z_][a-zA-Z0-9_@]*[?!]?|@specialAtomName|@operator/, + specialAtomName: /\.\.\.|<<>>|%\{\}|%|\{\}/, + + aliasPart: /[A-Z][a-zA-Z0-9_]*/, + moduleName: /@aliasPart(?:\.@aliasPart)*/, + + // Sigil pairs are: """ """, ''' ''', " ", ' ', / /, | |, < >, { }, [ ], ( ) + sigilSymmetricDelimiter: /"""|'''|"|'|\/|\|/, + sigilStartDelimiter: /@sigilSymmetricDelimiter|<|\{|\[|\(/, + sigilEndDelimiter: /@sigilSymmetricDelimiter|>|\}|\]|\)/, + + decimal: /\d(?:_?\d)*/, + hex: /[0-9a-fA-F](_?[0-9a-fA-F])*/, + octal: /[0-7](_?[0-7])*/, + binary: /[01](_?[01])*/, + + // See https://hexdocs.pm/elixir/master/String.html#module-escape-characters + escape: /\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}|\\./, + + // The keys below correspond to tokenizer states. + // We start from the root state and match against its rules + // until we explicitly transition into another state. + // The `include` simply brings in all operations from the given state + // and is useful for improving readability. + tokenizer: { + root: [ + { include: '@whitespace' }, + { include: '@comments' }, + // Keywords start as either an identifier or a string, + // but end with a : so it's important to match this first. + { include: '@keywordsShorthand' }, + { include: '@numbers' }, + { include: '@identifiers' }, + { include: '@strings' }, + { include: '@atoms' }, + { include: '@sigils' }, + { include: '@attributes' }, + { include: '@symbols' } + ], + + // Whitespace + + whitespace: [[/\s+/, 'white']], + + // Comments + + comments: [[/(#)(.*)/, ['comment.punctuation', 'comment']]], + + // Keyword list shorthand + + keywordsShorthand: [ + [/(@atomName)(:)/, ['constant', 'constant.punctuation']], + // Use positive look-ahead to ensure the string is followed by : + // and should be considered a keyword. + [ + /"(?=([^"]|#\{.*?\}|\\")*":)/, + { token: 'constant.delimiter', next: '@doubleQuotedStringKeyword' } + ], + [ + /'(?=([^']|#\{.*?\}|\\')*':)/, + { token: 'constant.delimiter', next: '@singleQuotedStringKeyword' } + ] + ], + + doubleQuotedStringKeyword: [ + [/":/, { token: 'constant.delimiter', next: '@pop' }], + { include: '@stringConstantContentInterpol' } + ], + + singleQuotedStringKeyword: [ + [/':/, { token: 'constant.delimiter', next: '@pop' }], + { include: '@stringConstantContentInterpol' } + ], + + // Numbers + + numbers: [ + [/0b@binary/, 'number.binary'], + [/0o@octal/, 'number.octal'], + [/0x@hex/, 'number.hex'], + [/@decimal\.@decimal([eE]-?@decimal)?/, 'number.float'], + [/@decimal/, 'number'] + ], + + // Identifiers + + identifiers: [ + // Tokenize identifier name in function-like definitions. + // Note: given `def a + b, do: nil`, `a` is not a function name, + // so we use negative look-ahead to ensure there's no operator. + [ + /\b(defp?|defnp?|defmacrop?|defguardp?|defdelegate)(\s+)(@variableName)(?!\s+@operator)/, + [ + 'keyword.declaration', + 'white', + { + cases: { + unquote: 'keyword', + '@default': 'function' + } + } + ] + ], + // Tokenize function calls + [ + // In-scope call - an identifier followed by ( or .( + /(@variableName)(?=\s*\.?\s*\()/, + { + cases: { + // Tokenize as keyword in cases like `if(..., do: ..., else: ...)` + '@declarationKeywords': 'keyword.declaration', + '@namespaceKeywords': 'keyword', + '@otherKeywords': 'keyword', + '@default': 'function.call' + } + } + ], + [ + // Referencing function in a module + /(@moduleName)(\s*)(\.)(\s*)(@variableName)/, + ['type.identifier', 'white', 'operator', 'white', 'function.call'] + ], + [ + // Referencing function in an Erlang module + /(:)(@atomName)(\s*)(\.)(\s*)(@variableName)/, + ['constant.punctuation', 'constant', 'white', 'operator', 'white', 'function.call'] + ], + [ + // Piping into a function (tokenized separately as it may not have parentheses) + /(\|>)(\s*)(@variableName)/, + [ + 'operator', + 'white', + { + cases: { + '@otherKeywords': 'keyword', + '@default': 'function.call' + } + } + ] + ], + [ + // Function reference passed to another function + /(&)(\s*)(@variableName)/, + ['operator', 'white', 'function.call'] + ], + // Language keywords, builtins, constants and variables + [ + /@variableName/, + { + cases: { + '@declarationKeywords': 'keyword.declaration', + '@operatorKeywords': 'keyword.operator', + '@namespaceKeywords': 'keyword', + '@otherKeywords': 'keyword', + '@constants': 'constant.language', + '@nameBuiltin': 'variable.language', + '_.*': 'comment.unused', + '@default': 'identifier' + } + } + ], + // Module names + [/@moduleName/, 'type.identifier'] + ], + + // Strings + + strings: [ + [/"""/, { token: 'string.delimiter', next: '@doubleQuotedHeredoc' }], + [/'''/, { token: 'string.delimiter', next: '@singleQuotedHeredoc' }], + [/"/, { token: 'string.delimiter', next: '@doubleQuotedString' }], + [/'/, { token: 'string.delimiter', next: '@singleQuotedString' }] + ], + + doubleQuotedHeredoc: [ + [/"""/, { token: 'string.delimiter', next: '@pop' }], + { include: '@stringContentInterpol' } + ], + + singleQuotedHeredoc: [ + [/'''/, { token: 'string.delimiter', next: '@pop' }], + { include: '@stringContentInterpol' } + ], + + doubleQuotedString: [ + [/"/, { token: 'string.delimiter', next: '@pop' }], + { include: '@stringContentInterpol' } + ], + + singleQuotedString: [ + [/'/, { token: 'string.delimiter', next: '@pop' }], + { include: '@stringContentInterpol' } + ], + + // Atoms + + atoms: [ + [/(:)(@atomName)/, ['constant.punctuation', 'constant']], + [/:"/, { token: 'constant.delimiter', next: '@doubleQuotedStringAtom' }], + [/:'/, { token: 'constant.delimiter', next: '@singleQuotedStringAtom' }] + ], + + doubleQuotedStringAtom: [ + [/"/, { token: 'constant.delimiter', next: '@pop' }], + { include: '@stringConstantContentInterpol' } + ], + + singleQuotedStringAtom: [ + [/'/, { token: 'constant.delimiter', next: '@pop' }], + { include: '@stringConstantContentInterpol' } + ], + + // Sigils + + // See https://elixir-lang.org/getting-started/sigils.html + // Sigils allow for typing values using their textual representation. + // All sigils start with ~ followed by a letter indicating sigil type + // and then a delimiter pair enclosing the textual representation. + // Optional modifiers are allowed after the closing delimiter. + // For instance a regular expressions can be written as: + // ~r/foo|bar/ ~r{foo|bar} ~r/foo|bar/g + // + // In general lowercase sigils allow for interpolation + // and escaped characters, whereas uppercase sigils don't + // + // During tokenization we want to distinguish some + // specific sigil types, namely string and regexp, + // so that they cen be themed separately. + // + // To reasonably handle all those combinations we leverage + // dot-separated states, so if we transition to @sigilStart.interpol.s.{.} + // then "sigilStart.interpol.s" state will match and also all + // the individual dot-separated parameters can be accessed. + + sigils: [ + [/~[a-z]@sigilStartDelimiter/, { token: '@rematch', next: '@sigil.interpol' }], + [/~[A-Z]@sigilStartDelimiter/, { token: '@rematch', next: '@sigil.noInterpol' }] + ], + + sigil: [ + [/~([a-zA-Z])\{/, { token: '@rematch', switchTo: '@sigilStart.$S2.$1.{.}' }], + [/~([a-zA-Z])\[/, { token: '@rematch', switchTo: '@sigilStart.$S2.$1.[.]' }], + [/~([a-zA-Z])\(/, { token: '@rematch', switchTo: '@sigilStart.$S2.$1.(.)' }], + [/~([a-zA-Z])\' }], + [ + /~([a-zA-Z])(@sigilSymmetricDelimiter)/, + { token: '@rematch', switchTo: '@sigilStart.$S2.$1.$2.$2' } + ] + ], + + // The definitions below expect states to be of the form: + // + // sigilStart.... + // sigilContinue.... + // + // The sigilStart state is used only to properly classify the token (as string/regex/sigil) + // and immediately switches to the sigilContinue sate, which handles the actual content + // and waits for the corresponding end delimiter. + + 'sigilStart.interpol.s': [ + [ + /~s@sigilStartDelimiter/, + { + token: 'string.delimiter', + switchTo: '@sigilContinue.$S2.$S3.$S4.$S5' + } + ] + ], + + 'sigilContinue.interpol.s': [ + [ + /(@sigilEndDelimiter)[a-zA-Z]*/, + { + cases: { + '$1==$S5': { token: 'string.delimiter', next: '@pop' }, + '@default': 'string' + } + } + ], + { include: '@stringContentInterpol' } + ], + + 'sigilStart.noInterpol.S': [ + [ + /~S@sigilStartDelimiter/, + { + token: 'string.delimiter', + switchTo: '@sigilContinue.$S2.$S3.$S4.$S5' + } + ] + ], + + 'sigilContinue.noInterpol.S': [ + // Ignore escaped sigil end + [/(^|[^\\])\\@sigilEndDelimiter/, 'string'], + [ + /(@sigilEndDelimiter)[a-zA-Z]*/, + { + cases: { + '$1==$S5': { token: 'string.delimiter', next: '@pop' }, + '@default': 'string' + } + } + ], + { include: '@stringContent' } + ], + + 'sigilStart.interpol.r': [ + [ + /~r@sigilStartDelimiter/, + { + token: 'regexp.delimiter', + switchTo: '@sigilContinue.$S2.$S3.$S4.$S5' + } + ] + ], + + 'sigilContinue.interpol.r': [ + [ + /(@sigilEndDelimiter)[a-zA-Z]*/, + { + cases: { + '$1==$S5': { token: 'regexp.delimiter', next: '@pop' }, + '@default': 'regexp' + } + } + ], + { include: '@regexpContentInterpol' } + ], + + 'sigilStart.noInterpol.R': [ + [ + /~R@sigilStartDelimiter/, + { + token: 'regexp.delimiter', + switchTo: '@sigilContinue.$S2.$S3.$S4.$S5' + } + ] + ], + + 'sigilContinue.noInterpol.R': [ + // Ignore escaped sigil end + [/(^|[^\\])\\@sigilEndDelimiter/, 'regexp'], + [ + /(@sigilEndDelimiter)[a-zA-Z]*/, + { + cases: { + '$1==$S5': { token: 'regexp.delimiter', next: '@pop' }, + '@default': 'regexp' + } + } + ], + { include: '@regexpContent' } + ], + + // Fallback to the generic sigil by default + 'sigilStart.interpol': [ + [ + /~([a-zA-Z])@sigilStartDelimiter/, + { + token: 'sigil.delimiter', + switchTo: '@sigilContinue.$S2.$S3.$S4.$S5' + } + ] + ], + + 'sigilContinue.interpol': [ + [ + /(@sigilEndDelimiter)[a-zA-Z]*/, + { + cases: { + '$1==$S5': { token: 'sigil.delimiter', next: '@pop' }, + '@default': 'sigil' + } + } + ], + { include: '@sigilContentInterpol' } + ], + + 'sigilStart.noInterpol': [ + [ + /~([a-zA-Z])@sigilStartDelimiter/, + { + token: 'sigil.delimiter', + switchTo: '@sigilContinue.$S2.$S3.$S4.$S5' + } + ] + ], + + 'sigilContinue.noInterpol': [ + // Ignore escaped sigil end + [/(^|[^\\])\\@sigilEndDelimiter/, 'sigil'], + [ + /(@sigilEndDelimiter)[a-zA-Z]*/, + { + cases: { + '$1==$S5': { token: 'sigil.delimiter', next: '@pop' }, + '@default': 'sigil' + } + } + ], + { include: '@sigilContent' } + ], + + // Attributes + + attributes: [ + // Module @doc* attributes - tokenized as comments + [ + /\@(module|type)?doc (~[sS])?"""/, + { + token: 'comment.block.documentation', + next: '@doubleQuotedHeredocDocstring' + } + ], + [ + /\@(module|type)?doc (~[sS])?"/, + { + token: 'comment.block.documentation', + next: '@doubleQuotedStringDocstring' + } + ], + [/\@(module|type)?doc false/, 'comment.block.documentation'], + // Module attributes + [/\@(@variableName)/, 'variable'] + ], + + doubleQuotedHeredocDocstring: [ + [/"""/, { token: 'comment.block.documentation', next: '@pop' }], + { include: '@docstringContent' } + ], + + doubleQuotedStringDocstring: [ + [/"/, { token: 'comment.block.documentation', next: '@pop' }], + { include: '@docstringContent' } + ], + + // Operators, punctuation, brackets + + symbols: [ + // Code point operator (either with regular character ?a or an escaped one ?\n) + [/\?(\\.|[^\\\s])/, 'number.constant'], + // Anonymous function arguments + [/&\d+/, 'operator'], + // Bitshift operators (must go before delimiters, so that << >> don't match first) + [/<<<|>>>/, 'operator'], + // Delimiter pairs + [/[()\[\]\{\}]|<<|>>/, '@brackets'], + // Triple dot is a valid name (must go before operators, so that .. doesn't match instead) + [/\.\.\./, 'identifier'], + // Punctuation => (must go before operators, so it's not tokenized as = then >) + [/=>/, 'punctuation'], + // Operators + [/@operator/, 'operator'], + // Punctuation + [/[:;,.%]/, 'punctuation'] + ], + + // Generic helpers + + stringContentInterpol: [ + { include: '@interpolation' }, + { include: '@escapeChar' }, + { include: '@stringContent' } + ], + + stringContent: [[/./, 'string']], + + stringConstantContentInterpol: [ + { include: '@interpolation' }, + { include: '@escapeChar' }, + { include: '@stringConstantContent' } + ], + + stringConstantContent: [[/./, 'constant']], + + regexpContentInterpol: [ + { include: '@interpolation' }, + { include: '@escapeChar' }, + { include: '@regexpContent' } + ], + + regexpContent: [ + // # may be a regular regexp char, so we use a heuristic + // assuming a # surrounded by whitespace is actually a comment. + [/(\s)(#)(\s.*)$/, ['white', 'comment.punctuation', 'comment']], + [/./, 'regexp'] + ], + + sigilContentInterpol: [ + { include: '@interpolation' }, + { include: '@escapeChar' }, + { include: '@sigilContent' } + ], + + sigilContent: [[/./, 'sigil']], + + docstringContent: [[/./, 'comment.block.documentation']], + + escapeChar: [[/@escape/, 'constant.character.escape']], + + interpolation: [ + [/#{/, { token: 'delimiter.bracket.embed', next: '@interpolationContinue' }] + ], + + interpolationContinue: [ + [/}/, { token: 'delimiter.bracket.embed', next: '@pop' }], + // Interpolation brackets may contain arbitrary code, + // so we simply match against all the root rules, + // until we reach interpolation end (the above matches). + { include: '@root' } + ] + } +}; diff --git a/monaco-languages/src/fillers/monaco-editor-core-amd.ts b/monaco-languages/src/fillers/monaco-editor-core-amd.ts new file mode 100644 index 00000000..6af108be --- /dev/null +++ b/monaco-languages/src/fillers/monaco-editor-core-amd.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// Resolves with the global monaco API + +declare const define: any; + +define([], function () { + return (self).monaco; +}); diff --git a/monaco-languages/src/fillers/monaco-editor-core.ts b/monaco-languages/src/fillers/monaco-editor-core.ts new file mode 100644 index 00000000..cd996aa7 --- /dev/null +++ b/monaco-languages/src/fillers/monaco-editor-core.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export * from 'monaco-editor-core'; diff --git a/monaco-languages/src/flow9/flow9.contribution.ts b/monaco-languages/src/flow9/flow9.contribution.ts new file mode 100644 index 00000000..649114b4 --- /dev/null +++ b/monaco-languages/src/flow9/flow9.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'flow9', + extensions: ['.flow'], + aliases: ['Flow9', 'Flow', 'flow9', 'flow'], + loader: () => import('./flow9') +}); diff --git a/monaco-languages/src/flow9/flow9.test.ts b/monaco-languages/src/flow9/flow9.test.ts new file mode 100644 index 00000000..6bf9b04e --- /dev/null +++ b/monaco-languages/src/flow9/flow9.test.ts @@ -0,0 +1,148 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('flow9', [ + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.flow' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.flow' } + ] + } + ], + + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.flow' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.flow' } + ] + } + ], + + [ + { + line: '/import file 1', + tokens: [ + { startIndex: 0, type: 'delimiter.flow' }, + { startIndex: 1, type: 'keyword.flow' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.flow' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'number.flow' } + ] + } + ], + + [ + { + line: 'getDefaults() -> [int] {}', + tokens: [ + { startIndex: 0, type: 'identifier.flow' }, + { startIndex: 11, type: 'delimiter.flow' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'delimiter.flow' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.flow' }, + { startIndex: 18, type: 'type.flow' }, + { startIndex: 21, type: 'delimiter.flow' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.flow' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.flow' }] + } + ], + + [ + { + line: '0.10', + tokens: [{ startIndex: 0, type: 'number.flow' }] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.flow' }] + } + ], + + [ + { + line: '052_', + tokens: [ + { startIndex: 0, type: 'number.flow' }, + { startIndex: 3, type: 'identifier.flow' } + ] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.flow' }, + { startIndex: 1, type: 'delimiter.flow' }, + { startIndex: 2, type: 'number.flow' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.flow' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.flow' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.flow' } + ] + } + ], + + [ + { + line: '"simple string"', + tokens: [{ startIndex: 0, type: 'string.flow' }] + } + ], + + [ + { + line: '""', + tokens: [{ startIndex: 0, type: 'string.flow' }] + } + ], + + [ + { + line: '"""', + tokens: [ + { startIndex: 0, type: 'string.flow' }, + { startIndex: 2, type: 'string.invalid.flow' } + ] + } + ] +]); diff --git a/monaco-languages/src/flow9/flow9.ts b/monaco-languages/src/flow9/flow9.ts new file mode 100644 index 00000000..2cea3b50 --- /dev/null +++ b/monaco-languages/src/flow9/flow9.ts @@ -0,0 +1,163 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + blockComment: ['/*', '*/'], + lineComment: '//' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}', notIn: ['string'] }, + { open: '[', close: ']', notIn: ['string'] }, + { open: '(', close: ')', notIn: ['string'] }, + { open: '"', close: '"', notIn: ['string'] }, + { open: "'", close: "'", notIn: ['string'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: '<', close: '>' } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.flow', + + keywords: [ + 'import', + 'require', + 'export', + 'forbid', + 'native', + 'if', + 'else', + 'cast', + 'unsafe', + 'switch', + 'default' + ], + + types: [ + 'io', + 'mutable', + 'bool', + 'int', + 'double', + 'string', + 'flow', + 'void', + 'ref', + 'true', + 'false', + 'with' + ], + + operators: [ + '=', + '>', + '<', + '<=', + '>=', + '==', + '!', + '!=', + ':=', + '::=', + '&&', + '||', + '+', + '-', + '*', + '/', + '@', + '&', + '%', + ':', + '->', + '\\', + '$', + '??', + '^' + ], + + symbols: /[@$=>](?!@symbols)/, 'delimiter'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [ + /((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)/, + 'number' + ], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], + [/"/, 'string', '@string'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'] + ] + } +}; diff --git a/monaco-languages/src/fsharp/fsharp.contribution.ts b/monaco-languages/src/fsharp/fsharp.contribution.ts new file mode 100644 index 00000000..d754dde5 --- /dev/null +++ b/monaco-languages/src/fsharp/fsharp.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'fsharp', + extensions: ['.fs', '.fsi', '.ml', '.mli', '.fsx', '.fsscript'], + aliases: ['F#', 'FSharp', 'fsharp'], + loader: () => import('./fsharp') +}); diff --git a/monaco-languages/src/fsharp/fsharp.test.ts b/monaco-languages/src/fsharp/fsharp.test.ts new file mode 100644 index 00000000..fd4a0744 --- /dev/null +++ b/monaco-languages/src/fsharp/fsharp.test.ts @@ -0,0 +1,491 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('fsharp', [ + // comments - single line + [ + { + line: '// one line comment', + tokens: [{ startIndex: 0, type: 'comment.fs' }] + } + ], + + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.fs' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.fs' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.fs' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.fs' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.fs' }, + { startIndex: 1, type: 'identifier.fs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.fs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.fs' } + ] + } + ], + + [ + { + line: '(/*almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.parenthesis.fs' }, + { startIndex: 1, type: 'delimiter.fs' }, + { startIndex: 3, type: 'identifier.fs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.fs' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'identifier.fs' } + ] + } + ], + + [ + { + line: '1 / 2; (* comment', + tokens: [ + { startIndex: 0, type: 'number.fs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.fs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.fs' }, + { startIndex: 5, type: 'delimiter.fs' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.fs' } + ] + } + ], + + [ + { + line: 'let x = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.let.fs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.fs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.fs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.fs' }, + { startIndex: 9, type: 'delimiter.fs' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.fs' } + ] + } + ], + + // Keywords + [ + { + line: 'namespace Application1', + tokens: [ + { startIndex: 0, type: 'keyword.namespace.fs' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.fs' } + ] + } + ], + + [ + { + line: 'type MyType', + tokens: [ + { startIndex: 0, type: 'keyword.type.fs' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.fs' } + ] + } + ], + + [ + { + line: 'module App =', + tokens: [ + { startIndex: 0, type: 'keyword.module.fs' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.fs' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.fs' } + ] + } + ], + + [ + { + line: 'let AppName = "App1"', + tokens: [ + { startIndex: 0, type: 'keyword.let.fs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.fs' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.fs' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'string.fs' } + ] + } + ], + + // Comments - range comment + [ + { + line: '(* a simple comment *)', + tokens: [{ startIndex: 0, type: 'comment.fs' }] + } + ], + + [ + { + line: 'let x = (* a simple comment *) 1', + tokens: [ + { startIndex: 0, type: 'keyword.let.fs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.fs' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.fs' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.fs' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.fs' } + ] + } + ], + + [ + { + line: 'x = (**)', + tokens: [ + { startIndex: 0, type: 'identifier.fs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.fs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.fs' } + ] + } + ], + + [ + { + line: 'x = (*)', + tokens: [ + { startIndex: 0, type: 'identifier.fs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.fs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.parenthesis.fs' }, + { startIndex: 5, type: 'delimiter.fs' }, + { startIndex: 6, type: 'delimiter.parenthesis.fs' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.fs' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '23.5F', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '23.5f', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72E3F', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72E3f', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72e3F', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72e3f', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '23.5M', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '23.5m', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72E3M', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72E3m', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72e3M', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '1.72e3m', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.fs' }, + { startIndex: 1, type: 'delimiter.fs' }, + { startIndex: 2, type: 'number.fs' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.fs' }, + { startIndex: 3, type: 'delimiter.fs' }, + { startIndex: 4, type: 'number.fs' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.fs' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.fs' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.fs' } + ] + } + ], + + [ + { + line: '0b00000101', + tokens: [{ startIndex: 0, type: 'number.bin.fs' }] + } + ], + + [ + { + line: '86y', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '0b00000101y', + tokens: [{ startIndex: 0, type: 'number.bin.fs' }] + } + ], + + [ + { + line: '86s', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '86us', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '86', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '86l', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '86u', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '86ul', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '0x00002D3Fn', + tokens: [{ startIndex: 0, type: 'number.hex.fs' }] + } + ], + + [ + { + line: '0x00002D3Fun', + tokens: [{ startIndex: 0, type: 'number.hex.fs' }] + } + ], + + [ + { + line: '86L', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '86UL', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '9999999999999999999999999999I', + tokens: [{ startIndex: 0, type: 'number.fs' }] + } + ], + + [ + { + line: '0x00002D3FLF', + tokens: [{ startIndex: 0, type: 'number.float.fs' }] + } + ], + + [ + { + line: '(* This operator -> (*) should be ignored *) let i = 0', + tokens: [ + { startIndex: 0, type: 'comment.fs' }, + { startIndex: 44, type: '' }, + { startIndex: 45, type: 'keyword.let.fs' }, + { startIndex: 48, type: '' }, + { startIndex: 49, type: 'identifier.fs' }, + { startIndex: 50, type: '' }, + { startIndex: 51, type: 'delimiter.fs' }, + { startIndex: 52, type: '' }, + { startIndex: 53, type: 'number.fs' } + ] + } + ] +]); diff --git a/monaco-languages/src/fsharp/fsharp.ts b/monaco-languages/src/fsharp/fsharp.ts new file mode 100644 index 00000000..2b6ea177 --- /dev/null +++ b/monaco-languages/src/fsharp/fsharp.ts @@ -0,0 +1,237 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['(*', '*)'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + folding: { + markers: { + start: new RegExp('^\\s*//\\s*#region\\b|^\\s*\\(\\*\\s*#region(.*)\\*\\)'), + end: new RegExp('^\\s*//\\s*#endregion\\b|^\\s*\\(\\*\\s*#endregion\\s*\\*\\)') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.fs', + + keywords: [ + 'abstract', + 'and', + 'atomic', + 'as', + 'assert', + 'asr', + 'base', + 'begin', + 'break', + 'checked', + 'component', + 'const', + 'constraint', + 'constructor', + 'continue', + 'class', + 'default', + 'delegate', + 'do', + 'done', + 'downcast', + 'downto', + 'elif', + 'else', + 'end', + 'exception', + 'eager', + 'event', + 'external', + 'extern', + 'false', + 'finally', + 'for', + 'fun', + 'function', + 'fixed', + 'functor', + 'global', + 'if', + 'in', + 'include', + 'inherit', + 'inline', + 'interface', + 'internal', + 'land', + 'lor', + 'lsl', + 'lsr', + 'lxor', + 'lazy', + 'let', + 'match', + 'member', + 'mod', + 'module', + 'mutable', + 'namespace', + 'method', + 'mixin', + 'new', + 'not', + 'null', + 'of', + 'open', + 'or', + 'object', + 'override', + 'private', + 'parallel', + 'process', + 'protected', + 'pure', + 'public', + 'rec', + 'return', + 'static', + 'sealed', + 'struct', + 'sig', + 'then', + 'to', + 'true', + 'tailcall', + 'trait', + 'try', + 'type', + 'upcast', + 'use', + 'val', + 'void', + 'virtual', + 'volatile', + 'when', + 'while', + 'with', + 'yield' + ], + + // we include these common regular expressions + symbols: /[=>]. + [/\[<.*>\]/, 'annotation'], + + // Preprocessor directive + [/^#(if|else|endif)/, 'keyword'], + + // delimiters and operators + [/[{}()\[\]]/, '@brackets'], + [/[<>](?!@symbols)/, '@brackets'], + [/@symbols/, 'delimiter'], + + // numbers + [/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'], + [/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/, 'number.float'], + [/0x[0-9a-fA-F]+LF/, 'number.float'], + [/0x[0-9a-fA-F]+(@integersuffix)/, 'number.hex'], + [/0b[0-1]+(@integersuffix)/, 'number.bin'], + [/\d+(@integersuffix)/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"""/, 'string', '@string."""'], + [/"/, 'string', '@string."'], + + // literal string + [/\@"/, { token: 'string.quote', next: '@litstring' }], + + // characters + [/'[^\\']'B?/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\(\*(?!\))/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^*(]+/, 'comment'], + [/\*\)/, 'comment', '@pop'], + [/\*/, 'comment'], + [/\(\*\)/, 'comment'], + [/\(/, 'comment'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [ + /("""|"B?)/, + { + cases: { + '$#==$S2': { token: 'string', next: '@pop' }, + '@default': 'string' + } + } + ] + ], + + litstring: [ + [/[^"]+/, 'string'], + [/""/, 'string.escape'], + [/"/, { token: 'string.quote', next: '@pop' }] + ] + } +}; diff --git a/monaco-languages/src/go/go.contribution.ts b/monaco-languages/src/go/go.contribution.ts new file mode 100644 index 00000000..1ee8d4bb --- /dev/null +++ b/monaco-languages/src/go/go.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'go', + extensions: ['.go'], + aliases: ['Go'], + loader: () => import('./go') +}); diff --git a/monaco-languages/src/go/go.test.ts b/monaco-languages/src/go/go.test.ts new file mode 100644 index 00000000..2afb7687 --- /dev/null +++ b/monaco-languages/src/go/go.test.ts @@ -0,0 +1,1492 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('go', [ + // Tests + [ + { + line: '/* Block comment. */', + tokens: [{ startIndex: 0, type: 'comment.go' }] + } + ], + + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.go' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.go' } + ] + } + ], + + [ + { + line: '// Inline comment.', + tokens: [{ startIndex: 0, type: 'comment.go' }] + } + ], + + [ + { + line: '', + tokens: [] + } + ], + + [ + { + line: 'import {', + tokens: [ + { startIndex: 0, type: 'keyword.import.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.curly.go' } + ] + } + ], + + [ + { + line: ' "io"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'string.go' } + ] + } + ], + + [ + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.go' }] + } + ], + + [ + { + line: '', + tokens: [] + } + ], + + [ + { + line: 'type name struct {', + tokens: [ + { startIndex: 0, type: 'keyword.type.go' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.go' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'keyword.struct.go' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.curly.go' } + ] + } + ], + + [ + { + line: ' firstname string', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'keyword.string.go' } + ] + } + ], + + [ + { + line: ' lastname string', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.string.go' } + ] + } + ], + + [ + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.go' }] + } + ], + + [ + { + line: '', + tokens: [] + } + ], + + [ + { + line: 'func testTypes() {', + tokens: [ + { startIndex: 0, type: 'keyword.func.go' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.go' }, + { startIndex: 14, type: 'delimiter.parenthesis.go' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.curly.go' } + ] + } + ], + + [ + { + line: ' a int;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.int.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' b uint;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.uint.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' c uintptr;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.uintptr.go' }, + { startIndex: 11, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' d string;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.string.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' e byte;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.byte.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' f rune;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.rune.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' g uint8;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.uint8.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' h uint16;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.uint16.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' i uint32;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.uint32.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' j uint64;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.uint64.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' k int8;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.int8.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' l int16;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.int16.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' m int32;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.int32.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' n int64;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.int64.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' o float32;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.float32.go' }, + { startIndex: 11, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' p float64;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.float64.go' }, + { startIndex: 11, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' q complex64;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.complex64.go' }, + { startIndex: 13, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' r complex128;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'keyword.complex128.go' }, + { startIndex: 14, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.go' }] + } + ], + + [ + { + line: '', + tokens: [] + } + ], + + [ + { + line: 'func testOperators() {', + tokens: [ + { startIndex: 0, type: 'keyword.func.go' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.go' }, + { startIndex: 18, type: 'delimiter.parenthesis.go' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.curly.go' } + ] + } + ], + + [ + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: ' var a;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.var.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' var b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.var.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: ' a + b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a - b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a * b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a / b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a % b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a & b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a | b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a ^ b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a << b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a >> b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a &^ b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a += b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a -= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a *= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a /= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a %= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a &= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a |= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a ^= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a <<= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a >>= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a &^= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a && b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a || b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a <- b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a++;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' b--;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a == b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a < b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.angle.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a > b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.angle.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a = b; ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' }, + { startIndex: 8, type: '' } + ] + } + ], + + [ + { + line: ' !a;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.go' }, + { startIndex: 3, type: 'identifier.go' }, + { startIndex: 4, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a != b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a <= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a >= b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a := b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a...;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' (a)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.parenthesis.go' }, + { startIndex: 3, type: 'identifier.go' }, + { startIndex: 4, type: 'delimiter.parenthesis.go' } + ] + } + ], + + [ + { + line: ' [a]', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.square.go' }, + { startIndex: 3, type: 'identifier.go' }, + { startIndex: 4, type: 'delimiter.square.go' } + ] + } + ], + + [ + { + line: ' a.b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: 'delimiter.go' }, + { startIndex: 4, type: 'identifier.go' }, + { startIndex: 5, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a, b;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: 'delimiter.go' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.go' }, + { startIndex: 6, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' a : b; ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.go' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' }, + { startIndex: 8, type: '' } + ] + } + ], + + [ + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.go' }] + } + ], + + [ + { + line: '', + tokens: [] + } + ], + + [ + { + line: 'func keywords() {', + tokens: [ + { startIndex: 0, type: 'keyword.func.go' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.go' }, + { startIndex: 13, type: 'delimiter.parenthesis.go' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.curly.go' } + ] + } + ], + + [ + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: ' var a;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.var.go' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' break;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.break.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' switch(a) {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.switch.go' }, + { startIndex: 8, type: 'delimiter.parenthesis.go' }, + { startIndex: 9, type: 'identifier.go' }, + { startIndex: 10, type: 'delimiter.parenthesis.go' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.curly.go' } + ] + } + ], + + [ + { + line: ' case 1:', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.case.go' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'number.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' fallthrough;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'keyword.fallthrough.go' }, + { startIndex: 17, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' default:', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.default.go' }, + { startIndex: 11, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' break;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'keyword.break.go' }, + { startIndex: 11, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.go' } + ] + } + ], + + [ + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: ' chan;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.chan.go' }, + { startIndex: 6, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' const;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.const.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' continue;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.continue.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' defer;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.defer.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' if (a)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.if.go' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.parenthesis.go' }, + { startIndex: 6, type: 'identifier.go' }, + { startIndex: 7, type: 'delimiter.parenthesis.go' } + ] + } + ], + + [ + { + line: ' return;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.return.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' else', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.else.go' } + ] + } + ], + + [ + { + line: ' return;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.return.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' for (i = 0; i < 10; i++);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.for.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.parenthesis.go' }, + { startIndex: 8, type: 'identifier.go' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.go' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'number.go' }, + { startIndex: 13, type: 'delimiter.go' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'identifier.go' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.angle.go' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'number.go' }, + { startIndex: 21, type: 'delimiter.go' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'identifier.go' }, + { startIndex: 24, type: 'delimiter.go' }, + { startIndex: 26, type: 'delimiter.parenthesis.go' }, + { startIndex: 27, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' go;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.go.go' }, + { startIndex: 5, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' goto;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.goto.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' interface;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.interface.go' }, + { startIndex: 12, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' map;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.map.go' }, + { startIndex: 6, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' package;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.package.go' }, + { startIndex: 10, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' range;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.range.go' }, + { startIndex: 8, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' return;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.return.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' select;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.select.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' struct;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.struct.go' }, + { startIndex: 9, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' type;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.type.go' }, + { startIndex: 7, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' ', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: ' var x = true;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.var.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.go' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.true.go' }, + { startIndex: 15, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' var y = false;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.var.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.go' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.false.go' }, + { startIndex: 16, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: ' var z = nil;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.var.go' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.go' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.go' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.nil.go' }, + { startIndex: 14, type: 'delimiter.go' } + ] + } + ], + + [ + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.go' }] + } + ], + + [ + { + line: '`Hello world() ""`', + tokens: [{ startIndex: 0, type: 'string.go' }] + } + ] +]); diff --git a/monaco-languages/src/go/go.ts b/monaco-languages/src/go/go.ts new file mode 100644 index 00000000..6e3bbab5 --- /dev/null +++ b/monaco-languages/src/go/go.ts @@ -0,0 +1,238 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '`', close: '`', notIn: ['string'] }, + { open: '"', close: '"', notIn: ['string'] }, + { open: "'", close: "'", notIn: ['string', 'comment'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '`', close: '`' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.go', + + keywords: [ + 'break', + 'case', + 'chan', + 'const', + 'continue', + 'default', + 'defer', + 'else', + 'fallthrough', + 'for', + 'func', + 'go', + 'goto', + 'if', + 'import', + 'interface', + 'map', + 'package', + 'range', + 'return', + 'select', + 'struct', + 'switch', + 'type', + 'var', + 'bool', + 'true', + 'false', + 'uint8', + 'uint16', + 'uint32', + 'uint64', + 'int8', + 'int16', + 'int32', + 'int64', + 'float32', + 'float64', + 'complex64', + 'complex128', + 'byte', + 'rune', + 'uint', + 'int', + 'uintptr', + 'string', + 'nil' + ], + + operators: [ + '+', + '-', + '*', + '/', + '%', + '&', + '|', + '^', + '<<', + '>>', + '&^', + '+=', + '-=', + '*=', + '/=', + '%=', + '&=', + '|=', + '^=', + '<<=', + '>>=', + '&^=', + '&&', + '||', + '<-', + '++', + '--', + '==', + '<', + '>', + '=', + '!', + '!=', + '<=', + '>=', + ':=', + '...', + '(', + ')', + '', + ']', + '{', + '}', + ',', + ';', + '.', + ':' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // numbers + [/\d*\d+[eE]([\-+]?\d+)?/, 'number.float'], + [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], + [/0[xX][0-9a-fA-F']*[0-9a-fA-F]/, 'number.hex'], + [/0[0-7']*[0-7]/, 'number.octal'], + [/0[bB][0-1']*[0-1]/, 'number.binary'], + [/\d[\d']*/, 'number'], + [/\d/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, 'string', '@string'], + [/`/, 'string', '@rawstring'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@doccomment'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + // [/\/\*/, 'comment', '@push' ], // nested comment not allowed :-( + // [/\/\*/, 'comment.invalid' ], // this breaks block comments in the shape of /* //*/ + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + //Identical copy of comment above, except for the addition of .doc + doccomment: [ + [/[^\/*]+/, 'comment.doc'], + // [/\/\*/, 'comment.doc', '@push' ], // nested comment not allowed :-( + [/\/\*/, 'comment.doc.invalid'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'] + ], + + rawstring: [ + [/[^\`]/, 'string'], + [/`/, 'string', '@pop'] + ] + } +}; diff --git a/monaco-languages/src/graphql/graphql.contribution.ts b/monaco-languages/src/graphql/graphql.contribution.ts new file mode 100644 index 00000000..7fa911c9 --- /dev/null +++ b/monaco-languages/src/graphql/graphql.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'graphql', + extensions: ['.graphql', '.gql'], + aliases: ['GraphQL', 'graphql', 'gql'], + mimetypes: ['application/graphql'], + loader: () => import('./graphql') +}); diff --git a/monaco-languages/src/graphql/graphql.test.ts b/monaco-languages/src/graphql/graphql.test.ts new file mode 100644 index 00000000..56c33047 --- /dev/null +++ b/monaco-languages/src/graphql/graphql.test.ts @@ -0,0 +1,138 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('graphql', [ + // Keywords + [ + { + line: 'scalar Date', + tokens: [ + { startIndex: 0, type: 'keyword.gql' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'type.identifier.gql' } + ] + } + ], + + // Root schema definition + [ + { + line: 'schema { query: Query, mutation: Mutation subscription: Subscription }', + tokens: [ + { startIndex: 0, type: 'keyword.gql' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.curly.gql' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.gql' }, // this should be identifier + { startIndex: 14, type: 'operator.gql' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'type.identifier.gql' }, + { startIndex: 21, type: 'delimiter.gql' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'keyword.gql' }, // this should be identifier + { startIndex: 31, type: 'operator.gql' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'type.identifier.gql' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'keyword.gql' }, // this should be identifier + { startIndex: 54, type: 'operator.gql' }, + { startIndex: 55, type: '' }, + { startIndex: 56, type: 'type.identifier.gql' }, + { startIndex: 68, type: '' }, + { startIndex: 69, type: 'delimiter.curly.gql' } + ] + } + ], + + [ + { + line: `query testQuery($intValue:Int=3){value(arg:{string:"string" int:$intValue}){field1 field2}}`, + tokens: [ + { startIndex: 0, type: 'keyword.gql' }, // 'query' + { startIndex: 5, type: '' }, // ' ' + { startIndex: 6, type: 'key.identifier.gql' }, // 'testQuery' + { startIndex: 15, type: 'delimiter.parenthesis.gql' }, // '(' + { startIndex: 16, type: 'argument.identifier.gql' }, // '$intValue' + { startIndex: 25, type: 'operator.gql' }, // ':' + { startIndex: 26, type: 'keyword.gql' }, // 'Int' + { startIndex: 29, type: 'operator.gql' }, // '=' + { startIndex: 30, type: 'number.gql' }, // '3' + { startIndex: 31, type: 'delimiter.parenthesis.gql' }, // ')' + { startIndex: 32, type: 'delimiter.curly.gql' }, // '{' + { startIndex: 33, type: 'key.identifier.gql' }, // 'value' + { startIndex: 38, type: 'delimiter.parenthesis.gql' }, // '(' + { startIndex: 39, type: 'key.identifier.gql' }, // 'arg' + { startIndex: 42, type: 'operator.gql' }, // ':' + { startIndex: 43, type: 'delimiter.curly.gql' }, // '{' + { startIndex: 44, type: 'key.identifier.gql' }, // 'string' + { startIndex: 50, type: 'operator.gql' }, // ':' + { startIndex: 51, type: 'string.quote.gql' }, // '"' + { startIndex: 52, type: 'string.gql' }, // 'string' + { startIndex: 58, type: 'string.quote.gql' }, // '"' + { startIndex: 59, type: '' }, // ' ' + { startIndex: 60, type: 'key.identifier.gql' }, // 'int' + { startIndex: 63, type: 'operator.gql' }, // ':' + { startIndex: 64, type: 'argument.identifier.gql' }, // '$intValue' + { startIndex: 73, type: 'delimiter.curly.gql' }, // '}' + { startIndex: 74, type: 'delimiter.parenthesis.gql' }, // ')' + { startIndex: 75, type: 'delimiter.curly.gql' }, // '{' + { startIndex: 76, type: 'key.identifier.gql' }, // 'field1' + { startIndex: 82, type: '' }, // ' ' + { startIndex: 83, type: 'key.identifier.gql' }, // 'field2' + { startIndex: 89, type: 'delimiter.curly.gql' } // '}}' + ] + } + ], + + // More complex test: + // """ + // Node interface + // - allows (re)fetch arbitrary entity only by ID + // """ + // interface Node { + // id: ID! + // } + [ + { + line: '"""', + tokens: [{ startIndex: 0, type: 'string.gql' }] + }, + { + line: 'This is MarkDown', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: '"""', + tokens: [{ startIndex: 0, type: 'string.gql' }] + }, + { + line: 'interface Node {', + tokens: [ + { startIndex: 0, type: 'keyword.gql' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'type.identifier.gql' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.curly.gql' } + ] + }, + { + line: ' id: ID!', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'key.identifier.gql' }, + { startIndex: 4, type: 'operator.gql' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.gql' }, + { startIndex: 8, type: 'operator.gql' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.gql' }] + } + ] +]); diff --git a/monaco-languages/src/graphql/graphql.ts b/monaco-languages/src/graphql/graphql.ts new file mode 100644 index 00000000..a96b93e8 --- /dev/null +++ b/monaco-languages/src/graphql/graphql.ts @@ -0,0 +1,174 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '#' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"""', close: '"""', notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"""', close: '"""' }, + { open: '"', close: '"' } + ], + folding: { + offSide: true + } +}; + +export const language = { + // Set defaultToken to invalid to see what you do not tokenize yet + defaultToken: 'invalid', + tokenPostfix: '.gql', + + keywords: [ + 'null', + 'true', + 'false', + 'query', + 'mutation', + 'subscription', + 'extend', + 'schema', + 'directive', + 'scalar', + 'type', + 'interface', + 'union', + 'enum', + 'input', + 'implements', + 'fragment', + 'on' + ], + + typeKeywords: ['Int', 'Float', 'String', 'Boolean', 'ID'], + + directiveLocations: [ + 'SCHEMA', + 'SCALAR', + 'OBJECT', + 'FIELD_DEFINITION', + 'ARGUMENT_DEFINITION', + 'INTERFACE', + 'UNION', + 'ENUM', + 'ENUM_VALUE', + 'INPUT_OBJECT', + 'INPUT_FIELD_DEFINITION', + 'QUERY', + 'MUTATION', + 'SUBSCRIPTION', + 'FIELD', + 'FRAGMENT_DEFINITION', + 'FRAGMENT_SPREAD', + 'INLINE_FRAGMENT', + 'VARIABLE_DEFINITION' + ], + + operators: ['=', '!', '?', ':', '&', '|'], + + // we include these common regular expressions + symbols: /[=!?:&|]+/, + + // https://facebook.github.io/graphql/draft/#sec-String-Value + escapes: /\\(?:["\\\/bfnrt]|u[0-9A-Fa-f]{4})/, + + // The main tokenizer for our languages + tokenizer: { + root: [ + // fields and argument names + [ + /[a-z_][\w$]*/, + { + cases: { + '@keywords': 'keyword', + '@default': 'key.identifier' + } + } + ], + + // identify typed input variables + [ + /[$][\w$]*/, + { + cases: { + '@keywords': 'keyword', + '@default': 'argument.identifier' + } + } + ], + + // to show class names nicely + [ + /[A-Z][\w\$]*/, + { + cases: { + '@typeKeywords': 'keyword', + '@default': 'type.identifier' + } + } + ], + + // whitespace + { include: '@whitespace' }, + + // delimiters and operators + [/[{}()\[\]]/, '@brackets'], + [/@symbols/, { cases: { '@operators': 'operator', '@default': '' } }], + + // @ annotations. + // As an example, we emit a debugging log message on these tokens. + // Note: message are supressed during the first load -- change some lines to see them. + [/@\s*[a-zA-Z_\$][\w\$]*/, { token: 'annotation', log: 'annotation token: $0' }], + + // numbers + [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], + [/0[xX][0-9a-fA-F]+/, 'number.hex'], + [/\d+/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + [/"""/, { token: 'string', next: '@mlstring', nextEmbedded: 'markdown' }], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, { token: 'string.quote', bracket: '@open', next: '@string' }] + ], + + mlstring: [ + [/[^"]+/, 'string'], + ['"""', { token: 'string', next: '@pop', nextEmbedded: '@pop' }] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/#.*$/, 'comment'] + ] + } +}; diff --git a/monaco-languages/src/handlebars/handlebars.contribution.ts b/monaco-languages/src/handlebars/handlebars.contribution.ts new file mode 100644 index 00000000..68481549 --- /dev/null +++ b/monaco-languages/src/handlebars/handlebars.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'handlebars', + extensions: ['.handlebars', '.hbs'], + aliases: ['Handlebars', 'handlebars', 'hbs'], + mimetypes: ['text/x-handlebars-template'], + loader: () => import('./handlebars') +}); diff --git a/monaco-languages/src/handlebars/handlebars.test.ts b/monaco-languages/src/handlebars/handlebars.test.ts new file mode 100644 index 00000000..75a087d0 --- /dev/null +++ b/monaco-languages/src/handlebars/handlebars.test.ts @@ -0,0 +1,354 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization( + ['handlebars', 'css'], + [ + // Just HTML + [ + { + line: '

handlebars!

', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: '' }, + { startIndex: 15, type: 'delimiter.html' }, + { startIndex: 17, type: 'tag.html' }, + { startIndex: 19, type: 'delimiter.html' } + ] + } + ], + + // Expressions + [ + { + line: '

{{ title }}

', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: 'delimiter.handlebars' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'variable.parameter.handlebars' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.handlebars' }, + { startIndex: 15, type: 'delimiter.html' }, + { startIndex: 17, type: 'tag.html' }, + { startIndex: 19, type: 'delimiter.html' } + ] + } + ], + + // Expressions Sans Whitespace + [ + { + line: '

{{title}}

', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: 'delimiter.handlebars' }, + { startIndex: 6, type: 'variable.parameter.handlebars' }, + { startIndex: 11, type: 'delimiter.handlebars' }, + { startIndex: 13, type: 'delimiter.html' }, + { startIndex: 15, type: 'tag.html' }, + { startIndex: 17, type: 'delimiter.html' } + ] + } + ], + + // Unescaped Expressions + [ + { + line: '

{{{ title }}}

', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: 'delimiter.handlebars' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'variable.parameter.handlebars' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'delimiter.handlebars' }, + { startIndex: 17, type: 'delimiter.html' }, + { startIndex: 19, type: 'tag.html' }, + { startIndex: 21, type: 'delimiter.html' } + ] + } + ], + + // Blocks + [ + { + line: '
    {{#each items}}
  • {{item}}
  • {{/each}}
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: 'delimiter.handlebars' }, + { startIndex: 6, type: 'keyword.helper.handlebars' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'variable.parameter.handlebars' }, + { startIndex: 17, type: 'delimiter.handlebars' }, + { startIndex: 19, type: 'delimiter.html' }, + { startIndex: 20, type: 'tag.html' }, + { startIndex: 22, type: 'delimiter.html' }, + { startIndex: 23, type: 'delimiter.handlebars' }, + { startIndex: 25, type: 'variable.parameter.handlebars' }, + { startIndex: 29, type: 'delimiter.handlebars' }, + { startIndex: 31, type: 'delimiter.html' }, + { startIndex: 33, type: 'tag.html' }, + { startIndex: 35, type: 'delimiter.html' }, + { startIndex: 36, type: 'delimiter.handlebars' }, + { startIndex: 38, type: 'keyword.helper.handlebars' }, + { startIndex: 43, type: 'delimiter.handlebars' }, + { startIndex: 45, type: 'delimiter.html' }, + { startIndex: 47, type: 'tag.html' }, + { startIndex: 49, type: 'delimiter.html' } + ] + } + ], + + // Multiline + [ + { + line: '
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: 'delimiter.html' } + ] + }, + { + line: '{{#if foo}}', + tokens: [ + { startIndex: 0, type: 'delimiter.handlebars' }, + { startIndex: 2, type: 'keyword.helper.handlebars' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'variable.parameter.handlebars' }, + { startIndex: 9, type: 'delimiter.handlebars' } + ] + }, + { + line: '{{bar}}', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 5, type: 'delimiter.html' }, + { startIndex: 6, type: 'delimiter.handlebars' }, + { startIndex: 8, type: 'variable.parameter.handlebars' }, + { startIndex: 11, type: 'delimiter.handlebars' }, + { startIndex: 13, type: 'delimiter.html' }, + { startIndex: 15, type: 'tag.html' }, + { startIndex: 19, type: 'delimiter.html' } + ] + }, + { + line: '{{/if}}', + tokens: [ + { startIndex: 0, type: 'delimiter.handlebars' }, + { startIndex: 2, type: 'keyword.helper.handlebars' }, + { startIndex: 5, type: 'delimiter.handlebars' } + ] + } + ], + + // Div end + [ + { + line: '
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 2, type: 'tag.html' }, + { startIndex: 5, type: 'delimiter.html' } + ] + } + ], + + // HTML Expressions + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name' }, + { startIndex: 12, type: 'delimiter' }, + { startIndex: 13, type: 'attribute.value' }, + { startIndex: 41, type: 'delimiter.html' }, + { startIndex: 42, type: 'delimiter.html' }, + { startIndex: 43, type: 'tag.html' }, + { startIndex: 45, type: 'delimiter.html' }, + { startIndex: 46, type: 'delimiter.handlebars' }, + { startIndex: 48, type: '' }, + { startIndex: 49, type: 'variable.parameter.handlebars' }, + { startIndex: 54, type: '' }, + { startIndex: 55, type: 'delimiter.handlebars' }, + { startIndex: 57, type: 'delimiter.html' }, + { startIndex: 59, type: 'tag.html' }, + { startIndex: 61, type: 'delimiter.html' }, + { startIndex: 62, type: 'delimiter.html' }, + { startIndex: 64, type: 'tag.html' }, + { startIndex: 70, type: 'delimiter.html' } + ] + } + ], + + // Multi-line HTML Expressions + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 2, type: 'tag.html' }, + { startIndex: 8, type: 'delimiter.html' } + ] + } + ], + + // HTML Nested Modes + [ + { + line: '{{foo}}{{bar}}', + tokens: [ + { startIndex: 0, type: 'delimiter.handlebars' }, + { startIndex: 2, type: 'variable.parameter.handlebars' }, + { startIndex: 5, type: 'delimiter.handlebars' }, + { startIndex: 7, type: 'delimiter.html' }, + { startIndex: 8, type: 'tag.html' }, + { startIndex: 14, type: 'delimiter.html' }, + // { startIndex:15, type: 'delimiter.html' }, + { startIndex: 17, type: 'tag.html' }, + { startIndex: 23, type: 'delimiter.html' }, + { startIndex: 24, type: 'delimiter.handlebars' }, + { startIndex: 26, type: 'variable.parameter.handlebars' }, + { startIndex: 29, type: 'delimiter.handlebars' } + ] + } + ], + + // else keyword + [ + { + line: '{{else}}', + tokens: [ + { startIndex: 0, type: 'delimiter.handlebars' }, + { startIndex: 2, type: 'keyword.helper.handlebars' }, + { startIndex: 6, type: 'delimiter.handlebars' } + ] + } + ], + + // else keyword #2 + [ + { + line: '{{elseFoo}}', + tokens: [ + { startIndex: 0, type: 'delimiter.handlebars' }, + { startIndex: 2, type: 'variable.parameter.handlebars' }, + { startIndex: 9, type: 'delimiter.handlebars' } + ] + } + ], + + // Token inside attribute + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'attribute.name' }, + { startIndex: 7, type: 'delimiter' }, + { startIndex: 8, type: 'attribute.value' }, + { startIndex: 30, type: 'delimiter.html' } + ] + } + ], + + [ + { + line: '{{test "coloring/looks broken"}}">', + tokens: [ + { startIndex: 0, type: 'delimiter.handlebars' }, + { startIndex: 2, type: 'variable.parameter.handlebars' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.handlebars' }, + { startIndex: 30, type: 'delimiter.handlebars' }, + { startIndex: 32, type: '' } + ] + } + ], + + // Block comment + [ + { + line: '{{!-- block comment --}}', + tokens: [ + { startIndex: 0, type: 'comment.block.start.handlebars' }, + { startIndex: 5, type: 'comment.content.handlebars' }, + { startIndex: 20, type: 'comment.block.end.handlebars' } + ] + } + ], + + // Block comment with mustache + [ + { + line: '{{!-- block comment }} with mustache --}}', + tokens: [ + { startIndex: 0, type: 'comment.block.start.handlebars' }, + { startIndex: 5, type: 'comment.content.handlebars' }, + { startIndex: 37, type: 'comment.block.end.handlebars' } + ] + } + ], + + // Handlebars comment + [ + { + line: '{{! comment }}', + tokens: [ + { startIndex: 0, type: 'comment.start.handlebars' }, + { startIndex: 3, type: 'comment.content.handlebars' }, + { startIndex: 12, type: 'comment.end.handlebars' } + ] + } + ] + ] +); diff --git a/monaco-languages/src/handlebars/handlebars.ts b/monaco-languages/src/handlebars/handlebars.ts new file mode 100644 index 00000000..92bb81a7 --- /dev/null +++ b/monaco-languages/src/handlebars/handlebars.ts @@ -0,0 +1,432 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { languages } from '../fillers/monaco-editor-core'; + +const EMPTY_ELEMENTS: string[] = [ + 'area', + 'base', + 'br', + 'col', + 'embed', + 'hr', + 'img', + 'input', + 'keygen', + 'link', + 'menuitem', + 'meta', + 'param', + 'source', + 'track', + 'wbr' +]; + +export const conf: languages.LanguageConfiguration = { + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, + + comments: { + blockComment: ['{{!--', '--}}'] + }, + + brackets: [ + [''], + ['<', '>'], + ['{{', '}}'], + ['{', '}'], + ['(', ')'] + ], + + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + surroundingPairs: [ + { open: '<', close: '>' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + onEnterRules: [ + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + afterText: /^<\/(\w[\w\d]*)\s*>$/i, + action: { + indentAction: languages.IndentAction.IndentOutdent + } + }, + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + action: { indentAction: languages.IndentAction.Indent } + } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '', + // ignoreCase: true, + + // The main tokenizer for our languages + tokenizer: { + root: [ + [/\{\{!--/, 'comment.block.start.handlebars', '@commentBlock'], + [/\{\{!/, 'comment.start.handlebars', '@comment'], + [/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.root' }], + [/)/, ['delimiter.html', 'tag.html', 'delimiter.html']], + [/(<)(script)/, ['delimiter.html', { token: 'tag.html', next: '@script' }]], + [/(<)(style)/, ['delimiter.html', { token: 'tag.html', next: '@style' }]], + [/(<)([:\w]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [/(<\/)(\w+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [/]+/, 'metatag.content.html'], + [/>/, 'metatag.html', '@pop'] + ], + + comment: [ + [/\}\}/, 'comment.end.handlebars', '@pop'], + [/./, 'comment.content.handlebars'] + ], + + commentBlock: [ + [/--\}\}/, 'comment.block.end.handlebars', '@pop'], + [/./, 'comment.content.handlebars'] + ], + + commentHtml: [ + [ + /\{\{/, + { + token: '@rematch', + switchTo: '@handlebarsInSimpleState.comment' + } + ], + [/-->/, 'comment.html', '@pop'], + [/[^-]+/, 'comment.content.html'], + [/./, 'comment.content.html'] + ], + + otherTag: [ + [ + /\{\{/, + { + token: '@rematch', + switchTo: '@handlebarsInSimpleState.otherTag' + } + ], + [/\/?>/, 'delimiter.html', '@pop'], + [/"([^"]*)"/, 'attribute.value'], + [/'([^']*)'/, 'attribute.value'], + [/[\w\-]+/, 'attribute.name'], + [/=/, 'delimiter'], + [/[ \t\r\n]+/] // whitespace + ], + + // -- BEGIN ', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' }, + { startIndex: 13, type: 'attribute.value.html' }, + { startIndex: 30, type: 'delimiter.html' }, + { startIndex: 31, type: 'keyword.js' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'identifier.js' }, + { startIndex: 36, type: 'delimiter.js' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'number.js' }, + { startIndex: 40, type: 'delimiter.js' }, + { startIndex: 41, type: 'delimiter.html' }, + { startIndex: 43, type: 'tag.html' }, + { startIndex: 49, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #2 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 2, type: 'tag.html' }, + { startIndex: 8, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #3 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 2, type: 'tag.html' }, + { startIndex: 8, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #4 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'keyword.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: 'delimiter.js' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.js' }, + { startIndex: 9, type: 'delimiter.js' }, + { startIndex: 10, type: 'delimiter.html' }, + { startIndex: 12, type: 'tag.html' }, + { startIndex: 18, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #5 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.html' }, + { startIndex: 4, type: 'tag.html' }, + { startIndex: 10, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #6 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: 'delimiter.html' }, + { startIndex: 8, type: 'identifier.js' }, + { startIndex: 9, type: 'delimiter.html' }, + { startIndex: 11, type: 'tag.html' }, + { startIndex: 17, type: 'delimiter.html' }, + // { startIndex:18, type: 'delimiter.html' }, + { startIndex: 19, type: 'tag.html' }, + { startIndex: 25, type: 'delimiter.html' }, + { startIndex: 26, type: 'identifier.js' }, + { startIndex: 27, type: 'delimiter.html' }, + { startIndex: 29, type: 'tag.html' }, + { startIndex: 35, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #7 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' }, + { startIndex: 13, type: 'attribute.value.html' }, + { startIndex: 30, type: 'delimiter.html' }, + // { startIndex:31, type: 'delimiter.html' }, + { startIndex: 33, type: 'tag.html' }, + { startIndex: 39, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #8 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: 'delimiter.html' }, + { startIndex: 8, type: 'keyword.js' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'identifier.js' }, + { startIndex: 13, type: 'delimiter.js' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'number.js' }, + { startIndex: 17, type: 'delimiter.js' }, + { startIndex: 18, type: 'delimiter.html' }, + { startIndex: 20, type: 'tag.html' }, + { startIndex: 26, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #9 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' }, + { startIndex: 13, type: 'attribute.value.html' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'attribute.name.html' }, + { startIndex: 34, type: 'delimiter.html' }, + { startIndex: 35, type: 'attribute.value.html' }, + { startIndex: 44, type: 'delimiter.html' }, + // { startIndex:45, type: 'delimiter.html' }, + { startIndex: 47, type: 'tag.html' }, + { startIndex: 53, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attribute + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 14, type: 'delimiter.html' } + ] + } + ], + + // Tag with Empty Attribute Value + [ + { + line: "", + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 14, type: 'delimiter.html' } + ] + } + ], + + // Tag with empty attributes + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 11, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attributes + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.name.html' }, + { startIndex: 18, type: 'delimiter.html' }, + { startIndex: 19, type: 'attribute.value.html' }, + { startIndex: 24, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attributes, no quotes + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.name.html' }, // slightly incorrect + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.name.html' }, + { startIndex: 16, type: 'delimiter.html' }, + { startIndex: 17, type: 'attribute.name.html' }, // slightly incorrect + { startIndex: 24, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attribute And Whitespace + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: '' }, + { startIndex: 11, type: 'attribute.value.html' }, + { startIndex: 16, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attribute And Whitespace #2 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.html' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'attribute.value.html' }, + { startIndex: 16, type: 'delimiter.html' } + ] + } + ], + + // Tag with Name-Only-Attribute #1 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' } + ] + } + ], + + // Tag with Name-Only-Attribute #2 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' } + ] + } + ], + + // Tag with Interesting Attribute Name + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: '' }, + { startIndex: 11, type: 'delimiter.html' }, + { startIndex: 12, type: 'attribute.value.html' }, + { startIndex: 17, type: 'delimiter.html' } + ] + } + ], + + // Tag with Angular Attribute Name + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 6, type: 'attribute.name.html' }, + { startIndex: 13, type: '' }, + { startIndex: 15, type: 'attribute.name.html' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.html' }, + { startIndex: 22, type: 'attribute.value.html' }, + { startIndex: 27, type: '' }, + { startIndex: 29, type: 'attribute.name.html' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'delimiter.html' }, + { startIndex: 36, type: 'attribute.value.html' }, + { startIndex: 50, type: '' }, + { startIndex: 52, type: 'attribute.name.html' }, + { startIndex: 56, type: 'delimiter.html' }, + { startIndex: 57, type: 'attribute.value.html' }, + { startIndex: 72, type: 'delimiter.html' } + ] + } + ], + + // Tag with Invalid Attribute Value + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'metatag.content.html' }, + { startIndex: 11, type: 'metatag.html' } + ] + } + ], + + // PR #14 + [ + { + line: 'asd', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 9, type: 'delimiter.html' }, + { startIndex: 10, type: '' }, + { startIndex: 13, type: 'delimiter.html' }, + { startIndex: 15, type: 'tag.html' }, + { startIndex: 23, type: 'delimiter.html' } + ] + } + ] + ] +); diff --git a/monaco-languages/src/html/html.ts b/monaco-languages/src/html/html.ts new file mode 100644 index 00000000..a8476184 --- /dev/null +++ b/monaco-languages/src/html/html.ts @@ -0,0 +1,341 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { languages } from '../fillers/monaco-editor-core'; + +const EMPTY_ELEMENTS: string[] = [ + 'area', + 'base', + 'br', + 'col', + 'embed', + 'hr', + 'img', + 'input', + 'keygen', + 'link', + 'menuitem', + 'meta', + 'param', + 'source', + 'track', + 'wbr' +]; + +export const conf: languages.LanguageConfiguration = { + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, + + comments: { + blockComment: [''] + }, + + brackets: [ + [''], + ['<', '>'], + ['{', '}'], + ['(', ')'] + ], + + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + surroundingPairs: [ + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' } + ], + + onEnterRules: [ + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>$/i, + action: { + indentAction: languages.IndentAction.IndentOutdent + } + }, + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + action: { indentAction: languages.IndentAction.Indent } + } + ], + + folding: { + markers: { + start: new RegExp('^\\s*'), + end: new RegExp('^\\s*') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.html', + ignoreCase: true, + + // The main tokenizer for our languages + tokenizer: { + root: [ + [/)/, ['delimiter', 'tag', '', 'delimiter']], + [/(<)(script)/, ['delimiter', { token: 'tag', next: '@script' }]], + [/(<)(style)/, ['delimiter', { token: 'tag', next: '@style' }]], + [/(<)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter', { token: 'tag', next: '@otherTag' }]], + [/(<\/)((?:[\w\-]+:)?[\w\-]+)/, ['delimiter', { token: 'tag', next: '@otherTag' }]], + [/]+/, 'metatag.content'], + [/>/, 'metatag', '@pop'] + ], + + comment: [ + [/-->/, 'comment', '@pop'], + [/[^-]+/, 'comment.content'], + [/./, 'comment.content'] + ], + + otherTag: [ + [/\/?>/, 'delimiter', '@pop'], + [/"([^"]*)"/, 'attribute.value'], + [/'([^']*)'/, 'attribute.value'], + [/[\w\-]+/, 'attribute.name'], + [/=/, 'delimiter'], + [/[ \t\r\n]+/] // whitespace + ], + + // -- BEGIN +// +// +// +// diff --git a/monaco-languages/src/ini/ini.contribution.ts b/monaco-languages/src/ini/ini.contribution.ts new file mode 100644 index 00000000..7ca9805f --- /dev/null +++ b/monaco-languages/src/ini/ini.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'ini', + extensions: ['.ini', '.properties', '.gitconfig'], + filenames: ['config', '.gitattributes', '.gitconfig', '.editorconfig'], + aliases: ['Ini', 'ini'], + loader: () => import('./ini') +}); diff --git a/monaco-languages/src/ini/ini.ts b/monaco-languages/src/ini/ini.ts new file mode 100644 index 00000000..7a68557d --- /dev/null +++ b/monaco-languages/src/ini/ini.ts @@ -0,0 +1,82 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '#' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.ini', + + // we include these common regular expressions + escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, + + // The main tokenizer for our languages + tokenizer: { + root: [ + // sections + [/^\[[^\]]*\]/, 'metatag'], + + // keys + [/(^\w+)(\s*)(\=)/, ['key', '', 'delimiter']], + + // whitespace + { include: '@whitespace' }, + + // numbers + [/\d+/, 'number'], + + // strings: recover on non-terminated strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/'([^'\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, 'string', '@string."'], + [/'/, 'string', "@string.'"] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/^\s*[#;].*$/, 'comment'] + ], + + string: [ + [/[^\\"']+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [ + /["']/, + { + cases: { + '$#==$S2': { token: 'string', next: '@pop' }, + '@default': 'string' + } + } + ] + ] + } +}; diff --git a/monaco-languages/src/java/java.contribution.ts b/monaco-languages/src/java/java.contribution.ts new file mode 100644 index 00000000..0254c6e5 --- /dev/null +++ b/monaco-languages/src/java/java.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'java', + extensions: ['.java', '.jav'], + aliases: ['Java', 'java'], + mimetypes: ['text/x-java-source', 'text/x-java'], + loader: () => import('./java') +}); diff --git a/monaco-languages/src/java/java.test.ts b/monaco-languages/src/java/java.test.ts new file mode 100644 index 00000000..158a73bd --- /dev/null +++ b/monaco-languages/src/java/java.test.ts @@ -0,0 +1,878 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('java', [ + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.java' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.java' } + ] + } + ], + + // Broken nested tokens due to invalid comment tokenization + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.java' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.java' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.java' }, + { startIndex: 1, type: 'identifier.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.java' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.java' }, + { startIndex: 5, type: 'delimiter.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.java' } + ] + } + ], + + [ + { + line: 'int x = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.int.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.java' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.java' }, + { startIndex: 9, type: 'delimiter.java' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.java' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.java' }] + } + ], + + [ + { + line: 'int x = /* a simple comment */ 1;', + tokens: [ + { startIndex: 0, type: 'keyword.int.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.java' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.java' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.java' }, + { startIndex: 32, type: 'delimiter.java' } + ] + } + ], + + [ + { + line: 'int x = /* comment */ 1; */', + tokens: [ + { startIndex: 0, type: 'keyword.int.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.java' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.java' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.java' }, + { startIndex: 23, type: 'delimiter.java' }, + { startIndex: 24, type: '' } + ] + } + ], + + [ + { + line: 'x = /**/;', + tokens: [ + { startIndex: 0, type: 'identifier.java' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.java' }, + { startIndex: 8, type: 'delimiter.java' } + ] + } + ], + + [ + { + line: 'x = /*/;', + tokens: [ + { startIndex: 0, type: 'identifier.java' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.java' } + ] + } + ], + + // Comments - range comment, multiple lines + [ + { + line: '/* start of multiline comment', + tokens: [{ startIndex: 0, type: 'comment.java' }] + }, + { + line: 'a comment between without a star', + tokens: [{ startIndex: 0, type: 'comment.java' }] + }, + { + line: 'end of multiline comment*/', + tokens: [{ startIndex: 0, type: 'comment.java' }] + } + ], + + [ + { + line: 'int x = /* start a comment', + tokens: [ + { startIndex: 0, type: 'keyword.int.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.java' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.java' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.java' }] + }, + { + line: 'and end it */ 2;', + tokens: [ + { startIndex: 0, type: 'comment.java' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.java' }, + { startIndex: 15, type: 'delimiter.java' } + ] + } + ], + + // Java Doc, multiple lines + [ + { + line: '/** start of Java Doc', + tokens: [{ startIndex: 0, type: 'comment.doc.java' }] + }, + { + line: 'a comment between without a star', + tokens: [{ startIndex: 0, type: 'comment.doc.java' }] + }, + { + line: 'end of multiline comment*/', + tokens: [{ startIndex: 0, type: 'comment.doc.java' }] + } + ], + + // Keywords + [ + { + line: 'package test; class Program { static void main(String[] args) {} } }', + tokens: [ + { startIndex: 0, type: 'keyword.package.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.java' }, + { startIndex: 12, type: 'delimiter.java' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.class.java' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'identifier.java' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.curly.java' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'keyword.static.java' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'keyword.void.java' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'identifier.java' }, + { startIndex: 46, type: 'delimiter.parenthesis.java' }, + { startIndex: 47, type: 'identifier.java' }, + { startIndex: 53, type: 'delimiter.square.java' }, + { startIndex: 55, type: '' }, + { startIndex: 56, type: 'identifier.java' }, + { startIndex: 60, type: 'delimiter.parenthesis.java' }, + { startIndex: 61, type: '' }, + { startIndex: 62, type: 'delimiter.curly.java' }, + { startIndex: 64, type: '' }, + { startIndex: 65, type: 'delimiter.curly.java' }, + { startIndex: 66, type: '' }, + { startIndex: 67, type: 'delimiter.curly.java' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.java' }] + } + ], + + [ + { + line: '0.10', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '0x', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.java' }] + } + ], + + [ + { + line: '0x5_2', + tokens: [{ startIndex: 0, type: 'number.hex.java' }] + } + ], + + [ + { + line: '023L', + tokens: [{ startIndex: 0, type: 'number.octal.java' }] + } + ], + + [ + { + line: '0123l', + tokens: [{ startIndex: 0, type: 'number.octal.java' }] + } + ], + + [ + { + line: '05_2', + tokens: [{ startIndex: 0, type: 'number.octal.java' }] + } + ], + + [ + { + line: '0b1010_0101', + tokens: [{ startIndex: 0, type: 'number.binary.java' }] + } + ], + + [ + { + line: '0B001', + tokens: [{ startIndex: 0, type: 'number.binary.java' }] + } + ], + + [ + { + line: '10e3', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '10f', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5e-3', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5E-3', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5F', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5f', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5D', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23.5d', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '1.72E3D', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '1.72E3d', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '1.72E-3d', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '1.72e3D', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '1.72e3d', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '1.72e-3d', + tokens: [{ startIndex: 0, type: 'number.float.java' }] + } + ], + + [ + { + line: '23L', + tokens: [{ startIndex: 0, type: 'number.java' }] + } + ], + + [ + { + line: '23l', + tokens: [{ startIndex: 0, type: 'number.java' }] + } + ], + + [ + { + line: '0_52', + tokens: [{ startIndex: 0, type: 'number.java' }] + } + ], + + [ + { + line: '5_2', + tokens: [{ startIndex: 0, type: 'number.java' }] + } + ], + + [ + { + line: '5_______2', + tokens: [{ startIndex: 0, type: 'number.java' }] + } + ], + + [ + { + line: '3_.1415F', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: 'identifier.java' }, + { startIndex: 2, type: 'delimiter.java' }, + { startIndex: 3, type: 'number.float.java' } + ] + } + ], + + [ + { + line: '3._1415F', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: 'delimiter.java' }, + { startIndex: 2, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '999_99_9999_L', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 11, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '52_', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 2, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '0_x52', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '0x_52', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '0x52_', + tokens: [ + { startIndex: 0, type: 'number.hex.java' }, + { startIndex: 4, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '052_', + tokens: [ + { startIndex: 0, type: 'number.octal.java' }, + { startIndex: 3, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '23.5L', + tokens: [ + { startIndex: 0, type: 'number.float.java' }, + { startIndex: 4, type: 'identifier.java' } + ] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: 'delimiter.java' }, + { startIndex: 2, type: 'number.java' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 3, type: 'delimiter.java' }, + { startIndex: 4, type: 'number.java' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.java' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.java' } + ] + } + ], + + // single line Strings + [ + { + line: 'String s = "I\'m a Java String";', + tokens: [ + { startIndex: 0, type: 'identifier.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.java' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.java' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.java' }, + { startIndex: 30, type: 'delimiter.java' } + ] + } + ], + + [ + { + line: 'String s = "concatenated" + " String" ;', + tokens: [ + { startIndex: 0, type: 'identifier.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.java' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.java' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.java' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'delimiter.java' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'string.java' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'delimiter.java' } + ] + } + ], + + [ + { + line: '"quote in a string"', + tokens: [{ startIndex: 0, type: 'string.java' }] + } + ], + + [ + { + line: '"escaping \\"quotes\\" is cool"', + tokens: [ + { startIndex: 0, type: 'string.java' }, + { startIndex: 10, type: 'string.escape.java' }, + { startIndex: 12, type: 'string.java' }, + { startIndex: 18, type: 'string.escape.java' }, + { startIndex: 20, type: 'string.java' } + ] + } + ], + + [ + { + line: '"\\"', + tokens: [{ startIndex: 0, type: 'string.invalid.java' }] + } + ], + + // Annotations + [ + { + line: '@', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: '@Override', + tokens: [{ startIndex: 0, type: 'annotation.java' }] + } + ], + + [ + { + line: '@SuppressWarnings(value = "aString")', + tokens: [ + { startIndex: 0, type: 'annotation.java' }, + { startIndex: 17, type: 'delimiter.parenthesis.java' }, + { startIndex: 18, type: 'identifier.java' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'delimiter.java' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'string.java' }, + { startIndex: 35, type: 'delimiter.parenthesis.java' } + ] + } + ], + + [ + { + line: '@ AnnotationWithKeywordAfter private', + tokens: [ + { startIndex: 0, type: 'annotation.java' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'keyword.private.java' } + ] + } + ], + + [ + { + line: 'String s = """Multiline string""";', + tokens: [ + { startIndex: 0, type: 'identifier.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.java' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.java' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.java' }, + { startIndex: 33, type: 'delimiter.java' } + ] + } + ], + + [ + { + line: 'String s = """', + tokens: [ + { startIndex: 0, type: 'identifier.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.java' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.java' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.java' } + ] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: 'string.java' }] + }, + { + line: ' """;', + tokens: [ + { startIndex: 0, type: 'string.java' }, + { startIndex: 8, type: 'delimiter.java' } + ] + } + ], + + [ + { + line: 'String s = """', + tokens: [ + { startIndex: 0, type: 'identifier.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.java' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.java' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.java' } + ] + }, + + { + line: ' \\"""Triple quoted string inside text block\\"""', + tokens: [ + { startIndex: 0, type: 'string.java' }, + { startIndex: 5, type: 'string.escape.java' }, + { startIndex: 7, type: 'string.java' }, + { startIndex: 47, type: 'string.escape.java' }, + { startIndex: 49, type: 'string.java' } + ] + }, + + { + line: ' """;', + tokens: [ + { startIndex: 0, type: 'string.java' }, + { startIndex: 8, type: 'delimiter.java' } + ] + } + ], + + [ + { + line: 'yield "123"', + tokens: [ + { startIndex: 0, type: 'keyword.yield.java' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'string.java' } + ] + } + ], + + [ + { + line: 'public sealed class Shape permits Circle, Square { }', + tokens: [ + { startIndex: 0, type: 'keyword.public.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'keyword.sealed.java' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.class.java' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'identifier.java' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'keyword.permits.java' }, + { startIndex: 33, type: '' }, + { startIndex: 34, type: 'identifier.java' }, + { startIndex: 40, type: 'delimiter.java' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'identifier.java' }, + { startIndex: 48, type: '' }, + { startIndex: 49, type: 'delimiter.curly.java' }, + { startIndex: 50, type: '' }, + { startIndex: 51, type: 'delimiter.curly.java' } + ] + } + ], + + [ + { + line: 'public non-sealed class Shape', + tokens: [ + { startIndex: 0, type: 'keyword.public.java' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'keyword.non-sealed.java' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'keyword.class.java' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'identifier.java' } + ] + } + ], + + [ + { + line: 'int x = y-z;', // Make sure "y-z" is not identifier + tokens: [ + { startIndex: 0, type: 'keyword.int.java' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.java' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.java' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.java' }, + { startIndex: 9, type: 'delimiter.java' }, + { startIndex: 10, type: 'identifier.java' }, + { startIndex: 11, type: 'delimiter.java' } + ] + } + ] +]); diff --git a/monaco-languages/src/java/java.ts b/monaco-languages/src/java/java.ts new file mode 100644 index 00000000..18d6291f --- /dev/null +++ b/monaco-languages/src/java/java.ts @@ -0,0 +1,253 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + // the default separators except `@$` + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: '<', close: '>' } + ], + folding: { + markers: { + start: new RegExp('^\\s*//\\s*(?:(?:#?region\\b)|(?:))') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.java', + + keywords: [ + 'abstract', + 'continue', + 'for', + 'new', + 'switch', + 'assert', + 'default', + 'goto', + 'package', + 'synchronized', + 'boolean', + 'do', + 'if', + 'private', + 'this', + 'break', + 'double', + 'implements', + 'protected', + 'throw', + 'byte', + 'else', + 'import', + 'public', + 'throws', + 'case', + 'enum', + 'instanceof', + 'return', + 'transient', + 'catch', + 'extends', + 'int', + 'short', + 'try', + 'char', + 'final', + 'interface', + 'static', + 'void', + 'class', + 'finally', + 'long', + 'strictfp', + 'volatile', + 'const', + 'float', + 'native', + 'super', + 'while', + 'true', + 'false', + 'yield', + 'record', + 'sealed', + 'non-sealed', + 'permits' + ], + + operators: [ + '=', + '>', + '<', + '!', + '~', + '?', + ':', + '==', + '<=', + '>=', + '!=', + '&&', + '||', + '++', + '--', + '+', + '-', + '*', + '/', + '&', + '|', + '^', + '%', + '<<', + '>>', + '>>>', + '+=', + '-=', + '*=', + '/=', + '&=', + '|=', + '^=', + '%=', + '<<=', + '>>=', + '>>>=' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // @ annotations. + [/@\s*[a-zA-Z_\$][\w\$]*/, 'annotation'], + + // numbers + [/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/0[xX](@hexdigits)[Ll]?/, 'number.hex'], + [/0(@octaldigits)[Ll]?/, 'number.octal'], + [/0[bB](@binarydigits)[Ll]?/, 'number.binary'], + [/(@digits)[fFdD]/, 'number.float'], + [/(@digits)[lL]?/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"""/, 'string', '@multistring'], + [/"/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@javadoc'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + // [/\/\*/, 'comment', '@push' ], // nested comment not allowed :-( + // [/\/\*/, 'comment.invalid' ], // this breaks block comments in the shape of /* //*/ + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + //Identical copy of comment above, except for the addition of .doc + javadoc: [ + [/[^\/*]+/, 'comment.doc'], + // [/\/\*/, 'comment.doc', '@push' ], // nested comment not allowed :-( + [/\/\*/, 'comment.doc.invalid'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'] + ], + + multistring: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"""/, 'string', '@pop'], + [/./, 'string'] + ] + } +}; diff --git a/monaco-languages/src/javascript/javascript.contribution.ts b/monaco-languages/src/javascript/javascript.contribution.ts new file mode 100644 index 00000000..622ce789 --- /dev/null +++ b/monaco-languages/src/javascript/javascript.contribution.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'javascript', + extensions: ['.js', '.es6', '.jsx', '.mjs'], + firstLine: '^#!.*\\bnode', + filenames: ['jakefile'], + aliases: ['JavaScript', 'javascript', 'js'], + mimetypes: ['text/javascript'], + loader: () => import('./javascript') +}); diff --git a/monaco-languages/src/javascript/javascript.test.ts b/monaco-languages/src/javascript/javascript.test.ts new file mode 100644 index 00000000..a3566422 --- /dev/null +++ b/monaco-languages/src/javascript/javascript.test.ts @@ -0,0 +1,865 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('javascript', [ + // Keywords + [ + { + line: 'var x = function() { };', + tokens: [ + { startIndex: 0, type: 'keyword.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'keyword.js' }, + { startIndex: 16, type: 'delimiter.parenthesis.js' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'delimiter.bracket.js' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.bracket.js' }, + { startIndex: 22, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: ' var ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.js' }, + { startIndex: 7, type: '' } + ] + } + ], + + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.js' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: '// a comment /*', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: '// a comment /**', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: 'var x = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.js' }, + { startIndex: 9, type: 'delimiter.js' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.js' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: 'var x = /* a simple comment */ 1;', + tokens: [ + { startIndex: 0, type: 'keyword.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.js' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.js' }, + { startIndex: 32, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: 'x = /**/;', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.js' }, + { startIndex: 8, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: 'x = /*/;', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.js' } + ] + } + ], + + // Comments - range comment, multi lines + [ + { + line: '/* a multiline comment', + tokens: [{ startIndex: 0, type: 'comment.js' }] + }, + { + line: 'can actually span', + tokens: [{ startIndex: 0, type: 'comment.js' }] + }, + { + line: 'multiple lines */', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: 'var x = /* start a comment', + tokens: [ + { startIndex: 0, type: 'keyword.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.js' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.js' }] + }, + { + line: 'and end it */ var a = 2;', + tokens: [ + { startIndex: 0, type: 'comment.js' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.js' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'identifier.js' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'delimiter.js' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.js' }, + { startIndex: 23, type: 'delimiter.js' } + ] + } + ], + + // Strings + [ + { + line: "var a = 'a';", + tokens: [ + { startIndex: 0, type: 'keyword.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.js' }, + { startIndex: 11, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: '"use strict";', + tokens: [ + { startIndex: 0, type: 'string.js' }, + { startIndex: 12, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: 'b = a + " \'cool\' "', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.js' } + ] + } + ], + + [ + { + line: '"escaping \\"quotes\\" is cool"', + tokens: [ + { startIndex: 0, type: 'string.js' }, + { startIndex: 10, type: 'string.escape.js' }, + { startIndex: 12, type: 'string.js' }, + { startIndex: 18, type: 'string.escape.js' }, + { startIndex: 20, type: 'string.js' } + ] + } + ], + + [ + { + line: "'''", + tokens: [ + { startIndex: 0, type: 'string.js' }, + { startIndex: 2, type: 'string.invalid.js' } + ] + } + ], + + [ + { + line: "'\\''", + tokens: [ + { startIndex: 0, type: 'string.js' }, + { startIndex: 1, type: 'string.escape.js' }, + { startIndex: 3, type: 'string.js' } + ] + } + ], + + [ + { + line: "'be careful \\not to escape'", + tokens: [ + { startIndex: 0, type: 'string.js' }, + { startIndex: 12, type: 'string.escape.js' }, + { startIndex: 14, type: 'string.js' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.js' }] + } + ], + + [ + { + line: ' 0', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'number.js' } + ] + } + ], + + [ + { + line: ' 0 ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'number.js' }, + { startIndex: 2, type: '' } + ] + } + ], + + [ + { + line: '0 ', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: '' } + ] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: 'delimiter.js' }, + { startIndex: 2, type: 'number.js' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 3, type: 'delimiter.js' }, + { startIndex: 4, type: 'number.js' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.js' } + ] + } + ], + + [ + { + line: '0123', + tokens: [{ startIndex: 0, type: 'number.octal.js' }] + } + ], + + [ + { + line: '01239', + tokens: [ + { startIndex: 0, type: 'number.octal.js' }, + { startIndex: 4, type: 'number.js' } + ] + } + ], + + [ + { + line: '0o123', + tokens: [{ startIndex: 0, type: 'number.octal.js' }] + } + ], + + [ + { + line: '0O123', + tokens: [{ startIndex: 0, type: 'number.octal.js' }] + } + ], + + [ + { + line: '0x', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: 'identifier.js' } + ] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.js' }] + } + ], + + [ + { + line: '0X123', + tokens: [{ startIndex: 0, type: 'number.hex.js' }] + } + ], + + [ + { + line: '0b101', + tokens: [{ startIndex: 0, type: 'number.binary.js' }] + } + ], + + [ + { + line: '0B101', + tokens: [{ startIndex: 0, type: 'number.binary.js' }] + } + ], + + // Bigint + [ + { + line: '0n', + tokens: [{ startIndex: 0, type: 'number.js' }] + } + ], + + [ + { + line: ' 0n', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'number.js' } + ] + } + ], + + [ + { + line: ' 0n ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'number.js' }, + { startIndex: 3, type: '' } + ] + } + ], + + [ + { + line: '0n ', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 2, type: '' } + ] + } + ], + + [ + { + line: '0n+0n', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: 'number.js' } + ] + } + ], + + [ + { + line: '100n+10n', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 4, type: 'delimiter.js' }, + { startIndex: 5, type: 'number.js' } + ] + } + ], + + [ + { + line: '0n + 0n', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.js' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'number.js' } + ] + } + ], + + [ + { + line: '0b101n', + tokens: [{ startIndex: 0, type: 'number.binary.js' }] + } + ], + + [ + { + line: '0123n', + tokens: [{ startIndex: 0, type: 'number.octal.js' }] + } + ], + + [ + { + line: '0o123n', + tokens: [{ startIndex: 0, type: 'number.octal.js' }] + } + ], + + [ + { + line: '0x123n', + tokens: [{ startIndex: 0, type: 'number.hex.js' }] + } + ], + + // Regular Expressions + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: '/**/', + tokens: [{ startIndex: 0, type: 'comment.js' }] + } + ], + + [ + { + line: '/***/', + tokens: [{ startIndex: 0, type: 'comment.doc.js' }] + } + ], + + [ + { + line: '5 / 3;', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.js' }, + { startIndex: 5, type: 'delimiter.js' } + ] + } + ], + + // Advanced regular expressions + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.js' }, + { startIndex: 5, type: 'delimiter.js' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.js' } + ] + } + ], + + [ + { + line: '1 / 2 / x / b;', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.js' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'delimiter.js' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'identifier.js' }, + { startIndex: 13, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: "x = /foo/.test('')", + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'regexp.js' }, + { startIndex: 9, type: 'delimiter.js' }, + { startIndex: 10, type: 'identifier.js' }, + { startIndex: 14, type: 'delimiter.parenthesis.js' }, + { startIndex: 15, type: 'string.js' }, + { startIndex: 17, type: 'delimiter.parenthesis.js' } + ] + } + ], + + [ + { + line: '/foo/', + tokens: [{ startIndex: 0, type: 'regexp.js' }] + } + ], + + [ + { + line: '/foo/g', + tokens: [ + { startIndex: 0, type: 'regexp.js' }, + { startIndex: 5, type: 'keyword.other.js' } + ] + } + ], + + [ + { + line: '/foo/dgimsuy', + tokens: [ + { startIndex: 0, type: 'regexp.js' }, + { startIndex: 5, type: 'keyword.other.js' } + ] + } + ], + + [ + { + line: '/foo/q', // invalid flag + tokens: [ + { startIndex: 0, type: 'delimiter.js' }, + { startIndex: 1, type: 'identifier.js' }, + { startIndex: 4, type: 'delimiter.js' }, + { startIndex: 5, type: 'identifier.js' } + ] + } + ], + + [ + { + line: 'x = 1 + f(2 / 3, /foo/)', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.js' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.js' }, + { startIndex: 9, type: 'delimiter.parenthesis.js' }, + { startIndex: 10, type: 'number.js' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.js' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.js' }, + { startIndex: 15, type: 'delimiter.js' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'regexp.js' }, + { startIndex: 22, type: 'delimiter.parenthesis.js' } + ] + } + ], + + [ + { + line: 'a /ads/ b;', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: 'identifier.js' }, + { startIndex: 6, type: 'delimiter.js' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.js' }, + { startIndex: 9, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: '1/(2/3)/2/3;', + tokens: [ + { startIndex: 0, type: 'number.js' }, + { startIndex: 1, type: 'delimiter.js' }, + { startIndex: 2, type: 'delimiter.parenthesis.js' }, + { startIndex: 3, type: 'number.js' }, + { startIndex: 4, type: 'delimiter.js' }, + { startIndex: 5, type: 'number.js' }, + { startIndex: 6, type: 'delimiter.parenthesis.js' }, + { startIndex: 7, type: 'delimiter.js' }, + { startIndex: 8, type: 'number.js' }, + { startIndex: 9, type: 'delimiter.js' }, + { startIndex: 10, type: 'number.js' }, + { startIndex: 11, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: '{ key: 123 }', + tokens: [ + { startIndex: 0, type: 'delimiter.bracket.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'identifier.js' }, + { startIndex: 5, type: 'delimiter.js' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.js' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.bracket.js' } + ] + } + ], + + [ + { + line: '[1,2,3]', + tokens: [ + { startIndex: 0, type: 'delimiter.square.js' }, + { startIndex: 1, type: 'number.js' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: 'number.js' }, + { startIndex: 4, type: 'delimiter.js' }, + { startIndex: 5, type: 'number.js' }, + { startIndex: 6, type: 'delimiter.square.js' } + ] + } + ], + + [ + { + line: 'foo(123);', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 3, type: 'delimiter.parenthesis.js' }, + { startIndex: 4, type: 'number.js' }, + { startIndex: 7, type: 'delimiter.parenthesis.js' }, + { startIndex: 8, type: 'delimiter.js' } + ] + } + ], + + [ + { + line: '{a:{b:[]}}', + tokens: [ + { startIndex: 0, type: 'delimiter.bracket.js' }, + { startIndex: 1, type: 'identifier.js' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: 'delimiter.bracket.js' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: 'delimiter.js' }, + { startIndex: 6, type: 'delimiter.square.js' }, + { startIndex: 8, type: 'delimiter.bracket.js' } + ] + } + ], + + [ + { + line: 'x = "[{()}]"', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'string.js' } + ] + } + ], + + [ + { + line: 'test ? 1 : 2', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.js' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.js' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.js' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'number.js' } + ] + } + ], + + [ + { + line: 'couldBeNullish ?? 1', + tokens: [ + { startIndex: 0, type: 'identifier.js' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.js' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'number.js' } + ] + } + ], + + [ + { + line: "`${5 + 'x' + 3}a${4}`", + tokens: [ + { startIndex: 0, type: 'string.js' }, + { startIndex: 1, type: 'delimiter.bracket.js' }, + { startIndex: 3, type: 'number.js' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.js' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.js' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.js' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'number.js' }, + { startIndex: 14, type: 'delimiter.bracket.js' }, + { startIndex: 15, type: 'string.js' }, + { startIndex: 16, type: 'delimiter.bracket.js' }, + { startIndex: 18, type: 'number.js' }, + { startIndex: 19, type: 'delimiter.bracket.js' }, + { startIndex: 20, type: 'string.js' } + ] + } + ] +]); diff --git a/monaco-languages/src/javascript/javascript.ts b/monaco-languages/src/javascript/javascript.ts new file mode 100644 index 00000000..6e34efe6 --- /dev/null +++ b/monaco-languages/src/javascript/javascript.ts @@ -0,0 +1,76 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { conf as tsConf, language as tsLanguage } from '../typescript/typescript'; +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = tsConf; + +export const language = { + // Set defaultToken to invalid to see what you do not tokenize yet + defaultToken: 'invalid', + tokenPostfix: '.js', + + keywords: [ + 'break', + 'case', + 'catch', + 'class', + 'continue', + 'const', + 'constructor', + 'debugger', + 'default', + 'delete', + 'do', + 'else', + 'export', + 'extends', + 'false', + 'finally', + 'for', + 'from', + 'function', + 'get', + 'if', + 'import', + 'in', + 'instanceof', + 'let', + 'new', + 'null', + 'return', + 'set', + 'super', + 'switch', + 'symbol', + 'this', + 'throw', + 'true', + 'try', + 'typeof', + 'undefined', + 'var', + 'void', + 'while', + 'with', + 'yield', + 'async', + 'await', + 'of' + ], + typeKeywords: [], + + operators: tsLanguage.operators, + symbols: tsLanguage.symbols, + escapes: tsLanguage.escapes, + digits: tsLanguage.digits, + octaldigits: tsLanguage.octaldigits, + binarydigits: tsLanguage.binarydigits, + hexdigits: tsLanguage.hexdigits, + regexpctl: tsLanguage.regexpctl, + regexpesc: tsLanguage.regexpesc, + tokenizer: tsLanguage.tokenizer +}; diff --git a/monaco-languages/src/julia/julia.contribution.ts b/monaco-languages/src/julia/julia.contribution.ts new file mode 100644 index 00000000..76f2780e --- /dev/null +++ b/monaco-languages/src/julia/julia.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'julia', + extensions: ['.jl'], + aliases: ['julia', 'Julia'], + loader: () => import('./julia') +}); diff --git a/monaco-languages/src/julia/julia.test.ts b/monaco-languages/src/julia/julia.test.ts new file mode 100644 index 00000000..14e21268 --- /dev/null +++ b/monaco-languages/src/julia/julia.test.ts @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('julia', [ + [ + { + line: 'a = 1', + tokens: [ + { startIndex: 0, type: 'identifier.julia' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'source.julia' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.julia' } + ] + } + ], + + [ + { + line: 'b(c) = 2c', + tokens: [ + { startIndex: 0, type: 'keyword.flow.julia' }, + { startIndex: 1, type: 'delimiter.parenthesis.julia' }, + { startIndex: 2, type: 'identifier.julia' }, + { startIndex: 3, type: 'delimiter.parenthesis.julia' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'source.julia' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.julia' }, + { startIndex: 8, type: 'identifier.julia' } + ] + } + ] +]); diff --git a/monaco-languages/src/julia/julia.ts b/monaco-languages/src/julia/julia.ts new file mode 100644 index 00000000..2d62f1a7 --- /dev/null +++ b/monaco-languages/src/julia/julia.ts @@ -0,0 +1,550 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ] +}; + +export const language = { + tokenPostfix: '.julia', + + keywords: [ + 'begin', + 'while', + 'if', + 'for', + 'try', + 'return', + 'break', + 'continue', + 'function', + 'macro', + 'quote', + 'let', + 'local', + 'global', + 'const', + 'do', + 'struct', + 'module', + 'baremodule', + 'using', + 'import', + 'export', + 'end', + 'else', + 'elseif', + 'catch', + 'finally', + 'mutable', + 'primitive', + 'abstract', + 'type', + 'in', + 'isa', + 'where', + 'new' + ], + + types: [ + 'LinRange', + 'LineNumberNode', + 'LinearIndices', + 'LoadError', + 'MIME', + 'Matrix', + 'Method', + 'MethodError', + 'Missing', + 'MissingException', + 'Module', + 'NTuple', + 'NamedTuple', + 'Nothing', + 'Number', + 'OrdinalRange', + 'OutOfMemoryError', + 'OverflowError', + 'Pair', + 'PartialQuickSort', + 'PermutedDimsArray', + 'Pipe', + 'Ptr', + 'QuoteNode', + 'Rational', + 'RawFD', + 'ReadOnlyMemoryError', + 'Real', + 'ReentrantLock', + 'Ref', + 'Regex', + 'RegexMatch', + 'RoundingMode', + 'SegmentationFault', + 'Set', + 'Signed', + 'Some', + 'StackOverflowError', + 'StepRange', + 'StepRangeLen', + 'StridedArray', + 'StridedMatrix', + 'StridedVecOrMat', + 'StridedVector', + 'String', + 'StringIndexError', + 'SubArray', + 'SubString', + 'SubstitutionString', + 'Symbol', + 'SystemError', + 'Task', + 'Text', + 'TextDisplay', + 'Timer', + 'Tuple', + 'Type', + 'TypeError', + 'TypeVar', + 'UInt', + 'UInt128', + 'UInt16', + 'UInt32', + 'UInt64', + 'UInt8', + 'UndefInitializer', + 'AbstractArray', + 'UndefKeywordError', + 'AbstractChannel', + 'UndefRefError', + 'AbstractChar', + 'UndefVarError', + 'AbstractDict', + 'Union', + 'AbstractDisplay', + 'UnionAll', + 'AbstractFloat', + 'UnitRange', + 'AbstractIrrational', + 'Unsigned', + 'AbstractMatrix', + 'AbstractRange', + 'Val', + 'AbstractSet', + 'Vararg', + 'AbstractString', + 'VecElement', + 'AbstractUnitRange', + 'VecOrMat', + 'AbstractVecOrMat', + 'Vector', + 'AbstractVector', + 'VersionNumber', + 'Any', + 'WeakKeyDict', + 'ArgumentError', + 'WeakRef', + 'Array', + 'AssertionError', + 'BigFloat', + 'BigInt', + 'BitArray', + 'BitMatrix', + 'BitSet', + 'BitVector', + 'Bool', + 'BoundsError', + 'CapturedException', + 'CartesianIndex', + 'CartesianIndices', + 'Cchar', + 'Cdouble', + 'Cfloat', + 'Channel', + 'Char', + 'Cint', + 'Cintmax_t', + 'Clong', + 'Clonglong', + 'Cmd', + 'Colon', + 'Complex', + 'ComplexF16', + 'ComplexF32', + 'ComplexF64', + 'CompositeException', + 'Condition', + 'Cptrdiff_t', + 'Cshort', + 'Csize_t', + 'Cssize_t', + 'Cstring', + 'Cuchar', + 'Cuint', + 'Cuintmax_t', + 'Culong', + 'Culonglong', + 'Cushort', + 'Cvoid', + 'Cwchar_t', + 'Cwstring', + 'DataType', + 'DenseArray', + 'DenseMatrix', + 'DenseVecOrMat', + 'DenseVector', + 'Dict', + 'DimensionMismatch', + 'Dims', + 'DivideError', + 'DomainError', + 'EOFError', + 'Enum', + 'ErrorException', + 'Exception', + 'ExponentialBackOff', + 'Expr', + 'Float16', + 'Float32', + 'Float64', + 'Function', + 'GlobalRef', + 'HTML', + 'IO', + 'IOBuffer', + 'IOContext', + 'IOStream', + 'IdDict', + 'IndexCartesian', + 'IndexLinear', + 'IndexStyle', + 'InexactError', + 'InitError', + 'Int', + 'Int128', + 'Int16', + 'Int32', + 'Int64', + 'Int8', + 'Integer', + 'InterruptException', + 'InvalidStateException', + 'Irrational', + 'KeyError' + ], + + keywordops: ['<:', '>:', ':', '=>', '...', '.', '->', '?'], + + allops: /[^\w\d\s()\[\]{}"'#]+/, + + constants: [ + 'true', + 'false', + 'nothing', + 'missing', + 'undef', + 'Inf', + 'pi', + 'NaN', + 'π', + 'ℯ', + 'ans', + 'PROGRAM_FILE', + 'ARGS', + 'C_NULL', + 'VERSION', + 'DEPOT_PATH', + 'LOAD_PATH' + ], + + operators: [ + '!', + '!=', + '!==', + '%', + '&', + '*', + '+', + '-', + '/', + '//', + '<', + '<<', + '<=', + '==', + '===', + '=>', + '>', + '>=', + '>>', + '>>>', + '\\', + '^', + '|', + '|>', + '~', + '÷', + '∈', + '∉', + '∋', + '∌', + '∘', + '√', + '∛', + '∩', + '∪', + '≈', + '≉', + '≠', + '≡', + '≢', + '≤', + '≥', + '⊆', + '⊇', + '⊈', + '⊉', + '⊊', + '⊋', + '⊻' + ], + + brackets: [ + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' } + ], + + ident: /π|ℯ|\b(?!\d)\w+\b/, + + // escape sequences + escape: /(?:[abefnrstv\\"'\n\r]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4})/, + escapes: /\\(?:C\-(@escape|.)|c(@escape|.)|@escape)/, + + // The main tokenizer for our languages + tokenizer: { + root: [ + [/(::)\s*|\b(isa)\s+/, 'keyword', '@typeanno'], + [/\b(isa)(\s*\(@ident\s*,\s*)/, ['keyword', { token: '', next: '@typeanno' }]], + [/\b(type|struct)[ \t]+/, 'keyword', '@typeanno'], + + // symbols + [/^\s*:@ident[!?]?/, 'metatag'], + [/(return)(\s*:@ident[!?]?)/, ['keyword', 'metatag']], + [/(\(|\[|\{|@allops)(\s*:@ident[!?]?)/, ['', 'metatag']], + [/:\(/, 'metatag', '@quote'], + + // regular expressions + [/r"""/, 'regexp.delim', '@tregexp'], + [/r"/, 'regexp.delim', '@sregexp'], + + // strings + [/raw"""/, 'string.delim', '@rtstring'], + [/[bv]?"""/, 'string.delim', '@dtstring'], + + [/raw"/, 'string.delim', '@rsstring'], + [/[bv]?"/, 'string.delim', '@dsstring'], + + [ + /(@ident)\{/, + { + cases: { + '$1@types': { token: 'type', next: '@gen' }, + '@default': { token: 'type', next: '@gen' } + } + } + ], + + [ + /@ident[!?'']?(?=\.?\()/, + { + cases: { + '@types': 'type', + '@keywords': 'keyword', + '@constants': 'variable', + '@default': 'keyword.flow' + } + } + ], + + [ + /@ident[!?']?/, + { + cases: { + '@types': 'type', + '@keywords': 'keyword', + '@constants': 'variable', + '@default': 'identifier' + } + } + ], + + [/\$\w+/, 'key'], + [/\$\(/, 'key', '@paste'], + + [/@@@ident/, 'annotation'], + + // whitespace + { include: '@whitespace' }, + + // characters + [/'(?:@escapes|.)'/, 'string.character'], + + // delimiters and operators + [/[()\[\]{}]/, '@brackets'], + [ + /@allops/, + { + cases: { + '@keywordops': 'keyword', + '@operators': 'operator' + } + } + ], + [/[;,]/, 'delimiter'], + + // numbers + [/0[xX][0-9a-fA-F](_?[0-9a-fA-F])*/, 'number.hex'], + [/0[_oO][0-7](_?[0-7])*/, 'number.octal'], + [/0[bB][01](_?[01])*/, 'number.binary'], + [/[+\-]?\d+(\.\d+)?(im?|[eE][+\-]?\d+(\.\d+)?)?/, 'number'] + ], + + // type + typeanno: [ + [/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*\{/, 'type', '@gen'], + [/([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(\s*<:\s*)/, ['type', 'keyword']], + [/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*/, 'type', '@pop'], + ['', '', '@pop'] + ], + + // generic type + gen: [ + [/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*\{/, 'type', '@push'], + [/[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*/, 'type'], + [/<:/, 'keyword'], + [/(\})(\s*<:\s*)/, ['type', { token: 'keyword', next: '@pop' }]], + [/\}/, 'type', '@pop'], + { include: '@root' } + ], + + // $(...) + quote: [ + [/\$\(/, 'key', '@paste'], + [/\(/, '@brackets', '@paren'], + [/\)/, 'metatag', '@pop'], + { include: '@root' } + ], + + // :(...) + paste: [ + [/:\(/, 'metatag', '@quote'], + [/\(/, '@brackets', '@paren'], + [/\)/, 'key', '@pop'], + { include: '@root' } + ], + + // (...) + paren: [ + [/\$\(/, 'key', '@paste'], + [/:\(/, 'metatag', '@quote'], + [/\(/, '@brackets', '@push'], + [/\)/, '@brackets', '@pop'], + { include: '@root' } + ], + + // r"egex string" + sregexp: [ + [/^.*/, 'invalid'], + [/[^\\"()\[\]{}]/, 'regexp'], + [/[()\[\]{}]/, '@brackets'], + [/\\./, 'operator.scss'], + [/"[imsx]*/, 'regexp.delim', '@pop'] + ], + tregexp: [ + [/[^\\"()\[\]{}]/, 'regexp'], + [/[()\[\]{}]/, '@brackets'], + [/\\./, 'operator.scss'], + [/"(?!"")/, 'string'], + [/"""[imsx]*/, 'regexp.delim', '@pop'] + ], + + // raw"string" + rsstring: [ + [/^.*/, 'invalid'], + [/[^\\"]/, 'string'], + [/\\./, 'string.escape'], + [/"/, 'string.delim', '@pop'] + ], + rtstring: [ + [/[^\\"]/, 'string'], + [/\\./, 'string.escape'], + [/"(?!"")/, 'string'], + [/"""/, 'string.delim', '@pop'] + ], + + // "string". + dsstring: [ + [/^.*/, 'invalid'], + [/[^\\"\$]/, 'string'], + [/\$/, '', '@interpolated'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string.delim', '@pop'] + ], + dtstring: [ + [/[^\\"\$]/, 'string'], + [/\$/, '', '@interpolated'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"(?!"")/, 'string'], + [/"""/, 'string.delim', '@pop'] + ], + + // interpolated sequence + interpolated: [ + [/\(/, { token: '', switchTo: '@interpolated_compound' }], + [/[a-zA-Z_]\w*/, 'identifier'], + ['', '', '@pop'] // just a $ is interpreted as a $ + ], + + // any code + interpolated_compound: [[/\)/, '', '@pop'], { include: '@root' }], + + // whitespace & comments + whitespace: [ + [/[ \t\r\n]+/, ''], + [/#=/, 'comment', '@multi_comment'], + [/#.*$/, 'comment'] + ], + + multi_comment: [ + [/#=/, 'comment', '@push'], + [/=#/, 'comment', '@pop'], + [/=(?!#)|#(?!=)/, 'comment'], + [/[^#=]+/, 'comment'] + ] + } +}; diff --git a/monaco-languages/src/kotlin/kotlin.contribution.ts b/monaco-languages/src/kotlin/kotlin.contribution.ts new file mode 100644 index 00000000..0faa5ab6 --- /dev/null +++ b/monaco-languages/src/kotlin/kotlin.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'kotlin', + extensions: ['.kt'], + aliases: ['Kotlin', 'kotlin'], + mimetypes: ['text/x-kotlin-source', 'text/x-kotlin'], + loader: () => import('./kotlin') +}); diff --git a/monaco-languages/src/kotlin/kotlin.test.ts b/monaco-languages/src/kotlin/kotlin.test.ts new file mode 100644 index 00000000..11b2bbb7 --- /dev/null +++ b/monaco-languages/src/kotlin/kotlin.test.ts @@ -0,0 +1,753 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('kotlin', [ + // inline reified function + [ + { + line: 'inline fun foo()', + tokens: [ + { startIndex: 0, type: 'keyword.inline.kt' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'keyword.fun.kt' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.angle.kt' }, + { startIndex: 12, type: 'keyword.reified.kt' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'type.identifier.kt' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'delimiter.kt' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'type.identifier.kt' }, + { startIndex: 27, type: 'delimiter.angle.kt' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'identifier.kt' }, + { startIndex: 32, type: 'delimiter.parenthesis.kt' } + ] + } + ], + + // Val declaration and assignment + [ + { + line: 'val x: X=5', + tokens: [ + { startIndex: 0, type: 'keyword.val.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.kt' }, + { startIndex: 5, type: 'delimiter.kt' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'type.identifier.kt' }, + { startIndex: 8, type: 'delimiter.kt' }, + { startIndex: 9, type: 'number.kt' } + ] + } + ], + + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.kt' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.kt' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.kt' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.kt' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'delimiter.kt' }, + { startIndex: 1, type: 'identifier.kt' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.kt' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.kt' }, + { startIndex: 5, type: 'delimiter.kt' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.kt' } + ] + } + ], + + // [{ + // line: 'var x = 1 // my comment // is a nice one', + // tokens: [ + // { startIndex: 0, type: 'keyword.var.kt' }, + // { startIndex: 3, type: '' }, + // { startIndex: 4, type: 'identifier.kt' }, + // { startIndex: 5, type: '' }, + // { startIndex: 6, type: 'delimiter.kt' }, + // { startIndex: 7, type: '' }, + // { startIndex: 8, type: 'number.kt' }, + // { startIndex: 9, type: '' }, + // { startIndex: 10, type: 'comment.kt' }, + // { startIndex: 12, type: '' }, + // { startIndex: 13, type: 'comment.kt' } + // ] + // }], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.kt' }] + } + ], + + [ + { + line: 'var x = /* a simple comment */ 1', + tokens: [ + { startIndex: 0, type: 'keyword.var.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.kt' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.kt' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.kt' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'number.kt' } + ] + } + ], + + [ + { + line: 'var x = /* comment */ 1; */', + tokens: [ + { startIndex: 0, type: 'keyword.var.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.kt' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.kt' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.kt' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.kt' }, + { startIndex: 23, type: 'delimiter.kt' }, + { startIndex: 24, type: '' } + ] + } + ], + + [ + { + line: 'x = /**/', + tokens: [ + { startIndex: 0, type: 'identifier.kt' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.kt' } + ] + } + ], + + [ + { + line: 'var x = /** start a Java Doc comment', + tokens: [ + { startIndex: 0, type: 'keyword.var.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.kt' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.kt' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.doc.kt' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.doc.kt' }] + }, + { + line: 'and end it */ 2', + tokens: [ + { startIndex: 0, type: 'comment.doc.kt' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.kt' } + ] + } + ], + + [ + { + line: '/** start of Java Doc', + tokens: [{ startIndex: 0, type: 'comment.doc.kt' }] + }, + { + line: 'a comment between without a star', + tokens: [{ startIndex: 0, type: 'comment.doc.kt' }] + }, + { + line: 'end of multiline comment*/', + tokens: [{ startIndex: 0, type: 'comment.doc.kt' }] + } + ], + + // Keywords + [ + { + line: 'package test class Program { fun main(vararg args: String) {} } }', + tokens: [ + { startIndex: 0, type: 'keyword.package.kt' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.kt' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'keyword.class.kt' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'type.identifier.kt' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'delimiter.curly.kt' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'keyword.fun.kt' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'identifier.kt' }, + { startIndex: 37, type: 'delimiter.parenthesis.kt' }, + { startIndex: 38, type: 'keyword.vararg.kt' }, + { startIndex: 44, type: '' }, + { startIndex: 45, type: 'identifier.kt' }, + { startIndex: 49, type: 'delimiter.kt' }, + { startIndex: 50, type: '' }, + { startIndex: 51, type: 'type.identifier.kt' }, + { startIndex: 57, type: 'delimiter.parenthesis.kt' }, + { startIndex: 58, type: '' }, + { startIndex: 59, type: 'delimiter.curly.kt' }, + { startIndex: 61, type: '' }, + { startIndex: 62, type: 'delimiter.curly.kt' }, + { startIndex: 63, type: '' }, + { startIndex: 64, type: 'delimiter.curly.kt' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.kt' }] + } + ], + + [ + { + line: '0.10', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '0x', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.kt' }] + } + ], + + [ + { + line: '0x5_2', + tokens: [{ startIndex: 0, type: 'number.hex.kt' }] + } + ], + + [ + { + line: '023L', + tokens: [{ startIndex: 0, type: 'number.octal.kt' }] + } + ], + + [ + { + line: '0123l', + tokens: [{ startIndex: 0, type: 'number.octal.kt' }] + } + ], + + [ + { + line: '05_2', + tokens: [{ startIndex: 0, type: 'number.octal.kt' }] + } + ], + + [ + { + line: '0b1010_0101', + tokens: [{ startIndex: 0, type: 'number.binary.kt' }] + } + ], + + [ + { + line: '0B001', + tokens: [{ startIndex: 0, type: 'number.binary.kt' }] + } + ], + + [ + { + line: '10e3', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '10f', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5e-3', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5E-3', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5F', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5f', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5D', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23.5d', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '1.72E3D', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '1.72E3d', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '1.72E-3d', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '1.72e3D', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '1.72e3d', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '1.72e-3d', + tokens: [{ startIndex: 0, type: 'number.float.kt' }] + } + ], + + [ + { + line: '23L', + tokens: [{ startIndex: 0, type: 'number.kt' }] + } + ], + + [ + { + line: '23l', + tokens: [{ startIndex: 0, type: 'number.kt' }] + } + ], + + [ + { + line: '0_52', + tokens: [{ startIndex: 0, type: 'number.kt' }] + } + ], + + [ + { + line: '5_2', + tokens: [{ startIndex: 0, type: 'number.kt' }] + } + ], + + [ + { + line: '5_______2', + tokens: [{ startIndex: 0, type: 'number.kt' }] + } + ], + + [ + { + line: '3_.1415F', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: 'identifier.kt' }, + { startIndex: 2, type: 'delimiter.kt' }, + { startIndex: 3, type: 'number.float.kt' } + ] + } + ], + + [ + { + line: '3._1415F', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: 'delimiter.kt' }, + { startIndex: 2, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '999_99_9999_L', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 11, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '52_', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 2, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '0_x52', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '0x_52', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '0x52_', + tokens: [ + { startIndex: 0, type: 'number.hex.kt' }, + { startIndex: 4, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '052_', + tokens: [ + { startIndex: 0, type: 'number.octal.kt' }, + { startIndex: 3, type: 'identifier.kt' } + ] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: 'delimiter.kt' }, + { startIndex: 2, type: 'number.kt' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 3, type: 'delimiter.kt' }, + { startIndex: 4, type: 'number.kt' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.kt' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.kt' } + ] + } + ], + + // single line Strings + [ + { + line: 'var s = "I\'m a Kotlin String"', + tokens: [ + { startIndex: 0, type: 'keyword.var.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.kt' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.kt' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.kt' } + ] + } + ], + + [ + { + line: 'var s = "concatenated" + " String"', + tokens: [ + { startIndex: 0, type: 'keyword.var.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.kt' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.kt' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.kt' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.kt' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'string.kt' } + ] + } + ], + + [ + { + line: '"quote in a string"', + tokens: [{ startIndex: 0, type: 'string.kt' }] + } + ], + + [ + { + line: '"escaping \\"quotes\\" is cool"', + tokens: [ + { startIndex: 0, type: 'string.kt' }, + { startIndex: 10, type: 'string.escape.kt' }, + { startIndex: 12, type: 'string.kt' }, + { startIndex: 18, type: 'string.escape.kt' }, + { startIndex: 20, type: 'string.kt' } + ] + } + ], + + [ + { + line: '"\\"', + tokens: [{ startIndex: 0, type: 'string.invalid.kt' }] + } + ], + + // Annotations + [ + { + line: '@', + tokens: [{ startIndex: 0, type: '' }] + } + ], + + [ + { + line: '@Inject', + tokens: [{ startIndex: 0, type: 'annotation.kt' }] + } + ], + + [ + { + line: '@SuppressWarnings("aString")', + tokens: [ + { startIndex: 0, type: 'annotation.kt' }, + { startIndex: 17, type: 'delimiter.parenthesis.kt' }, + { startIndex: 18, type: 'string.kt' }, + { startIndex: 27, type: 'delimiter.parenthesis.kt' } + ] + } + ], + + [ + { + line: '@ AnnotationWithKeywordAfter private', + tokens: [ + { startIndex: 0, type: 'annotation.kt' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'keyword.private.kt' } + ] + } + ], + + [ + { + line: 'fun /* /* */ */ main() {', + tokens: [ + { startIndex: 0, type: 'keyword.fun.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.kt' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'identifier.kt' }, + { startIndex: 20, type: 'delimiter.parenthesis.kt' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.curly.kt' } + ] + } + ], + + [ + { + line: 'val text = """', + tokens: [ + { startIndex: 0, type: 'keyword.val.kt' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.kt' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.kt' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.kt' } + ] + }, + { + line: ' for (c in "foo")', + tokens: [{ startIndex: 0, type: 'string.kt' }] + }, + { + line: ' print(c)', + tokens: [{ startIndex: 0, type: 'string.kt' }] + }, + { + line: '"""', + tokens: [{ startIndex: 0, type: 'string.kt' }] + } + ] +]); diff --git a/monaco-languages/src/kotlin/kotlin.ts b/monaco-languages/src/kotlin/kotlin.ts new file mode 100644 index 00000000..8fa6102e --- /dev/null +++ b/monaco-languages/src/kotlin/kotlin.ts @@ -0,0 +1,274 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + // the default separators except `@$` + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: '<', close: '>' } + ], + folding: { + markers: { + start: new RegExp('^\\s*//\\s*(?:(?:#?region\\b)|(?:))') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.kt', + + keywords: [ + 'as', + 'as?', + 'break', + 'class', + 'continue', + 'do', + 'else', + 'false', + 'for', + 'fun', + 'if', + 'in', + '!in', + 'interface', + 'is', + '!is', + 'null', + 'object', + 'package', + 'return', + 'super', + 'this', + 'throw', + 'true', + 'try', + 'typealias', + 'val', + 'var', + 'when', + 'while', + 'by', + 'catch', + 'constructor', + 'delegate', + 'dynamic', + 'field', + 'file', + 'finally', + 'get', + 'import', + 'init', + 'param', + 'property', + 'receiver', + 'set', + 'setparam', + 'where', + 'actual', + 'abstract', + 'annotation', + 'companion', + 'const', + 'crossinline', + 'data', + 'enum', + 'expect', + 'external', + 'final', + 'infix', + 'inline', + 'inner', + 'internal', + 'lateinit', + 'noinline', + 'open', + 'operator', + 'out', + 'override', + 'private', + 'protected', + 'public', + 'reified', + 'sealed', + 'suspend', + 'tailrec', + 'vararg', + 'field', + 'it' + ], + + operators: [ + '+', + '-', + '*', + '/', + '%', + '=', + '+=', + '-=', + '*=', + '/=', + '%=', + '++', + '--', + '&&', + '||', + '!', + '==', + '!=', + '===', + '!==', + '>', + '<', + '<=', + '>=', + '[', + ']', + '!!', + '?.', + '?:', + '::', + '..', + ':', + '?', + '->', + '@', + ';', + '$', + '_' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [ + /@symbols/, + { + cases: { + '@operators': 'delimiter', + '@default': '' + } + } + ], + + // @ annotations. + [/@\s*[a-zA-Z_\$][\w\$]*/, 'annotation'], + + // numbers + [/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/, 'number.float'], + [/0[xX](@hexdigits)[Ll]?/, 'number.hex'], + [/0(@octaldigits)[Ll]?/, 'number.octal'], + [/0[bB](@binarydigits)[Ll]?/, 'number.binary'], + [/(@digits)[fFdD]/, 'number.float'], + [/(@digits)[lL]?/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'], + + // strings + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"""/, 'string', '@multistring'], + [/"/, 'string', '@string'], + + // characters + [/'[^\\']'/, 'string'], + [/(')(@escapes)(')/, ['string', 'string.escape', 'string']], + [/'/, 'string.invalid'] + ], + + whitespace: [ + [/[ \t\r\n]+/, ''], + [/\/\*\*(?!\/)/, 'comment.doc', '@javadoc'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\/\*/, 'comment', '@comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + //Identical copy of comment above, except for the addition of .doc + javadoc: [ + [/[^\/*]+/, 'comment.doc'], + [/\/\*/, 'comment.doc', '@push'], + [/\/\*/, 'comment.doc.invalid'], + [/\*\//, 'comment.doc', '@pop'], + [/[\/*]/, 'comment.doc'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'] + ], + + multistring: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"""/, 'string', '@pop'], + [/./, 'string'] + ] + } +}; diff --git a/monaco-languages/src/less/less.contribution.ts b/monaco-languages/src/less/less.contribution.ts new file mode 100644 index 00000000..ed5b380a --- /dev/null +++ b/monaco-languages/src/less/less.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'less', + extensions: ['.less'], + aliases: ['Less', 'less'], + mimetypes: ['text/x-less', 'text/less'], + loader: () => import('./less') +}); diff --git a/monaco-languages/src/less/less.test.ts b/monaco-languages/src/less/less.test.ts new file mode 100644 index 00000000..89ffbf76 --- /dev/null +++ b/monaco-languages/src/less/less.test.ts @@ -0,0 +1,1560 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization( + ['less', 'javascript'], + [ + // Keywords + [ + { + line: 'isnumber(10);', + tokens: [ + { startIndex: 0, type: 'keyword.less' }, + { startIndex: 8, type: 'delimiter.parenthesis.less' }, + { startIndex: 9, type: 'attribute.value.number.less' }, + { startIndex: 11, type: 'delimiter.parenthesis.less' }, + { startIndex: 12, type: 'delimiter.less' } + ] + } + ], + + [ + { + line: 'iskeyword(@test) ;mix', + tokens: [ + { startIndex: 0, type: 'keyword.less' }, + { startIndex: 9, type: 'delimiter.parenthesis.less' }, + { startIndex: 10, type: 'variable.less' }, + { startIndex: 15, type: 'delimiter.parenthesis.less' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.less' }, + { startIndex: 18, type: 'keyword.less' } + ] + } + ], + + [ + { + line: 'whenn', + tokens: [{ startIndex: 0, type: 'tag.less' }] + } + ], + + [ + { + line: ' round ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'keyword.less' }, + { startIndex: 9, type: '' } + ] + } + ], + + // Units + [ + { + line: 'isnumber(10px);', + tokens: [ + { startIndex: 0, type: 'keyword.less' }, + { startIndex: 8, type: 'delimiter.parenthesis.less' }, + { startIndex: 9, type: 'attribute.value.number.less' }, + { startIndex: 11, type: 'attribute.value.unit.less' }, + { startIndex: 13, type: 'delimiter.parenthesis.less' }, + { startIndex: 14, type: 'delimiter.less' } + ] + } + ], + + [ + { + line: 'pxx ', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 3, type: '' } + ] + } + ], + + // single line Strings + [ + { + line: '@test: "I\'m a LESS String";', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 25, type: 'string.delimiter.less' }, + { startIndex: 26, type: 'delimiter.less' } + ] + } + ], + + [ + { + line: '@test: "concatenated" + "String";', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 20, type: 'string.delimiter.less' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'operator.less' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'string.delimiter.less' }, + { startIndex: 25, type: 'string.less' }, + { startIndex: 31, type: 'string.delimiter.less' }, + { startIndex: 32, type: 'delimiter.less' } + ] + } + ], + + [ + { + line: '@test: "quote in\'adasdsa\\"asd\' a string"', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 39, type: 'string.delimiter.less' } + ] + } + ], + + [ + { + line: "@test: 'doublequote in\"ada\\'sds\\'a\"asd a string'", + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 47, type: 'string.delimiter.less' } + ] + } + ], + + // Comments - range comment, multiple lines + [ + { + line: '/* start of multiline comment', + tokens: [{ startIndex: 0, type: 'comment.less' }] + }, + { + line: 'a comment between without a star', + tokens: [{ startIndex: 0, type: 'comment.less' }] + }, + { + line: 'end of multiline comment*/', + tokens: [{ startIndex: 0, type: 'comment.less' }] + }, + { + line: 'when /* start a comment', + tokens: [ + { startIndex: 0, type: 'keyword.less' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'comment.less' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.less' }] + }, + { + line: 'and end it */ 2;', + tokens: [ + { startIndex: 0, type: 'comment.less' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'attribute.value.number.less' }, + { startIndex: 15, type: 'delimiter.less' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'attribute.value.number.less' }] + } + ], + + [ + { + line: ' 0', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'attribute.value.number.less' } + ] + } + ], + + [ + { + line: ' 0 ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'attribute.value.number.less' }, + { startIndex: 2, type: '' } + ] + } + ], + + [ + { + line: '0 ', + tokens: [ + { startIndex: 0, type: 'attribute.value.number.less' }, + { startIndex: 1, type: '' } + ] + } + ], + + [ + { + line: '@test: 0+0', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'attribute.value.number.less' }, + { startIndex: 8, type: 'operator.less' }, + { startIndex: 9, type: 'attribute.value.number.less' } + ] + } + ], + + [ + { + line: '@test: 100+10.00', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'attribute.value.number.less' }, + { startIndex: 10, type: 'operator.less' }, + { startIndex: 11, type: 'attribute.value.number.less' } + ] + } + ], + + [ + { + line: '@test: 0 + 0', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'attribute.value.number.less' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'operator.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'attribute.value.number.less' } + ] + } + ], + + [ + { + line: '0123', + tokens: [{ startIndex: 0, type: 'attribute.value.number.less' }] + } + ], + + [ + { + line: '#012343', + tokens: [{ startIndex: 0, type: 'attribute.value.hex.less' }] + } + ], + + // Bracket Matching + [ + { + line: '[1,2,3]', + tokens: [ + { startIndex: 0, type: 'delimiter.bracket.less' }, + { startIndex: 1, type: 'attribute.value.number.less' }, + { startIndex: 2, type: 'delimiter.less' }, + { startIndex: 3, type: 'attribute.value.number.less' }, + { startIndex: 4, type: 'delimiter.less' }, + { startIndex: 5, type: 'attribute.value.number.less' }, + { startIndex: 6, type: 'delimiter.bracket.less' } + ] + } + ], + + [ + { + line: 'foo(123);', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 3, type: 'delimiter.parenthesis.less' }, + { startIndex: 4, type: 'attribute.value.number.less' }, + { startIndex: 7, type: 'delimiter.parenthesis.less' }, + { startIndex: 8, type: 'delimiter.less' } + ] + } + ], + + // No Bracket Matching inside strings + [ + { + line: "@test: '[{()}]'", + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 14, type: 'string.delimiter.less' } + ] + } + ], + + // Singleline Comments + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.less' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: '@something : 2; // my comment // this is a nice one', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.less' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.value.number.less' }, + { startIndex: 14, type: 'delimiter.less' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'comment.less' } + ] + } + ], + + [ + { + line: '.something(@some, @other) when (iscolor(@other)) { aname// my commen', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 10, type: 'delimiter.parenthesis.less' }, + { startIndex: 11, type: 'variable.less' }, + { startIndex: 16, type: 'delimiter.less' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'variable.less' }, + { startIndex: 24, type: 'delimiter.parenthesis.less' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'keyword.less' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'delimiter.parenthesis.less' }, + { startIndex: 32, type: 'keyword.less' }, + { startIndex: 39, type: 'delimiter.parenthesis.less' }, + { startIndex: 40, type: 'variable.less' }, + { startIndex: 46, type: 'delimiter.parenthesis.less' }, + { startIndex: 48, type: '' }, + { startIndex: 49, type: 'delimiter.curly.less' }, + { startIndex: 50, type: '' }, + { startIndex: 51, type: 'tag.less' }, + { startIndex: 56, type: 'comment.less' } + ] + } + ], + + [ + { + line: '.something(@some//mycomment', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 10, type: 'delimiter.parenthesis.less' }, + { startIndex: 11, type: 'variable.less' }, + { startIndex: 16, type: 'comment.less' } + ] + } + ], + + [ + { + line: '@something : #2;', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.less' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.value.hex.less' }, + { startIndex: 15, type: 'delimiter.less' } + ] + } + ], + + // Singleline Range-Comments + [ + { + line: '/*slcomment*/', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: '/* slcomment */', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: '/*sl/com* ment*/', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: '/**/', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: '@something: /*comm/* * /ent*/2;', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 10, type: 'delimiter.less' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'comment.less' }, + { startIndex: 29, type: 'attribute.value.number.less' }, + { startIndex: 30, type: 'delimiter.less' } + ] + } + ], + + [ + { + line: '@something: /*comment*/ 2;', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 10, type: 'delimiter.less' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'comment.less' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'attribute.value.number.less' }, + { startIndex: 25, type: 'delimiter.less' } + ] + } + ], + + // Comments - range comment, multi lines + [ + { + line: '/* a multiline comment', + tokens: [{ startIndex: 0, type: 'comment.less' }] + }, + { + line: 'can actually span', + tokens: [{ startIndex: 0, type: 'comment.less' }] + }, + { + line: 'multiple lines */', + tokens: [{ startIndex: 0, type: 'comment.less' }] + } + ], + + [ + { + line: '@some /* start a comment here', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'comment.less' } + ] + }, + { + line: ' span over this line and ', + tokens: [{ startIndex: 0, type: 'comment.less' }] + }, + { + line: 'end it there */ : 2;', + tokens: [ + { startIndex: 0, type: 'comment.less' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.less' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'attribute.value.number.less' }, + { startIndex: 19, type: 'delimiter.less' } + ] + } + ], + + // Escape Strings + [ + { + line: '.class { filter: ~"ms:alwaysHasItsOwnSyntax.For.Stuff()";', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.curly.less' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'attribute.name.less' }, + { startIndex: 15, type: 'delimiter.less' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'string.delimiter.less' }, + { startIndex: 19, type: 'string.less' }, + { startIndex: 55, type: 'string.delimiter.less' }, + { startIndex: 56, type: 'delimiter.less' } + ] + } + ], + + // Guards + [ + { + line: '.class {.mixin (@a) when (@a > 10), (@a < -10) { }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.curly.less' }, + { startIndex: 8, type: 'tag.class.less' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.parenthesis.less' }, + { startIndex: 16, type: 'variable.less' }, + { startIndex: 18, type: 'delimiter.parenthesis.less' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'keyword.less' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'delimiter.parenthesis.less' }, + { startIndex: 26, type: 'variable.less' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'operator.less' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'attribute.value.number.less' }, + { startIndex: 33, type: 'delimiter.parenthesis.less' }, + { startIndex: 34, type: 'delimiter.less' }, + { startIndex: 35, type: '' }, + { startIndex: 36, type: 'delimiter.parenthesis.less' }, + { startIndex: 37, type: 'variable.less' }, + { startIndex: 39, type: '' }, + { startIndex: 40, type: 'operator.less' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'operator.less' }, + { startIndex: 43, type: 'attribute.value.number.less' }, + { startIndex: 45, type: 'delimiter.parenthesis.less' }, + { startIndex: 46, type: '' }, + { startIndex: 47, type: 'delimiter.curly.less' }, + { startIndex: 48, type: '' }, + { startIndex: 49, type: 'delimiter.curly.less' } + ] + } + ], + + [ + { + line: '.truth (@a) when (@a = true) { }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.parenthesis.less' }, + { startIndex: 8, type: 'variable.less' }, + { startIndex: 10, type: 'delimiter.parenthesis.less' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'keyword.less' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.parenthesis.less' }, + { startIndex: 18, type: 'variable.less' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'operator.less' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'keyword.less' }, + { startIndex: 27, type: 'delimiter.parenthesis.less' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'delimiter.curly.less' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'delimiter.curly.less' } + ] + } + ], + + [ + { + line: '.max (@a, @b) when (@a > @b) { width: @a; }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.parenthesis.less' }, + { startIndex: 6, type: 'variable.less' }, + { startIndex: 8, type: 'delimiter.less' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'variable.less' }, + { startIndex: 12, type: 'delimiter.parenthesis.less' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.less' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'delimiter.parenthesis.less' }, + { startIndex: 20, type: 'variable.less' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'operator.less' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'variable.less' }, + { startIndex: 27, type: 'delimiter.parenthesis.less' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'delimiter.curly.less' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'attribute.name.less' }, + { startIndex: 36, type: 'delimiter.less' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'variable.less' }, + { startIndex: 40, type: 'delimiter.less' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'delimiter.curly.less' } + ] + } + ], + + [ + { + line: '.mixin (@a, @b: 0) when (isnumber(@b)) { }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.parenthesis.less' }, + { startIndex: 8, type: 'variable.less' }, + { startIndex: 10, type: 'delimiter.less' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'variable.less' }, + { startIndex: 14, type: 'delimiter.less' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'attribute.value.number.less' }, + { startIndex: 17, type: 'delimiter.parenthesis.less' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'keyword.less' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'delimiter.parenthesis.less' }, + { startIndex: 25, type: 'keyword.less' }, + { startIndex: 33, type: 'delimiter.parenthesis.less' }, + { startIndex: 34, type: 'variable.less' }, + { startIndex: 36, type: 'delimiter.parenthesis.less' }, + { startIndex: 38, type: '' }, + { startIndex: 39, type: 'delimiter.curly.less' }, + { startIndex: 40, type: '' }, + { startIndex: 41, type: 'delimiter.curly.less' } + ] + } + ], + + [ + { + line: '.mixin (@a, @b: black) when (iscolor(@b)) { }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.parenthesis.less' }, + { startIndex: 8, type: 'variable.less' }, + { startIndex: 10, type: 'delimiter.less' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'variable.less' }, + { startIndex: 14, type: 'delimiter.less' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'attribute.value.less' }, + { startIndex: 21, type: 'delimiter.parenthesis.less' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'keyword.less' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.parenthesis.less' }, + { startIndex: 29, type: 'keyword.less' }, + { startIndex: 36, type: 'delimiter.parenthesis.less' }, + { startIndex: 37, type: 'variable.less' }, + { startIndex: 39, type: 'delimiter.parenthesis.less' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'delimiter.curly.less' }, + { startIndex: 43, type: '' }, + { startIndex: 44, type: 'delimiter.curly.less' } + ] + } + ], + + // Nested JavaScript + [ + { + line: '@test: `function display()` //works well', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 5, type: 'delimiter.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.backtick.less' }, + { startIndex: 8, type: 'keyword.js' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'identifier.js' }, + { startIndex: 24, type: 'delimiter.parenthesis.js' }, + { startIndex: 26, type: 'delimiter.backtick.less' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'comment.less' } + ] + } + ], + + // Attribute in a .class(...) + [ + { + line: '.box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6));', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 11, type: 'delimiter.parenthesis.less' }, + { startIndex: 12, type: 'attribute.value.less' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'attribute.value.number.less' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'attribute.value.number.less' }, + { startIndex: 21, type: 'attribute.value.unit.less' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'attribute.value.number.less' }, + { startIndex: 25, type: 'attribute.value.unit.less' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'attribute.value.less' }, + { startIndex: 32, type: 'delimiter.parenthesis.less' }, + { startIndex: 33, type: 'attribute.value.number.less' }, + { startIndex: 34, type: 'delimiter.less' }, + { startIndex: 35, type: 'attribute.value.number.less' }, + { startIndex: 36, type: 'delimiter.less' }, + { startIndex: 37, type: 'attribute.value.number.less' }, + { startIndex: 38, type: 'delimiter.less' }, + { startIndex: 39, type: 'attribute.value.number.less' }, + { startIndex: 43, type: 'delimiter.parenthesis.less' }, + { startIndex: 44, type: 'delimiter.less' }, + { startIndex: 45, type: '' }, + { startIndex: 46, type: 'attribute.value.number.less' }, + { startIndex: 47, type: '' }, + { startIndex: 48, type: 'attribute.value.number.less' }, + { startIndex: 49, type: '' }, + { startIndex: 50, type: 'attribute.value.number.less' }, + { startIndex: 51, type: 'attribute.value.unit.less' }, + { startIndex: 53, type: '' }, + { startIndex: 54, type: 'attribute.value.less' }, + { startIndex: 58, type: 'delimiter.parenthesis.less' }, + { startIndex: 59, type: 'attribute.value.number.less' }, + { startIndex: 61, type: 'delimiter.less' }, + { startIndex: 62, type: 'attribute.value.number.less' }, + { startIndex: 65, type: 'delimiter.less' }, + { startIndex: 66, type: 'attribute.value.number.less' }, + { startIndex: 69, type: 'delimiter.less' }, + { startIndex: 70, type: 'attribute.value.number.less' }, + { startIndex: 72, type: 'delimiter.parenthesis.less' }, + { startIndex: 74, type: 'delimiter.less' } + ] + } + ], + + // Difficult little bugs... => String mismatches + [ + { + line: 'input[type="radio"]', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 5, type: 'delimiter.bracket.less' }, + { startIndex: 6, type: 'tag.less' }, + { startIndex: 10, type: 'operator.less' }, + { startIndex: 11, type: 'string.delimiter.less' }, + { startIndex: 12, type: 'string.less' }, + { startIndex: 17, type: 'string.delimiter.less' }, + { startIndex: 18, type: 'delimiter.bracket.less' } + ] + } + ], + + [ + { + line: "~'.offset@{index}')", + tokens: [ + { startIndex: 0, type: 'string.delimiter.less' }, + { startIndex: 2, type: 'string.less' }, + { startIndex: 17, type: 'string.delimiter.less' }, + { startIndex: 18, type: 'delimiter.parenthesis.less' } + ] + } + ], + + [ + { + line: 'some("\\42");', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 4, type: 'delimiter.parenthesis.less' }, + { startIndex: 5, type: 'string.delimiter.less' }, + { startIndex: 6, type: 'string.less' }, + { startIndex: 9, type: 'string.delimiter.less' }, + { startIndex: 10, type: 'delimiter.parenthesis.less' }, + { startIndex: 11, type: 'delimiter.less' } + ] + } + ], + + [ + { + line: ' ~ "icon-"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'operator.less' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'string.delimiter.less' }, + { startIndex: 4, type: 'string.less' }, + { startIndex: 9, type: 'string.delimiter.less' } + ] + } + ], + + // Difficult little bugs... => Operator mismatches + [ + { + line: 'class^="icon-"', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 5, type: 'operator.less' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 13, type: 'string.delimiter.less' } + ] + } + ], + + [ + { + line: 'class*="icon-"', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 5, type: 'operator.less' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 13, type: 'string.delimiter.less' } + ] + } + ], + + [ + { + line: 'class~="icon-"', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 5, type: 'operator.less' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 13, type: 'string.delimiter.less' } + ] + } + ], + + [ + { + line: 'class ~ = "icon-"', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'operator.less' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'operator.less' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'string.delimiter.less' }, + { startIndex: 11, type: 'string.less' }, + { startIndex: 16, type: 'string.delimiter.less' } + ] + } + ], + + [ + { + line: 'class|="icon-"', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 5, type: 'operator.less' }, + { startIndex: 7, type: 'string.delimiter.less' }, + { startIndex: 8, type: 'string.less' }, + { startIndex: 13, type: 'string.delimiter.less' } + ] + } + ], + + [ + { + line: '.hide-text { font: 0/0 a; }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.curly.less' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.name.less' }, + { startIndex: 17, type: 'delimiter.less' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'attribute.value.number.less' }, + { startIndex: 20, type: 'operator.less' }, + { startIndex: 21, type: 'attribute.value.number.less' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'attribute.value.less' }, + { startIndex: 24, type: 'delimiter.less' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'delimiter.curly.less' } + ] + } + ], + + // Difficult little bugs... => Numbers in classes + [ + { + line: '.translate3d(@x, @y, @z) { -webkit-transform: translate3d(@x, @y, @z); }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 12, type: 'delimiter.parenthesis.less' }, + { startIndex: 13, type: 'variable.less' }, + { startIndex: 15, type: 'delimiter.less' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'variable.less' }, + { startIndex: 19, type: 'delimiter.less' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'variable.less' }, + { startIndex: 23, type: 'delimiter.parenthesis.less' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'delimiter.curly.less' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'attribute.name.less' }, + { startIndex: 44, type: 'delimiter.less' }, + { startIndex: 45, type: '' }, + { startIndex: 46, type: 'attribute.value.less' }, + { startIndex: 57, type: 'delimiter.parenthesis.less' }, + { startIndex: 58, type: 'variable.less' }, + { startIndex: 60, type: 'delimiter.less' }, + { startIndex: 61, type: '' }, + { startIndex: 62, type: 'variable.less' }, + { startIndex: 64, type: 'delimiter.less' }, + { startIndex: 65, type: '' }, + { startIndex: 66, type: 'variable.less' }, + { startIndex: 68, type: 'delimiter.parenthesis.less' }, + { startIndex: 69, type: 'delimiter.less' }, + { startIndex: 70, type: '' }, + { startIndex: 71, type: 'delimiter.curly.less' } + ] + } + ], + + // Difficult little bugs... => Generic mismatches, worst case... + [ + { + line: '.dropdown-menu > li > a:hover > [class=" icon-"]', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'operator.less' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'tag.less' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'operator.less' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'tag.less' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'operator.less' }, + { startIndex: 31, type: '' }, + { startIndex: 32, type: 'delimiter.bracket.less' }, + { startIndex: 33, type: 'tag.less' }, + { startIndex: 38, type: 'operator.less' }, + { startIndex: 39, type: 'string.delimiter.less' }, + { startIndex: 40, type: 'string.less' }, + { startIndex: 46, type: 'string.delimiter.less' }, + { startIndex: 47, type: 'delimiter.bracket.less' } + ] + } + ], + + [ + { + line: '.bw-gradient(@color: #F5F5F5, @start: 0, @stop: 255) { background: -webkit-gradient(color-stop(0, rgb(@start,@start,@start)), color-stop(1, rgb(@stop,@stop,@stop))); }', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 12, type: 'delimiter.parenthesis.less' }, + { startIndex: 13, type: 'variable.less' }, + { startIndex: 19, type: 'delimiter.less' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'attribute.value.hex.less' }, + { startIndex: 28, type: 'delimiter.less' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'variable.less' }, + { startIndex: 36, type: 'delimiter.less' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'attribute.value.number.less' }, + { startIndex: 39, type: 'delimiter.less' }, + { startIndex: 40, type: '' }, + { startIndex: 41, type: 'variable.less' }, + { startIndex: 46, type: 'delimiter.less' }, + { startIndex: 47, type: '' }, + { startIndex: 48, type: 'attribute.value.number.less' }, + { startIndex: 51, type: 'delimiter.parenthesis.less' }, + { startIndex: 52, type: '' }, + { startIndex: 53, type: 'delimiter.curly.less' }, + { startIndex: 54, type: '' }, + { startIndex: 55, type: 'attribute.name.less' }, + { startIndex: 65, type: 'delimiter.less' }, + { startIndex: 66, type: '' }, + { startIndex: 67, type: 'attribute.value.less' }, + { startIndex: 83, type: 'delimiter.parenthesis.less' }, + { startIndex: 84, type: 'attribute.value.less' }, + { startIndex: 94, type: 'delimiter.parenthesis.less' }, + { startIndex: 95, type: 'attribute.value.number.less' }, + { startIndex: 96, type: 'delimiter.less' }, + { startIndex: 97, type: '' }, + { startIndex: 98, type: 'attribute.value.less' }, + { startIndex: 101, type: 'delimiter.parenthesis.less' }, + { startIndex: 102, type: 'variable.less' }, + { startIndex: 108, type: 'delimiter.less' }, + { startIndex: 109, type: 'variable.less' }, + { startIndex: 115, type: 'delimiter.less' }, + { startIndex: 116, type: 'variable.less' }, + { startIndex: 122, type: 'delimiter.parenthesis.less' }, + { startIndex: 124, type: 'delimiter.less' }, + { startIndex: 125, type: '' }, + { startIndex: 126, type: 'attribute.value.less' }, + { startIndex: 136, type: 'delimiter.parenthesis.less' }, + { startIndex: 137, type: 'attribute.value.number.less' }, + { startIndex: 138, type: 'delimiter.less' }, + { startIndex: 139, type: '' }, + { startIndex: 140, type: 'attribute.value.less' }, + { startIndex: 143, type: 'delimiter.parenthesis.less' }, + { startIndex: 144, type: 'variable.less' }, + { startIndex: 149, type: 'delimiter.less' }, + { startIndex: 150, type: 'variable.less' }, + { startIndex: 155, type: 'delimiter.less' }, + { startIndex: 156, type: 'variable.less' }, + { startIndex: 161, type: 'delimiter.parenthesis.less' }, + { startIndex: 164, type: 'delimiter.less' }, + { startIndex: 165, type: '' }, + { startIndex: 166, type: 'delimiter.curly.less' } + ] + } + ], + + // Here CSS Tests from CSS File + // Skip whitespace + [ + { + line: ' body ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 6, type: 'tag.less' }, + { startIndex: 10, type: '' } + ] + } + ], + + // CSS rule + // body { + // margin: 0; + // padding: 3em 6em; + // font-family: tahoma, arial, sans-serif; + // text-decoration: none !important; + // color: #000 + // } + [ + { + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.curly.less' } + ] + }, + { + line: ' margin: 0;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 8, type: 'delimiter.less' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'attribute.value.number.less' }, + { startIndex: 11, type: 'delimiter.less' } + ] + }, + { + line: ' padding: 3em 6em;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 9, type: 'delimiter.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'attribute.value.number.less' }, + { startIndex: 12, type: 'attribute.value.unit.less' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.value.number.less' }, + { startIndex: 16, type: 'attribute.value.unit.less' }, + { startIndex: 18, type: 'delimiter.less' } + ] + }, + { + line: ' font-family: tahoma, arial, sans-serif;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 13, type: 'delimiter.less' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.value.less' }, + { startIndex: 21, type: 'delimiter.less' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'attribute.value.less' }, + { startIndex: 28, type: 'delimiter.less' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'attribute.value.less' }, + { startIndex: 40, type: 'delimiter.less' } + ] + }, + { + line: ' text-decoration: none !important;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 17, type: 'delimiter.less' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'attribute.value.less' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'keyword.less' }, + { startIndex: 34, type: 'delimiter.less' } + ] + }, + { + line: ' color: #000;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 7, type: 'delimiter.less' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'attribute.value.hex.less' }, + { startIndex: 13, type: 'delimiter.less' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.less' } + ] + } + ], + + // CSS units and numbers + [ + { + line: '* { padding: 3em -9pt -0.5px; }', + tokens: [ + { startIndex: 0, type: 'operator.less' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.curly.less' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'attribute.name.less' }, + { startIndex: 11, type: 'delimiter.less' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.value.number.less' }, + { startIndex: 14, type: 'attribute.value.unit.less' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'operator.less' }, + { startIndex: 18, type: 'attribute.value.number.less' }, + { startIndex: 19, type: 'attribute.value.unit.less' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'operator.less' }, + { startIndex: 23, type: 'attribute.value.number.less' }, + { startIndex: 26, type: 'attribute.value.unit.less' }, + { startIndex: 28, type: 'delimiter.less' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'delimiter.curly.less' } + ] + } + ], + + // CSS single line comment + // h1 /*comment*/ p { + [ + { + line: 'h1 /*comment*/ p {', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'comment.less' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'tag.less' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.curly.less' } + ] + } + ], + + // CSS multi line comment + // h1 /*com + // ment*/ p { + [ + { + line: 'h1 /*com', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'comment.less' } + ] + }, + { + line: 'ment*/ p', + tokens: [ + { startIndex: 0, type: 'comment.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'tag.less' } + ] + } + ], + + // CSS ID rule + // #myID { + // font-size: 80%; + // content: 'contents'; + // } + [ + { + line: '#myID {', + tokens: [ + { startIndex: 0, type: 'tag.id.less' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.curly.less' } + ] + } + ], + + // CSS Class rules + // .myID { + // h1 > p { + [ + { + line: '.myID {', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.curly.less' } + ] + } + ], + + // CSS @import etc + // @import url('something.less'); { + [ + { + line: '@import url("something.less");', + tokens: [ + { startIndex: 0, type: 'keyword.less' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'tag.less' }, + { startIndex: 12, type: 'string.delimiter.less' }, + { startIndex: 13, type: 'string.less' }, + { startIndex: 27, type: 'string.delimiter.less' }, + { startIndex: 28, type: 'delimiter.parenthesis.less' }, + { startIndex: 29, type: 'delimiter.less' } + ] + } + ], + + // CSS multi-line string with an escaped newline + // body { + // content: 'con\ + // tent'; + [ + { + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.curly.less' } + ] + }, + { + line: ' content: "con\\', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 9, type: 'delimiter.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.delimiter.less' }, + { startIndex: 12, type: 'string.less' } + ] + }, + { + line: 'tent";', + tokens: [ + { startIndex: 0, type: 'string.less' }, + { startIndex: 4, type: 'string.delimiter.less' }, + { startIndex: 5, type: 'delimiter.less' } + ] + } + ], + + // CSS empty string value + // body { + // content: ''; + [ + { + line: 'body {', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.curly.less' } + ] + }, + { + line: ' content: "";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 9, type: 'delimiter.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.delimiter.less' }, + { startIndex: 13, type: 'delimiter.less' } + ] + } + ], + + // CSS font face + // @font-face { + // font-family: 'Opificio'; + // } + [ + { + line: '@font-face {', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.curly.less' } + ] + }, + { + line: ' font-family: "Opificio";', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 13, type: 'delimiter.less' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'string.delimiter.less' }, + { startIndex: 16, type: 'string.less' }, + { startIndex: 24, type: 'string.delimiter.less' }, + { startIndex: 25, type: 'delimiter.less' } + ] + } + ], + + // CSS string with escaped quotes + // 's\"tr' + [ + { + line: '"s\\"tr\\"sadsad', + tokens: [ + { startIndex: 0, type: 'string.delimiter.less' }, + { startIndex: 1, type: 'string.less' } + ] + } + ], + + // EG: Bracket Matching + [ + { + line: 'p{}', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 1, type: 'delimiter.curly.less' } + ] + } + ], + + [ + { + line: 'p:nth() {}', + tokens: [ + { startIndex: 0, type: 'tag.less' }, + { startIndex: 5, type: 'delimiter.parenthesis.less' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.curly.less' } + ] + } + ], + + // EG: import statement - bug #10308 + // @import url('something.css');@import url('something.css'); + [ + { + line: '@import url("something.css");@import url("something.css");', + tokens: [ + { startIndex: 0, type: 'keyword.less' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'tag.less' }, + { startIndex: 12, type: 'string.delimiter.less' }, + { startIndex: 13, type: 'string.less' }, + { startIndex: 26, type: 'string.delimiter.less' }, + { startIndex: 27, type: 'delimiter.parenthesis.less' }, + { startIndex: 28, type: 'delimiter.less' }, + { startIndex: 29, type: 'keyword.less' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'tag.less' }, + { startIndex: 41, type: 'string.delimiter.less' }, + { startIndex: 42, type: 'string.less' }, + { startIndex: 55, type: 'string.delimiter.less' }, + { startIndex: 56, type: 'delimiter.parenthesis.less' }, + { startIndex: 57, type: 'delimiter.less' } + ] + } + ], + + // EG: Triple quotes - bug #9870 + [ + { + line: '""""', + tokens: [{ startIndex: 0, type: 'string.delimiter.less' }] + } + ], + + // EG: CSS @import related coloring bug 9553 + // @import url('something.css'); + // .rule1{} + // .rule2{} + [ + { + line: '@import url("something.css");', + tokens: [ + { startIndex: 0, type: 'keyword.less' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'tag.less' }, + { startIndex: 12, type: 'string.delimiter.less' }, + { startIndex: 13, type: 'string.less' }, + { startIndex: 26, type: 'string.delimiter.less' }, + { startIndex: 27, type: 'delimiter.parenthesis.less' }, + { startIndex: 28, type: 'delimiter.less' } + ] + }, + { + line: '.rule1{}', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 6, type: 'delimiter.curly.less' } + ] + }, + { + line: '.rule2{}', + tokens: [ + { startIndex: 0, type: 'tag.class.less' }, + { startIndex: 6, type: 'delimiter.curly.less' } + ] + } + ], + + // EG: CSS key frame animation syntax + [ + { + line: '@-webkit-keyframes infinite-spinning {', + tokens: [ + { startIndex: 0, type: 'variable.less' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'tag.less' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'delimiter.curly.less' } + ] + }, + { + line: ' from {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'tag.less' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.curly.less' } + ] + }, + { + line: ' -webkit-transform: rotate(0deg);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 19, type: 'delimiter.less' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'attribute.value.less' }, + { startIndex: 27, type: 'delimiter.parenthesis.less' }, + { startIndex: 28, type: 'attribute.value.number.less' }, + { startIndex: 29, type: 'attribute.value.unit.less' }, + { startIndex: 32, type: 'delimiter.parenthesis.less' }, + { startIndex: 33, type: 'delimiter.less' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.less' } + ] + }, + { + line: ' to {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'tag.less' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.curly.less' } + ] + }, + { + line: ' -webkit-transform: rotate(360deg);', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'attribute.name.less' }, + { startIndex: 19, type: 'delimiter.less' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'attribute.value.less' }, + { startIndex: 27, type: 'delimiter.parenthesis.less' }, + { startIndex: 28, type: 'attribute.value.number.less' }, + { startIndex: 31, type: 'attribute.value.unit.less' }, + { startIndex: 34, type: 'delimiter.parenthesis.less' }, + { startIndex: 35, type: 'delimiter.less' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.less' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.less' }] + } + ] + ] +); diff --git a/monaco-languages/src/less/less.ts b/monaco-languages/src/less/less.ts new file mode 100644 index 00000000..0690d934 --- /dev/null +++ b/monaco-languages/src/less/less.ts @@ -0,0 +1,201 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + wordPattern: /(#?-?\d*\.\d\w*%?)|([@#!.:]?[\w-?]+%?)|[@#!.]/g, + comments: { + blockComment: ['/*', '*/'], + lineComment: '//' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}', notIn: ['string', 'comment'] }, + { open: '[', close: ']', notIn: ['string', 'comment'] }, + { open: '(', close: ')', notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] }, + { open: "'", close: "'", notIn: ['string', 'comment'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + folding: { + markers: { + start: new RegExp('^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/'), + end: new RegExp('^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.less', + + identifier: + '-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*', + identifierPlus: + '-?-?([a-zA-Z:.]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-:.]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*', + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.bracket' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + tokenizer: { + root: [ + { include: '@nestedJSBegin' }, + + ['[ \\t\\r\\n]+', ''], + + { include: '@comments' }, + { include: '@keyword' }, + { include: '@strings' }, + { include: '@numbers' }, + ['[*_]?[a-zA-Z\\-\\s]+(?=:.*(;|(\\\\$)))', 'attribute.name', '@attribute'], + + ['url(\\-prefix)?\\(', { token: 'tag', next: '@urldeclaration' }], + + ['[{}()\\[\\]]', '@brackets'], + ['[,:;]', 'delimiter'], + + ['#@identifierPlus', 'tag.id'], + ['&', 'tag'], + + ['\\.@identifierPlus(?=\\()', 'tag.class', '@attribute'], + ['\\.@identifierPlus', 'tag.class'], + + ['@identifierPlus', 'tag'], + { include: '@operators' }, + + ['@(@identifier(?=[:,\\)]))', 'variable', '@attribute'], + ['@(@identifier)', 'variable'], + ['@', 'key', '@atRules'] + ], + + nestedJSBegin: [ + ['``', 'delimiter.backtick'], + [ + '`', + { + token: 'delimiter.backtick', + next: '@nestedJSEnd', + nextEmbedded: 'text/javascript' + } + ] + ], + + nestedJSEnd: [ + [ + '`', + { + token: 'delimiter.backtick', + next: '@pop', + nextEmbedded: '@pop' + } + ] + ], + + operators: [['[<>=\\+\\-\\*\\/\\^\\|\\~]', 'operator']], + + keyword: [ + [ + '(@[\\s]*import|![\\s]*important|true|false|when|iscolor|isnumber|isstring|iskeyword|isurl|ispixel|ispercentage|isem|hue|saturation|lightness|alpha|lighten|darken|saturate|desaturate|fadein|fadeout|fade|spin|mix|round|ceil|floor|percentage)\\b', + 'keyword' + ] + ], + + urldeclaration: [ + { include: '@strings' }, + ['[^)\r\n]+', 'string'], + ['\\)', { token: 'tag', next: '@pop' }] + ], + + attribute: [ + { include: '@nestedJSBegin' }, + { include: '@comments' }, + { include: '@strings' }, + { include: '@numbers' }, + + { include: '@keyword' }, + + ['[a-zA-Z\\-]+(?=\\()', 'attribute.value', '@attribute'], + ['>', 'operator', '@pop'], + ['@identifier', 'attribute.value'], + { include: '@operators' }, + ['@(@identifier)', 'variable'], + + ['[)\\}]', '@brackets', '@pop'], + ['[{}()\\[\\]>]', '@brackets'], + + ['[;]', 'delimiter', '@pop'], + ['[,=:]', 'delimiter'], + + ['\\s', ''], + ['.', 'attribute.value'] + ], + + comments: [ + ['\\/\\*', 'comment', '@comment'], + ['\\/\\/+.*', 'comment'] + ], + + comment: [ + ['\\*\\/', 'comment', '@pop'], + ['.', 'comment'] + ], + + numbers: [ + [ + '(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', + { token: 'attribute.value.number', next: '@units' } + ], + ['#[0-9a-fA-F_]+(?!\\w)', 'attribute.value.hex'] + ], + + units: [ + [ + '(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?', + 'attribute.value.unit', + '@pop' + ] + ], + + strings: [ + ['~?"', { token: 'string.delimiter', next: '@stringsEndDoubleQuote' }], + ["~?'", { token: 'string.delimiter', next: '@stringsEndQuote' }] + ], + + stringsEndDoubleQuote: [ + ['\\\\"', 'string'], + ['"', { token: 'string.delimiter', next: '@popall' }], + ['.', 'string'] + ], + + stringsEndQuote: [ + ["\\\\'", 'string'], + ["'", { token: 'string.delimiter', next: '@popall' }], + ['.', 'string'] + ], + + atRules: [ + { include: '@comments' }, + { include: '@strings' }, + ['[()]', 'delimiter'], + ['[\\{;]', 'delimiter', '@pop'], + ['.', 'key'] + ] + } +}; diff --git a/monaco-languages/src/lexon/lexon.contribution.ts b/monaco-languages/src/lexon/lexon.contribution.ts new file mode 100644 index 00000000..3ff3b84f --- /dev/null +++ b/monaco-languages/src/lexon/lexon.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'lexon', + extensions: ['.lex'], + aliases: ['Lexon'], + loader: () => import('./lexon') +}); diff --git a/monaco-languages/src/lexon/lexon.test.ts b/monaco-languages/src/lexon/lexon.test.ts new file mode 100644 index 00000000..a1a72dfc --- /dev/null +++ b/monaco-languages/src/lexon/lexon.test.ts @@ -0,0 +1,145 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('lexon', [ + // Tests + + [ + { + line: 'LEX Paid Escrow', + tokens: [ + { startIndex: 0, type: 'keyword.lexon' }, + { startIndex: 3, type: 'white.lexon' }, + { startIndex: 4, type: 'identifier.lexon' }, + { startIndex: 8, type: 'white.lexon' }, + { startIndex: 9, type: 'identifier.lexon' } + ] + } + ], + + [ + { + line: 'LEXON: 0.2.20', + tokens: [ + { startIndex: 0, type: 'keyword.lexon' }, + { startIndex: 5, type: 'delimiter.lexon' }, + { startIndex: 6, type: 'white.lexon' }, + { startIndex: 7, type: 'number.semver.lexon' } + ] + } + ], + + [ + { + line: 'COMMENT: 3.f - an escrow that is controlled by a third party for a fee.', + tokens: [{ startIndex: 0, type: 'comment.lexon' }] + } + ], + + [ + { + line: '"Payer" is a person.', + tokens: [ + { startIndex: 0, type: 'identifier.quote.lexon' }, + { startIndex: 1, type: 'identifier.lexon' }, + { startIndex: 6, type: 'identifier.quote.lexon' }, + { startIndex: 7, type: 'white.lexon' }, + { startIndex: 8, type: 'operator.lexon' }, + { startIndex: 10, type: 'white.lexon' }, + { startIndex: 11, type: 'identifier.lexon' }, + { startIndex: 12, type: 'white.lexon' }, + { startIndex: 13, type: 'keyword.type.lexon' }, + { startIndex: 19, type: 'delimiter.lexon' } + ] + } + ], + + [ + { + line: '"Fee" is an amount.', + tokens: [ + { startIndex: 0, type: 'identifier.quote.lexon' }, + { startIndex: 1, type: 'identifier.lexon' }, + { startIndex: 4, type: 'identifier.quote.lexon' }, + { startIndex: 5, type: 'white.lexon' }, + { startIndex: 6, type: 'operator.lexon' }, + { startIndex: 8, type: 'white.lexon' }, + { startIndex: 9, type: 'identifier.lexon' }, + { startIndex: 11, type: 'white.lexon' }, + { startIndex: 12, type: 'keyword.type.lexon' }, + { startIndex: 18, type: 'delimiter.lexon' } + ] + } + ], + + [ + { + line: 'The Payer pays an Amount into escrow,', + tokens: [ + { startIndex: 0, type: 'identifier.lexon' }, // The + { startIndex: 3, type: 'white.lexon' }, + { startIndex: 4, type: 'identifier.lexon' }, // Payer + { startIndex: 9, type: 'white.lexon' }, + { startIndex: 10, type: 'keyword.lexon' }, // pays + { startIndex: 14, type: 'white.lexon' }, + { startIndex: 15, type: 'identifier.lexon' }, // an + { startIndex: 17, type: 'white.lexon' }, + { startIndex: 18, type: 'keyword.type.lexon' }, // Amount + { startIndex: 24, type: 'white.lexon' }, + { startIndex: 25, type: 'keyword.lexon' }, // into + { startIndex: 29, type: 'white.lexon' }, + { startIndex: 30, type: 'identifier.lexon' }, // escrow + { startIndex: 36, type: 'delimiter.lexon' } // , + ] + } + ], + + [ + { + line: 'appoints the Payee,', + tokens: [ + { startIndex: 0, type: 'keyword.lexon' }, // Appoints + { startIndex: 8, type: 'white.lexon' }, + { startIndex: 9, type: 'identifier.lexon' }, // the + { startIndex: 12, type: 'white.lexon' }, + { startIndex: 13, type: 'identifier.lexon' }, // Payee + { startIndex: 18, type: 'delimiter.lexon' } // , + ] + } + ], + + [ + { + line: 'and also fixes the Fee.', + tokens: [ + { startIndex: 0, type: 'operator.lexon' }, // and + { startIndex: 3, type: 'white.lexon' }, + { startIndex: 4, type: 'identifier.lexon' }, // also + { startIndex: 8, type: 'white.lexon' }, + { startIndex: 9, type: 'identifier.lexon' }, // fixes + { startIndex: 14, type: 'white.lexon' }, + { startIndex: 15, type: 'identifier.lexon' }, // the + { startIndex: 18, type: 'white.lexon' }, + { startIndex: 19, type: 'identifier.lexon' }, // Fee + { startIndex: 22, type: 'delimiter.lexon' } // . + ] + } + ], + + [ + { + line: 'CLAUSE: Pay Out.', + tokens: [ + { startIndex: 0, type: 'keyword.lexon' }, // CLAUSE + { startIndex: 6, type: 'delimiter.lexon' }, // : + { startIndex: 7, type: 'white.lexon' }, + { startIndex: 8, type: 'identifier.lexon' }, // Pay out + { startIndex: 15, type: 'delimiter.lexon' } // . + ] + } + ] +]); diff --git a/monaco-languages/src/lexon/lexon.ts b/monaco-languages/src/lexon/lexon.ts new file mode 100644 index 00000000..29865ea9 --- /dev/null +++ b/monaco-languages/src/lexon/lexon.ts @@ -0,0 +1,179 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: 'COMMENT' + // blockComment: ['COMMENT', '.'], + }, + brackets: [['(', ')']], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: ':', close: '.' } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '`', close: '`' }, + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: ':', close: '.' } + ], + folding: { + markers: { + start: new RegExp('^\\s*(::\\s*|COMMENT\\s+)#region'), + end: new RegExp('^\\s*(::\\s*|COMMENT\\s+)#endregion') + } + } +}; + +export const language = { + // Set defaultToken to invalid to see what you do not tokenize yet + // defaultToken: 'invalid', + tokenPostfix: '.lexon', + ignoreCase: true, + + keywords: [ + 'lexon', + 'lex', + 'clause', + 'terms', + 'contracts', + 'may', + 'pay', + 'pays', + 'appoints', + 'into', + 'to' + ], + + typeKeywords: ['amount', 'person', 'key', 'time', 'date', 'asset', 'text'], + + operators: [ + 'less', + 'greater', + 'equal', + 'le', + 'gt', + 'or', + 'and', + 'add', + 'added', + 'subtract', + 'subtracted', + 'multiply', + 'multiplied', + 'times', + 'divide', + 'divided', + 'is', + 'be', + 'certified' + ], + + // we include these common regular expressions + symbols: /[=>](?!@symbols)/, '@brackets'], + [/@symbols/, 'delimiter'], + + // numbers + [/\d*\.\d*\.\d*/, 'number.semver'], + [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], + [/0[xX][0-9a-fA-F]+/, 'number.hex'], + [/\d+/, 'number'], + + // delimiter: after number because of .\d floats + [/[;,.]/, 'delimiter'] + ], + + quoted_identifier: [ + [/[^\\"]+/, 'identifier'], + [/"/, { token: 'identifier.quote', bracket: '@close', next: '@pop' }] + ], + + space_identifier_until_period: [ + [':', 'delimiter'], + [' ', { token: 'white', next: '@identifier_rest' }] + ], + + identifier_until_period: [ + { include: '@whitespace' }, + [':', { token: 'delimiter', next: '@identifier_rest' }], + [/[^\\.]+/, 'identifier'], + [/\./, { token: 'delimiter', bracket: '@close', next: '@pop' }] + ], + + identifier_rest: [ + [/[^\\.]+/, 'identifier'], + [/\./, { token: 'delimiter', bracket: '@close', next: '@pop' }] + ], + + semver: [ + { include: '@whitespace' }, + [':', 'delimiter'], + [/\d*\.\d*\.\d*/, { token: 'number.semver', bracket: '@close', next: '@pop' }] + ], + + whitespace: [[/[ \t\r\n]+/, 'white']] + } +}; diff --git a/monaco-languages/src/liquid/liquid.contribution.ts b/monaco-languages/src/liquid/liquid.contribution.ts new file mode 100644 index 00000000..e4c14a62 --- /dev/null +++ b/monaco-languages/src/liquid/liquid.contribution.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'liquid', + extensions: ['.liquid', '.html.liquid'], + aliases: ['Liquid', 'liquid'], + mimetypes: ['application/liquid'], + loader: () => import('./liquid') +}); diff --git a/monaco-languages/src/liquid/liquid.test.ts b/monaco-languages/src/liquid/liquid.test.ts new file mode 100644 index 00000000..b067fd09 --- /dev/null +++ b/monaco-languages/src/liquid/liquid.test.ts @@ -0,0 +1,209 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization( + ['liquid', 'css'], + [ + // Just HTML + [ + { + line: '

liquid!

', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: '' }, + { startIndex: 11, type: 'delimiter.html' }, + { startIndex: 13, type: 'tag.html' }, + { startIndex: 15, type: 'delimiter.html' } + ] + } + ], + + // Simple output + [ + { + line: '

{{ title }}

', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: 'delimiter.output.liquid' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'variable.liquid' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.output.liquid' }, + { startIndex: 15, type: 'delimiter.html' }, + { startIndex: 17, type: 'tag.html' }, + { startIndex: 19, type: 'delimiter.html' } + ] + } + ], + + // // Output filter + [ + { + line: '

{{ 3.14159265 | round | default: "pi" }}

', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 3, type: 'delimiter.html' }, + { startIndex: 4, type: 'delimiter.output.liquid' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.liquid' }, + { startIndex: 17, type: '' }, + { startIndex: 20, type: 'predefined.liquid' }, + { startIndex: 25, type: '' }, + { startIndex: 28, type: 'predefined.liquid' }, + { startIndex: 35, type: 'variable.liquid' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'string.liquid' }, + { startIndex: 41, type: '' }, + { startIndex: 43, type: 'delimiter.output.liquid' }, + { startIndex: 45, type: 'delimiter.html' }, + { startIndex: 47, type: 'tag.html' }, + { startIndex: 49, type: 'delimiter.html' } + ] + } + ], + + // Simple Tag + [ + { + line: '
{% render "files/file123.html" %}
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: 'delimiter.html' }, + { startIndex: 5, type: 'delimiter.tag.liquid' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'predefined.liquid' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'string.liquid' }, + { startIndex: 35, type: '' }, + { startIndex: 36, type: 'delimiter.tag.liquid' }, + { startIndex: 38, type: 'delimiter.html' }, + { startIndex: 40, type: 'tag.html' }, + { startIndex: 43, type: 'delimiter.html' } + ] + } + ], + + // Tag with drop + [ + { + line: '
{{ thing.other_thing }}
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: 'delimiter.html' }, + { startIndex: 5, type: 'delimiter.output.liquid' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'variable.liquid' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'variable.liquid' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'delimiter.output.liquid' }, + { startIndex: 28, type: 'delimiter.html' }, + { startIndex: 30, type: 'tag.html' }, + { startIndex: 33, type: 'delimiter.html' } + ] + } + ], + + // If tag / keywords / block style tags + [ + { + line: '
{% if true=false %}
True
{% else %}
False
{% endif %}
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: 'delimiter.html' }, + { startIndex: 5, type: 'delimiter.tag.liquid' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'predefined.liquid' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.liquid' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'keyword.liquid' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'delimiter.tag.liquid' }, + { startIndex: 24, type: 'delimiter.html' }, + { startIndex: 25, type: 'tag.html' }, + { startIndex: 28, type: 'delimiter.html' }, + { startIndex: 29, type: '' }, + { startIndex: 33, type: 'delimiter.html' }, + { startIndex: 35, type: 'tag.html' }, + { startIndex: 38, type: 'delimiter.html' }, + { startIndex: 39, type: 'delimiter.tag.liquid' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'predefined.liquid' }, + { startIndex: 46, type: '' }, + { startIndex: 47, type: 'delimiter.tag.liquid' }, + { startIndex: 49, type: 'delimiter.html' }, + { startIndex: 50, type: 'tag.html' }, + { startIndex: 53, type: 'delimiter.html' }, + { startIndex: 54, type: '' }, + { startIndex: 59, type: 'delimiter.html' }, + { startIndex: 61, type: 'tag.html' }, + { startIndex: 64, type: 'delimiter.html' }, + { startIndex: 65, type: 'delimiter.tag.liquid' }, + { startIndex: 67, type: '' }, + { startIndex: 68, type: 'predefined.liquid' }, + { startIndex: 73, type: '' }, + { startIndex: 74, type: 'delimiter.tag.liquid' }, + { startIndex: 76, type: 'delimiter.html' }, + { startIndex: 78, type: 'tag.html' }, + { startIndex: 81, type: 'delimiter.html' } + ] + } + ], + + // Comment tag + [ + { + line: '
Anything you put between {% comment %} and {% endcomment %} tags
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: 'delimiter.html' }, + { startIndex: 5, type: '' }, + { startIndex: 30, type: 'comment.start.liquid' }, + { startIndex: 43, type: 'comment.content.liquid' }, + { startIndex: 48, type: 'comment.end.liquid' }, + { startIndex: 64, type: '' }, + { startIndex: 69, type: 'delimiter.html' }, + { startIndex: 71, type: 'tag.html' }, + { startIndex: 74, type: 'delimiter.html' } + ] + } + ], + + // Raw tag + [ + { + line: '
Everything here should be escaped {% raw %} In Handlebars, {{ this }} will be HTML-escaped, but {{{ that }}} will not. {% endraw %}
', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: 'delimiter.html' }, + { startIndex: 5, type: '' }, + { startIndex: 39, type: 'delimiter.tag.liquid' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'delimiter.tag.liquid' }, + { startIndex: 48, type: '' }, + { startIndex: 124, type: 'delimiter.tag.liquid' }, + { startIndex: 126, type: '' }, + { startIndex: 134, type: 'delimiter.tag.liquid' }, + { startIndex: 136, type: 'delimiter.html' }, + { startIndex: 138, type: 'tag.html' }, + { startIndex: 141, type: 'delimiter.html' } + ] + } + ] + ] +); diff --git a/monaco-languages/src/liquid/liquid.ts b/monaco-languages/src/liquid/liquid.ts new file mode 100644 index 00000000..65384185 --- /dev/null +++ b/monaco-languages/src/liquid/liquid.ts @@ -0,0 +1,251 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { languages } from '../fillers/monaco-editor-core'; + +const EMPTY_ELEMENTS: string[] = [ + 'area', + 'base', + 'br', + 'col', + 'embed', + 'hr', + 'img', + 'input', + 'keygen', + 'link', + 'menuitem', + 'meta', + 'param', + 'source', + 'track', + 'wbr' +]; + +export const conf: languages.LanguageConfiguration = { + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, + + brackets: [ + [''], + ['<', '>'], + ['{{', '}}'], + ['{%', '%}'], + ['{', '}'], + ['(', ')'] + ], + + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '%', close: '%' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + surroundingPairs: [ + { open: '<', close: '>' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + onEnterRules: [ + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + afterText: /^<\/(\w[\w\d]*)\s*>$/i, + action: { + indentAction: languages.IndentAction.IndentOutdent + } + }, + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + action: { indentAction: languages.IndentAction.Indent } + } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '', + + builtinTags: [ + 'if', + 'else', + 'elseif', + 'endif', + 'render', + 'assign', + 'capture', + 'endcapture', + 'case', + 'endcase', + 'comment', + 'endcomment', + 'cycle', + 'decrement', + 'for', + 'endfor', + 'include', + 'increment', + 'layout', + 'raw', + 'endraw', + 'render', + 'tablerow', + 'endtablerow', + 'unless', + 'endunless' + ], + + builtinFilters: [ + 'abs', + 'append', + 'at_least', + 'at_most', + 'capitalize', + 'ceil', + 'compact', + 'date', + 'default', + 'divided_by', + 'downcase', + 'escape', + 'escape_once', + 'first', + 'floor', + 'join', + 'json', + 'last', + 'lstrip', + 'map', + 'minus', + 'modulo', + 'newline_to_br', + 'plus', + 'prepend', + 'remove', + 'remove_first', + 'replace', + 'replace_first', + 'reverse', + 'round', + 'rstrip', + 'size', + 'slice', + 'sort', + 'sort_natural', + 'split', + 'strip', + 'strip_html', + 'strip_newlines', + 'times', + 'truncate', + 'truncatewords', + 'uniq', + 'upcase', + 'url_decode', + 'url_encode', + 'where' + ], + + constants: ['true', 'false'], + operators: ['==', '!=', '>', '<', '>=', '<='], + + symbol: /[=>)/, ['delimiter.html', 'tag.html', 'delimiter.html']], + [/(<)([:\w]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [/(<\/)([\w\-]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [//, 'delimiter.html', '@pop'], + [/"([^"]*)"/, 'attribute.value'], + [/'([^']*)'/, 'attribute.value'], + [/[\w\-]+/, 'attribute.name'], + [/=/, 'delimiter'], + [/[ \t\r\n]+/] // whitespace + ], + + liquidState: [ + [/\{\{/, 'delimiter.output.liquid'], + [/\}\}/, { token: 'delimiter.output.liquid', switchTo: '@$S2.$S3' }], + [/\{\%/, 'delimiter.tag.liquid'], + [/raw\s*\%\}/, 'delimiter.tag.liquid', '@liquidRaw'], + [/\%\}/, { token: 'delimiter.tag.liquid', switchTo: '@$S2.$S3' }], + { include: 'liquidRoot' } + ], + + liquidRaw: [ + [/^(?!\{\%\s*endraw\s*\%\}).+/], + [/\{\%/, 'delimiter.tag.liquid'], + [/@identifier/], + [/\%\}/, { token: 'delimiter.tag.liquid', next: '@root' }] + ], + + liquidRoot: [ + [/\d+(\.\d+)?/, 'number.liquid'], + [/"[^"]*"/, 'string.liquid'], + [/'[^']*'/, 'string.liquid'], + [/\s+/], + [ + /@symbol/, + { + cases: { + '@operators': 'operator.liquid', + '@default': '' + } + } + ], + [/\./], + [ + /@identifier/, + { + cases: { + '@constants': 'keyword.liquid', + '@builtinFilters': 'predefined.liquid', + '@builtinTags': 'predefined.liquid', + '@default': 'variable.liquid' + } + } + ], + [/[^}|%]/, 'variable.liquid'] + ] + } +}; diff --git a/monaco-languages/src/lua/lua.contribution.ts b/monaco-languages/src/lua/lua.contribution.ts new file mode 100644 index 00000000..f88a08d5 --- /dev/null +++ b/monaco-languages/src/lua/lua.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'lua', + extensions: ['.lua'], + aliases: ['Lua', 'lua'], + loader: () => import('./lua') +}); diff --git a/monaco-languages/src/lua/lua.test.ts b/monaco-languages/src/lua/lua.test.ts new file mode 100644 index 00000000..37fc779e --- /dev/null +++ b/monaco-languages/src/lua/lua.test.ts @@ -0,0 +1,86 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('lua', [ + // Keywords + [ + { + line: 'local x, y = 1, 10', + tokens: [ + { startIndex: 0, type: 'keyword.local.lua' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.lua' }, + { startIndex: 7, type: 'delimiter.lua' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.lua' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.lua' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'number.lua' }, + { startIndex: 14, type: 'delimiter.lua' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'number.lua' } + ] + } + ], + + [ + { + line: 'foo = "Hello" .. "World"; local foo = foo', + tokens: [ + { startIndex: 0, type: 'identifier.lua' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.lua' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'string.lua' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'delimiter.lua' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'string.lua' }, + { startIndex: 24, type: 'delimiter.lua' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'keyword.local.lua' }, + { startIndex: 31, type: '' }, + { startIndex: 32, type: 'identifier.lua' }, + { startIndex: 35, type: '' }, + { startIndex: 36, type: 'delimiter.lua' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'identifier.lua' } + ] + } + ], + + // Comments + [ + { + line: '--[[ text ]] x', + tokens: [ + { startIndex: 0, type: 'comment.lua' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.lua' } + ] + } + ], + + [ + { + line: '--[===[ text ]===] x', + tokens: [ + { startIndex: 0, type: 'comment.lua' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'identifier.lua' } + ] + } + ], + + [ + { + line: '--[===[ text ]==] x', + tokens: [{ startIndex: 0, type: 'comment.lua' }] + } + ] +]); diff --git a/monaco-languages/src/lua/lua.ts b/monaco-languages/src/lua/lua.ts new file mode 100644 index 00000000..13cef28e --- /dev/null +++ b/monaco-languages/src/lua/lua.ts @@ -0,0 +1,178 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '--', + blockComment: ['--[[', ']]'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.lua', + + keywords: [ + 'and', + 'break', + 'do', + 'else', + 'elseif', + 'end', + 'false', + 'for', + 'function', + 'goto', + 'if', + 'in', + 'local', + 'nil', + 'not', + 'or', + 'repeat', + 'return', + 'then', + 'true', + 'until', + 'while' + ], + + brackets: [ + { token: 'delimiter.bracket', open: '{', close: '}' }, + { token: 'delimiter.array', open: '[', close: ']' }, + { token: 'delimiter.parenthesis', open: '(', close: ')' } + ], + + operators: [ + '+', + '-', + '*', + '/', + '%', + '^', + '#', + '==', + '~=', + '<=', + '>=', + '<', + '>', + '=', + ';', + ':', + ',', + '.', + '..', + '...' + ], + + // we include these common regular expressions + symbols: /[=> import('./m3') +}); diff --git a/monaco-languages/src/m3/m3.test.ts b/monaco-languages/src/m3/m3.test.ts new file mode 100644 index 00000000..c089527e --- /dev/null +++ b/monaco-languages/src/m3/m3.test.ts @@ -0,0 +1,119 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('m3', [ + [ + { + line: '(**)', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + } + ], + + [ + { + line: ' (* a comment *)', + tokens: [ + { startIndex: 0, type: 'white.m3' }, + { startIndex: 4, type: 'comment.m3' } + ] + } + ], + + [ + { + line: '(* Lorem ipsum dolor sit amet, consectetur ', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' adipiscing elit, sed do eiusmod tempor', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' incididunt ut labore et dolore magna aliqua. *)', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + } + ], + + [ + { + line: '(* Lorem ipsum dolor sit amet (*, consectetur ', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' adipiscing elit, sed do eiusmod tempor', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + }, + { + line: ' incididunt*) ut labore et dolore magna aliqua. *)', + tokens: [{ startIndex: 0, type: 'comment.m3' }] + } + ], + + [ + { + line: 'MODULE Test EXPORTS Main; FROM IO IMPORT Put; BEGIN Put("test\\n") END Test.', + tokens: [ + { startIndex: 0, type: 'keyword.MODULE.m3' }, + { startIndex: 6, type: 'white.m3' }, + { startIndex: 7, type: 'identifier.m3' }, + { startIndex: 11, type: 'white.m3' }, + { startIndex: 12, type: 'keyword.EXPORTS.m3' }, + { startIndex: 19, type: 'white.m3' }, + { startIndex: 20, type: 'identifier.m3' }, + { startIndex: 24, type: 'delimiter.m3' }, + { startIndex: 25, type: 'white.m3' }, + + { startIndex: 26, type: 'keyword.FROM.m3' }, + { startIndex: 30, type: 'white.m3' }, + { startIndex: 31, type: 'identifier.m3' }, + { startIndex: 33, type: 'white.m3' }, + { startIndex: 34, type: 'keyword.IMPORT.m3' }, + { startIndex: 40, type: 'white.m3' }, + { startIndex: 41, type: 'identifier.m3' }, + { startIndex: 44, type: 'delimiter.m3' }, + { startIndex: 45, type: 'white.m3' }, + + { startIndex: 46, type: 'keyword.BEGIN.m3' }, + { startIndex: 51, type: 'white.m3' }, + { startIndex: 52, type: 'identifier.m3' }, + { startIndex: 55, type: 'delimiter.parenthesis.m3' }, + { startIndex: 56, type: 'string.text.m3' }, + { startIndex: 61, type: 'string.escape.m3' }, + { startIndex: 63, type: 'string.text.m3' }, + { startIndex: 64, type: 'delimiter.parenthesis.m3' }, + { startIndex: 65, type: 'white.m3' }, + + { startIndex: 66, type: 'keyword.END.m3' }, + { startIndex: 69, type: 'white.m3' }, + { startIndex: 70, type: 'identifier.m3' }, + { startIndex: 74, type: 'operators.m3' } + ] + } + ], + + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.m3' }] + } + ], + [ + { + line: '-16_B33f', + tokens: [ + { startIndex: 0, type: 'operators.m3' }, + { startIndex: 1, type: 'number.m3' } + ] + } + ], + [ + { + line: '2.0D-5', + tokens: [{ startIndex: 0, type: 'number.float.m3' }] + } + ] +]); diff --git a/monaco-languages/src/m3/m3.ts b/monaco-languages/src/m3/m3.ts new file mode 100644 index 00000000..243f36bd --- /dev/null +++ b/monaco-languages/src/m3/m3.ts @@ -0,0 +1,226 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + blockComment: ['(*', '*)'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '[', close: ']' }, + { open: '{', close: '}' }, + { open: '(', close: ')' }, + { open: '(*', close: '*)' }, + { open: '<*', close: '*>' }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '"', close: '"', notIn: ['string', 'comment'] } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.m3', + + brackets: [ + { token: 'delimiter.curly', open: '{', close: '}' }, + { token: 'delimiter.parenthesis', open: '(', close: ')' }, + { token: 'delimiter.square', open: '[', close: ']' } + ], + keywords: [ + 'AND', + 'ANY', + 'ARRAY', + 'AS', + 'BEGIN', + 'BITS', + 'BRANDED', + 'BY', + 'CASE', + 'CONST', + 'DIV', + 'DO', + 'ELSE', + 'ELSIF', + 'END', + 'EVAL', + 'EXCEPT', + 'EXCEPTION', + 'EXIT', + 'EXPORTS', + 'FINALLY', + 'FOR', + 'FROM', + 'GENERIC', + 'IF', + 'IMPORT', + 'IN', + 'INTERFACE', + 'LOCK', + 'LOOP', + 'METHODS', + 'MOD', + 'MODULE', + 'NOT', + 'OBJECT', + 'OF', + 'OR', + 'OVERRIDES', + 'PROCEDURE', + 'RAISE', + 'RAISES', + 'READONLY', + 'RECORD', + 'REF', + 'REPEAT', + 'RETURN', + 'REVEAL', + 'SET', + 'THEN', + 'TO', + 'TRY', + 'TYPE', + 'TYPECASE', + 'UNSAFE', + 'UNTIL', + 'UNTRACED', + 'VALUE', + 'VAR', + 'WHILE', + 'WITH' + ], + reservedConstNames: [ + 'ABS', + 'ADR', + 'ADRSIZE', + 'BITSIZE', + 'BYTESIZE', + 'CEILING', + 'DEC', + 'DISPOSE', + 'FALSE', + 'FIRST', + 'FLOAT', + 'FLOOR', + 'INC', + 'ISTYPE', + 'LAST', + 'LOOPHOLE', + 'MAX', + 'MIN', + 'NARROW', + 'NEW', + 'NIL', + 'NUMBER', + 'ORD', + 'ROUND', + 'SUBARRAY', + 'TRUE', + 'TRUNC', + 'TYPECODE', + 'VAL' + ], + reservedTypeNames: [ + 'ADDRESS', + 'ANY', + 'BOOLEAN', + 'CARDINAL', + 'CHAR', + 'EXTENDED', + 'INTEGER', + 'LONGCARD', + 'LONGINT', + 'LONGREAL', + 'MUTEX', + 'NULL', + 'REAL', + 'REFANY', + 'ROOT', + 'TEXT' + ], + operators: ['+', '-', '*', '/', '&', '^', '.'], + relations: ['=', '#', '<', '<=', '>', '>=', '<:', ':'], + delimiters: ['|', '..', '=>', ',', ';', ':='], + symbols: /[>=<#.,:;+\-*/&^]+/, + escapes: /\\(?:[\\fnrt"']|[0-7]{3})/, + + tokenizer: { + root: [ + // Identifiers and keywords + [/_\w*/, 'invalid'], + [ + /[a-zA-Z][a-zA-Z0-9_]*/, + { + cases: { + '@keywords': { token: 'keyword.$0' }, + '@reservedConstNames': { token: 'constant.reserved.$0' }, + '@reservedTypeNames': { token: 'type.reserved.$0' }, + '@default': 'identifier' + } + } + ], + + // Whitespace + { include: '@whitespace' }, + [/[{}()\[\]]/, '@brackets'], + + // Integer- and real literals + [/[0-9]+\.[0-9]+(?:[DdEeXx][\+\-]?[0-9]+)?/, 'number.float'], + [/[0-9]+(?:\_[0-9a-fA-F]+)?L?/, 'number'], + + // Operators, relations, and delimiters + [ + /@symbols/, + { + cases: { + '@operators': 'operators', + '@relations': 'operators', + '@delimiters': 'delimiter', + '@default': 'invalid' + } + } + ], + + // Character literals + [/'[^\\']'/, 'string.char'], + [/(')(@escapes)(')/, ['string.char', 'string.escape', 'string.char']], + [/'/, 'invalid'], + + // Text literals + [/"([^"\\]|\\.)*$/, 'invalid'], + [/"/, 'string.text', '@text'] + ], + + text: [ + [/[^\\"]+/, 'string.text'], + [/@escapes/, 'string.escape'], + [/\\./, 'invalid'], + [/"/, 'string.text', '@pop'] + ], + + comment: [ + [/\(\*/, 'comment', '@push'], + [/\*\)/, 'comment', '@pop'], + [/./, 'comment'] + ], + + pragma: [ + [/<\*/, 'keyword.pragma', '@push'], + [/\*>/, 'keyword.pragma', '@pop'], + [/./, 'keyword.pragma'] + ], + + whitespace: [ + [/[ \t\r\n]+/, 'white'], + [/\(\*/, 'comment', '@comment'], + [/<\*/, 'keyword.pragma', '@pragma'] + ] + } +}; diff --git a/monaco-languages/src/markdown/markdown.contribution.ts b/monaco-languages/src/markdown/markdown.contribution.ts new file mode 100644 index 00000000..e13fd47e --- /dev/null +++ b/monaco-languages/src/markdown/markdown.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'markdown', + extensions: ['.md', '.markdown', '.mdown', '.mkdn', '.mkd', '.mdwn', '.mdtxt', '.mdtext'], + aliases: ['Markdown', 'markdown'], + loader: () => import('./markdown') +}); diff --git a/monaco-languages/src/markdown/markdown.test.ts b/monaco-languages/src/markdown/markdown.test.ts new file mode 100644 index 00000000..7253cbe6 --- /dev/null +++ b/monaco-languages/src/markdown/markdown.test.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('markdown', [ + [ + { + line: '# Some header', + tokens: [{ startIndex: 0, type: 'keyword.md' }] + } + ], + + [ + { + line: '* Some list item', + tokens: [ + { startIndex: 0, type: 'keyword.md' }, + { startIndex: 2, type: '' } + ] + } + ], + + [ + { + line: 'some `code`', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'variable.md' } + ] + } + ], + + [ + { + line: 'some ![link](http://link.com)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'string.link.md' }, + { startIndex: 7, type: '' }, + { startIndex: 11, type: 'string.link.md' } + ] + } + ] +]); diff --git a/monaco-languages/src/markdown/markdown.ts b/monaco-languages/src/markdown/markdown.ts new file mode 100644 index 00000000..358ec6fe --- /dev/null +++ b/monaco-languages/src/markdown/markdown.ts @@ -0,0 +1,262 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + blockComment: [''] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>', notIn: ['string'] } + ], + surroundingPairs: [ + { open: '(', close: ')' }, + { open: '[', close: ']' }, + { open: '`', close: '`' } + ], + folding: { + markers: { + start: new RegExp('^\\s*'), + end: new RegExp('^\\s*') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.md', + + // escape codes + control: /[\\`*_\[\]{}()#+\-\.!]/, + noncontrol: /[^\\`*_\[\]{}()#+\-\.!]/, + escapes: /\\(?:@control)/, + + // escape codes for javascript/CSS strings + jsescapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/, + + // non matched elements + empty: [ + 'area', + 'base', + 'basefont', + 'br', + 'col', + 'frame', + 'hr', + 'img', + 'input', + 'isindex', + 'link', + 'meta', + 'param' + ], + + tokenizer: { + root: [ + // markdown tables + [/^\s*\|/, '@rematch', '@table_header'], + + // headers (with #) + [ + /^(\s{0,3})(#+)((?:[^\\#]|@escapes)+)((?:#+)?)/, + ['white', 'keyword', 'keyword', 'keyword'] + ], + + // headers (with =) + [/^\s*(=+|\-+)\s*$/, 'keyword'], + + // headers (with ***) + [/^\s*((\*[ ]?)+)\s*$/, 'meta.separator'], + + // quote + [/^\s*>+/, 'comment'], + + // list (starting with * or number) + [/^\s*([\*\-+:]|\d+\.)\s/, 'keyword'], + + // code block (4 spaces indent) + [/^(\t|[ ]{4})[^ ].*$/, 'string'], + + // code block (3 tilde) + [/^\s*~~~\s*((?:\w|[\/\-#])+)?\s*$/, { token: 'string', next: '@codeblock' }], + + // github style code blocks (with backticks and language) + [ + /^\s*```\s*((?:\w|[\/\-#])+).*$/, + { token: 'string', next: '@codeblockgh', nextEmbedded: '$1' } + ], + + // github style code blocks (with backticks but no language) + [/^\s*```\s*$/, { token: 'string', next: '@codeblock' }], + + // markup within lines + { include: '@linecontent' } + ], + + table_header: [ + { include: '@table_common' }, + [/[^\|]+/, 'keyword.table.header'] // table header + ], + + table_body: [{ include: '@table_common' }, { include: '@linecontent' }], + + table_common: [ + [/\s*[\-:]+\s*/, { token: 'keyword', switchTo: 'table_body' }], // header-divider + [/^\s*\|/, 'keyword.table.left'], // opening | + [/^\s*[^\|]/, '@rematch', '@pop'], // exiting + [/^\s*$/, '@rematch', '@pop'], // exiting + [ + /\|/, + { + cases: { + '@eos': 'keyword.table.right', // closing | + '@default': 'keyword.table.middle' // inner | + } + } + ] + ], + + codeblock: [ + [/^\s*~~~\s*$/, { token: 'string', next: '@pop' }], + [/^\s*```\s*$/, { token: 'string', next: '@pop' }], + [/.*$/, 'variable.source'] + ], + + // github style code blocks + codeblockgh: [ + [/```\s*$/, { token: 'string', next: '@pop', nextEmbedded: '@pop' }], + [/[^`]+/, 'variable.source'] + ], + + linecontent: [ + // escapes + [/&\w+;/, 'string.escape'], + [/@escapes/, 'escape'], + + // various markup + [/\b__([^\\_]|@escapes|_(?!_))+__\b/, 'strong'], + [/\*\*([^\\*]|@escapes|\*(?!\*))+\*\*/, 'strong'], + [/\b_[^_]+_\b/, 'emphasis'], + [/\*([^\\*]|@escapes)+\*/, 'emphasis'], + [/`([^\\`]|@escapes)+`/, 'variable'], + + // links + [/\{+[^}]+\}+/, 'string.target'], + [/(!?\[)((?:[^\]\\]|@escapes)*)(\]\([^\)]+\))/, ['string.link', '', 'string.link']], + [/(!?\[)((?:[^\]\\]|@escapes)*)(\])/, 'string.link'], + + // or html + { include: 'html' } + ], + + // Note: it is tempting to rather switch to the real HTML mode instead of building our own here + // but currently there is a limitation in Monarch that prevents us from doing it: The opening + // '<' would start the HTML mode, however there is no way to jump 1 character back to let the + // HTML mode also tokenize the opening angle bracket. Thus, even though we could jump to HTML, + // we cannot correctly tokenize it in that mode yet. + html: [ + // html tags + [/<(\w+)\/>/, 'tag'], + [ + /<(\w+)/, + { + cases: { + '@empty': { token: 'tag', next: '@tag.$1' }, + '@default': { token: 'tag', next: '@tag.$1' } + } + } + ], + [/<\/(\w+)\s*>/, { token: 'tag' }], + + [//, 'comment', '@pop'], + [/*/?> */var y = 4;', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 5, type: 'delimiter.html' }, + // { startIndex:6, type: 'delimiter.html' }, + { startIndex: 7, type: 'tag.html' }, + { startIndex: 12, type: 'delimiter.html' }, + { startIndex: 13, type: 'metatag.php' }, + { startIndex: 16, type: 'string.php' }, + { startIndex: 21, type: 'metatag.php' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'delimiter.bracket.css' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'attribute.name.css' }, + { startIndex: 32, type: 'attribute.value.css' }, + { startIndex: 36, type: 'delimiter.css' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'delimiter.bracket.css' }, + { startIndex: 39, type: 'delimiter.html' }, + { startIndex: 41, type: 'tag.html' }, + { startIndex: 46, type: 'delimiter.html' }, + { startIndex: 47, type: 'comment.html' }, + { startIndex: 51, type: 'metatag.php' }, + { startIndex: 54, type: 'string.php' }, + { startIndex: 68, type: 'metatag.php' }, + { startIndex: 70, type: 'comment.html' }, + { startIndex: 73, type: 'delimiter.html' }, + { startIndex: 74, type: 'tag.html' }, + { startIndex: 80, type: 'delimiter.html' }, + { startIndex: 81, type: 'keyword.js' }, + { startIndex: 84, type: '' }, + { startIndex: 85, type: 'identifier.js' }, + { startIndex: 86, type: '' }, + { startIndex: 87, type: 'delimiter.js' }, + { startIndex: 88, type: '' }, + { startIndex: 89, type: 'number.js' }, + { startIndex: 90, type: 'delimiter.js' }, + { startIndex: 91, type: 'comment.js' }, + { startIndex: 94, type: 'metatag.php' }, + { startIndex: 97, type: 'string.php' }, + { startIndex: 109, type: 'comment.php' }, + { startIndex: 122, type: 'metatag.php' }, + { startIndex: 124, type: '' }, + { startIndex: 127, type: 'keyword.js' }, + { startIndex: 130, type: '' }, + { startIndex: 131, type: 'identifier.js' }, + { startIndex: 132, type: '' }, + { startIndex: 133, type: 'delimiter.js' }, + { startIndex: 134, type: '' }, + { startIndex: 135, type: 'number.js' }, + { startIndex: 136, type: 'delimiter.js' }, + { startIndex: 137, type: 'delimiter.html' }, + { startIndex: 139, type: 'tag.html' }, + { startIndex: 145, type: 'delimiter.html' }, + // { startIndex:146, type: 'delimiter.html' }, + { startIndex: 148, type: 'tag.html' }, + { startIndex: 152, type: 'delimiter.html' }, + { startIndex: 153, type: 'metatag.php' }, + { startIndex: 155, type: '' }, + { startIndex: 156, type: 'variable.php' }, + { startIndex: 158, type: '' }, + { startIndex: 159, type: 'delimiter.php' }, + { startIndex: 160, type: '' }, + { startIndex: 161, type: 'number.php' }, + { startIndex: 162, type: 'delimiter.php' }, + { startIndex: 163, type: 'metatag.php' } + ] + } + ], + + // PHP-tag detection + [ + { + line: '//""', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: 'delimiter.html' }, + { startIndex: 8, type: 'string.invalid.js' }, + { startIndex: 9, type: 'metatag.php' }, + { startIndex: 14, type: 'number.php' }, + { startIndex: 15, type: 'delimiter.php' }, + { startIndex: 16, type: 'number.php' }, + { startIndex: 17, type: 'metatag.php' }, + { startIndex: 19, type: 'string.invalid.js' } + ] + } + ], + + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'metatag.php' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.php' }, + { startIndex: 14, type: 'delimiter.parenthesis.php' }, + { startIndex: 16, type: 'delimiter.php' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'metatag.php' } + ] + } + ], + + [ + { + line: '\/\?\s]+)/g, + + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + + autoClosingPairs: [ + { open: '{', close: '}', notIn: ['string'] }, + { open: '[', close: ']', notIn: ['string'] }, + { open: '(', close: ')', notIn: ['string'] }, + { open: '"', close: '"', notIn: ['string'] }, + { open: "'", close: "'", notIn: ['string', 'comment'] } + ], + + folding: { + markers: { + start: new RegExp('^\\s*(#|//)region\\b'), + end: new RegExp('^\\s*(#|//)endregion\\b') + } + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '', + // ignoreCase: true, + + // The main tokenizer for our languages + tokenizer: { + root: [ + [/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.root' }], + [/)/, ['delimiter.html', 'tag.html', 'delimiter.html']], + [/(<)(script)/, ['delimiter.html', { token: 'tag.html', next: '@script' }]], + [/(<)(style)/, ['delimiter.html', { token: 'tag.html', next: '@style' }]], + [/(<)([:\w]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [/(<\/)(\w+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [/]+/, 'metatag.content.html'], + [/>/, 'metatag.html', '@pop'] + ], + + comment: [ + [/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.comment' }], + [/-->/, 'comment.html', '@pop'], + [/[^-]+/, 'comment.content.html'], + [/./, 'comment.content.html'] + ], + + otherTag: [ + [/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.otherTag' }], + [/\/?>/, 'delimiter.html', '@pop'], + [/"([^"]*)"/, 'attribute.value'], + [/'([^']*)'/, 'attribute.value'], + [/[\w\-]+/, 'attribute.name'], + [/=/, 'delimiter'], + [/[ \t\r\n]+/] // whitespace + ], + + // -- BEGIN + +//
+// Hello +// +// +// +// guest +// +// ! +//
+ +// "); + +// // display shuffled cards (EXAMPLE ONLY) +// for ($index = 0; $index < 52; $index++) { +// if ($starting_point == 52) { $starting_point = 0; } +// print("Uncut Point: $deck[$index] "); +// print("Starting Point: $deck[$starting_point]
"); +// $starting_point++; +// } +// ?> + +// +// diff --git a/monaco-languages/src/pla/pla.contribution.ts b/monaco-languages/src/pla/pla.contribution.ts new file mode 100644 index 00000000..9a3b13e9 --- /dev/null +++ b/monaco-languages/src/pla/pla.contribution.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'pla', + extensions: ['.pla'], + loader: () => import('./pla') +}); diff --git a/monaco-languages/src/pla/pla.test.ts b/monaco-languages/src/pla/pla.test.ts new file mode 100644 index 00000000..553d8675 --- /dev/null +++ b/monaco-languages/src/pla/pla.test.ts @@ -0,0 +1,598 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('pla', [ + // Keywords + // .i + [ + { + line: '.i 50', + tokens: [ + { startIndex: 0, type: 'keyword.i.pla' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.pla' } + ] + }, + { + line: ' .i 333 # Input', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.i.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'number.pla' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'comment.pla' } + ] + } + ], + // .o + [ + { + line: '.o 7', + tokens: [ + { startIndex: 0, type: 'keyword.o.pla' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.pla' } + ] + }, + { + line: ' .o 1000 ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.o.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.pla' }, + { startIndex: 8, type: '' } + ] + } + ], + // .mv + [ + { + line: '.mv 9 4 3 21 1', + tokens: [ + { startIndex: 0, type: 'keyword.mv.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'number.pla' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.pla' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'number.pla' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'number.pla' } + ] + }, + { + line: '.mv 22 22', + tokens: [ + { startIndex: 0, type: 'keyword.mv.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.pla' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.pla' } + ] + } + ], + // .ilb + [ + { + line: '.ilb in1 in2 in3 in4 in5', + tokens: [ + { startIndex: 0, type: 'keyword.ilb.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.pla' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.pla' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.pla' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'identifier.pla' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'identifier.pla' } + ] + }, + { + line: '.ilb input<0> input<1> input<2> input<3>', + tokens: [ + { startIndex: 0, type: 'keyword.ilb.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.pla' }, + { startIndex: 10, type: 'delimiter.angle.pla' }, + { startIndex: 11, type: 'number.pla' }, + { startIndex: 12, type: 'delimiter.angle.pla' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.pla' }, + { startIndex: 19, type: 'delimiter.angle.pla' }, + { startIndex: 20, type: 'number.pla' }, + { startIndex: 21, type: 'delimiter.angle.pla' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'identifier.pla' }, + { startIndex: 28, type: 'delimiter.angle.pla' }, + { startIndex: 29, type: 'number.pla' }, + { startIndex: 30, type: 'delimiter.angle.pla' }, + { startIndex: 31, type: '' }, + { startIndex: 32, type: 'identifier.pla' }, + { startIndex: 37, type: 'delimiter.angle.pla' }, + { startIndex: 38, type: 'number.pla' }, + { startIndex: 39, type: 'delimiter.angle.pla' } + ] + } + ], + // .ob + [ + { + line: '.ob out1 out2 out3', + tokens: [ + { startIndex: 0, type: 'keyword.ob.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pla' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.pla' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.pla' } + ] + }, + { + line: '.ob output<0> output<1>', + tokens: [ + { startIndex: 0, type: 'keyword.ob.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pla' }, + { startIndex: 10, type: 'delimiter.angle.pla' }, + { startIndex: 11, type: 'number.pla' }, + { startIndex: 12, type: 'delimiter.angle.pla' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.pla' }, + { startIndex: 20, type: 'delimiter.angle.pla' }, + { startIndex: 21, type: 'number.pla' }, + { startIndex: 22, type: 'delimiter.angle.pla' } + ] + } + ], + // .label + [ + { + line: '.label in1 in2 in3 in4 in5', + tokens: [ + { startIndex: 0, type: 'keyword.label.pla' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.pla' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'identifier.pla' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'identifier.pla' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'identifier.pla' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'identifier.pla' } + ] + }, + { + line: '.label var=5 part1 part2 part3 part4', + tokens: [ + { startIndex: 0, type: 'keyword.label.pla' }, + { startIndex: 6, type: '' }, + { startIndex: 8, type: 'identifier.pla' }, + { startIndex: 11, type: 'delimiter.pla' }, + { startIndex: 12, type: 'number.pla' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.pla' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'identifier.pla' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'identifier.pla' }, + { startIndex: 31, type: '' }, + { startIndex: 32, type: 'identifier.pla' } + ] + } + ], + // .type + [ + { + line: '.type fr', + tokens: [ + { startIndex: 0, type: 'keyword.type.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'type.pla' } + ] + }, + { + line: ' .type fdr # Comment ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.type.pla' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'type.pla' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'comment.pla' } + ] + }, + { + line: '.type other', + tokens: [ + { startIndex: 0, type: 'keyword.type.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'type.pla' } + ] + } + ], + // .phase + [ + { + line: '.phase 010', + tokens: [ + { startIndex: 0, type: 'keyword.phase.pla' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.pla' } + ] + } + ], + // .pair + [ + { + line: '.pair 2 (aa bb) (cc dd) ## Comment', + tokens: [ + { startIndex: 0, type: 'keyword.pair.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'number.pla' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.pla' }, + { startIndex: 9, type: 'identifier.pla' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'identifier.pla' }, + { startIndex: 14, type: 'delimiter.parenthesis.pla' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'delimiter.parenthesis.pla' }, + { startIndex: 17, type: 'identifier.pla' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'identifier.pla' }, + { startIndex: 22, type: 'delimiter.parenthesis.pla' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'comment.pla' } + ] + } + ], + // .symbolic + [ + { + line: '.symbolic aa<2> aa<1> aa<0> ; BB CC DD ;', + tokens: [ + { startIndex: 0, type: 'keyword.symbolic.pla' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.pla' }, + { startIndex: 12, type: 'delimiter.angle.pla' }, + { startIndex: 13, type: 'number.pla' }, + { startIndex: 14, type: 'delimiter.angle.pla' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'identifier.pla' }, + { startIndex: 18, type: 'delimiter.angle.pla' }, + { startIndex: 19, type: 'number.pla' }, + { startIndex: 20, type: 'delimiter.angle.pla' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'identifier.pla' }, + { startIndex: 24, type: 'delimiter.angle.pla' }, + { startIndex: 25, type: 'number.pla' }, + { startIndex: 26, type: 'delimiter.angle.pla' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.pla' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'identifier.pla' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'identifier.pla' }, + { startIndex: 35, type: '' }, + { startIndex: 36, type: 'identifier.pla' }, + { startIndex: 38, type: '' }, + { startIndex: 39, type: 'delimiter.pla' } + ] + }, + { + line: '.symbolic state<3> state<2>;aaa bbb; # comment', + tokens: [ + { startIndex: 0, type: 'keyword.symbolic.pla' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.pla' }, + { startIndex: 15, type: 'delimiter.angle.pla' }, + { startIndex: 16, type: 'number.pla' }, + { startIndex: 17, type: 'delimiter.angle.pla' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'identifier.pla' }, + { startIndex: 24, type: 'delimiter.angle.pla' }, + { startIndex: 25, type: 'number.pla' }, + { startIndex: 26, type: 'delimiter.angle.pla' }, + { startIndex: 27, type: 'delimiter.pla' }, + { startIndex: 28, type: 'identifier.pla' }, + { startIndex: 31, type: '' }, + { startIndex: 32, type: 'identifier.pla' }, + { startIndex: 35, type: 'delimiter.pla' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'comment.pla' } + ] + } + ], + // .symbolic-output + [ + { + line: '.symbolic-output out<2> out<1> out<0> ; signal_a signal_b signal_c ;', + tokens: [ + { startIndex: 0, type: 'keyword.symbolic-output.pla' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'identifier.pla' }, + { startIndex: 20, type: 'delimiter.angle.pla' }, + { startIndex: 21, type: 'number.pla' }, + { startIndex: 22, type: 'delimiter.angle.pla' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'identifier.pla' }, + { startIndex: 27, type: 'delimiter.angle.pla' }, + { startIndex: 28, type: 'number.pla' }, + { startIndex: 29, type: 'delimiter.angle.pla' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'identifier.pla' }, + { startIndex: 34, type: 'delimiter.angle.pla' }, + { startIndex: 35, type: 'number.pla' }, + { startIndex: 36, type: 'delimiter.angle.pla' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'delimiter.pla' }, + { startIndex: 39, type: '' }, + { startIndex: 40, type: 'identifier.pla' }, + { startIndex: 48, type: '' }, + { startIndex: 49, type: 'identifier.pla' }, + { startIndex: 57, type: '' }, + { startIndex: 58, type: 'identifier.pla' }, + { startIndex: 66, type: '' }, + { startIndex: 67, type: 'delimiter.pla' } + ] + } + ], + // .kiss + [ + { + line: '.kiss #.kiss', + tokens: [ + { startIndex: 0, type: 'keyword.kiss.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'comment.pla' } + ] + } + ], + // .p + [ + { + line: '.p 400', + tokens: [ + { startIndex: 0, type: 'keyword.p.pla' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.pla' } + ] + } + ], + // .e + [ + { + line: ' .e ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.e.pla' }, + { startIndex: 3, type: '' } + ] + } + ], + // PLA rows + [ + { + line: '0-010|1000|100000000000000000000000000|0010000000', + tokens: [{ startIndex: 0, type: 'string.pla' }] + }, + { + line: '--------------0 00000000000010', + tokens: [ + { startIndex: 0, type: 'string.pla' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'string.pla' } + ] + }, + { + line: '0~~0 1-0 # Comment', + tokens: [ + { startIndex: 0, type: 'string.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'string.pla' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'comment.pla' } + ] + } + ], + // Full example #1 + [ + { + line: '.i 4', + tokens: [ + { startIndex: 0, type: 'keyword.i.pla' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.pla' } + ] + }, + { + line: '.o 3', + tokens: [ + { startIndex: 0, type: 'keyword.o.pla' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.pla' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '# Comment only line', + tokens: [{ startIndex: 0, type: 'comment.pla' }] + }, + { + line: '.ilb Q1 Q0 D N', + tokens: [ + { startIndex: 0, type: 'keyword.ilb.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.pla' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.pla' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'identifier.pla' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.pla' } + ] + }, + { + line: '.ob T1 T0 input_1', + tokens: [ + { startIndex: 0, type: 'keyword.ob.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pla' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.pla' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.pla' } + ] + }, + { + line: '.p 5', + tokens: [ + { startIndex: 0, type: 'keyword.p.pla' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.pla' } + ] + }, + { + line: '0--- 100', + tokens: [ + { startIndex: 0, type: 'string.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'string.pla' } + ] + }, + { + line: '1-1- 010', + tokens: [ + { startIndex: 0, type: 'string.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'string.pla' } + ] + }, + { + line: '.e', + tokens: [{ startIndex: 0, type: 'keyword.e.pla' }] + } + ], + // Full example #2 + [ + { + line: '.mv 8 5 -10 -10 6', + tokens: [ + { startIndex: 0, type: 'keyword.mv.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'number.pla' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.pla' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'number.pla' }, + { startIndex: 15, type: '' }, + { startIndex: 16, type: 'number.pla' } + ] + }, + { + line: '.ilb in1 in0 wait ack nack', + tokens: [ + { startIndex: 0, type: 'keyword.ilb.pla' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'identifier.pla' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.pla' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.pla' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'identifier.pla' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'identifier.pla' } + ] + }, + { + line: '.ob wait wait2 in3 pending ack delay', + tokens: [ + { startIndex: 0, type: 'keyword.ob.pla' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pla' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.pla' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'identifier.pla' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'identifier.pla' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'identifier.pla' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'identifier.pla' } + ] + }, + { + line: '.type fr', + tokens: [ + { startIndex: 0, type: 'keyword.type.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'type.pla' } + ] + }, + { + line: '.kiss', + tokens: [{ startIndex: 0, type: 'keyword.kiss.pla' }] + }, + { + line: '--1-- - wait 110000', + tokens: [ + { startIndex: 0, type: 'string.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 10, type: 'string.pla' }, + { startIndex: 11, type: '' }, + { startIndex: 19, type: 'identifier.pla' }, + { startIndex: 23, type: '' }, + { startIndex: 28, type: 'string.pla' } + ] + }, + { + line: '--1-- wait wait2 110000 # row comment', + tokens: [ + { startIndex: 0, type: 'string.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 10, type: 'identifier.pla' }, + { startIndex: 14, type: '' }, + { startIndex: 18, type: 'identifier.pla' }, + { startIndex: 23, type: '' }, + { startIndex: 28, type: 'string.pla' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'comment.pla' } + ] + }, + { + line: '--0-1 delay ack 101000', + tokens: [ + { startIndex: 0, type: 'string.pla' }, + { startIndex: 5, type: '' }, + { startIndex: 10, type: 'identifier.pla' }, + { startIndex: 15, type: '' }, + { startIndex: 19, type: 'identifier.pla' }, + { startIndex: 22, type: '' }, + { startIndex: 27, type: 'string.pla' } + ] + }, + { + line: '.end', + tokens: [{ startIndex: 0, type: 'keyword.end.pla' }] + } + ] +]); diff --git a/monaco-languages/src/pla/pla.ts b/monaco-languages/src/pla/pla.ts new file mode 100644 index 00000000..0f45d80e --- /dev/null +++ b/monaco-languages/src/pla/pla.ts @@ -0,0 +1,157 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '#' + }, + brackets: [ + ['[', ']'], + ['<', '>'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '[', close: ']' }, + { open: '<', close: '>' }, + { open: '(', close: ')' } + ], + surroundingPairs: [ + { open: '[', close: ']' }, + { open: '<', close: '>' }, + { open: '(', close: ')' } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.pla', + + brackets: [ + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '<', close: '>', token: 'delimiter.angle' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' } + ], + + keywords: [ + '.i', + '.o', + '.mv', + '.ilb', + '.ob', + '.label', + '.type', + '.phase', + '.pair', + '.symbolic', + '.symbolic-output', + '.kiss', + '.p', + '.e', + '.end' + ], + + // regular expressions + comment: /#.*$/, + identifier: /[a-zA-Z]+[a-zA-Z0-9_\-]*/, + plaContent: /[01\-~\|]+/, + + // The main tokenizer for our languages + tokenizer: { + root: [ + // comments and whitespace + { include: '@whitespace' }, + [/@comment/, 'comment'], + + // keyword + [ + /\.([a-zA-Z_\-]+)/, + { + cases: { + '@eos': { token: 'keyword.$1' }, + '@keywords': { + cases: { + '.type': { token: 'keyword.$1', next: '@type' }, + '@default': { token: 'keyword.$1', next: '@keywordArg' } + } + }, + '@default': { token: 'keyword.$1' } + } + } + ], + + // identifiers + [/@identifier/, 'identifier'], + + // PLA row + [/@plaContent/, 'string'] + ], + + whitespace: [[/[ \t\r\n]+/, '']], + + type: [{ include: '@whitespace' }, [/\w+/, { token: 'type', next: '@pop' }]], + + keywordArg: [ + // whitespace + [ + /[ \t\r\n]+/, + { + cases: { + '@eos': { token: '', next: '@pop' }, + '@default': '' + } + } + ], + + // comments + [/@comment/, 'comment', '@pop'], + + // brackets + [ + /[<>()\[\]]/, + { + cases: { + '@eos': { token: '@brackets', next: '@pop' }, + '@default': '@brackets' + } + } + ], + + // numbers + [ + /\-?\d+/, + { + cases: { + '@eos': { token: 'number', next: '@pop' }, + '@default': 'number' + } + } + ], + + // identifiers + [ + /@identifier/, + { + cases: { + '@eos': { token: 'identifier', next: '@pop' }, + '@default': 'identifier' + } + } + ], + + // delimiter + [ + /[;=]/, + { + cases: { + '@eos': { token: 'delimiter', next: '@pop' }, + '@default': 'delimiter' + } + } + ] + ] + } +}; diff --git a/monaco-languages/src/postiats/postiats.contribution.ts b/monaco-languages/src/postiats/postiats.contribution.ts new file mode 100644 index 00000000..a57faf37 --- /dev/null +++ b/monaco-languages/src/postiats/postiats.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'postiats', + extensions: ['.dats', '.sats', '.hats'], + aliases: ['ATS', 'ATS/Postiats'], + loader: () => import('./postiats') +}); diff --git a/monaco-languages/src/postiats/postiats.test.ts b/monaco-languages/src/postiats/postiats.test.ts new file mode 100644 index 00000000..c8d41a55 --- /dev/null +++ b/monaco-languages/src/postiats/postiats.test.ts @@ -0,0 +1,1050 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Artyom Shalkhakov. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('postiats', [ + // Keywords + [ + { + line: 'implement main(argc, argv) =', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.pats' }, + { startIndex: 14, type: 'delimiter.parenthesis.pats' }, + { startIndex: 15, type: 'identifier.pats' }, + { startIndex: 19, type: 'delimiter.comma.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'identifier.pats' }, + { startIndex: 25, type: 'delimiter.parenthesis.pats' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'keyword.pats' } + ] + } + ], + + // Comments - single line + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + } + ], + + [ + { + line: ' // a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.pats' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + } + ], + + [ + { + line: '//sticky comment', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + } + ], + + [ + { + line: '/almost a comment', + tokens: [ + { startIndex: 0, type: 'operator.pats' }, + { startIndex: 1, type: 'identifier.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.pats' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.pats' } + ] + } + ], + + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.pats' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.decimal.pats' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'operator.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.decimal.pats' }, + { startIndex: 5, type: 'delimiter.semicolon.pats' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.pats' } + ] + } + ], + + [ + { + line: 'val x:int = 1; // my comment // is a nice one', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 5, type: 'keyword.pats' }, + { startIndex: 6, type: 'type.pats' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'keyword.pats' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'number.decimal.pats' }, + { startIndex: 13, type: 'delimiter.semicolon.pats' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'comment.pats' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '/* a simple comment */', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + } + ], + + [ + { + line: 'var x : int = /* a simple comment */ 1;', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'type.pats' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'keyword.pats' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'comment.pats' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'number.decimal.pats' }, + { startIndex: 38, type: 'delimiter.semicolon.pats' } + ] + } + ], + + [ + { + line: 'val x = /* comment */ 1; */', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.pats' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.decimal.pats' }, + { startIndex: 23, type: 'delimiter.semicolon.pats' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'operator.pats' } + ] + } + ], + + [ + { + line: 'x = /**/;', + tokens: [ + { startIndex: 0, type: 'identifier.pats' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.pats' }, + { startIndex: 8, type: 'delimiter.semicolon.pats' } + ] + } + ], + + [ + { + line: 'x = /*/;', + tokens: [ + { startIndex: 0, type: 'identifier.pats' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.pats' } + ] + } + ], + + // block comments, single line + [ + { + line: '(* a simple comment *)', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + } + ], + + [ + { + line: '(* a simple (* nested *) comment *)', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + } + ], + + [ + { + line: '(* ****** ****** *)', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + } + ], + + [ + { + line: 'var x : int = (* a simple comment *) 1;', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'type.pats' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'keyword.pats' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'comment.pats' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'number.decimal.pats' }, + { startIndex: 38, type: 'delimiter.semicolon.pats' } + ] + } + ], + + [ + { + line: 'val x = (* comment *) 1; *)', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'comment.pats' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'number.decimal.pats' }, + { startIndex: 23, type: 'delimiter.semicolon.pats' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'operator.pats' }, + { startIndex: 26, type: 'delimiter.parenthesis.pats' } + ] + } + ], + + [ + { + line: 'x = (**);', + tokens: [ + { startIndex: 0, type: 'identifier.pats' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.pats' }, + { startIndex: 8, type: 'delimiter.semicolon.pats' } + ] + } + ], + + [ + { + line: '(*)', + tokens: [ + { startIndex: 0, type: 'invalid.pats' } // not a comment! + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.decimal.pats' }] + } + ], + + [ + { + line: '12l', + tokens: [{ startIndex: 0, type: 'number.decimal.pats' }] + } + ], + + [ + { + line: '34U', + tokens: [{ startIndex: 0, type: 'number.decimal.pats' }] + } + ], + + [ + { + line: '55LL', + tokens: [{ startIndex: 0, type: 'number.decimal.pats' }] + } + ], + + [ + { + line: '34ul', + tokens: [{ startIndex: 0, type: 'number.decimal.pats' }] + } + ], + + [ + { + line: '55llU', + tokens: [{ startIndex: 0, type: 'number.decimal.pats' }] + } + ], + + /* + [{ + line: '5\'5llU', + tokens: [ + { startIndex: 0, type: 'number.pats' } + ]}], + + [{ + line: '100\'000\'000', + tokens: [ + { startIndex: 0, type: 'number.pats' } + ]}], + */ + [ + { + line: '0x100aafllU', + tokens: [{ startIndex: 0, type: 'number.hex.pats' }] + } + ], + + [ + { + line: '0342325', + tokens: [{ startIndex: 0, type: 'number.octal.pats' }] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.pats' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '23.5F', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '23.5f', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72E3F', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72E3f', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72e3F', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72e3f', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '23.5L', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '23.5l', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72E3L', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72E3l', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72e3L', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '1.72e3l', + tokens: [{ startIndex: 0, type: 'number.float.pats' }] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.decimal.pats' }, + { startIndex: 1, type: 'operator.pats' }, + { startIndex: 2, type: 'number.decimal.pats' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.decimal.pats' }, + { startIndex: 3, type: 'operator.pats' }, + { startIndex: 4, type: 'number.decimal.pats' } + ] + } + ], + + [ + { + line: '0 + 0', + tokens: [ + { startIndex: 0, type: 'number.decimal.pats' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'operator.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.decimal.pats' } + ] + } + ], + + // hi-lighting of variables in staload/dynload + [ + { + line: '"{$LIBATSCC2JS}/staloadall.hats"', + tokens: [ + { startIndex: 0, type: 'string.quote.pats' }, + { startIndex: 1, type: 'string.escape.pats' }, + { startIndex: 3, type: 'identifier.pats' }, + { startIndex: 14, type: 'string.escape.pats' }, + { startIndex: 15, type: 'string.pats' }, + { startIndex: 31, type: 'string.quote.pats' } + ] + } + ], + + // Monarch Generated + [ + { + line: '#include "/path/to/my/file.h"', + tokens: [ + { startIndex: 0, type: 'keyword.srp.pats' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'string.quote.pats' }, + { startIndex: 10, type: 'string.pats' }, + { startIndex: 28, type: 'string.quote.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '#ifdef VAR #then', + tokens: [ + { startIndex: 0, type: 'keyword.srp.pats' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'identifier.pats' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.srp.pats' } + ] + }, + { + line: '#define SUM(A,B) (A) + (B)', + tokens: [ + { startIndex: 0, type: 'keyword.srp.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.pats' }, + { startIndex: 11, type: 'delimiter.parenthesis.pats' }, + { startIndex: 12, type: 'identifier.pats' }, + { startIndex: 13, type: 'delimiter.comma.pats' }, + { startIndex: 14, type: 'identifier.pats' }, + { startIndex: 15, type: 'delimiter.parenthesis.pats' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.parenthesis.pats' }, + { startIndex: 18, type: 'identifier.pats' }, + { startIndex: 19, type: 'delimiter.parenthesis.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'operator.pats' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.parenthesis.pats' }, + { startIndex: 24, type: 'identifier.pats' }, + { startIndex: 25, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: 'staload Asdf_CDE = "./myfile.sats"', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.pats' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'keyword.pats' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'string.quote.pats' }, + { startIndex: 20, type: 'string.pats' }, + { startIndex: 33, type: 'string.quote.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'implement main(argc, argv)', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.pats' }, + { startIndex: 14, type: 'delimiter.parenthesis.pats' }, + { startIndex: 15, type: 'identifier.pats' }, + { startIndex: 19, type: 'delimiter.comma.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'identifier.pats' }, + { startIndex: 25, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: ' = begin', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.pats' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'keyword.pats' } + ] + }, + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.decimal.pats' }] + }, + { + line: 'end', + tokens: [{ startIndex: 0, type: 'keyword.pats' }] + }, + { + line: '', + tokens: [] + }, + { + line: '', + tokens: [] + }, + { + line: 'dataprop FACT (int, int) =', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'identifier.pats' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'delimiter.parenthesis.pats' }, + { startIndex: 15, type: 'type.pats' }, + { startIndex: 18, type: 'delimiter.comma.pats' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'type.pats' }, + { startIndex: 23, type: 'delimiter.parenthesis.pats' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'keyword.pats' } + ] + }, + { + line: ' | FACTbas (0, 1) of ()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.pats' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'identifier.pats' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.parenthesis.pats' }, + { startIndex: 12, type: 'number.decimal.pats' }, + { startIndex: 13, type: 'delimiter.comma.pats' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'number.decimal.pats' }, + { startIndex: 16, type: 'delimiter.parenthesis.pats' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'keyword.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: ' | {n:pos}{r:int} FACTind (n, n*r) of FACT (n-1, r)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.pats' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.curly.pats' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 5, type: 'keyword.pats' }, + { startIndex: 6, type: 'identifier.pats' }, + { startIndex: 9, type: 'delimiter.parenthesis.pats' }, + { startIndex: 10, type: 'delimiter.curly.pats' }, + { startIndex: 11, type: 'identifier.pats' }, + { startIndex: 12, type: 'keyword.pats' }, + { startIndex: 13, type: 'type.pats' }, + { startIndex: 16, type: 'delimiter.parenthesis.pats' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'identifier.pats' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'delimiter.parenthesis.pats' }, + { startIndex: 27, type: 'identifier.pats' }, + { startIndex: 28, type: 'delimiter.comma.pats' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'identifier.pats' }, + { startIndex: 31, type: 'operator.pats' }, + { startIndex: 32, type: 'identifier.pats' }, + { startIndex: 33, type: 'delimiter.parenthesis.pats' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'keyword.pats' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'identifier.pats' }, + { startIndex: 42, type: '' }, + { startIndex: 43, type: 'delimiter.parenthesis.pats' }, + { startIndex: 44, type: 'identifier.pats' }, + { startIndex: 45, type: 'operator.pats' }, + { startIndex: 46, type: 'number.decimal.pats' }, + { startIndex: 47, type: 'delimiter.comma.pats' }, + { startIndex: 48, type: '' }, + { startIndex: 49, type: 'identifier.pats' }, + { startIndex: 50, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'fun fact {n:nat} .. (x: int n) : [r:int] (FACT(n, r) | int(r)) = (', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.curly.pats' }, + { startIndex: 10, type: 'identifier.pats' }, + { startIndex: 11, type: 'keyword.pats' }, + { startIndex: 12, type: 'identifier.pats' }, + { startIndex: 15, type: 'delimiter.parenthesis.pats' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'identifier.sym.pats' }, + { startIndex: 19, type: 'identifier.pats' }, + { startIndex: 20, type: 'keyword.pats' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.parenthesis.pats' }, + { startIndex: 24, type: 'identifier.pats' }, + { startIndex: 25, type: 'keyword.pats' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'type.pats' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'identifier.pats' }, + { startIndex: 32, type: 'delimiter.parenthesis.pats' }, + { startIndex: 33, type: '' }, + { startIndex: 34, type: 'keyword.pats' }, + { startIndex: 35, type: '' }, + { startIndex: 36, type: 'delimiter.square.pats' }, + { startIndex: 37, type: 'identifier.pats' }, + { startIndex: 38, type: 'keyword.pats' }, + { startIndex: 39, type: 'type.pats' }, + { startIndex: 42, type: 'delimiter.square.pats' }, + { startIndex: 43, type: '' }, + { startIndex: 44, type: 'delimiter.parenthesis.pats' }, + { startIndex: 45, type: 'identifier.pats' }, + { startIndex: 49, type: 'delimiter.parenthesis.pats' }, + { startIndex: 50, type: 'identifier.pats' }, + { startIndex: 51, type: 'delimiter.comma.pats' }, + { startIndex: 52, type: '' }, + { startIndex: 53, type: 'identifier.pats' }, + { startIndex: 54, type: 'delimiter.parenthesis.pats' }, + { startIndex: 55, type: '' }, + { startIndex: 56, type: 'keyword.pats' }, + { startIndex: 57, type: '' }, + { startIndex: 58, type: 'type.pats' }, + { startIndex: 61, type: 'delimiter.parenthesis.pats' }, + { startIndex: 62, type: 'identifier.pats' }, + { startIndex: 63, type: 'delimiter.parenthesis.pats' }, + { startIndex: 65, type: '' }, + { startIndex: 66, type: 'keyword.pats' }, + { startIndex: 67, type: '' }, + { startIndex: 68, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: 'if x > 0 then let', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'identifier.pats' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'keyword.pats' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.decimal.pats' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'keyword.pats' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.pats' } + ] + }, + { + line: ' val [r1:int] (pf1 | r1) = fact (x-1)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.pats' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.square.pats' }, + { startIndex: 7, type: 'identifier.pats' }, + { startIndex: 9, type: 'keyword.pats' }, + { startIndex: 10, type: 'type.pats' }, + { startIndex: 13, type: 'delimiter.square.pats' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.parenthesis.pats' }, + { startIndex: 16, type: 'identifier.pats' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'keyword.pats' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'identifier.pats' }, + { startIndex: 24, type: 'delimiter.parenthesis.pats' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'keyword.pats' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'identifier.pats' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'delimiter.parenthesis.pats' }, + { startIndex: 34, type: 'identifier.pats' }, + { startIndex: 35, type: 'operator.pats' }, + { startIndex: 36, type: 'number.decimal.pats' }, + { startIndex: 37, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: ' prval pf = FACTind {n}{r1} (pf1)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.pats' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.pats' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'identifier.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.curly.pats' }, + { startIndex: 22, type: 'identifier.pats' }, + { startIndex: 23, type: 'delimiter.parenthesis.pats' }, + { startIndex: 24, type: 'delimiter.curly.pats' }, + { startIndex: 25, type: 'identifier.pats' }, + { startIndex: 27, type: 'delimiter.parenthesis.pats' }, + { startIndex: 28, type: '' }, + { startIndex: 29, type: 'delimiter.parenthesis.pats' }, + { startIndex: 30, type: 'identifier.pats' }, + { startIndex: 33, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: ' val r = x * r1', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.pats' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'identifier.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'keyword.pats' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'identifier.pats' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'operator.pats' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'identifier.pats' } + ] + }, + { + line: 'in', + tokens: [{ startIndex: 0, type: 'keyword.pats' }] + }, + { + line: ' (pf | r)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.parenthesis.pats' }, + { startIndex: 3, type: 'identifier.pats' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'keyword.pats' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.pats' }, + { startIndex: 9, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: 'end // end of [then]', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.pats' } + ] + }, + { + line: 'else (FACTbas () | 1)', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.parenthesis.pats' }, + { startIndex: 6, type: 'identifier.pats' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'delimiter.parenthesis.pats' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'keyword.pats' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'number.decimal.pats' }, + { startIndex: 20, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: ') (* end of [fact] *)', + tokens: [ + { startIndex: 0, type: 'delimiter.parenthesis.pats' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'comment.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'local', + tokens: [{ startIndex: 0, type: 'keyword.pats' }] + }, + { + line: 'var __count: int = 0 // it is statically allocated', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 11, type: 'keyword.pats' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'type.pats' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'keyword.pats' }, + { startIndex: 18, type: '' }, + { startIndex: 19, type: 'number.decimal.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'comment.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'val theCount =', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'keyword.pats' } + ] + }, + { + line: ' ref_make_viewptr{int}(view@(__count) | addr@(__count))', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'identifier.pats' }, + { startIndex: 18, type: 'delimiter.curly.pats' }, + { startIndex: 19, type: 'type.pats' }, + { startIndex: 22, type: 'delimiter.parenthesis.pats' }, + { startIndex: 24, type: 'keyword.pats' }, + { startIndex: 29, type: 'delimiter.parenthesis.pats' }, + { startIndex: 30, type: 'identifier.pats' }, + { startIndex: 37, type: 'delimiter.parenthesis.pats' }, + { startIndex: 38, type: '' }, + { startIndex: 39, type: 'keyword.pats' }, + { startIndex: 40, type: '' }, + { startIndex: 41, type: 'keyword.pats' }, + { startIndex: 46, type: 'delimiter.parenthesis.pats' }, + { startIndex: 47, type: 'identifier.pats' }, + { startIndex: 54, type: 'delimiter.parenthesis.pats' } + ] + }, + { + line: '// end of [val]', + tokens: [{ startIndex: 0, type: 'comment.pats' }] + }, + { + line: '', + tokens: [] + }, + { + line: 'in (* in of [local] *)', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'comment.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'fun theCount_get (): int = !theCount', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.parenthesis.pats' }, + { startIndex: 19, type: 'keyword.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'type.pats' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'keyword.pats' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'keyword.pats' }, + { startIndex: 28, type: 'identifier.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'fun theCount_inc (): void = !theCount := !theCount + 1', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.pats' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'delimiter.parenthesis.pats' }, + { startIndex: 19, type: 'keyword.pats' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'type.pats' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'keyword.pats' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'keyword.pats' }, + { startIndex: 29, type: 'identifier.pats' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'operator.pats' }, + { startIndex: 40, type: '' }, + { startIndex: 41, type: 'keyword.pats' }, + { startIndex: 42, type: 'identifier.pats' }, + { startIndex: 50, type: '' }, + { startIndex: 51, type: 'operator.pats' }, + { startIndex: 52, type: '' }, + { startIndex: 53, type: 'number.decimal.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: 'end // end of [local]', + tokens: [ + { startIndex: 0, type: 'keyword.pats' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'comment.pats' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '#endif', + tokens: [{ startIndex: 0, type: 'keyword.srp.pats' }] + } + ] +]); diff --git a/monaco-languages/src/postiats/postiats.ts b/monaco-languages/src/postiats/postiats.ts new file mode 100644 index 00000000..89d8dc66 --- /dev/null +++ b/monaco-languages/src/postiats/postiats.ts @@ -0,0 +1,752 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Artyom Shalkhakov. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * + * Based on the ATS/Postiats lexer by Hongwei Xi. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['(*', '*)'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'], + ['<', '>'] + ], + autoClosingPairs: [ + { open: '"', close: '"', notIn: ['string', 'comment'] }, + { open: '{', close: '}', notIn: ['string', 'comment'] }, + { open: '[', close: ']', notIn: ['string', 'comment'] }, + { open: '(', close: ')', notIn: ['string', 'comment'] } + ] +}; + +export const language = { + tokenPostfix: '.pats', + + // TODO: staload and dynload are followed by a special kind of string literals + // with {$IDENTIFER} variables, and it also may make sense to highlight + // the punctuation (. and / and \) differently. + + // Set defaultToken to invalid to see what you do not tokenize yet + defaultToken: 'invalid', + + // keyword reference: https://github.com/githwxi/ATS-Postiats/blob/master/src/pats_lexing_token.dats + + keywords: [ + // + 'abstype', // ABSTYPE + 'abst0ype', // ABST0YPE + 'absprop', // ABSPROP + 'absview', // ABSVIEW + 'absvtype', // ABSVIEWTYPE + 'absviewtype', // ABSVIEWTYPE + 'absvt0ype', // ABSVIEWT0YPE + 'absviewt0ype', // ABSVIEWT0YPE + // + 'as', // T_AS + // + 'and', // T_AND + // + 'assume', // T_ASSUME + // + 'begin', // T_BEGIN + // + /* + "case", // CASE + */ + // + 'classdec', // T_CLASSDEC + // + 'datasort', // T_DATASORT + // + 'datatype', // DATATYPE + 'dataprop', // DATAPROP + 'dataview', // DATAVIEW + 'datavtype', // DATAVIEWTYPE + 'dataviewtype', // DATAVIEWTYPE + // + 'do', // T_DO + // + 'end', // T_END + // + 'extern', // T_EXTERN + 'extype', // T_EXTYPE + 'extvar', // T_EXTVAR + // + 'exception', // T_EXCEPTION + // + 'fn', // FN // non-recursive + 'fnx', // FNX // mutual tail-rec. + 'fun', // FUN // general-recursive + // + 'prfn', // PRFN + 'prfun', // PRFUN + // + 'praxi', // PRAXI + 'castfn', // CASTFN + // + 'if', // T_IF + 'then', // T_THEN + 'else', // T_ELSE + // + 'ifcase', // T_IFCASE + // + 'in', // T_IN + // + 'infix', // INFIX + 'infixl', // INFIXL + 'infixr', // INFIXR + 'prefix', // PREFIX + 'postfix', // POSTFIX + // + 'implmnt', // IMPLMNT // 0 + 'implement', // IMPLEMENT // 1 + // + 'primplmnt', // PRIMPLMNT // ~1 + 'primplement', // PRIMPLMNT // ~1 + // + 'import', // T_IMPORT // for importing packages + // + /* + "lam", // LAM + "llam", // LLAM + "fix", // FIX + */ + // + 'let', // T_LET + // + 'local', // T_LOCAL + // + 'macdef', // MACDEF + 'macrodef', // MACRODEF + // + 'nonfix', // T_NONFIX + // + 'symelim', // T_SYMELIM + 'symintr', // T_SYMINTR + 'overload', // T_OVERLOAD + // + 'of', // T_OF + 'op', // T_OP + // + 'rec', // T_REC + // + 'sif', // T_SIF + 'scase', // T_SCASE + // + 'sortdef', // T_SORTDEF + /* + // HX: [sta] is now deprecated + */ + 'sta', // T_STACST + 'stacst', // T_STACST + 'stadef', // T_STADEF + 'static', // T_STATIC + /* + "stavar", // T_STAVAR + */ + // + 'staload', // T_STALOAD + 'dynload', // T_DYNLOAD + // + 'try', // T_TRY + // + 'tkindef', // T_TKINDEF // HX-2012-05-23 + // + /* + "type", // TYPE + */ + 'typedef', // TYPEDEF + 'propdef', // PROPDEF + 'viewdef', // VIEWDEF + 'vtypedef', // VIEWTYPEDEF + 'viewtypedef', // VIEWTYPEDEF + // + /* + "val", // VAL + */ + 'prval', // PRVAL + // + 'var', // VAR + 'prvar', // PRVAR + // + 'when', // T_WHEN + 'where', // T_WHERE + // + /* + "for", // T_FOR + "while", // T_WHILE + */ + // + 'with', // T_WITH + // + 'withtype', // WITHTYPE + 'withprop', // WITHPROP + 'withview', // WITHVIEW + 'withvtype', // WITHVIEWTYPE + 'withviewtype' // WITHVIEWTYPE + // + ], + keywords_dlr: [ + '$delay', // DLRDELAY + '$ldelay', // DLRLDELAY + // + '$arrpsz', // T_DLRARRPSZ + '$arrptrsize', // T_DLRARRPSZ + // + '$d2ctype', // T_DLRD2CTYPE + // + '$effmask', // DLREFFMASK + '$effmask_ntm', // DLREFFMASK_NTM + '$effmask_exn', // DLREFFMASK_EXN + '$effmask_ref', // DLREFFMASK_REF + '$effmask_wrt', // DLREFFMASK_WRT + '$effmask_all', // DLREFFMASK_ALL + // + '$extern', // T_DLREXTERN + '$extkind', // T_DLREXTKIND + '$extype', // T_DLREXTYPE + '$extype_struct', // T_DLREXTYPE_STRUCT + // + '$extval', // T_DLREXTVAL + '$extfcall', // T_DLREXTFCALL + '$extmcall', // T_DLREXTMCALL + // + '$literal', // T_DLRLITERAL + // + '$myfilename', // T_DLRMYFILENAME + '$mylocation', // T_DLRMYLOCATION + '$myfunction', // T_DLRMYFUNCTION + // + '$lst', // DLRLST + '$lst_t', // DLRLST_T + '$lst_vt', // DLRLST_VT + '$list', // DLRLST + '$list_t', // DLRLST_T + '$list_vt', // DLRLST_VT + // + '$rec', // DLRREC + '$rec_t', // DLRREC_T + '$rec_vt', // DLRREC_VT + '$record', // DLRREC + '$record_t', // DLRREC_T + '$record_vt', // DLRREC_VT + // + '$tup', // DLRTUP + '$tup_t', // DLRTUP_T + '$tup_vt', // DLRTUP_VT + '$tuple', // DLRTUP + '$tuple_t', // DLRTUP_T + '$tuple_vt', // DLRTUP_VT + // + '$break', // T_DLRBREAK + '$continue', // T_DLRCONTINUE + // + '$raise', // T_DLRRAISE + // + '$showtype', // T_DLRSHOWTYPE + // + '$vcopyenv_v', // DLRVCOPYENV_V + '$vcopyenv_vt', // DLRVCOPYENV_VT + // + '$tempenver', // T_DLRTEMPENVER + // + '$solver_assert', // T_DLRSOLASSERT + '$solver_verify' // T_DLRSOLVERIFY + ], + keywords_srp: [ + // + '#if', // T_SRPIF + '#ifdef', // T_SRPIFDEF + '#ifndef', // T_SRPIFNDEF + // + '#then', // T_SRPTHEN + // + '#elif', // T_SRPELIF + '#elifdef', // T_SRPELIFDEF + '#elifndef', // T_SRPELIFNDEF + // + '#else', // T_SRPELSE + '#endif', // T_SRPENDIF + // + '#error', // T_SRPERROR + // + '#prerr', // T_SRPPRERR // outpui to stderr + '#print', // T_SRPPRINT // output to stdout + // + '#assert', // T_SRPASSERT + // + '#undef', // T_SRPUNDEF + '#define', // T_SRPDEFINE + // + '#include', // T_SRPINCLUDE + '#require', // T_SRPREQUIRE + // + '#pragma', // T_SRPPRAGMA // HX: general pragma + '#codegen2', // T_SRPCODEGEN2 // for level-2 codegen + '#codegen3' // T_SRPCODEGEN3 // for level-3 codegen + // + // HX: end of special tokens + // + ], + + irregular_keyword_list: [ + 'val+', + 'val-', + 'val', + 'case+', + 'case-', + 'case', + 'addr@', + 'addr', + 'fold@', + 'free@', + 'fix@', + 'fix', + 'lam@', + 'lam', + 'llam@', + 'llam', + 'viewt@ype+', + 'viewt@ype-', + 'viewt@ype', + 'viewtype+', + 'viewtype-', + 'viewtype', + 'view+', + 'view-', + 'view@', + 'view', + 'type+', + 'type-', + 'type', + 'vtype+', + 'vtype-', + 'vtype', + 'vt@ype+', + 'vt@ype-', + 'vt@ype', + 'viewt@ype+', + 'viewt@ype-', + 'viewt@ype', + 'viewtype+', + 'viewtype-', + 'viewtype', + 'prop+', + 'prop-', + 'prop', + 'type+', + 'type-', + 'type', + 't@ype', + 't@ype+', + 't@ype-', + 'abst@ype', + 'abstype', + 'absviewt@ype', + 'absvt@ype', + 'for*', + 'for', + 'while*', + 'while' + ], + + keywords_types: [ + 'bool', + 'double', + 'byte', + 'int', + 'short', + 'char', + 'void', + 'unit', + 'long', + 'float', + 'string', + 'strptr' + ], + + // TODO: reference for this? + keywords_effects: [ + '0', // no effects + 'fun', + 'clo', + 'prf', + 'funclo', + 'cloptr', + 'cloref', + 'ref', + 'ntm', + '1' // all effects + ], + + operators: [ + '@', // T_AT + '!', // T_BANG + '|', // T_BAR + '`', // T_BQUOTE + ':', // T_COLON + '$', // T_DOLLAR + '.', // T_DOT + '=', // T_EQ + '#', // T_HASH + '~', // T_TILDE + // + '..', // T_DOTDOT + '...', // T_DOTDOTDOT + // + '=>', // T_EQGT + // "=<", // T_EQLT + '=<>', // T_EQLTGT + '=/=>', // T_EQSLASHEQGT + '=>>', // T_EQGTGT + '=/=>>', // T_EQSLASHEQGTGT + // + '<', // T_LT // opening a tmparg + '>', // T_GT // closing a tmparg + // + '><', // T_GTLT + // + '.<', // T_DOTLT + '>.', // T_GTDOT + // + '.<>.', // T_DOTLTGTDOT + // + '->', // T_MINUSGT + //"-<", // T_MINUSLT + '-<>' // T_MINUSLTGT + // + /* + ":<", // T_COLONLT + */ + ], + + brackets: [ + { open: ',(', close: ')', token: 'delimiter.parenthesis' }, // meta-programming syntax + { open: '`(', close: ')', token: 'delimiter.parenthesis' }, + { open: '%(', close: ')', token: 'delimiter.parenthesis' }, + { open: "'(", close: ')', token: 'delimiter.parenthesis' }, + { open: "'{", close: '}', token: 'delimiter.parenthesis' }, + { open: '@(', close: ')', token: 'delimiter.parenthesis' }, + { open: '@{', close: '}', token: 'delimiter.brace' }, + { open: '@[', close: ']', token: 'delimiter.square' }, + { open: '#[', close: ']', token: 'delimiter.square' }, + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + // we include these common regular expressions + symbols: /[=>]/, + digit: /[0-9]/, + digitseq0: /@digit*/, + xdigit: /[0-9A-Za-z]/, + xdigitseq0: /@xdigit*/, + INTSP: /[lLuU]/, + FLOATSP: /[fFlL]/, + fexponent: /[eE][+-]?[0-9]+/, + fexponent_bin: /[pP][+-]?[0-9]+/, + deciexp: /\.[0-9]*@fexponent?/, + hexiexp: /\.[0-9a-zA-Z]*@fexponent_bin?/, + irregular_keywords: + /val[+-]?|case[+-]?|addr\@?|fold\@|free\@|fix\@?|lam\@?|llam\@?|prop[+-]?|type[+-]?|view[+-@]?|viewt@?ype[+-]?|t@?ype[+-]?|v(iew)?t@?ype[+-]?|abst@?ype|absv(iew)?t@?ype|for\*?|while\*?/, + ESCHAR: /[ntvbrfa\\\?'"\(\[\{]/, + + start: 'root', + + // The main tokenizer for ATS/Postiats + // reference: https://github.com/githwxi/ATS-Postiats/blob/master/src/pats_lexing.dats + tokenizer: { + root: [ + // lexing_blankseq0 + { regex: /[ \t\r\n]+/, action: { token: '' } }, + + // NOTE: (*) is an invalid ML-like comment! + { regex: /\(\*\)/, action: { token: 'invalid' } }, + { + regex: /\(\*/, + action: { token: 'comment', next: 'lexing_COMMENT_block_ml' } + }, + { + regex: /\(/, + action: '@brackets' /*{ token: 'delimiter.parenthesis' }*/ + }, + { + regex: /\)/, + action: '@brackets' /*{ token: 'delimiter.parenthesis' }*/ + }, + { + regex: /\[/, + action: '@brackets' /*{ token: 'delimiter.bracket' }*/ + }, + { + regex: /\]/, + action: '@brackets' /*{ token: 'delimiter.bracket' }*/ + }, + { + regex: /\{/, + action: '@brackets' /*{ token: 'delimiter.brace' }*/ + }, + { + regex: /\}/, + action: '@brackets' /*{ token: 'delimiter.brace' }*/ + }, + + // lexing_COMMA + { + regex: /,\(/, + action: '@brackets' /*{ token: 'delimiter.parenthesis' }*/ + }, // meta-programming syntax + { regex: /,/, action: { token: 'delimiter.comma' } }, + + { regex: /;/, action: { token: 'delimiter.semicolon' } }, + + // lexing_AT + { + regex: /@\(/, + action: '@brackets' /* { token: 'delimiter.parenthesis' }*/ + }, + { + regex: /@\[/, + action: '@brackets' /* { token: 'delimiter.bracket' }*/ + }, + { + regex: /@\{/, + action: '@brackets' /*{ token: 'delimiter.brace' }*/ + }, + + // lexing_COLON + { + regex: /: lexing_IDENT_sym + . FLOATDOT => lexing_FLOAT_deciexp + . DIGIT => T_DOTINT + */ + { regex: /\.@symbolic+/, action: { token: 'identifier.sym' } }, + // FLOATDOT case + { + regex: /\.@digit*@fexponent@FLOATSP*/, + action: { token: 'number.float' } + }, + { regex: /\.@digit+/, action: { token: 'number.float' } }, // T_DOTINT + + // lexing_DOLLAR: + // '$' IDENTFST IDENTRST* => lexing_IDENT_dlr, _ => lexing_IDENT_sym + { + regex: /\$@IDENTFST@IDENTRST*/, + action: { + cases: { + '@keywords_dlr': { token: 'keyword.dlr' }, + '@default': { token: 'namespace' } // most likely a module qualifier + } + } + }, + // lexing_SHARP: + // '#' IDENTFST IDENTRST* => lexing_ident_srp, _ => lexing_IDENT_sym + { + regex: /\#@IDENTFST@IDENTRST*/, + action: { + cases: { + '@keywords_srp': { token: 'keyword.srp' }, + '@default': { token: 'identifier' } + } + } + }, + + // lexing_PERCENT: + { regex: /%\(/, action: { token: 'delimiter.parenthesis' } }, + { + regex: /^%{(#|\^|\$)?/, + action: { + token: 'keyword', + next: '@lexing_EXTCODE', + nextEmbedded: 'text/javascript' + } + }, + { regex: /^%}/, action: { token: 'keyword' } }, + + // lexing_QUOTE + { regex: /'\(/, action: { token: 'delimiter.parenthesis' } }, + { regex: /'\[/, action: { token: 'delimiter.bracket' } }, + { regex: /'\{/, action: { token: 'delimiter.brace' } }, + [/(')(\\@ESCHAR|\\[xX]@xdigit+|\\@digit+)(')/, ['string', 'string.escape', 'string']], + [/'[^\\']'/, 'string'], + + // lexing_DQUOTE + [/"/, 'string.quote', '@lexing_DQUOTE'], + + // lexing_BQUOTE + { + regex: /`\(/, + action: '@brackets' /* { token: 'delimiter.parenthesis' }*/ + }, + // TODO: otherwise, try lexing_IDENT_sym + + { regex: /\\/, action: { token: 'punctuation' } }, // just T_BACKSLASH + + // lexing_IDENT_alp: + // NOTE: (?!regex) is syntax for "not-followed-by" regex + // to resolve ambiguity such as foreach$fwork being incorrectly lexed as [for] [each$fwork]! + { + regex: /@irregular_keywords(?!@IDENTRST)/, + action: { token: 'keyword' } + }, + { + regex: /@IDENTFST@IDENTRST*[ punctuation + // ({\$)([a-zA-Z_][a-zA-Z_0-9]*)(}) => punctuation,keyword,punctuation + // [^"] => identifier/literal + '@keywords': { token: 'keyword' }, + '@keywords_types': { token: 'type' }, + '@default': { token: 'identifier' } + } + } + }, + // lexing_IDENT_sym: + { + regex: /\/\/\/\//, + action: { token: 'comment', next: '@lexing_COMMENT_rest' } + }, + { regex: /\/\/.*$/, action: { token: 'comment' } }, + { + regex: /\/\*/, + action: { token: 'comment', next: '@lexing_COMMENT_block_c' } + }, + // AS-20160627: specifically for effect annotations + { + regex: /-<|= lexing_FLOAT_hexiexp + // - testing_fexponent_bin => lexing_FLOAT_hexiexp + // - testing_intspseq0 => T_INT_hex + + // lexing_INT_hex: + { + regex: /0[xX]@xdigit+(@hexiexp|@fexponent_bin)@FLOATSP*/, + action: { token: 'number.float' } + }, + { regex: /0[xX]@xdigit+@INTSP*/, action: { token: 'number.hex' } }, + { + regex: /0[0-7]+(?![0-9])@INTSP*/, + action: { token: 'number.octal' } + }, // lexing_INT_oct + //{regex: /0/, action: { token: 'number' } }, // INTZERO + + // lexing_INT_dec: + // - testing_deciexp => lexing_FLOAT_deciexp + // - testing_fexponent => lexing_FLOAT_deciexp + // - otherwise => intspseq0 ([0-9]*[lLuU]?) + { + regex: /@digit+(@fexponent|@deciexp)@FLOATSP*/, + action: { token: 'number.float' } + }, + { + regex: /@digit@digitseq0@INTSP*/, + action: { token: 'number.decimal' } + }, + // DIGIT, if followed by digitseq0, is lexing_INT_dec + { regex: /@digit+@INTSP*/, action: { token: 'number' } } + ], + + lexing_COMMENT_block_ml: [ + [/[^\(\*]+/, 'comment'], + [/\(\*/, 'comment', '@push'], + [/\(\*/, 'comment.invalid'], + [/\*\)/, 'comment', '@pop'], + [/\*/, 'comment'] + ], + lexing_COMMENT_block_c: [ + [/[^\/*]+/, 'comment'], + // [/\/\*/, 'comment', '@push' ], // nested C-style block comments not allowed + // [/\/\*/, 'comment.invalid' ], // NOTE: this breaks block comments in the shape of /* //*/ + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + lexing_COMMENT_rest: [ + [/$/, 'comment', '@pop'], // FIXME: does it match? docs say 'no' + [/.*/, 'comment'] + ], + + // NOTE: added by AS, specifically for highlighting + lexing_EFFECT_commaseq0: [ + { + regex: /@IDENTFST@IDENTRST+|@digit+/, + action: { + cases: { + '@keywords_effects': { token: 'type.effect' }, + '@default': { token: 'identifier' } + } + } + }, + { regex: /,/, action: { token: 'punctuation' } }, + { regex: />/, action: { token: '@rematch', next: '@pop' } } + ], + + lexing_EXTCODE: [ + { + regex: /^%}/, + action: { + token: '@rematch', + next: '@pop', + nextEmbedded: '@pop' + } + }, + { regex: /[^%]+/, action: '' } + ], + + lexing_DQUOTE: [ + { regex: /"/, action: { token: 'string.quote', next: '@pop' } }, + // AS-20160628: additional hi-lighting for variables in staload/dynload strings + { + regex: /(\{\$)(@IDENTFST@IDENTRST*)(\})/, + action: [ + { token: 'string.escape' }, + { token: 'identifier' }, + { token: 'string.escape' } + ] + }, + { regex: /\\$/, action: { token: 'string.escape' } }, + { + regex: /\\(@ESCHAR|[xX]@xdigit+|@digit+)/, + action: { token: 'string.escape' } + }, + { regex: /[^\\"]+/, action: { token: 'string' } } + ] + } +}; diff --git a/monaco-languages/src/powerquery/powerquery.contribution.ts b/monaco-languages/src/powerquery/powerquery.contribution.ts new file mode 100644 index 00000000..2c2b84a5 --- /dev/null +++ b/monaco-languages/src/powerquery/powerquery.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'powerquery', + extensions: ['.pq', '.pqm'], + aliases: ['PQ', 'M', 'Power Query', 'Power Query M'], + loader: () => import('./powerquery') +}); diff --git a/monaco-languages/src/powerquery/powerquery.test.ts b/monaco-languages/src/powerquery/powerquery.test.ts new file mode 100644 index 00000000..9066966e --- /dev/null +++ b/monaco-languages/src/powerquery/powerquery.test.ts @@ -0,0 +1,416 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('powerquery', [ + // Comments + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.pq' }] + } + ], + + [ + { + line: ' // a comment */', + tokens: [ + { startIndex: 0, type: 'white.pq' }, + { startIndex: 4, type: 'comment.pq' } + ] + } + ], + + [ + { + line: '// a comment', + tokens: [{ startIndex: 0, type: 'comment.pq' }] + } + ], + + [ + { + line: '// /* #A */', + tokens: [{ startIndex: 0, type: 'comment.pq' }] + } + ], + + [ + { + line: '/*ABCD12$!()\\u000D%%%%%*/', + tokens: [{ startIndex: 0, type: 'comment.pq' }] + } + ], + + [ + { + line: '42 /* + 45 */ /*', + tokens: [ + { startIndex: 0, type: 'number.pq' }, + { startIndex: 2, type: 'white.pq' }, + { startIndex: 3, type: 'comment.pq' }, + { startIndex: 13, type: 'white.pq' }, + { startIndex: 14, type: 'comment.pq' } + ] + } + ], + + [ + { + line: '/* //*/ a', + tokens: [ + { startIndex: 0, type: 'comment.pq' }, + { startIndex: 7, type: 'white.pq' }, + { startIndex: 8, type: 'identifier.pq' } + ] + } + ], + + [ + { + line: '1 / 2; /* comment', + tokens: [ + { startIndex: 0, type: 'number.pq' }, + { startIndex: 1, type: 'white.pq' }, + { startIndex: 2, type: 'operators.pq' }, + { startIndex: 3, type: 'white.pq' }, + { startIndex: 4, type: 'number.pq' }, + { startIndex: 5, type: 'delimiter.pq' }, + { startIndex: 6, type: 'white.pq' }, + { startIndex: 7, type: 'comment.pq' } + ] + } + ], + + // Quoted Identifiers + [ + { + line: '#"Change Types"', + tokens: [{ startIndex: 0, type: 'identifier.quote.pq' }] + } + ], + + [ + { + line: '#"A B" = 1+2,', + tokens: [ + { startIndex: 0, type: 'identifier.quote.pq' }, + { startIndex: 7, type: 'white.pq' }, + { startIndex: 8, type: 'operators.pq' }, + { startIndex: 9, type: 'white.pq' }, + { startIndex: 10, type: 'number.pq' }, + { startIndex: 11, type: 'operators.pq' }, + { startIndex: 12, type: 'number.pq' }, + { startIndex: 13, type: 'delimiter.pq' } + ] + } + ], + + [ + { + line: 'a = #"escap ed"+ 1', + tokens: [ + { startIndex: 0, type: 'identifier.pq' }, + { startIndex: 1, type: 'white.pq' }, + { startIndex: 2, type: 'operators.pq' }, + { startIndex: 3, type: 'white.pq' }, + { startIndex: 4, type: 'identifier.quote.pq' }, + { startIndex: 15, type: 'operators.pq' }, + { startIndex: 16, type: 'white.pq' }, + { startIndex: 17, type: 'number.pq' } + ] + } + ], + + // Number formats + [ + { + line: '0Xabc', + tokens: [{ startIndex: 0, type: 'number.hex.pq' }] + } + ], + + [ + { + line: '0xA', + tokens: [{ startIndex: 0, type: 'number.hex.pq' }] + } + ], + + [ + { + line: '1e1', + tokens: [{ startIndex: 0, type: 'number.pq' }] + } + ], + + [ + { + line: '5 / 1.2e+2 + 0x1234abc', + tokens: [ + { startIndex: 0, type: 'number.pq' }, + { startIndex: 1, type: 'white.pq' }, + { startIndex: 2, type: 'operators.pq' }, + { startIndex: 3, type: 'white.pq' }, + { startIndex: 4, type: 'number.float.pq' }, + { startIndex: 10, type: 'white.pq' }, + { startIndex: 11, type: 'operators.pq' }, + { startIndex: 12, type: 'white.pq' }, + { startIndex: 13, type: 'number.hex.pq' } + ] + } + ], + + [ + { + line: '0xb *(.2)', + tokens: [ + { startIndex: 0, type: 'number.hex.pq' }, + { startIndex: 3, type: 'white.pq' }, + { startIndex: 4, type: 'operators.pq' }, + { startIndex: 5, type: 'delimiter.parenthesis.pq' }, + { startIndex: 6, type: 'number.float.pq' }, + { startIndex: 8, type: 'delimiter.parenthesis.pq' } + ] + } + ], + + [ + { + line: '1.23e34+1.2e-2-.3e2', + tokens: [ + { startIndex: 0, type: 'number.float.pq' }, + { startIndex: 7, type: 'operators.pq' }, + { startIndex: 8, type: 'number.float.pq' }, + { startIndex: 14, type: 'operators.pq' }, + { startIndex: 15, type: 'number.float.pq' } + ] + } + ], + + // strings + [ + { + line: ' "string"', + tokens: [ + { startIndex: 0, type: 'white.pq' }, + { startIndex: 2, type: 'string.pq' } + ] + } + ], + + [ + { + line: '"string" & "another"', + tokens: [ + { startIndex: 0, type: 'string.pq' }, + { startIndex: 8, type: 'white.pq' }, + { startIndex: 9, type: 'operators.pq' }, + { startIndex: 10, type: 'white.pq' }, + { startIndex: 11, type: 'string.pq' } + ] + } + ], + + [ + { + line: '"with ""escaped "" \'text', + tokens: [ + { startIndex: 0, type: 'string.pq' }, + { startIndex: 7, type: 'string.escape.pq' }, + { startIndex: 9, type: 'string.pq' }, + { startIndex: 17, type: 'string.escape.pq' }, + { startIndex: 19, type: 'string.pq' } + ] + } + ], + + // built-in keywords/identifiers + [ + { + line: 'And as Each each _', + tokens: [ + { startIndex: 0, type: 'identifier.pq' }, + { startIndex: 3, type: 'white.pq' }, + { startIndex: 4, type: 'keyword.pq' }, + { startIndex: 6, type: 'white.pq' }, + { startIndex: 7, type: 'identifier.pq' }, + { startIndex: 11, type: 'white.pq' }, + { startIndex: 12, type: 'keyword.pq' }, + { startIndex: 16, type: 'white.pq' }, + { startIndex: 17, type: 'identifier.pq' } + ] + } + ], + + [ + { + line: ' #table({})', + tokens: [ + { startIndex: 0, type: 'white.pq' }, + { startIndex: 2, type: 'constructor.pq' }, + { startIndex: 8, type: 'delimiter.parenthesis.pq' }, + { startIndex: 9, type: 'delimiter.brackets.pq' }, + { startIndex: 11, type: 'delimiter.parenthesis.pq' } + ] + } + ], + + [ + { + line: 'param as number', + tokens: [ + { startIndex: 0, type: 'identifier.pq' }, + { startIndex: 5, type: 'white.pq' }, + { startIndex: 6, type: 'keyword.pq' }, + { startIndex: 8, type: 'white.pq' }, + { startIndex: 9, type: 'type.pq' } + ] + } + ], + + [ + { + line: 'type table', + tokens: [ + { startIndex: 0, type: 'keyword.pq' }, + { startIndex: 4, type: 'white.pq' }, + { startIndex: 5, type: 'type.pq' } + ] + } + ], + + [ + { + line: 'if (a = #nan) then null else a', + tokens: [ + { startIndex: 0, type: 'keyword.pq' }, + { startIndex: 2, type: 'white.pq' }, + { startIndex: 3, type: 'delimiter.parenthesis.pq' }, + { startIndex: 4, type: 'identifier.pq' }, + { startIndex: 5, type: 'white.pq' }, + { startIndex: 6, type: 'operators.pq' }, + { startIndex: 7, type: 'white.pq' }, + { startIndex: 8, type: 'constant.pq' }, + { startIndex: 12, type: 'delimiter.parenthesis.pq' }, + { startIndex: 13, type: 'white.pq' }, + { startIndex: 14, type: 'keyword.pq' }, + { startIndex: 18, type: 'white.pq' }, + { startIndex: 19, type: 'type.pq' }, + { startIndex: 23, type: 'white.pq' }, + { startIndex: 24, type: 'keyword.pq' }, + { startIndex: 28, type: 'white.pq' }, + { startIndex: 29, type: 'identifier.pq' } + ] + } + ], + + // built-ins + [ + { + line: 'Text.From(1)', + tokens: [ + { startIndex: 0, type: 'keyword.function.pq' }, + { startIndex: 9, type: 'delimiter.parenthesis.pq' }, + { startIndex: 10, type: 'number.pq' }, + { startIndex: 11, type: 'delimiter.parenthesis.pq' } + ] + } + ], + + [ + { + line: 'Text.ToBinary("123", BinaryEncoding.Base64)', + tokens: [ + { startIndex: 0, type: 'keyword.function.pq' }, + { startIndex: 13, type: 'delimiter.parenthesis.pq' }, + { startIndex: 14, type: 'string.pq' }, + { startIndex: 19, type: 'delimiter.pq' }, + { startIndex: 20, type: 'white.pq' }, + { startIndex: 21, type: 'constant.pq' }, + { startIndex: 42, type: 'delimiter.parenthesis.pq' } + ] + } + ], + + [ + { + line: 'Int8.Type', + tokens: [{ startIndex: 0, type: 'type.pq' }] + } + ], + + [ + { + line: 'DB2.Database', + tokens: [{ startIndex: 0, type: 'keyword.function.pq' }] + } + ], + + [ + { + line: 'RelativePosition.Type', + tokens: [{ startIndex: 0, type: 'type.pq' }] + } + ], + + // other statements + [ + { + line: '[version="1.0.0.1"] section Foo; shared Member.Name = 1;', + tokens: [ + { startIndex: 0, type: 'delimiter.square.pq' }, + { startIndex: 1, type: 'identifier.pq' }, + { startIndex: 8, type: 'operators.pq' }, + { startIndex: 9, type: 'string.pq' }, + { startIndex: 18, type: 'delimiter.square.pq' }, + { startIndex: 19, type: 'white.pq' }, + { startIndex: 20, type: 'keyword.pq' }, + { startIndex: 27, type: 'white.pq' }, + { startIndex: 28, type: 'identifier.pq' }, + { startIndex: 31, type: 'delimiter.pq' }, + { startIndex: 32, type: 'white.pq' }, + { startIndex: 33, type: 'keyword.pq' }, + { startIndex: 39, type: 'white.pq' }, + { startIndex: 40, type: 'identifier.pq' }, + { startIndex: 51, type: 'white.pq' }, + { startIndex: 52, type: 'operators.pq' }, + { startIndex: 53, type: 'white.pq' }, + { startIndex: 54, type: 'number.pq' }, + { startIndex: 55, type: 'delimiter.pq' } + ] + } + ], + + [ + { + line: 'isFunctionthen = 1;// comment', + tokens: [ + { startIndex: 0, type: 'identifier.pq' }, + { startIndex: 14, type: 'white.pq' }, + { startIndex: 15, type: 'operators.pq' }, + { startIndex: 16, type: 'white.pq' }, + { startIndex: 17, type: 'number.pq' }, + { startIndex: 18, type: 'delimiter.pq' }, + { startIndex: 19, type: 'comment.pq' } + ] + } + ], + + [ + { + line: '@RecursiveFunction()+@Rec.Func()', + tokens: [ + { startIndex: 0, type: 'operators.pq' }, + { startIndex: 1, type: 'identifier.pq' }, + { startIndex: 18, type: 'delimiter.parenthesis.pq' }, + { startIndex: 20, type: 'operators.pq' }, + { startIndex: 22, type: 'identifier.pq' }, + { startIndex: 30, type: 'delimiter.parenthesis.pq' } + ] + } + ] +]); diff --git a/monaco-languages/src/powerquery/powerquery.ts b/monaco-languages/src/powerquery/powerquery.ts new file mode 100644 index 00000000..c7835bbc --- /dev/null +++ b/monaco-languages/src/powerquery/powerquery.ts @@ -0,0 +1,925 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['[', ']'], + ['(', ')'], + ['{', '}'] + ], + autoClosingPairs: [ + { open: '"', close: '"', notIn: ['string', 'comment', 'identifier'] }, + { open: '[', close: ']', notIn: ['string', 'comment', 'identifier'] }, + { open: '(', close: ')', notIn: ['string', 'comment', 'identifier'] }, + { open: '{', close: '}', notIn: ['string', 'comment', 'identifier'] } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.pq', + ignoreCase: false, + + brackets: [ + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '{', close: '}', token: 'delimiter.brackets' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' } + ], + + operatorKeywords: ['and', 'not', 'or'], + + keywords: [ + 'as', + 'each', + 'else', + 'error', + 'false', + 'if', + 'in', + 'is', + 'let', + 'meta', + 'otherwise', + 'section', + 'shared', + 'then', + 'true', + 'try', + 'type' + ], + + constructors: [ + '#binary', + '#date', + '#datetime', + '#datetimezone', + '#duration', + '#table', + '#time' + ], + + constants: ['#infinity', '#nan', '#sections', '#shared'], + + typeKeywords: [ + 'action', + 'any', + 'anynonnull', + 'none', + 'null', + 'logical', + 'number', + 'time', + 'date', + 'datetime', + 'datetimezone', + 'duration', + 'text', + 'binary', + 'list', + 'record', + 'table', + 'function' + ], + + builtinFunctions: [ + 'Access.Database', + 'Action.Return', + 'Action.Sequence', + 'Action.Try', + 'ActiveDirectory.Domains', + 'AdoDotNet.DataSource', + 'AdoDotNet.Query', + 'AdobeAnalytics.Cubes', + 'AnalysisServices.Database', + 'AnalysisServices.Databases', + 'AzureStorage.BlobContents', + 'AzureStorage.Blobs', + 'AzureStorage.Tables', + 'Binary.Buffer', + 'Binary.Combine', + 'Binary.Compress', + 'Binary.Decompress', + 'Binary.End', + 'Binary.From', + 'Binary.FromList', + 'Binary.FromText', + 'Binary.InferContentType', + 'Binary.Length', + 'Binary.ToList', + 'Binary.ToText', + 'BinaryFormat.7BitEncodedSignedInteger', + 'BinaryFormat.7BitEncodedUnsignedInteger', + 'BinaryFormat.Binary', + 'BinaryFormat.Byte', + 'BinaryFormat.ByteOrder', + 'BinaryFormat.Choice', + 'BinaryFormat.Decimal', + 'BinaryFormat.Double', + 'BinaryFormat.Group', + 'BinaryFormat.Length', + 'BinaryFormat.List', + 'BinaryFormat.Null', + 'BinaryFormat.Record', + 'BinaryFormat.SignedInteger16', + 'BinaryFormat.SignedInteger32', + 'BinaryFormat.SignedInteger64', + 'BinaryFormat.Single', + 'BinaryFormat.Text', + 'BinaryFormat.Transform', + 'BinaryFormat.UnsignedInteger16', + 'BinaryFormat.UnsignedInteger32', + 'BinaryFormat.UnsignedInteger64', + 'Byte.From', + 'Character.FromNumber', + 'Character.ToNumber', + 'Combiner.CombineTextByDelimiter', + 'Combiner.CombineTextByEachDelimiter', + 'Combiner.CombineTextByLengths', + 'Combiner.CombineTextByPositions', + 'Combiner.CombineTextByRanges', + 'Comparer.Equals', + 'Comparer.FromCulture', + 'Comparer.Ordinal', + 'Comparer.OrdinalIgnoreCase', + 'Csv.Document', + 'Cube.AddAndExpandDimensionColumn', + 'Cube.AddMeasureColumn', + 'Cube.ApplyParameter', + 'Cube.AttributeMemberId', + 'Cube.AttributeMemberProperty', + 'Cube.CollapseAndRemoveColumns', + 'Cube.Dimensions', + 'Cube.DisplayFolders', + 'Cube.Measures', + 'Cube.Parameters', + 'Cube.Properties', + 'Cube.PropertyKey', + 'Cube.ReplaceDimensions', + 'Cube.Transform', + 'Currency.From', + 'DB2.Database', + 'Date.AddDays', + 'Date.AddMonths', + 'Date.AddQuarters', + 'Date.AddWeeks', + 'Date.AddYears', + 'Date.Day', + 'Date.DayOfWeek', + 'Date.DayOfWeekName', + 'Date.DayOfYear', + 'Date.DaysInMonth', + 'Date.EndOfDay', + 'Date.EndOfMonth', + 'Date.EndOfQuarter', + 'Date.EndOfWeek', + 'Date.EndOfYear', + 'Date.From', + 'Date.FromText', + 'Date.IsInCurrentDay', + 'Date.IsInCurrentMonth', + 'Date.IsInCurrentQuarter', + 'Date.IsInCurrentWeek', + 'Date.IsInCurrentYear', + 'Date.IsInNextDay', + 'Date.IsInNextMonth', + 'Date.IsInNextNDays', + 'Date.IsInNextNMonths', + 'Date.IsInNextNQuarters', + 'Date.IsInNextNWeeks', + 'Date.IsInNextNYears', + 'Date.IsInNextQuarter', + 'Date.IsInNextWeek', + 'Date.IsInNextYear', + 'Date.IsInPreviousDay', + 'Date.IsInPreviousMonth', + 'Date.IsInPreviousNDays', + 'Date.IsInPreviousNMonths', + 'Date.IsInPreviousNQuarters', + 'Date.IsInPreviousNWeeks', + 'Date.IsInPreviousNYears', + 'Date.IsInPreviousQuarter', + 'Date.IsInPreviousWeek', + 'Date.IsInPreviousYear', + 'Date.IsInYearToDate', + 'Date.IsLeapYear', + 'Date.Month', + 'Date.MonthName', + 'Date.QuarterOfYear', + 'Date.StartOfDay', + 'Date.StartOfMonth', + 'Date.StartOfQuarter', + 'Date.StartOfWeek', + 'Date.StartOfYear', + 'Date.ToRecord', + 'Date.ToText', + 'Date.WeekOfMonth', + 'Date.WeekOfYear', + 'Date.Year', + 'DateTime.AddZone', + 'DateTime.Date', + 'DateTime.FixedLocalNow', + 'DateTime.From', + 'DateTime.FromFileTime', + 'DateTime.FromText', + 'DateTime.IsInCurrentHour', + 'DateTime.IsInCurrentMinute', + 'DateTime.IsInCurrentSecond', + 'DateTime.IsInNextHour', + 'DateTime.IsInNextMinute', + 'DateTime.IsInNextNHours', + 'DateTime.IsInNextNMinutes', + 'DateTime.IsInNextNSeconds', + 'DateTime.IsInNextSecond', + 'DateTime.IsInPreviousHour', + 'DateTime.IsInPreviousMinute', + 'DateTime.IsInPreviousNHours', + 'DateTime.IsInPreviousNMinutes', + 'DateTime.IsInPreviousNSeconds', + 'DateTime.IsInPreviousSecond', + 'DateTime.LocalNow', + 'DateTime.Time', + 'DateTime.ToRecord', + 'DateTime.ToText', + 'DateTimeZone.FixedLocalNow', + 'DateTimeZone.FixedUtcNow', + 'DateTimeZone.From', + 'DateTimeZone.FromFileTime', + 'DateTimeZone.FromText', + 'DateTimeZone.LocalNow', + 'DateTimeZone.RemoveZone', + 'DateTimeZone.SwitchZone', + 'DateTimeZone.ToLocal', + 'DateTimeZone.ToRecord', + 'DateTimeZone.ToText', + 'DateTimeZone.ToUtc', + 'DateTimeZone.UtcNow', + 'DateTimeZone.ZoneHours', + 'DateTimeZone.ZoneMinutes', + 'Decimal.From', + 'Diagnostics.ActivityId', + 'Diagnostics.Trace', + 'DirectQueryCapabilities.From', + 'Double.From', + 'Duration.Days', + 'Duration.From', + 'Duration.FromText', + 'Duration.Hours', + 'Duration.Minutes', + 'Duration.Seconds', + 'Duration.ToRecord', + 'Duration.ToText', + 'Duration.TotalDays', + 'Duration.TotalHours', + 'Duration.TotalMinutes', + 'Duration.TotalSeconds', + 'Embedded.Value', + 'Error.Record', + 'Excel.CurrentWorkbook', + 'Excel.Workbook', + 'Exchange.Contents', + 'Expression.Constant', + 'Expression.Evaluate', + 'Expression.Identifier', + 'Facebook.Graph', + 'File.Contents', + 'Folder.Contents', + 'Folder.Files', + 'Function.From', + 'Function.Invoke', + 'Function.InvokeAfter', + 'Function.IsDataSource', + 'GoogleAnalytics.Accounts', + 'Guid.From', + 'HdInsight.Containers', + 'HdInsight.Contents', + 'HdInsight.Files', + 'Hdfs.Contents', + 'Hdfs.Files', + 'Informix.Database', + 'Int16.From', + 'Int32.From', + 'Int64.From', + 'Int8.From', + 'ItemExpression.From', + 'Json.Document', + 'Json.FromValue', + 'Lines.FromBinary', + 'Lines.FromText', + 'Lines.ToBinary', + 'Lines.ToText', + 'List.Accumulate', + 'List.AllTrue', + 'List.Alternate', + 'List.AnyTrue', + 'List.Average', + 'List.Buffer', + 'List.Combine', + 'List.Contains', + 'List.ContainsAll', + 'List.ContainsAny', + 'List.Count', + 'List.Covariance', + 'List.DateTimeZones', + 'List.DateTimes', + 'List.Dates', + 'List.Difference', + 'List.Distinct', + 'List.Durations', + 'List.FindText', + 'List.First', + 'List.FirstN', + 'List.Generate', + 'List.InsertRange', + 'List.Intersect', + 'List.IsDistinct', + 'List.IsEmpty', + 'List.Last', + 'List.LastN', + 'List.MatchesAll', + 'List.MatchesAny', + 'List.Max', + 'List.MaxN', + 'List.Median', + 'List.Min', + 'List.MinN', + 'List.Mode', + 'List.Modes', + 'List.NonNullCount', + 'List.Numbers', + 'List.PositionOf', + 'List.PositionOfAny', + 'List.Positions', + 'List.Product', + 'List.Random', + 'List.Range', + 'List.RemoveFirstN', + 'List.RemoveItems', + 'List.RemoveLastN', + 'List.RemoveMatchingItems', + 'List.RemoveNulls', + 'List.RemoveRange', + 'List.Repeat', + 'List.ReplaceMatchingItems', + 'List.ReplaceRange', + 'List.ReplaceValue', + 'List.Reverse', + 'List.Select', + 'List.Single', + 'List.SingleOrDefault', + 'List.Skip', + 'List.Sort', + 'List.StandardDeviation', + 'List.Sum', + 'List.Times', + 'List.Transform', + 'List.TransformMany', + 'List.Union', + 'List.Zip', + 'Logical.From', + 'Logical.FromText', + 'Logical.ToText', + 'MQ.Queue', + 'MySQL.Database', + 'Number.Abs', + 'Number.Acos', + 'Number.Asin', + 'Number.Atan', + 'Number.Atan2', + 'Number.BitwiseAnd', + 'Number.BitwiseNot', + 'Number.BitwiseOr', + 'Number.BitwiseShiftLeft', + 'Number.BitwiseShiftRight', + 'Number.BitwiseXor', + 'Number.Combinations', + 'Number.Cos', + 'Number.Cosh', + 'Number.Exp', + 'Number.Factorial', + 'Number.From', + 'Number.FromText', + 'Number.IntegerDivide', + 'Number.IsEven', + 'Number.IsNaN', + 'Number.IsOdd', + 'Number.Ln', + 'Number.Log', + 'Number.Log10', + 'Number.Mod', + 'Number.Permutations', + 'Number.Power', + 'Number.Random', + 'Number.RandomBetween', + 'Number.Round', + 'Number.RoundAwayFromZero', + 'Number.RoundDown', + 'Number.RoundTowardZero', + 'Number.RoundUp', + 'Number.Sign', + 'Number.Sin', + 'Number.Sinh', + 'Number.Sqrt', + 'Number.Tan', + 'Number.Tanh', + 'Number.ToText', + 'OData.Feed', + 'Odbc.DataSource', + 'Odbc.Query', + 'OleDb.DataSource', + 'OleDb.Query', + 'Oracle.Database', + 'Percentage.From', + 'PostgreSQL.Database', + 'RData.FromBinary', + 'Record.AddField', + 'Record.Combine', + 'Record.Field', + 'Record.FieldCount', + 'Record.FieldNames', + 'Record.FieldOrDefault', + 'Record.FieldValues', + 'Record.FromList', + 'Record.FromTable', + 'Record.HasFields', + 'Record.RemoveFields', + 'Record.RenameFields', + 'Record.ReorderFields', + 'Record.SelectFields', + 'Record.ToList', + 'Record.ToTable', + 'Record.TransformFields', + 'Replacer.ReplaceText', + 'Replacer.ReplaceValue', + 'RowExpression.Column', + 'RowExpression.From', + 'Salesforce.Data', + 'Salesforce.Reports', + 'SapBusinessWarehouse.Cubes', + 'SapHana.Database', + 'SharePoint.Contents', + 'SharePoint.Files', + 'SharePoint.Tables', + 'Single.From', + 'Soda.Feed', + 'Splitter.SplitByNothing', + 'Splitter.SplitTextByAnyDelimiter', + 'Splitter.SplitTextByDelimiter', + 'Splitter.SplitTextByEachDelimiter', + 'Splitter.SplitTextByLengths', + 'Splitter.SplitTextByPositions', + 'Splitter.SplitTextByRanges', + 'Splitter.SplitTextByRepeatedLengths', + 'Splitter.SplitTextByWhitespace', + 'Sql.Database', + 'Sql.Databases', + 'SqlExpression.SchemaFrom', + 'SqlExpression.ToExpression', + 'Sybase.Database', + 'Table.AddColumn', + 'Table.AddIndexColumn', + 'Table.AddJoinColumn', + 'Table.AddKey', + 'Table.AggregateTableColumn', + 'Table.AlternateRows', + 'Table.Buffer', + 'Table.Column', + 'Table.ColumnCount', + 'Table.ColumnNames', + 'Table.ColumnsOfType', + 'Table.Combine', + 'Table.CombineColumns', + 'Table.Contains', + 'Table.ContainsAll', + 'Table.ContainsAny', + 'Table.DemoteHeaders', + 'Table.Distinct', + 'Table.DuplicateColumn', + 'Table.ExpandListColumn', + 'Table.ExpandRecordColumn', + 'Table.ExpandTableColumn', + 'Table.FillDown', + 'Table.FillUp', + 'Table.FilterWithDataTable', + 'Table.FindText', + 'Table.First', + 'Table.FirstN', + 'Table.FirstValue', + 'Table.FromColumns', + 'Table.FromList', + 'Table.FromPartitions', + 'Table.FromRecords', + 'Table.FromRows', + 'Table.FromValue', + 'Table.Group', + 'Table.HasColumns', + 'Table.InsertRows', + 'Table.IsDistinct', + 'Table.IsEmpty', + 'Table.Join', + 'Table.Keys', + 'Table.Last', + 'Table.LastN', + 'Table.MatchesAllRows', + 'Table.MatchesAnyRows', + 'Table.Max', + 'Table.MaxN', + 'Table.Min', + 'Table.MinN', + 'Table.NestedJoin', + 'Table.Partition', + 'Table.PartitionValues', + 'Table.Pivot', + 'Table.PositionOf', + 'Table.PositionOfAny', + 'Table.PrefixColumns', + 'Table.Profile', + 'Table.PromoteHeaders', + 'Table.Range', + 'Table.RemoveColumns', + 'Table.RemoveFirstN', + 'Table.RemoveLastN', + 'Table.RemoveMatchingRows', + 'Table.RemoveRows', + 'Table.RemoveRowsWithErrors', + 'Table.RenameColumns', + 'Table.ReorderColumns', + 'Table.Repeat', + 'Table.ReplaceErrorValues', + 'Table.ReplaceKeys', + 'Table.ReplaceMatchingRows', + 'Table.ReplaceRelationshipIdentity', + 'Table.ReplaceRows', + 'Table.ReplaceValue', + 'Table.ReverseRows', + 'Table.RowCount', + 'Table.Schema', + 'Table.SelectColumns', + 'Table.SelectRows', + 'Table.SelectRowsWithErrors', + 'Table.SingleRow', + 'Table.Skip', + 'Table.Sort', + 'Table.SplitColumn', + 'Table.ToColumns', + 'Table.ToList', + 'Table.ToRecords', + 'Table.ToRows', + 'Table.TransformColumnNames', + 'Table.TransformColumnTypes', + 'Table.TransformColumns', + 'Table.TransformRows', + 'Table.Transpose', + 'Table.Unpivot', + 'Table.UnpivotOtherColumns', + 'Table.View', + 'Table.ViewFunction', + 'TableAction.DeleteRows', + 'TableAction.InsertRows', + 'TableAction.UpdateRows', + 'Tables.GetRelationships', + 'Teradata.Database', + 'Text.AfterDelimiter', + 'Text.At', + 'Text.BeforeDelimiter', + 'Text.BetweenDelimiters', + 'Text.Clean', + 'Text.Combine', + 'Text.Contains', + 'Text.End', + 'Text.EndsWith', + 'Text.Format', + 'Text.From', + 'Text.FromBinary', + 'Text.Insert', + 'Text.Length', + 'Text.Lower', + 'Text.Middle', + 'Text.NewGuid', + 'Text.PadEnd', + 'Text.PadStart', + 'Text.PositionOf', + 'Text.PositionOfAny', + 'Text.Proper', + 'Text.Range', + 'Text.Remove', + 'Text.RemoveRange', + 'Text.Repeat', + 'Text.Replace', + 'Text.ReplaceRange', + 'Text.Select', + 'Text.Split', + 'Text.SplitAny', + 'Text.Start', + 'Text.StartsWith', + 'Text.ToBinary', + 'Text.ToList', + 'Text.Trim', + 'Text.TrimEnd', + 'Text.TrimStart', + 'Text.Upper', + 'Time.EndOfHour', + 'Time.From', + 'Time.FromText', + 'Time.Hour', + 'Time.Minute', + 'Time.Second', + 'Time.StartOfHour', + 'Time.ToRecord', + 'Time.ToText', + 'Type.AddTableKey', + 'Type.ClosedRecord', + 'Type.Facets', + 'Type.ForFunction', + 'Type.ForRecord', + 'Type.FunctionParameters', + 'Type.FunctionRequiredParameters', + 'Type.FunctionReturn', + 'Type.Is', + 'Type.IsNullable', + 'Type.IsOpenRecord', + 'Type.ListItem', + 'Type.NonNullable', + 'Type.OpenRecord', + 'Type.RecordFields', + 'Type.ReplaceFacets', + 'Type.ReplaceTableKeys', + 'Type.TableColumn', + 'Type.TableKeys', + 'Type.TableRow', + 'Type.TableSchema', + 'Type.Union', + 'Uri.BuildQueryString', + 'Uri.Combine', + 'Uri.EscapeDataString', + 'Uri.Parts', + 'Value.Add', + 'Value.As', + 'Value.Compare', + 'Value.Divide', + 'Value.Equals', + 'Value.Firewall', + 'Value.FromText', + 'Value.Is', + 'Value.Metadata', + 'Value.Multiply', + 'Value.NativeQuery', + 'Value.NullableEquals', + 'Value.RemoveMetadata', + 'Value.ReplaceMetadata', + 'Value.ReplaceType', + 'Value.Subtract', + 'Value.Type', + 'ValueAction.NativeStatement', + 'ValueAction.Replace', + 'Variable.Value', + 'Web.Contents', + 'Web.Page', + 'WebAction.Request', + 'Xml.Document', + 'Xml.Tables' + ], + + builtinConstants: [ + 'BinaryEncoding.Base64', + 'BinaryEncoding.Hex', + 'BinaryOccurrence.Optional', + 'BinaryOccurrence.Repeating', + 'BinaryOccurrence.Required', + 'ByteOrder.BigEndian', + 'ByteOrder.LittleEndian', + 'Compression.Deflate', + 'Compression.GZip', + 'CsvStyle.QuoteAfterDelimiter', + 'CsvStyle.QuoteAlways', + 'Culture.Current', + 'Day.Friday', + 'Day.Monday', + 'Day.Saturday', + 'Day.Sunday', + 'Day.Thursday', + 'Day.Tuesday', + 'Day.Wednesday', + 'ExtraValues.Error', + 'ExtraValues.Ignore', + 'ExtraValues.List', + 'GroupKind.Global', + 'GroupKind.Local', + 'JoinAlgorithm.Dynamic', + 'JoinAlgorithm.LeftHash', + 'JoinAlgorithm.LeftIndex', + 'JoinAlgorithm.PairwiseHash', + 'JoinAlgorithm.RightHash', + 'JoinAlgorithm.RightIndex', + 'JoinAlgorithm.SortMerge', + 'JoinKind.FullOuter', + 'JoinKind.Inner', + 'JoinKind.LeftAnti', + 'JoinKind.LeftOuter', + 'JoinKind.RightAnti', + 'JoinKind.RightOuter', + 'JoinSide.Left', + 'JoinSide.Right', + 'MissingField.Error', + 'MissingField.Ignore', + 'MissingField.UseNull', + 'Number.E', + 'Number.Epsilon', + 'Number.NaN', + 'Number.NegativeInfinity', + 'Number.PI', + 'Number.PositiveInfinity', + 'Occurrence.All', + 'Occurrence.First', + 'Occurrence.Last', + 'Occurrence.Optional', + 'Occurrence.Repeating', + 'Occurrence.Required', + 'Order.Ascending', + 'Order.Descending', + 'Precision.Decimal', + 'Precision.Double', + 'QuoteStyle.Csv', + 'QuoteStyle.None', + 'RelativePosition.FromEnd', + 'RelativePosition.FromStart', + 'RoundingMode.AwayFromZero', + 'RoundingMode.Down', + 'RoundingMode.ToEven', + 'RoundingMode.TowardZero', + 'RoundingMode.Up', + 'SapHanaDistribution.All', + 'SapHanaDistribution.Connection', + 'SapHanaDistribution.Off', + 'SapHanaDistribution.Statement', + 'SapHanaRangeOperator.Equals', + 'SapHanaRangeOperator.GreaterThan', + 'SapHanaRangeOperator.GreaterThanOrEquals', + 'SapHanaRangeOperator.LessThan', + 'SapHanaRangeOperator.LessThanOrEquals', + 'SapHanaRangeOperator.NotEquals', + 'TextEncoding.Ascii', + 'TextEncoding.BigEndianUnicode', + 'TextEncoding.Unicode', + 'TextEncoding.Utf16', + 'TextEncoding.Utf8', + 'TextEncoding.Windows', + 'TraceLevel.Critical', + 'TraceLevel.Error', + 'TraceLevel.Information', + 'TraceLevel.Verbose', + 'TraceLevel.Warning', + 'WebMethod.Delete', + 'WebMethod.Get', + 'WebMethod.Head', + 'WebMethod.Patch', + 'WebMethod.Post', + 'WebMethod.Put' + ], + + builtinTypes: [ + 'Action.Type', + 'Any.Type', + 'Binary.Type', + 'BinaryEncoding.Type', + 'BinaryOccurrence.Type', + 'Byte.Type', + 'ByteOrder.Type', + 'Character.Type', + 'Compression.Type', + 'CsvStyle.Type', + 'Currency.Type', + 'Date.Type', + 'DateTime.Type', + 'DateTimeZone.Type', + 'Day.Type', + 'Decimal.Type', + 'Double.Type', + 'Duration.Type', + 'ExtraValues.Type', + 'Function.Type', + 'GroupKind.Type', + 'Guid.Type', + 'Int16.Type', + 'Int32.Type', + 'Int64.Type', + 'Int8.Type', + 'JoinAlgorithm.Type', + 'JoinKind.Type', + 'JoinSide.Type', + 'List.Type', + 'Logical.Type', + 'MissingField.Type', + 'None.Type', + 'Null.Type', + 'Number.Type', + 'Occurrence.Type', + 'Order.Type', + 'Password.Type', + 'Percentage.Type', + 'Precision.Type', + 'QuoteStyle.Type', + 'Record.Type', + 'RelativePosition.Type', + 'RoundingMode.Type', + 'SapHanaDistribution.Type', + 'SapHanaRangeOperator.Type', + 'Single.Type', + 'Table.Type', + 'Text.Type', + 'TextEncoding.Type', + 'Time.Type', + 'TraceLevel.Type', + 'Type.Type', + 'Uri.Type', + 'WebMethod.Type' + ], + + tokenizer: { + root: [ + // quoted identifier + [/#"[\w \.]+"/, 'identifier.quote'], + + // numbers + [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'], + [/0[xX][0-9a-fA-F]+/, 'number.hex'], + [/\d+([eE][\-+]?\d+)?/, 'number'], + + // keywords + [ + /(#?[a-z]+)\b/, + { + cases: { + '@typeKeywords': 'type', + '@keywords': 'keyword', + '@constants': 'constant', + '@constructors': 'constructor', + '@operatorKeywords': 'operators', + '@default': 'identifier' + } + } + ], + + // built-in types + [ + /\b([A-Z][a-zA-Z0-9]+\.Type)\b/, + { + cases: { + '@builtinTypes': 'type', + '@default': 'identifier' + } + } + ], + + // other built-ins + [ + /\b([A-Z][a-zA-Z0-9]+\.[A-Z][a-zA-Z0-9]+)\b/, + { + cases: { + '@builtinFunctions': 'keyword.function', + '@builtinConstants': 'constant', + '@default': 'identifier' + } + } + ], + + // other identifiers + [/\b([a-zA-Z_][\w\.]*)\b/, 'identifier'], + + { include: '@whitespace' }, + { include: '@comments' }, + { include: '@strings' }, + + [/[{}()\[\]]/, '@brackets'], + [/([=\+<>\-\*&@\?\/!])|([<>]=)|(<>)|(=>)|(\.\.\.)|(\.\.)/, 'operators'], + [/[,;]/, 'delimiter'] + ], + + whitespace: [[/\s+/, 'white']], + + comments: [ + ['\\/\\*', 'comment', '@comment'], + ['\\/\\/+.*', 'comment'] + ], + + comment: [ + ['\\*\\/', 'comment', '@pop'], + ['.', 'comment'] + ], + + strings: [['"', 'string', '@string']], + + string: [ + ['""', 'string.escape'], + ['"', 'string', '@pop'], + ['.', 'string'] + ] + } +}; diff --git a/monaco-languages/src/powershell/powershell.contribution.ts b/monaco-languages/src/powershell/powershell.contribution.ts new file mode 100644 index 00000000..ad2878e5 --- /dev/null +++ b/monaco-languages/src/powershell/powershell.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'powershell', + extensions: ['.ps1', '.psm1', '.psd1'], + aliases: ['PowerShell', 'powershell', 'ps', 'ps1'], + loader: () => import('./powershell') +}); diff --git a/monaco-languages/src/powershell/powershell.test.ts b/monaco-languages/src/powershell/powershell.test.ts new file mode 100644 index 00000000..82762398 --- /dev/null +++ b/monaco-languages/src/powershell/powershell.test.ts @@ -0,0 +1,884 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('powershell', [ + // Comments - single line + [ + { + line: '#', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + } + ], + + [ + { + line: ' # a comment', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'comment.ps1' } + ] + } + ], + + [ + { + line: '# a comment', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + } + ], + + [ + { + line: '#sticky comment', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + } + ], + + [ + { + line: '##still a comment', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + } + ], + + [ + { + line: '1 / 2 /# comment', + tokens: [ + { startIndex: 0, type: 'number.ps1' }, + { startIndex: 1, type: '' }, + { startIndex: 2, type: 'delimiter.ps1' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'number.ps1' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.ps1' }, + { startIndex: 7, type: 'comment.ps1' } + ] + } + ], + + [ + { + line: '$x = 1 # my comment # is a nice one', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'number.ps1' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'comment.ps1' } + ] + } + ], + + // Comments - range comment, single line + [ + { + line: '<# a simple comment #>', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + } + ], + + [ + { + line: '$x = <# a simple comment #> 1', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'comment.ps1' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'number.ps1' } + ] + } + ], + + [ + { + line: '$yy = <# comment #> 14', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.ps1' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'comment.ps1' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'number.ps1' } + ] + } + ], + + [ + { + line: '$x = <##>7', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'comment.ps1' }, + { startIndex: 9, type: 'number.ps1' } + ] + } + ], + + [ + { + line: '$x = <#<85', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'comment.ps1' } + ] + } + ], + + // Comments - range comment, multiple lines + [ + { + line: '<# start of multiline comment', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: 'a comment between', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: 'end of multiline comment#>', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + } + ], + + [ + { + line: '$x = <# start a comment', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'comment.ps1' } + ] + }, + { + line: ' a ', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: 'and end it #> 2', + tokens: [ + { startIndex: 0, type: 'comment.ps1' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'number.ps1' } + ] + } + ], + + // Keywords + [ + { + line: 'foreach($i in $b) {if (7) continue}', + tokens: [ + { startIndex: 0, type: 'keyword.foreach.ps1' }, + { startIndex: 7, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 8, type: 'variable.ps1' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'keyword.in.ps1' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'variable.ps1' }, + { startIndex: 16, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'delimiter.curly.ps1' }, + { startIndex: 19, type: 'keyword.if.ps1' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 23, type: 'number.ps1' }, + { startIndex: 24, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'keyword.continue.ps1' }, + { startIndex: 34, type: 'delimiter.curly.ps1' } + ] + } + ], + + // Redirect operand + [ + { + line: '$i > output1.txt', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 12, type: 'delimiter.ps1' }, + { startIndex: 13, type: '' } + ] + } + ], + + // Numbers + [ + { + line: '0', + tokens: [{ startIndex: 0, type: 'number.ps1' }] + } + ], + + [ + { + line: '0.10', + tokens: [{ startIndex: 0, type: 'number.float.ps1' }] + } + ], + + [ + { + line: '0X123', + tokens: [{ startIndex: 0, type: 'number.hex.ps1' }] + } + ], + + [ + { + line: '0x123', + tokens: [{ startIndex: 0, type: 'number.hex.ps1' }] + } + ], + + [ + { + line: '23.5e3', + tokens: [{ startIndex: 0, type: 'number.float.ps1' }] + } + ], + + [ + { + line: '23.5e-3', + tokens: [{ startIndex: 0, type: 'number.float.ps1' }] + } + ], + + [ + { + line: '23.5E3', + tokens: [{ startIndex: 0, type: 'number.float.ps1' }] + } + ], + + [ + { + line: '23.5E-3', + tokens: [{ startIndex: 0, type: 'number.float.ps1' }] + } + ], + + [ + { + line: '23.5', + tokens: [{ startIndex: 0, type: 'number.float.ps1' }] + } + ], + + [ + { + line: '0+0', + tokens: [ + { startIndex: 0, type: 'number.ps1' }, + { startIndex: 1, type: 'delimiter.ps1' }, + { startIndex: 2, type: 'number.ps1' } + ] + } + ], + + [ + { + line: '100+10', + tokens: [ + { startIndex: 0, type: 'number.ps1' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: 'number.ps1' } + ] + } + ], + + [ + { + line: '10 + 0', + tokens: [ + { startIndex: 0, type: 'number.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'number.ps1' } + ] + } + ], + + // Strings + [ + { + line: '$s = "I am a String"', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'string.ps1' } + ] + } + ], + + [ + { + line: "'I am also a ( String'", + tokens: [{ startIndex: 0, type: 'string.ps1' }] + } + ], + + [ + { + line: '$s = "concatenated" + " String"', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'string.ps1' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'delimiter.ps1' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'string.ps1' } + ] + } + ], + + [ + { + line: '"escaping `"quotes`" is cool"', + tokens: [ + { startIndex: 0, type: 'string.ps1' }, + { startIndex: 10, type: 'string.escape.ps1' }, + { startIndex: 12, type: 'string.ps1' }, + { startIndex: 18, type: 'string.escape.ps1' }, + { startIndex: 20, type: 'string.ps1' } + ] + } + ], + + [ + { + line: "'`'end of the string", + tokens: [ + { startIndex: 0, type: 'string.ps1' }, + { startIndex: 1, type: 'string.escape.ps1' }, + { startIndex: 3, type: 'string.ps1' } + ] + } + ], + + [ + { + line: '@"I am an expandable String"@', + tokens: [{ startIndex: 0, type: 'string.ps1' }] + } + ], + + [ + { + line: "@'I am also an expandable String'@", + tokens: [{ startIndex: 0, type: 'string.ps1' }] + } + ], + + [ + { + line: "$s = @'I am also an expandable String'@", + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'string.ps1' } + ] + } + ], + + [ + { + line: "$s = @'I am also an expandable String'@+7", + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'string.ps1' } + ] + } + ], + + [ + { + line: "@'I am a multiline string,", + tokens: [{ startIndex: 0, type: 'string.ps1' }] + }, + { + line: 'and this is the middle line,', + tokens: [{ startIndex: 0, type: 'string.ps1' }] + }, + { + line: "and this is NOT the end of the string'@foreach $i", + tokens: [{ startIndex: 0, type: 'string.ps1' }] + }, + { + line: "'@", + tokens: [{ startIndex: 0, type: 'string.ps1' }] + }, + { + line: '${script:foo}', + tokens: [{ startIndex: 0, type: 'variable.ps1' }] + }, + { + line: 'foreach $i', + tokens: [ + { startIndex: 0, type: 'keyword.foreach.ps1' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'variable.ps1' } + ] + } + ], + + // Generated from sample + [ + { + line: '$SelectedObjectNames=@();', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 20, type: 'delimiter.ps1' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 24, type: 'delimiter.ps1' } + ] + }, + { + line: '$XenCenterNodeSelected = 0;', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.ps1' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'number.ps1' }, + { startIndex: 26, type: 'delimiter.ps1' } + ] + }, + { + line: '#the object info array contains hashmaps, each of which represent a parameter set and describe a target in the XenCenter resource list', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: 'foreach($parameterSet in $ObjInfoArray)', + tokens: [ + { startIndex: 0, type: 'keyword.foreach.ps1' }, + { startIndex: 7, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 8, type: 'variable.ps1' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'keyword.in.ps1' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'variable.ps1' }, + { startIndex: 38, type: 'delimiter.parenthesis.ps1' } + ] + }, + { + line: '{', + tokens: [{ startIndex: 0, type: 'delimiter.curly.ps1' }] + }, + { + line: ' if ($parameterSet["class"] -eq "blank")', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.if.ps1' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 5, type: 'variable.ps1' }, + { startIndex: 18, type: 'delimiter.square.ps1' }, + { startIndex: 19, type: 'string.ps1' }, + { startIndex: 26, type: 'delimiter.square.ps1' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.ps1' }, + { startIndex: 29, type: '' }, + { startIndex: 32, type: 'string.ps1' }, + { startIndex: 39, type: 'delimiter.parenthesis.ps1' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.ps1' } + ] + }, + { + line: ' #When the XenCenter node is selected a parameter set is created for each of your connected servers with the class and objUuid keys marked as blank', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'comment.ps1' } + ] + }, + { + line: ' if ($XenCenterNodeSelected)', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.if.ps1' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 6, type: 'variable.ps1' }, + { startIndex: 28, type: 'delimiter.parenthesis.ps1' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.ps1' } + ] + }, + { + line: ' continue', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 3, type: 'keyword.continue.ps1' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.curly.ps1' } + ] + }, + { + line: ' $XenCenterNodeSelected = 1;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.ps1' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'delimiter.ps1' }, + { startIndex: 26, type: '' }, + { startIndex: 27, type: 'number.ps1' }, + { startIndex: 28, type: 'delimiter.ps1' } + ] + }, + { + line: ' $SelectedObjectNames += "XenCenter"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.ps1' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.ps1' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'string.ps1' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.ps1' } + ] + }, + { + line: ' elseif ($parameterSet["sessionRef"] -eq "null")', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.elseif.ps1' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.parenthesis.ps1' }, + { startIndex: 9, type: 'variable.ps1' }, + { startIndex: 22, type: 'delimiter.square.ps1' }, + { startIndex: 23, type: 'string.ps1' }, + { startIndex: 35, type: 'delimiter.square.ps1' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'delimiter.ps1' }, + { startIndex: 38, type: '' }, + { startIndex: 41, type: 'string.ps1' }, + { startIndex: 47, type: 'delimiter.parenthesis.ps1' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.ps1' } + ] + }, + { + line: ' #When a disconnected server is selected there is no session information, we get null for everything except class', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'comment.ps1' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.ps1' } + ] + }, + { + line: ' $SelectedObjectNames += "a disconnected server"', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.ps1' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.ps1' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'string.ps1' } + ] + }, + { + line: ' else', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'keyword.else.ps1' } + ] + }, + { + line: ' {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.ps1' } + ] + }, + { + line: ' Connect-XenServer -url $parameterSet["url"] -opaqueref $parameterSet["sessionRef"]', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 20, type: 'delimiter.ps1' }, + { startIndex: 21, type: '' }, + { startIndex: 25, type: 'variable.ps1' }, + { startIndex: 38, type: 'delimiter.square.ps1' }, + { startIndex: 39, type: 'string.ps1' }, + { startIndex: 44, type: 'delimiter.square.ps1' }, + { startIndex: 45, type: '' }, + { startIndex: 46, type: 'delimiter.ps1' }, + { startIndex: 47, type: '' }, + { startIndex: 57, type: 'variable.ps1' }, + { startIndex: 70, type: 'delimiter.square.ps1' }, + { startIndex: 71, type: 'string.ps1' }, + { startIndex: 83, type: 'delimiter.square.ps1' } + ] + }, + { + line: ' #Use $class to determine which server objects to get', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'comment.ps1' } + ] + }, + { + line: ' #-properties allows us to filter the results to just include the selected object', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'comment.ps1' } + ] + }, + { + line: ' $exp = "Get-XenServer:{0} -properties @{{uuid=\'{1}\'}}" -f $parameterSet["class"], $parameterSet["objUuid"]', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.ps1' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.ps1' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'string.ps1' }, + { startIndex: 56, type: '' }, + { startIndex: 57, type: 'delimiter.ps1' }, + { startIndex: 58, type: '' }, + { startIndex: 60, type: 'variable.ps1' }, + { startIndex: 73, type: 'delimiter.square.ps1' }, + { startIndex: 74, type: 'string.ps1' }, + { startIndex: 81, type: 'delimiter.square.ps1' }, + { startIndex: 82, type: 'delimiter.ps1' }, + { startIndex: 83, type: '' }, + { startIndex: 84, type: 'variable.ps1' }, + { startIndex: 97, type: 'delimiter.square.ps1' }, + { startIndex: 98, type: 'string.ps1' }, + { startIndex: 107, type: 'delimiter.square.ps1' } + ] + }, + { + line: ' $obj = Invoke-Expression $exp', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.ps1' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.ps1' }, + { startIndex: 8, type: '' }, + { startIndex: 27, type: 'variable.ps1' } + ] + }, + { + line: ' $SelectedObjectNames += $obj.name_label;', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'variable.ps1' }, + { startIndex: 22, type: '' }, + { startIndex: 23, type: 'delimiter.ps1' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'variable.ps1' }, + { startIndex: 30, type: 'delimiter.ps1' }, + { startIndex: 31, type: '' }, + { startIndex: 41, type: 'delimiter.ps1' } + ] + }, + { + line: ' } ', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 1, type: 'delimiter.curly.ps1' }, + { startIndex: 2, type: '' } + ] + }, + { + line: '}', + tokens: [{ startIndex: 0, type: 'delimiter.curly.ps1' }] + }, + { + line: '', + tokens: [] + }, + { + line: '$test = "in string var$test"', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 5, type: '' }, + { startIndex: 6, type: 'delimiter.ps1' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'string.ps1' }, + { startIndex: 22, type: 'variable.ps1' }, + { startIndex: 27, type: 'string.ps1' } + ] + }, + { + line: "$another = 'not a $var'", + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.ps1' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'string.ps1' } + ] + }, + { + line: '$third = "a $var and not `$var string"', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.ps1' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'string.ps1' }, + { startIndex: 12, type: 'variable.ps1' }, + { startIndex: 16, type: 'string.ps1' }, + { startIndex: 25, type: 'string.escape.ps1' }, + { startIndex: 27, type: 'string.ps1' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: ':aLabel', + tokens: [{ startIndex: 0, type: 'metatag.ps1' }] + }, + { + line: '', + tokens: [] + }, + { + line: '<#', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: '.SYNOPSIS', + tokens: [{ startIndex: 0, type: 'comment.keyword.synopsis.ps1' }] + }, + { + line: ' some text', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: ' ', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: '.LINK', + tokens: [{ startIndex: 0, type: 'comment.keyword.link.ps1' }] + }, + { + line: ' some more text', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: '#>', + tokens: [{ startIndex: 0, type: 'comment.ps1' }] + }, + { + line: '', + tokens: [] + }, + { + line: '', + tokens: [] + }, + { + line: '$hereString = @"', + tokens: [ + { startIndex: 0, type: 'variable.ps1' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.ps1' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'string.ps1' } + ] + }, + { + line: ' a string', + tokens: [{ startIndex: 0, type: 'string.ps1' }] + }, + { + line: ' still "@ a string $withVar', + tokens: [ + { startIndex: 0, type: 'string.ps1' }, + { startIndex: 20, type: 'variable.ps1' } + ] + }, + { + line: ' still a string `$noVar', + tokens: [ + { startIndex: 0, type: 'string.ps1' }, + { startIndex: 17, type: 'string.escape.ps1' }, + { startIndex: 19, type: 'string.ps1' } + ] + }, + { + line: '', + tokens: [] + }, + { + line: '"@ still a string', + tokens: [ + { startIndex: 0, type: 'string.ps1' }, + { startIndex: 2, type: '' } + ] + } + ] +]); diff --git a/monaco-languages/src/powershell/powershell.ts b/monaco-languages/src/powershell/powershell.ts new file mode 100644 index 00000000..ddb8363b --- /dev/null +++ b/monaco-languages/src/powershell/powershell.ts @@ -0,0 +1,264 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + // the default separators except `$-` + wordPattern: + /(-?\d*\.\d\w*)|([^\`\~\!\@\#%\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g, + comments: { + lineComment: '#', + blockComment: ['<#', '#>'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"', notIn: ['string'] }, + { open: "'", close: "'", notIn: ['string', 'comment'] } + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + folding: { + markers: { + start: new RegExp('^\\s*#region\\b'), + end: new RegExp('^\\s*#endregion\\b') + } + } +}; + +export const language = { + defaultToken: '', + ignoreCase: true, + tokenPostfix: '.ps1', + + brackets: [ + { token: 'delimiter.curly', open: '{', close: '}' }, + { token: 'delimiter.square', open: '[', close: ']' }, + { token: 'delimiter.parenthesis', open: '(', close: ')' } + ], + + keywords: [ + 'begin', + 'break', + 'catch', + 'class', + 'continue', + 'data', + 'define', + 'do', + 'dynamicparam', + 'else', + 'elseif', + 'end', + 'exit', + 'filter', + 'finally', + 'for', + 'foreach', + 'from', + 'function', + 'if', + 'in', + 'param', + 'process', + 'return', + 'switch', + 'throw', + 'trap', + 'try', + 'until', + 'using', + 'var', + 'while', + 'workflow', + 'parallel', + 'sequence', + 'inlinescript', + 'configuration' + ], + + helpKeywords: + /SYNOPSIS|DESCRIPTION|PARAMETER|EXAMPLE|INPUTS|OUTPUTS|NOTES|LINK|COMPONENT|ROLE|FUNCTIONALITY|FORWARDHELPTARGETNAME|FORWARDHELPCATEGORY|REMOTEHELPRUNSPACE|EXTERNALHELP/, + + // we include these common regular expressions + symbols: /[=>/, 'comment', '@pop'], + [/(\.)(@helpKeywords)(?!\w)/, { token: 'comment.keyword.$2' }], + [/[\.#]/, 'comment'] + ] + } +}; diff --git a/monaco-languages/src/protobuf/protobuf.contribution.ts b/monaco-languages/src/protobuf/protobuf.contribution.ts new file mode 100644 index 00000000..3741ba94 --- /dev/null +++ b/monaco-languages/src/protobuf/protobuf.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'proto', + extensions: ['.proto'], + aliases: ['protobuf', 'Protocol Buffers'], + loader: () => import('./protobuf') +}); diff --git a/monaco-languages/src/protobuf/protobuf.test.ts b/monaco-languages/src/protobuf/protobuf.test.ts new file mode 100644 index 00000000..86e04b43 --- /dev/null +++ b/monaco-languages/src/protobuf/protobuf.test.ts @@ -0,0 +1,2073 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/* To generate an initial baseline from a .proto file, uncomment: + +import { readFileSync } from 'fs'; + +const lines = readFileSync('/home/tochi/code/scratches/proto2_advanced.proto', { + encoding: 'utf-8' +}).split(/\r?\n/); + +testTokenization('protobuf', [ + lines.map((line) => ({ + line, + tokens: [] + })) +]); +*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('proto', [ + // proto3 example file: https://developers.google.com/protocol-buffers/docs/reference/proto3-spec#proto_file + [ + { + line: 'syntax = "proto3";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'operators.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'string.quote.proto' }, + { startIndex: 10, type: 'string.proto' }, + { startIndex: 16, type: 'string.quote.proto' }, + { startIndex: 17, type: 'delimiter.proto' } + ] + }, + { + line: 'import public "other.proto";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'keyword.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'string.quote.proto' }, + { startIndex: 15, type: 'string.proto' }, + { startIndex: 26, type: 'string.quote.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: 'option java_package = "com.example.foo";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'annotation.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'operator.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'string.quote.proto' }, + { startIndex: 23, type: 'string.proto' }, + { startIndex: 38, type: 'string.quote.proto' }, + { startIndex: 39, type: 'delimiter.proto' } + ] + }, + { + line: 'enum EnumAllowingAlias {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 4, type: 'white.proto' }, + { startIndex: 5, type: 'type.identifier.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option allow_alias = true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'operator.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'keyword.constant.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' UNKNOWN = 0;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.octal.proto' }, + { startIndex: 13, type: 'delimiter.proto' } + ] + }, + { + line: ' STARTED = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'delimiter.proto' } + ] + }, + { + line: ' RUNNING = 2 [(custom_option) = "hello world"];', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.square.proto' }, + { startIndex: 15, type: 'annotation.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'operator.proto' }, + { startIndex: 32, type: 'white.proto' }, + { startIndex: 33, type: 'string.quote.proto' }, + { startIndex: 34, type: 'string.proto' }, + { startIndex: 45, type: 'string.quote.proto' }, + { startIndex: 46, type: 'delimiter.square.proto' }, + { startIndex: 47, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { + line: 'message Outer {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option (my_option).a = true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'operator.proto' }, + { startIndex: 24, type: 'white.proto' }, + { startIndex: 25, type: 'keyword.constant.proto' }, + { startIndex: 29, type: 'delimiter.proto' } + ] + }, + { + line: ' message Inner { // Level 2', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 20, type: 'comment.proto' } + ] + }, + { + line: ' int64 ival = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'identifier.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'delimiter.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'number.proto' }, + { startIndex: 18, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' repeated Inner inner_message = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'delimiter.proto' }, + { startIndex: 32, type: 'white.proto' }, + { startIndex: 33, type: 'number.proto' }, + { startIndex: 34, type: 'delimiter.proto' } + ] + }, + { + line: ' EnumAllowingAlias enum_field =3;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'type.identifier.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'identifier.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'delimiter.proto' }, + { startIndex: 32, type: 'number.proto' }, + { startIndex: 33, type: 'delimiter.proto' } + ] + }, + { + line: ' map my_map = 4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 5, type: 'delimiter.angle.proto' }, + { startIndex: 6, type: 'keyword.proto' }, + { startIndex: 11, type: 'delimiter.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 19, type: 'delimiter.angle.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'identifier.proto' }, + { startIndex: 27, type: 'white.proto' }, + { startIndex: 28, type: 'operators.proto' }, + { startIndex: 29, type: 'white.proto' }, + { startIndex: 30, type: 'number.proto' }, + { startIndex: 31, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] } + ], + // proto2 example file: https://developers.google.com/protocol-buffers/docs/reference/proto2-spec#proto_file + [ + { + line: 'syntax = "proto2";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'operators.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'string.quote.proto' }, + { startIndex: 10, type: 'string.proto' }, + { startIndex: 16, type: 'string.quote.proto' }, + { startIndex: 17, type: 'delimiter.proto' } + ] + }, + { + line: 'import public "other.proto";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'keyword.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'string.quote.proto' }, + { startIndex: 15, type: 'string.proto' }, + { startIndex: 26, type: 'string.quote.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: 'option java_package = "com.example.foo";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'annotation.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'operator.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'string.quote.proto' }, + { startIndex: 23, type: 'string.proto' }, + { startIndex: 38, type: 'string.quote.proto' }, + { startIndex: 39, type: 'delimiter.proto' } + ] + }, + { + line: 'enum EnumAllowingAlias {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 4, type: 'white.proto' }, + { startIndex: 5, type: 'type.identifier.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option allow_alias = true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'operator.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'keyword.constant.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' UNKNOWN = 0;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.octal.proto' }, + { startIndex: 13, type: 'delimiter.proto' } + ] + }, + { + line: ' STARTED = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'delimiter.proto' } + ] + }, + { + line: ' RUNNING = 2 [(custom_option) = "hello world"];', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.square.proto' }, + { startIndex: 15, type: 'annotation.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'operator.proto' }, + { startIndex: 32, type: 'white.proto' }, + { startIndex: 33, type: 'string.quote.proto' }, + { startIndex: 34, type: 'string.proto' }, + { startIndex: 45, type: 'string.quote.proto' }, + { startIndex: 46, type: 'delimiter.square.proto' }, + { startIndex: 47, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { + line: 'message Outer {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option (my_option).a = true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'operator.proto' }, + { startIndex: 24, type: 'white.proto' }, + { startIndex: 25, type: 'keyword.constant.proto' }, + { startIndex: 29, type: 'delimiter.proto' } + ] + }, + { + line: ' message Inner { // Level 2', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 20, type: 'comment.proto' } + ] + }, + { + line: ' required int64 ival = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'identifier.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'delimiter.proto' }, + { startIndex: 25, type: 'white.proto' }, + { startIndex: 26, type: 'number.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' repeated Inner inner_message = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'delimiter.proto' }, + { startIndex: 32, type: 'white.proto' }, + { startIndex: 33, type: 'number.proto' }, + { startIndex: 34, type: 'delimiter.proto' } + ] + }, + { + line: ' optional EnumAllowingAlias enum_field = 3;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'identifier.proto' }, + { startIndex: 39, type: 'white.proto' }, + { startIndex: 40, type: 'delimiter.proto' }, + { startIndex: 41, type: 'white.proto' }, + { startIndex: 42, type: 'number.proto' }, + { startIndex: 43, type: 'delimiter.proto' } + ] + }, + { + line: ' map my_map = 4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 5, type: 'delimiter.angle.proto' }, + { startIndex: 6, type: 'keyword.proto' }, + { startIndex: 11, type: 'delimiter.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 19, type: 'delimiter.angle.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'identifier.proto' }, + { startIndex: 27, type: 'white.proto' }, + { startIndex: 28, type: 'operators.proto' }, + { startIndex: 29, type: 'white.proto' }, + { startIndex: 30, type: 'number.proto' }, + { startIndex: 31, type: 'delimiter.proto' } + ] + }, + { + line: ' extensions 20 to 30;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'number.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'keyword.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'number.proto' }, + { startIndex: 21, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { + line: 'message Foo {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' optional group GroupMessage {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 29, type: 'white.proto' }, + { startIndex: 30, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' optional a = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'identifier.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'delimiter.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'number.proto' }, + { startIndex: 18, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] } + ], + // proto3 edge cases + [ + { + line: 'syntax = "proto3";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'operators.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'string.quote.proto' }, + { startIndex: 10, type: 'string.proto' }, + { startIndex: 16, type: 'string.quote.proto' }, + { startIndex: 17, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'package foo . /**/ bar;', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'comment.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 20, type: 'identifier.proto' }, + { startIndex: 23, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'import public "options.proto";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'keyword.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'string.quote.proto' }, + { startIndex: 15, type: 'string.proto' }, + { startIndex: 28, type: 'string.quote.proto' }, + { startIndex: 29, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'option java_package = "com.example.foo";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'annotation.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'operator.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'string.quote.proto' }, + { startIndex: 23, type: 'string.proto' }, + { startIndex: 38, type: 'string.quote.proto' }, + { startIndex: 39, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'message Foo {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' foo.bar.Bar nested_message = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'type.identifier.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'identifier.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'delimiter.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'number.proto' }, + { startIndex: 32, type: 'delimiter.proto' } + ] + }, + { + line: ' repeated int32 samples = 3 [packed=true];', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 24, type: 'white.proto' }, + { startIndex: 25, type: 'delimiter.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'number.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'delimiter.square.proto' }, + { startIndex: 30, type: 'annotation.proto' }, + { startIndex: 36, type: 'operator.proto' }, + { startIndex: 37, type: 'keyword.constant.proto' }, + { startIndex: 41, type: 'delimiter.square.proto' }, + { startIndex: 42, type: 'delimiter.proto' } + ] + }, + { + line: ' oneof foo {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' string name = 4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'number.proto' }, + { startIndex: 19, type: 'delimiter.proto' } + ] + }, + { + line: ' Bar sub_message = 92;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'type.identifier.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'delimiter.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'number.proto' }, + { startIndex: 24, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' reserved 5, 15, 203 to 30;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'number.proto' }, + { startIndex: 12, type: 'delimiter.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'number.proto' }, + { startIndex: 16, type: 'delimiter.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'number.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'keyword.proto' }, + { startIndex: 24, type: 'white.proto' }, + { startIndex: 25, type: 'number.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' reserved "$46_ _$%$%\\"bar" "baz";', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'string.quote.proto' }, + { startIndex: 12, type: 'string.proto' }, + { startIndex: 22, type: 'string.escape.invalid.proto' }, + { startIndex: 24, type: 'string.proto' }, + { startIndex: 27, type: 'string.quote.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'string.quote.proto' }, + { startIndex: 30, type: 'string.proto' }, + { startIndex: 33, type: 'string.quote.proto' }, + { startIndex: 34, type: 'delimiter.proto' } + ] + }, + { + line: ' reserved 100 to max ;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'number.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'keyword.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'keyword.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.proto' } + ] + }, + { + line: ' string baz = 10;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'identifier.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'delimiter.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'number.proto' }, + { startIndex: 17, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { line: 'message', tokens: [{ startIndex: 0, type: 'keyword.proto' }] }, + { + line: 'map {}', + tokens: [ + { startIndex: 0, type: 'type.identifier.proto' }, + { startIndex: 3, type: 'white.proto' }, + { startIndex: 4, type: 'delimiter.curly.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'message Bar {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' int32 x = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'delimiter.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message int32 {}', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.curly.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'enum EnumAllowingAlias {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 4, type: 'white.proto' }, + { startIndex: 5, type: 'type.identifier.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option allow_alias = true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'operator.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'keyword.constant.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' uNkNoWN2 = 0;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'operators.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'number.octal.proto' }, + { startIndex: 14, type: 'delimiter.proto' } + ] + }, + { + line: ' ENUM_ALLOWING_ALIAS_UNKNOWN = 0;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 29, type: 'white.proto' }, + { startIndex: 30, type: 'operators.proto' }, + { startIndex: 31, type: 'white.proto' }, + { startIndex: 32, type: 'number.octal.proto' }, + { startIndex: 33, type: 'delimiter.proto' } + ] + }, + { + line: ' STARTED = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'delimiter.proto' } + ] + }, + { + line: " running = 2 [( /***/ custom_option) = 'hello world'];", + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.square.proto' }, + { startIndex: 15, type: 'annotation.brackets.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'comment.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'annotation.proto' }, + { startIndex: 36, type: 'annotation.brackets.proto' }, + { startIndex: 37, type: 'white.proto' }, + { startIndex: 38, type: 'operator.proto' }, + { startIndex: 39, type: 'white.proto' }, + { startIndex: 40, type: 'string.quote.proto' }, + { startIndex: 41, type: 'string.proto' }, + { startIndex: 52, type: 'string.quote.proto' }, + { startIndex: 53, type: 'delimiter.square.proto' }, + { startIndex: 54, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message Outer {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option (my_option).a= true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 22, type: 'operator.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'keyword.constant.proto' }, + { startIndex: 28, type: 'delimiter.proto' } + ] + }, + { + line: ' message Inner { // Level 2', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 20, type: 'comment.proto' } + ] + }, + { + line: ' int64 ival = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'identifier.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'delimiter.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'number.proto' }, + { startIndex: 18, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' repeated Inner inner_message = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'delimiter.proto' }, + { startIndex: 32, type: 'white.proto' }, + { startIndex: 33, type: 'number.proto' }, + { startIndex: 34, type: 'delimiter.proto' } + ] + }, + { + line: ' foo .bar', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'type.identifier.proto' } + ] + }, + { + line: ' /**/ .EnumAllowingAlias enum_field =3;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 3, type: 'comment.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'identifier.proto' }, + { startIndex: 37, type: 'white.proto' }, + { startIndex: 38, type: 'delimiter.proto' }, + { startIndex: 39, type: 'number.proto' }, + { startIndex: 40, type: 'delimiter.proto' } + ] + }, + { + line: ' map my_map = 4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'type.identifier.proto' }, + { startIndex: 5, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'delimiter.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'number.proto' }, + { startIndex: 16, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message message {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' repeated Foo enum = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'identifier.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'delimiter.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'number.proto' }, + { startIndex: 23, type: 'delimiter.proto' } + ] + }, + { + line: ' Foo int32 = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'type.identifier.proto' }, + { startIndex: 5, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'number.proto' }, + { startIndex: 15, type: 'delimiter.proto' } + ] + }, + { + line: ' service x = 3;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'type.identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'number.proto' }, + { startIndex: 15, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message service {}', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: '/** SearchService does nothing and returns the string "foo"', + tokens: [{ startIndex: 0, type: 'comment.proto' }] + }, + { line: '*/', tokens: [{ startIndex: 0, type: 'comment.proto' }] }, + { + line: 'service SearchService {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' rpc Search (stream SearchRequest) returns (SearchResponse) {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 5, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'delimiter.parenthesis.proto' }, + { startIndex: 14, type: 'keyword.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'type.identifier.proto' }, + { startIndex: 34, type: 'delimiter.parenthesis.proto' }, + { startIndex: 35, type: 'white.proto' }, + { startIndex: 36, type: 'keyword.proto' }, + { startIndex: 43, type: 'white.proto' }, + { startIndex: 44, type: 'delimiter.parenthesis.proto' }, + { startIndex: 45, type: 'type.identifier.proto' }, + { startIndex: 59, type: 'delimiter.parenthesis.proto' }, + { startIndex: 60, type: 'white.proto' }, + { startIndex: 61, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option (method_option) = {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'annotation.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'operator.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' method_id: 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 15, type: 'delimiter.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'number.proto' }, + { startIndex: 18, type: 'delimiter.proto' } + ] + }, + { + line: ' method_name: "hello";', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 17, type: 'delimiter.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'string.quote.proto' }, + { startIndex: 20, type: 'string.proto' }, + { startIndex: 25, type: 'string.quote.proto' }, + { startIndex: 26, type: 'delimiter.proto' } + ] + }, + { + line: ' method_sla: 9.807E+4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 16, type: 'delimiter.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'number.proto' }, + { startIndex: 19, type: 'number.float.proto' }, + { startIndex: 26, type: 'delimiter.proto' } + ] + }, + { + line: ' };', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'delimiter.curly.proto' }, + { startIndex: 5, type: 'delimiter.proto' } + ] + }, + { + line: ' };', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' }, + { startIndex: 3, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message SearchRequest {};', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.curly.proto' }, + { startIndex: 24, type: 'delimiter.proto' } + ] + }, + { + line: 'message SearchResponse {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' string response = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'identifier.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'delimiter.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'number.proto' }, + { startIndex: 21, type: 'delimiter.proto' } + ] + }, + { + line: '};', + tokens: [ + { startIndex: 0, type: 'delimiter.curly.proto' }, + { startIndex: 1, type: 'delimiter.proto' } + ] + } + ], + // proto2 edge cases + [ + { + line: 'syntax = "proto2";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'operators.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'string.quote.proto' }, + { startIndex: 10, type: 'string.proto' }, + { startIndex: 16, type: 'string.quote.proto' }, + { startIndex: 17, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'package foo . /**/ bar;', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'comment.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 20, type: 'identifier.proto' }, + { startIndex: 23, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'import public "options.proto";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'keyword.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'string.quote.proto' }, + { startIndex: 15, type: 'string.proto' }, + { startIndex: 28, type: 'string.quote.proto' }, + { startIndex: 29, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'option java_package = "com.example.foo";', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'annotation.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'operator.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'string.quote.proto' }, + { startIndex: 23, type: 'string.proto' }, + { startIndex: 38, type: 'string.quote.proto' }, + { startIndex: 39, type: 'delimiter.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'message Foo {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' required foo.bar.Bar nested_message = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'identifier.proto' }, + { startIndex: 37, type: 'white.proto' }, + { startIndex: 38, type: 'delimiter.proto' }, + { startIndex: 39, type: 'white.proto' }, + { startIndex: 40, type: 'number.proto' }, + { startIndex: 41, type: 'delimiter.proto' } + ] + }, + { + line: ' repeated int32 samples = 3 [packed=true];', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 24, type: 'white.proto' }, + { startIndex: 25, type: 'delimiter.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'number.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'delimiter.square.proto' }, + { startIndex: 30, type: 'annotation.proto' }, + { startIndex: 36, type: 'operator.proto' }, + { startIndex: 37, type: 'keyword.constant.proto' }, + { startIndex: 41, type: 'delimiter.square.proto' }, + { startIndex: 42, type: 'delimiter.proto' } + ] + }, + { + line: ' oneof foo {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' string name = 4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'number.proto' }, + { startIndex: 19, type: 'delimiter.proto' } + ] + }, + { + line: ' Bar sub_message = 6;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'type.identifier.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'delimiter.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'number.proto' }, + { startIndex: 23, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' reserved 5, 15, 20 to 30;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'number.proto' }, + { startIndex: 12, type: 'delimiter.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'number.proto' }, + { startIndex: 16, type: 'delimiter.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'number.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'keyword.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'number.proto' }, + { startIndex: 26, type: 'delimiter.proto' } + ] + }, + { + line: ' reserved \'bar\' "baz";', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'string.quote.proto' }, + { startIndex: 12, type: 'string.proto' }, + { startIndex: 15, type: 'string.quote.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'string.quote.proto' }, + { startIndex: 18, type: 'string.proto' }, + { startIndex: 21, type: 'string.quote.proto' }, + { startIndex: 22, type: 'delimiter.proto' } + ] + }, + { + line: ' extensions 50 to 99;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'number.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'keyword.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'number.proto' }, + { startIndex: 21, type: 'delimiter.proto' } + ] + }, + { + line: ' reserved 100 to max ;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'number.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'keyword.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'keyword.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.proto' } + ] + }, + { + line: ' optional string baz = 10;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'identifier.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'number.proto' }, + { startIndex: 26, type: 'delimiter.proto' } + ] + }, + { + line: ' repeated group Result = 1 {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'operator.proto' }, + { startIndex: 25, type: 'white.proto' }, + { startIndex: 26, type: 'number.proto' }, + { startIndex: 27, type: 'white.proto' }, + { startIndex: 28, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' required string url = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'identifier.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'delimiter.proto' }, + { startIndex: 25, type: 'white.proto' }, + { startIndex: 26, type: 'number.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' optional string title = 3;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'identifier.proto' }, + { startIndex: 25, type: 'white.proto' }, + { startIndex: 26, type: 'delimiter.proto' }, + { startIndex: 27, type: 'white.proto' }, + { startIndex: 28, type: 'number.proto' }, + { startIndex: 29, type: 'delimiter.proto' } + ] + }, + { + line: ' repeated string snippets = 4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'identifier.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'delimiter.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'number.proto' }, + { startIndex: 32, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'extend Foo {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 6, type: 'white.proto' }, + { startIndex: 7, type: 'type.identifier.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' optional int32 bar = 50;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'delimiter.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'number.proto' }, + { startIndex: 25, type: 'delimiter.proto' } + ] + }, + { + line: ' repeated group More = 51 {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'operator.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'number.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' required string url = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'identifier.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'delimiter.proto' }, + { startIndex: 25, type: 'white.proto' }, + { startIndex: 26, type: 'number.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { line: 'message', tokens: [{ startIndex: 0, type: 'keyword.proto' }] }, + { + line: 'map {}', + tokens: [ + { startIndex: 0, type: 'type.identifier.proto' }, + { startIndex: 3, type: 'white.proto' }, + { startIndex: 4, type: 'delimiter.curly.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'message Bar {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' optional int32 x = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'delimiter.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'number.proto' }, + { startIndex: 22, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message int32 {}', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.curly.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: 'enum EnumAllowingAlias {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 4, type: 'white.proto' }, + { startIndex: 5, type: 'type.identifier.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option allow_alias = true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'operator.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'keyword.constant.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' uNkNoWN2 = 0;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'operators.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'number.octal.proto' }, + { startIndex: 14, type: 'delimiter.proto' } + ] + }, + { + line: ' ENUM_ALLOWING_ALIAS_UNKNOWN = 0;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 29, type: 'white.proto' }, + { startIndex: 30, type: 'operators.proto' }, + { startIndex: 31, type: 'white.proto' }, + { startIndex: 32, type: 'number.octal.proto' }, + { startIndex: 33, type: 'delimiter.proto' } + ] + }, + { + line: ' STARTED = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'delimiter.proto' } + ] + }, + { + line: " running = 2 [( /***/ custom_option) = 'hello world'];", + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'identifier.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'operators.proto' }, + { startIndex: 11, type: 'white.proto' }, + { startIndex: 12, type: 'number.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.square.proto' }, + { startIndex: 15, type: 'annotation.brackets.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'comment.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'annotation.proto' }, + { startIndex: 36, type: 'annotation.brackets.proto' }, + { startIndex: 37, type: 'white.proto' }, + { startIndex: 38, type: 'operator.proto' }, + { startIndex: 39, type: 'white.proto' }, + { startIndex: 40, type: 'string.quote.proto' }, + { startIndex: 41, type: 'string.proto' }, + { startIndex: 52, type: 'string.quote.proto' }, + { startIndex: 53, type: 'delimiter.square.proto' }, + { startIndex: 54, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message Outer {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 13, type: 'white.proto' }, + { startIndex: 14, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option (my_option).a= true;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 8, type: 'white.proto' }, + { startIndex: 9, type: 'annotation.proto' }, + { startIndex: 22, type: 'operator.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'keyword.constant.proto' }, + { startIndex: 28, type: 'delimiter.proto' } + ] + }, + { + line: ' message Inner { // Level 2', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 9, type: 'white.proto' }, + { startIndex: 10, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 20, type: 'comment.proto' } + ] + }, + { + line: ' required int64 ival = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'keyword.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'identifier.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'delimiter.proto' }, + { startIndex: 25, type: 'white.proto' }, + { startIndex: 26, type: 'number.proto' }, + { startIndex: 27, type: 'delimiter.proto' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' repeated Inner inner_message = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'identifier.proto' }, + { startIndex: 30, type: 'white.proto' }, + { startIndex: 31, type: 'delimiter.proto' }, + { startIndex: 32, type: 'white.proto' }, + { startIndex: 33, type: 'number.proto' }, + { startIndex: 34, type: 'delimiter.proto' } + ] + }, + { + line: ' optional foo .bar', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' } + ] + }, + { + line: ' /**/ .EnumAllowingAlias enum_field =3;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 3, type: 'comment.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'identifier.proto' }, + { startIndex: 37, type: 'white.proto' }, + { startIndex: 38, type: 'delimiter.proto' }, + { startIndex: 39, type: 'number.proto' }, + { startIndex: 40, type: 'delimiter.proto' } + ] + }, + { + line: ' optional map my_map = 4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'identifier.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.proto' }, + { startIndex: 23, type: 'white.proto' }, + { startIndex: 24, type: 'number.proto' }, + { startIndex: 25, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message message {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' repeated Foo enum = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'identifier.proto' }, + { startIndex: 19, type: 'white.proto' }, + { startIndex: 20, type: 'delimiter.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'number.proto' }, + { startIndex: 23, type: 'delimiter.proto' } + ] + }, + { + line: ' optional Foo int32 = 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 14, type: 'white.proto' }, + { startIndex: 15, type: 'identifier.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'delimiter.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'number.proto' }, + { startIndex: 24, type: 'delimiter.proto' } + ] + }, + { + line: ' optional service x = 3;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'type.identifier.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'identifier.proto' }, + { startIndex: 20, type: 'white.proto' }, + { startIndex: 21, type: 'delimiter.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'number.proto' }, + { startIndex: 24, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message service {}', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 15, type: 'white.proto' }, + { startIndex: 16, type: 'delimiter.curly.proto' } + ] + }, + { line: '', tokens: [] }, + { + line: '/** SearchService does nothing and returns the string "foo"', + tokens: [{ startIndex: 0, type: 'comment.proto' }] + }, + { line: '*/', tokens: [{ startIndex: 0, type: 'comment.proto' }] }, + { + line: 'service SearchService {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'identifier.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' rpc Search (SearchRequest) returns (SearchResponse) {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 5, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 12, type: 'white.proto' }, + { startIndex: 13, type: 'delimiter.parenthesis.proto' }, + { startIndex: 14, type: 'type.identifier.proto' }, + { startIndex: 27, type: 'delimiter.parenthesis.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'keyword.proto' }, + { startIndex: 36, type: 'white.proto' }, + { startIndex: 37, type: 'delimiter.parenthesis.proto' }, + { startIndex: 38, type: 'type.identifier.proto' }, + { startIndex: 52, type: 'delimiter.parenthesis.proto' }, + { startIndex: 53, type: 'white.proto' }, + { startIndex: 54, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' option (method_option) = {', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'annotation.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'operator.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' method_id: 2;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 15, type: 'delimiter.proto' }, + { startIndex: 16, type: 'white.proto' }, + { startIndex: 17, type: 'number.proto' }, + { startIndex: 18, type: 'delimiter.proto' } + ] + }, + { + line: ' method_name: "hello";', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 17, type: 'delimiter.proto' }, + { startIndex: 18, type: 'white.proto' }, + { startIndex: 19, type: 'string.quote.proto' }, + { startIndex: 20, type: 'string.proto' }, + { startIndex: 25, type: 'string.quote.proto' }, + { startIndex: 26, type: 'delimiter.proto' } + ] + }, + { + line: ' method_sla: 9.807E+4;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 6, type: 'identifier.proto' }, + { startIndex: 16, type: 'delimiter.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'number.proto' }, + { startIndex: 19, type: 'number.float.proto' }, + { startIndex: 26, type: 'delimiter.proto' } + ] + }, + { + line: ' };', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 4, type: 'delimiter.curly.proto' }, + { startIndex: 5, type: 'delimiter.proto' } + ] + }, + { + line: ' };', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'delimiter.curly.proto' }, + { startIndex: 3, type: 'delimiter.proto' } + ] + }, + { line: '}', tokens: [{ startIndex: 0, type: 'delimiter.curly.proto' }] }, + { line: '', tokens: [] }, + { + line: 'message SearchRequest {};', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 21, type: 'white.proto' }, + { startIndex: 22, type: 'delimiter.curly.proto' }, + { startIndex: 24, type: 'delimiter.proto' } + ] + }, + { + line: 'message SearchResponse {', + tokens: [ + { startIndex: 0, type: 'keyword.proto' }, + { startIndex: 7, type: 'white.proto' }, + { startIndex: 8, type: 'type.identifier.proto' }, + { startIndex: 22, type: 'white.proto' }, + { startIndex: 23, type: 'delimiter.curly.proto' } + ] + }, + { + line: ' optional string response = 1;', + tokens: [ + { startIndex: 0, type: 'white.proto' }, + { startIndex: 2, type: 'keyword.proto' }, + { startIndex: 10, type: 'white.proto' }, + { startIndex: 11, type: 'keyword.proto' }, + { startIndex: 17, type: 'white.proto' }, + { startIndex: 18, type: 'identifier.proto' }, + { startIndex: 26, type: 'white.proto' }, + { startIndex: 27, type: 'delimiter.proto' }, + { startIndex: 28, type: 'white.proto' }, + { startIndex: 29, type: 'number.proto' }, + { startIndex: 30, type: 'delimiter.proto' } + ] + }, + { + line: '};', + tokens: [ + { startIndex: 0, type: 'delimiter.curly.proto' }, + { startIndex: 1, type: 'delimiter.proto' } + ] + } + ] +]); diff --git a/monaco-languages/src/protobuf/protobuf.ts b/monaco-languages/src/protobuf/protobuf.ts new file mode 100644 index 00000000..88ef1b68 --- /dev/null +++ b/monaco-languages/src/protobuf/protobuf.ts @@ -0,0 +1,464 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import type { languages } from '../fillers/monaco-editor-core'; + +const namedLiterals = ['true', 'false']; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//', + blockComment: ['/*', '*/'] + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'], + ['<', '>'] + ], + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '<', close: '>' }, + { open: '"', close: '"', notIn: ['string'] }, + { open: "'", close: "'", notIn: ['string'] } + ], + autoCloseBefore: ".,=}])>' \n\t", + indentationRules: { + increaseIndentPattern: new RegExp( + '^((?!\\/\\/).)*(\\{[^}"\'`]*|\\([^)"\'`]*|\\[[^\\]"\'`]*)$' + ), + decreaseIndentPattern: new RegExp('^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$') + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.proto', + + brackets: [ + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '<', close: '>', token: 'delimiter.angle' } + ], + + symbols: /[=>/, { token: '@brackets', bracket: '@close', switchTo: 'identifier' }] + ], + + field: [ + { include: '@whitespace' }, + [ + 'group', + { + cases: { + '$S2==proto2': { token: 'keyword', switchTo: '@groupDecl.$S2' } + } + } + ], + [ + /(@identifier)(\s*)(=)/, + ['identifier', 'white', { token: 'delimiter', next: '@pop' }] + ], + [ + /@fullIdentifier|\./, + { + cases: { + '@builtinTypes': 'keyword', + '@default': 'type.identifier' + } + } + ] + ], + + groupDecl: [ + { include: '@whitespace' }, + [/@identifier/, 'identifier'], + ['=', 'operator'], + [/{/, { token: '@brackets', bracket: '@open', switchTo: '@messageBody.$S2' }], + { include: '@constant' } + ], + + type: [ + { include: '@whitespace' }, + [/@identifier/, 'type.identifier', '@pop'], + [/./, 'delimiter'] + ], + + identifier: [{ include: '@whitespace' }, [/@identifier/, 'identifier', '@pop']], + + serviceDecl: [ + { include: '@whitespace' }, + [/@identifier/, 'identifier'], + [/{/, { token: '@brackets', bracket: '@open', switchTo: '@serviceBody.$S2' }] + ], + + serviceBody: [ + { include: '@whitespace' }, + { include: '@constant' }, + [/;/, 'delimiter'], + [/option\b/, 'keyword', '@option.$S2'], + [/rpc\b/, 'keyword', '@rpc.$S2'], + [/\[/, { token: '@brackets', bracket: '@open', next: '@options.$S2' }], + [/}/, { token: '@brackets', bracket: '@close', next: '@pop' }] + ], + + rpc: [ + { include: '@whitespace' }, + [/@identifier/, 'identifier'], + [/\(/, { token: '@brackets', bracket: '@open', switchTo: '@request.$S2' }], + [/{/, { token: '@brackets', bracket: '@open', next: '@methodOptions.$S2' }], + [/;/, 'delimiter', '@pop'] + ], + + request: [ + { include: '@whitespace' }, + [ + /@messageType/, + { + cases: { + stream: { token: 'keyword', next: '@type.$S2' }, + '@default': 'type.identifier' + } + } + ], + [/\)/, { token: '@brackets', bracket: '@close', switchTo: '@returns.$S2' }] + ], + + returns: [ + { include: '@whitespace' }, + [/returns\b/, 'keyword'], + [/\(/, { token: '@brackets', bracket: '@open', switchTo: '@response.$S2' }] + ], + + response: [ + { include: '@whitespace' }, + [ + /@messageType/, + { + cases: { + stream: { token: 'keyword', next: '@type.$S2' }, + '@default': 'type.identifier' + } + } + ], + [/\)/, { token: '@brackets', bracket: '@close', switchTo: '@rpc.$S2' }] + ], + + methodOptions: [ + { include: '@whitespace' }, + { include: '@constant' }, + [/;/, 'delimiter'], + ['option', 'keyword'], + [/@optionName/, 'annotation'], + [/[()]/, 'annotation.brackets'], + [/=/, 'operator'], + [/}/, { token: '@brackets', bracket: '@close', next: '@pop' }] + ], + + comment: [ + [/[^\/*]+/, 'comment'], + [/\/\*/, 'comment', '@push'], // nested comment + ['\\*/', 'comment', '@pop'], + [/[\/*]/, 'comment'] + ], + + string: [ + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }] + ], + + stringSingle: [ + [/[^\\']+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/'/, { token: 'string.quote', bracket: '@close', next: '@pop' }] + ], + + constant: [ + ['@boolLit', 'keyword.constant'], + ['@hexLit', 'number.hex'], + ['@octalLit', 'number.octal'], + ['@decimalLit', 'number'], + ['@floatLit', 'number.float'], + [/("([^"\\]|\\.)*|'([^'\\]|\\.)*)$/, 'string.invalid'], // non-terminated string + [/"/, { token: 'string.quote', bracket: '@open', next: '@string' }], + [/'/, { token: 'string.quote', bracket: '@open', next: '@stringSingle' }], + [/{/, { token: '@brackets', bracket: '@open', next: '@prototext' }], + [/identifier/, 'identifier'] + ], + + whitespace: [ + [/[ \t\r\n]+/, 'white'], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'] + ], + + prototext: [ + { include: '@whitespace' }, + { include: '@constant' }, + [/@identifier/, 'identifier'], + [/[:;]/, 'delimiter'], + [/}/, { token: '@brackets', bracket: '@close', next: '@pop' }] + ] + } +}; diff --git a/monaco-languages/src/pug/pug.contribution.ts b/monaco-languages/src/pug/pug.contribution.ts new file mode 100644 index 00000000..d097ee30 --- /dev/null +++ b/monaco-languages/src/pug/pug.contribution.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerLanguage } from '../_.contribution'; + +registerLanguage({ + id: 'pug', + extensions: ['.jade', '.pug'], + aliases: ['Pug', 'Jade', 'jade'], + loader: () => import('./pug') +}); diff --git a/monaco-languages/src/pug/pug.test.ts b/monaco-languages/src/pug/pug.test.ts new file mode 100644 index 00000000..8e701014 --- /dev/null +++ b/monaco-languages/src/pug/pug.test.ts @@ -0,0 +1,473 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { testTokenization } from '../test/testRunner'; + +testTokenization('pug', [ + // Tags [Pug] + [ + { + line: 'p 5', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 1, type: '' } + ] + } + ], + + [ + { + line: 'div#container.stuff', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 3, type: 'tag.id.pug' }, + { startIndex: 13, type: 'tag.class.pug' } + ] + } + ], + + [ + { + line: 'div.container#stuff', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 3, type: 'tag.class.pug' }, + { startIndex: 13, type: 'tag.id.pug' } + ] + } + ], + + [ + { + line: 'div.container#stuff .container', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 3, type: 'tag.class.pug' }, + { startIndex: 13, type: 'tag.id.pug' }, + { startIndex: 19, type: '' } + ] + } + ], + + [ + { + line: '#tag-id-1', + tokens: [{ startIndex: 0, type: 'tag.id.pug' }] + } + ], + + [ + { + line: '.tag-id-1', + tokens: [{ startIndex: 0, type: 'tag.class.pug' }] + } + ], + + // Attributes - Single Line [Pug] + [ + { + line: 'input(type="checkbox")', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 5, type: 'delimiter.parenthesis.pug' }, + { startIndex: 6, type: 'attribute.name.pug' }, + { startIndex: 10, type: 'delimiter.pug' }, + { startIndex: 11, type: 'attribute.value.pug' }, + { startIndex: 21, type: 'delimiter.parenthesis.pug' } + ] + } + ], + + [ + { + line: 'input (type="checkbox")', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 5, type: '' } + ] + } + ], + + [ + { + line: 'input(type="checkbox",name="agreement",checked)', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 5, type: 'delimiter.parenthesis.pug' }, + { startIndex: 6, type: 'attribute.name.pug' }, + { startIndex: 10, type: 'delimiter.pug' }, + { startIndex: 11, type: 'attribute.value.pug' }, + { startIndex: 21, type: 'attribute.delimiter.pug' }, + { startIndex: 22, type: 'attribute.name.pug' }, + { startIndex: 26, type: 'delimiter.pug' }, + { startIndex: 27, type: 'attribute.value.pug' }, + { startIndex: 38, type: 'attribute.delimiter.pug' }, + { startIndex: 39, type: 'attribute.name.pug' }, + { startIndex: 46, type: 'delimiter.parenthesis.pug' } + ] + } + ], + + [ + { + line: 'input(type="checkbox"', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 5, type: 'delimiter.parenthesis.pug' }, + { startIndex: 6, type: 'attribute.name.pug' }, + { startIndex: 10, type: 'delimiter.pug' }, + { startIndex: 11, type: 'attribute.value.pug' } + ] + }, + { + line: 'name="agreement"', + tokens: [ + { startIndex: 0, type: 'attribute.name.pug' }, + { startIndex: 4, type: 'delimiter.pug' }, + { startIndex: 5, type: 'attribute.value.pug' } + ] + }, + { + line: 'checked)', + tokens: [ + { startIndex: 0, type: 'attribute.name.pug' }, + { startIndex: 7, type: 'delimiter.parenthesis.pug' } + ] + }, + { + line: 'body', + tokens: [{ startIndex: 0, type: 'tag.pug' }] + } + ], + + // Attributes - MultiLine [Pug] + [ + { + line: 'input(type="checkbox"', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 5, type: 'delimiter.parenthesis.pug' }, + { startIndex: 6, type: 'attribute.name.pug' }, + { startIndex: 10, type: 'delimiter.pug' }, + { startIndex: 11, type: 'attribute.value.pug' } + ] + }, + { + line: 'disabled', + tokens: [{ startIndex: 0, type: 'attribute.name.pug' }] + }, + { + line: 'checked)', + tokens: [ + { startIndex: 0, type: 'attribute.name.pug' }, + { startIndex: 7, type: 'delimiter.parenthesis.pug' } + ] + }, + { + line: 'body', + tokens: [{ startIndex: 0, type: 'tag.pug' }] + } + ], + + // Interpolation [Pug] + [ + { + line: 'p print #{count} lines', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 1, type: '' }, + { startIndex: 8, type: 'interpolation.delimiter.pug' }, + { startIndex: 10, type: 'interpolation.pug' }, + { startIndex: 15, type: 'interpolation.delimiter.pug' }, + { startIndex: 16, type: '' } + ] + } + ], + + [ + { + line: 'p print "#{count}" lines', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 1, type: '' }, + { startIndex: 9, type: 'interpolation.delimiter.pug' }, + { startIndex: 11, type: 'interpolation.pug' }, + { startIndex: 16, type: 'interpolation.delimiter.pug' }, + { startIndex: 17, type: '' } + ] + } + ], + + [ + { + line: '{ key: 123 }', + tokens: [ + { startIndex: 0, type: 'delimiter.curly.pug' }, + { startIndex: 1, type: '' }, + { startIndex: 5, type: 'delimiter.pug' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.pug' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.curly.pug' } + ] + } + ], + + // Comments - Single Line [Pug] + [ + { + line: '// html#id1.class1', + tokens: [{ startIndex: 0, type: 'comment.pug' }] + } + ], + + [ + { + line: 'body hello // not a comment 123', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 4, type: '' } + ] + } + ], + + // Comments - MultiLine [Pug] + [ + { + line: '//', + tokens: [{ startIndex: 0, type: 'comment.pug' }] + }, + { + line: ' should be a comment', + tokens: [{ startIndex: 0, type: 'comment.pug' }] + }, + { + line: ' should still be a comment', + tokens: [{ startIndex: 0, type: 'comment.pug' }] + }, + { + line: 'div should not be a comment', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 3, type: '' } + ] + } + ], + + // Code [Pug] + [ + { + line: '- var a = 1', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.var.pug' }, + { startIndex: 5, type: '' }, + { startIndex: 8, type: 'delimiter.pug' }, + { startIndex: 9, type: '' }, + { startIndex: 10, type: 'number.pug' } + ] + } + ], + + [ + { + line: 'each item in items', + tokens: [ + { startIndex: 0, type: 'keyword.each.pug' }, + { startIndex: 4, type: '' }, + { startIndex: 10, type: 'keyword.in.pug' }, + { startIndex: 12, type: '' } + ] + } + ], + + [ + { + line: '- var html = ""', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'keyword.var.pug' }, + { startIndex: 5, type: '' }, + { startIndex: 11, type: 'delimiter.pug' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'string.pug' } + ] + } + ], + + // Generated from sample + [ + { + line: 'doctype 5', + tokens: [ + { startIndex: 0, type: 'keyword.doctype.pug' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'number.pug' } + ] + }, + { + line: 'html(lang="en")', + tokens: [ + { startIndex: 0, type: 'tag.pug' }, + { startIndex: 4, type: 'delimiter.parenthesis.pug' }, + { startIndex: 5, type: 'attribute.name.pug' }, + { startIndex: 9, type: 'delimiter.pug' }, + { startIndex: 10, type: 'attribute.value.pug' }, + { startIndex: 14, type: 'delimiter.parenthesis.pug' } + ] + }, + { + line: ' head', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'tag.pug' } + ] + }, + { + line: ' title= pageTitle', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'tag.pug' }, + { startIndex: 13, type: '' } + ] + }, + { + line: " script(type='text/javascript')", + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'tag.pug' }, + { startIndex: 14, type: 'delimiter.parenthesis.pug' }, + { startIndex: 15, type: 'attribute.name.pug' }, + { startIndex: 19, type: 'delimiter.pug' }, + { startIndex: 20, type: 'attribute.value.pug' }, + { startIndex: 37, type: 'delimiter.parenthesis.pug' } + ] + }, + { + line: ' if (foo) {', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 12, type: 'keyword.if.pug' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'delimiter.parenthesis.pug' }, + { startIndex: 16, type: '' }, + { startIndex: 19, type: 'delimiter.parenthesis.pug' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.curly.pug' } + ] + }, + { + line: ' bar()', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 19, type: 'delimiter.parenthesis.pug' } + ] + }, + { + line: ' }', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 12, type: 'delimiter.curly.pug' } + ] + }, + { + line: ' body', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 4, type: 'tag.pug' } + ] + }, + { + line: ' // Disclaimer: You will need to turn insertSpaces to true in order for the', + tokens: [{ startIndex: 0, type: 'comment.pug' }] + }, + { + line: ' syntax highlighting to kick in properly (especially for comments)', + tokens: [{ startIndex: 0, type: 'comment.pug' }] + }, + { + line: ' Enjoy :)', + tokens: [{ startIndex: 0, type: 'comment.pug' }] + }, + { + line: ' h1 Pug - node template engine if in', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'tag.pug' }, + { startIndex: 10, type: '' } + ] + }, + { + line: ' p.', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'tag.pug' }, + { startIndex: 9, type: 'delimiter.pug' } + ] + }, + { + line: ' text ', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' text', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' #container', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' #container', + tokens: [{ startIndex: 0, type: '' }] + }, + { + line: ' #container', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 8, type: 'tag.id.pug' } + ] + }, + { + line: ' if youAreUsingPug', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 10, type: 'keyword.if.pug' }, + { startIndex: 12, type: '' } + ] + }, + { + line: ' p You are amazing', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 12, type: 'tag.pug' }, + { startIndex: 13, type: '' } + ] + }, + { + line: ' else', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 10, type: 'keyword.else.pug' } + ] + }, + { + line: ' p Get on it!', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 12, type: 'tag.pug' }, + { startIndex: 13, type: '' } + ] + }, + { + line: ' p Text can be included in a number of different ways.', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 5, type: 'tag.pug' }, + { startIndex: 6, type: '' } + ] + } + ] +]); diff --git a/monaco-languages/src/pug/pug.ts b/monaco-languages/src/pug/pug.ts new file mode 100644 index 00000000..8b3afd4f --- /dev/null +++ b/monaco-languages/src/pug/pug.ts @@ -0,0 +1,441 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + comments: { + lineComment: '//' + }, + brackets: [ + ['{', '}'], + ['[', ']'], + ['(', ')'] + ], + autoClosingPairs: [ + { open: '"', close: '"', notIn: ['string', 'comment'] }, + { open: "'", close: "'", notIn: ['string', 'comment'] }, + { open: '{', close: '}', notIn: ['string', 'comment'] }, + { open: '[', close: ']', notIn: ['string', 'comment'] }, + { open: '(', close: ')', notIn: ['string', 'comment'] } + ], + folding: { + offSide: true + } +}; + +export const language = { + defaultToken: '', + tokenPostfix: '.pug', + + ignoreCase: true, + + brackets: [ + { token: 'delimiter.curly', open: '{', close: '}' }, + { token: 'delimiter.array', open: '[', close: ']' }, + { token: 'delimiter.parenthesis', open: '(', close: ')' } + ], + + keywords: [ + 'append', + 'block', + 'case', + 'default', + 'doctype', + 'each', + 'else', + 'extends', + 'for', + 'if', + 'in', + 'include', + 'mixin', + 'typeof', + 'unless', + 'var', + 'when' + ], + + tags: [ + 'a', + 'abbr', + 'acronym', + 'address', + 'area', + 'article', + 'aside', + 'audio', + 'b', + 'base', + 'basefont', + 'bdi', + 'bdo', + 'blockquote', + 'body', + 'br', + 'button', + 'canvas', + 'caption', + 'center', + 'cite', + 'code', + 'col', + 'colgroup', + 'command', + 'datalist', + 'dd', + 'del', + 'details', + 'dfn', + 'div', + 'dl', + 'dt', + 'em', + 'embed', + 'fieldset', + 'figcaption', + 'figure', + 'font', + 'footer', + 'form', + 'frame', + 'frameset', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'head', + 'header', + 'hgroup', + 'hr', + 'html', + 'i', + 'iframe', + 'img', + 'input', + 'ins', + 'keygen', + 'kbd', + 'label', + 'li', + 'link', + 'map', + 'mark', + 'menu', + 'meta', + 'meter', + 'nav', + 'noframes', + 'noscript', + 'object', + 'ol', + 'optgroup', + 'option', + 'output', + 'p', + 'param', + 'pre', + 'progress', + 'q', + 'rp', + 'rt', + 'ruby', + 's', + 'samp', + 'script', + 'section', + 'select', + 'small', + 'source', + 'span', + 'strike', + 'strong', + 'style', + 'sub', + 'summary', + 'sup', + 'table', + 'tbody', + 'td', + 'textarea', + 'tfoot', + 'th', + 'thead', + 'time', + 'title', + 'tr', + 'tracks', + 'tt', + 'u', + 'ul', + 'video', + 'wbr' + ], + + // we include these common regular expressions + symbols: /[\+\-\*\%\&\|\!\=\/\.\,\:]+/, + escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, + + tokenizer: { + root: [ + // Tag or a keyword at start + [ + /^(\s*)([a-zA-Z_-][\w-]*)/, + { + cases: { + '$2@tags': { + cases: { + '@eos': ['', 'tag'], + '@default': ['', { token: 'tag', next: '@tag.$1' }] + } + }, + '$2@keywords': ['', { token: 'keyword.$2' }], + '@default': ['', ''] + } + } + ], + + // id + [ + /^(\s*)(#[a-zA-Z_-][\w-]*)/, + { + cases: { + '@eos': ['', 'tag.id'], + '@default': ['', { token: 'tag.id', next: '@tag.$1' }] + } + } + ], + + // class + [ + /^(\s*)(\.[a-zA-Z_-][\w-]*)/, + { + cases: { + '@eos': ['', 'tag.class'], + '@default': ['', { token: 'tag.class', next: '@tag.$1' }] + } + } + ], + + // plain text with pipe + [/^(\s*)(\|.*)$/, ''], + + { include: '@whitespace' }, + + // keywords + [ + /[a-zA-Z_$][\w$]*/, + { + cases: { + '@keywords': { token: 'keyword.$0' }, + '@default': '' + } + } + ], + + // delimiters and operators + [/[{}()\[\]]/, '@brackets'], + [/@symbols/, 'delimiter'], + + // numbers + [/\d+\.\d+([eE][\-+]?\d+)?/, 'number.float'], + [/\d+/, 'number'], + + // strings: + [/"/, 'string', '@string."'], + [/'/, 'string', "@string.'"] + ], + + tag: [ + [/(\.)(\s*$)/, [{ token: 'delimiter', next: '@blockText.$S2.' }, '']], + [/\s+/, { token: '', next: '@simpleText' }], + + // id + [ + /#[a-zA-Z_-][\w-]*/, + { + cases: { + '@eos': { token: 'tag.id', next: '@pop' }, + '@default': 'tag.id' + } + } + ], + // class + [ + /\.[a-zA-Z_-][\w-]*/, + { + cases: { + '@eos': { token: 'tag.class', next: '@pop' }, + '@default': 'tag.class' + } + } + ], + // attributes + [/\(/, { token: 'delimiter.parenthesis', next: '@attributeList' }] + ], + + simpleText: [ + [/[^#]+$/, { token: '', next: '@popall' }], + [/[^#]+/, { token: '' }], + + // interpolation + [ + /(#{)([^}]*)(})/, + { + cases: { + '@eos': [ + 'interpolation.delimiter', + 'interpolation', + { + token: 'interpolation.delimiter', + next: '@popall' + } + ], + '@default': [ + 'interpolation.delimiter', + 'interpolation', + 'interpolation.delimiter' + ] + } + } + ], + + [/#$/, { token: '', next: '@popall' }], + [/#/, ''] + ], + + attributeList: [ + [/\s+/, ''], + [ + /(\w+)(\s*=\s*)("|')/, + ['attribute.name', 'delimiter', { token: 'attribute.value', next: '@value.$3' }] + ], + [/\w+/, 'attribute.name'], + + [ + /,/, + { + cases: { + '@eos': { + token: 'attribute.delimiter', + next: '@popall' + }, + '@default': 'attribute.delimiter' + } + } + ], + + [/\)$/, { token: 'delimiter.parenthesis', next: '@popall' }], + [/\)/, { token: 'delimiter.parenthesis', next: '@pop' }] + ], + + whitespace: [ + [/^(\s*)(\/\/.*)$/, { token: 'comment', next: '@blockText.$1.comment' }], + [/[ \t\r\n]+/, ''], + [//, { token: 'comment', next: '@pop' }], + [/'] + }, + + brackets: [ + [''], + ['<', '>'], + ['{', '}'], + ['(', ')'] + ], + + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + surroundingPairs: [ + { open: '"', close: '"' }, + { open: "'", close: "'" }, + { open: '<', close: '>' } + ], + + onEnterRules: [ + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + afterText: /^<\/(\w[\w\d]*)\s*>$/i, + action: { + indentAction: languages.IndentAction.IndentOutdent + } + }, + { + beforeText: new RegExp( + `<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, + 'i' + ), + action: { indentAction: languages.IndentAction.Indent } + } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '', + // ignoreCase: true, + + // The main tokenizer for our languages + tokenizer: { + root: [ + [/@@@@/], // text + [/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.root' }], + [/)/, ['delimiter.html', 'tag.html', 'delimiter.html']], + [/(<)(script)/, ['delimiter.html', { token: 'tag.html', next: '@script' }]], + [/(<)(style)/, ['delimiter.html', { token: 'tag.html', next: '@style' }]], + [/(<)([:\w\-]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [/(<\/)([\w\-]+)/, ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]], + [/]+/, 'metatag.content.html'], + [/>/, 'metatag.html', '@pop'] + ], + + comment: [ + [/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.comment' }], + [/-->/, 'comment.html', '@pop'], + [/[^-]+/, 'comment.content.html'], + [/./, 'comment.content.html'] + ], + + otherTag: [ + [/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.otherTag' }], + [/\/?>/, 'delimiter.html', '@pop'], + [/"([^"]*)"/, 'attribute.value'], + [/'([^']*)'/, 'attribute.value'], + [/[\w\-]+/, 'attribute.name'], + [/=/, 'delimiter'], + [/[ \t\r\n]+/] // whitespace + ], + + // -- BEGIN ', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' }, + { startIndex: 13, type: 'attribute.value.html' }, + { startIndex: 30, type: 'delimiter.html' }, + { startIndex: 31, type: 'keyword.js' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'identifier.js' }, + { startIndex: 36, type: 'delimiter.js' }, + { startIndex: 37, type: '' }, + { startIndex: 38, type: 'number.js' }, + { startIndex: 40, type: 'delimiter.js' }, + { startIndex: 41, type: 'delimiter.html' }, + { startIndex: 43, type: 'tag.html' }, + { startIndex: 49, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #2 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 2, type: 'tag.html' }, + { startIndex: 8, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #3 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 2, type: 'tag.html' }, + { startIndex: 8, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #4 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'keyword.js' }, + { startIndex: 3, type: '' }, + { startIndex: 4, type: 'identifier.js' }, + { startIndex: 5, type: 'delimiter.js' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.js' }, + { startIndex: 9, type: 'delimiter.js' }, + { startIndex: 10, type: 'delimiter.html' }, + { startIndex: 12, type: 'tag.html' }, + { startIndex: 18, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #5 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: '' }, + { startIndex: 2, type: 'delimiter.html' }, + { startIndex: 4, type: 'tag.html' }, + { startIndex: 10, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #6 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: 'delimiter.html' }, + { startIndex: 8, type: 'identifier.js' }, + { startIndex: 9, type: 'delimiter.html' }, + { startIndex: 11, type: 'tag.html' }, + { startIndex: 17, type: 'delimiter.html' }, + // { startIndex:18, type: 'delimiter.html' }, + { startIndex: 19, type: 'tag.html' }, + { startIndex: 25, type: 'delimiter.html' }, + { startIndex: 26, type: 'identifier.js' }, + { startIndex: 27, type: 'delimiter.html' }, + { startIndex: 29, type: 'tag.html' }, + { startIndex: 35, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #7 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' }, + { startIndex: 13, type: 'attribute.value.html' }, + { startIndex: 30, type: 'delimiter.html' }, + // { startIndex:31, type: 'delimiter.html' }, + { startIndex: 33, type: 'tag.html' }, + { startIndex: 39, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #8 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: 'delimiter.html' }, + { startIndex: 8, type: 'keyword.js' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'identifier.js' }, + { startIndex: 13, type: 'delimiter.js' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'number.js' }, + { startIndex: 17, type: 'delimiter.js' }, + { startIndex: 18, type: 'delimiter.html' }, + { startIndex: 20, type: 'tag.html' }, + { startIndex: 26, type: 'delimiter.html' } + ] + } + ], + + // Embedded Content #9 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' }, + { startIndex: 13, type: 'attribute.value.html' }, + { startIndex: 30, type: '' }, + { startIndex: 31, type: 'attribute.name.html' }, + { startIndex: 34, type: 'delimiter.html' }, + { startIndex: 35, type: 'attribute.value.html' }, + { startIndex: 44, type: 'delimiter.html' }, + // { startIndex:45, type: 'delimiter.html' }, + { startIndex: 47, type: 'tag.html' }, + { startIndex: 53, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attribute + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 14, type: 'delimiter.html' } + ] + } + ], + + // Tag with Empty Attribute Value + [ + { + line: "", + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 14, type: 'delimiter.html' } + ] + } + ], + + // Tag with empty attributes + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 11, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attributes + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.value.html' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'attribute.name.html' }, + { startIndex: 18, type: 'delimiter.html' }, + { startIndex: 19, type: 'attribute.value.html' }, + { startIndex: 24, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attributes, no quotes + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: 'attribute.name.html' }, // slightly incorrect + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'attribute.name.html' }, + { startIndex: 16, type: 'delimiter.html' }, + { startIndex: 17, type: 'attribute.name.html' }, // slightly incorrect + { startIndex: 24, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attribute And Whitespace + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' }, + { startIndex: 9, type: '' }, + { startIndex: 11, type: 'attribute.value.html' }, + { startIndex: 16, type: 'delimiter.html' } + ] + } + ], + + // Tag with Attribute And Whitespace #2 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'delimiter.html' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'attribute.value.html' }, + { startIndex: 16, type: 'delimiter.html' } + ] + } + ], + + // Tag with Name-Only-Attribute #1 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: 'delimiter.html' } + ] + } + ], + + // Tag with Name-Only-Attribute #2 + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'attribute.name.html' }, + { startIndex: 12, type: 'delimiter.html' } + ] + } + ], + + // Tag with Interesting Attribute Name + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'attribute.name.html' }, + { startIndex: 8, type: '' }, + { startIndex: 11, type: 'delimiter.html' }, + { startIndex: 12, type: 'attribute.value.html' }, + { startIndex: 17, type: 'delimiter.html' } + ] + } + ], + + // Tag with Angular Attribute Name + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 4, type: '' }, + { startIndex: 6, type: 'attribute.name.html' }, + { startIndex: 13, type: '' }, + { startIndex: 15, type: 'attribute.name.html' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'delimiter.html' }, + { startIndex: 22, type: 'attribute.value.html' }, + { startIndex: 27, type: '' }, + { startIndex: 29, type: 'attribute.name.html' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'delimiter.html' }, + { startIndex: 36, type: 'attribute.value.html' }, + { startIndex: 50, type: '' }, + { startIndex: 52, type: 'attribute.name.html' }, + { startIndex: 56, type: 'delimiter.html' }, + { startIndex: 57, type: 'attribute.value.html' }, + { startIndex: 72, type: 'delimiter.html' } + ] + } + ], + + // Tag with Invalid Attribute Value + [ + { + line: '', + tokens: [ + { startIndex: 0, type: 'metatag.content.html' }, + { startIndex: 11, type: 'metatag.html' } + ] + } + ], + + // PR #14 + [ + { + line: 'asd', + tokens: [ + { startIndex: 0, type: 'delimiter.html' }, + { startIndex: 1, type: 'tag.html' }, + { startIndex: 9, type: 'delimiter.html' }, + { startIndex: 10, type: '' }, + { startIndex: 13, type: 'delimiter.html' }, + { startIndex: 15, type: 'tag.html' }, + { startIndex: 23, type: 'delimiter.html' } + ] + } + ] + ] +); + +/** + * Twig Tests + */ +testTokenization( + ['twig'], + [ + /** + * Comments + */ + [ + { + line: '{# Hello World! #}', + tokens: [{ startIndex: 0, type: 'comment.twig' }] + } + ], + [ + { + line: '{#Hello World!#}', + tokens: [{ startIndex: 0, type: 'comment.twig' }] + } + ], + + /** + * Variables Tags + */ + // Whitespace + [ + { + line: '{{}}', + tokens: [{ startIndex: 0, type: 'delimiter.twig' }] + } + ], + [ + { + line: '{{ }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.twig' } + ] + } + ], + // Numbers + [ + { + line: '{{1}}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: 'number.twig' }, + { startIndex: 3, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{{ 1 }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.twig' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{{ 1 }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.twig' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{{ 1.1 }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.twig' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.twig' } + ] + } + ], + // Strings + [ + { + line: "{{ 'hi' }}", + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'string.twig' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{{ "hi" }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'string.twig' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{{ "hi #{1}" }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'string.twig' }, + { startIndex: 9, type: 'number.twig' }, + { startIndex: 10, type: 'string.twig' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'delimiter.twig' } + ] + } + ], + // Variables and functions + [ + { + line: '{{ foo }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'variable.twig' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{{ foo(42) }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'variable.twig' }, + { startIndex: 6, type: 'delimiter.twig' }, + { startIndex: 7, type: 'number.twig' }, + { startIndex: 9, type: 'delimiter.twig' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'delimiter.twig' } + ] + } + ], + // Operators + [ + { + line: '{{ 1 + 2 - 3 / 4 // 5 % 6 * 7 ** 8 }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'number.twig' }, + { startIndex: 4, type: '' }, + { startIndex: 5, type: 'operators.twig' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'number.twig' }, + { startIndex: 8, type: '' }, + { startIndex: 9, type: 'operators.twig' }, + { startIndex: 10, type: '' }, + { startIndex: 11, type: 'number.twig' }, + { startIndex: 12, type: '' }, + { startIndex: 13, type: 'operators.twig' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'number.twig' }, + { startIndex: 16, type: '' }, + { startIndex: 17, type: 'operators.twig' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'number.twig' }, + { startIndex: 21, type: '' }, + { startIndex: 22, type: 'operators.twig' }, + { startIndex: 23, type: '' }, + { startIndex: 24, type: 'number.twig' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'operators.twig' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'number.twig' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'operators.twig' }, + { startIndex: 32, type: '' }, + { startIndex: 33, type: 'number.twig' }, + { startIndex: 34, type: '' }, + { startIndex: 35, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{{ true and false or true and not false }}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'keyword.twig' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'operators.twig' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'keyword.twig' }, + { startIndex: 17, type: '' }, + { startIndex: 18, type: 'operators.twig' }, + { startIndex: 20, type: '' }, + { startIndex: 21, type: 'keyword.twig' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'operators.twig' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'operators.twig' }, + { startIndex: 33, type: '' }, + { startIndex: 34, type: 'keyword.twig' }, + { startIndex: 39, type: '' }, + { startIndex: 40, type: 'delimiter.twig' } + ] + } + ], + + /** + * Block Tags + */ + [ + { + line: '{%%}', + tokens: [{ startIndex: 0, type: 'delimiter.twig' }] + } + ], + [ + { + line: '{% %}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{% for item in navigation %}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'keyword.twig' }, + { startIndex: 6, type: '' }, + { startIndex: 7, type: 'variable.twig' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'operators.twig' }, + { startIndex: 14, type: '' }, + { startIndex: 15, type: 'variable.twig' }, + { startIndex: 25, type: '' }, + { startIndex: 26, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{% verbatim %}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'keyword.twig' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.twig' } + ] + } + ], + [ + { + line: '{% verbatim %}raw data{% endverbatim %}', + tokens: [ + { startIndex: 0, type: 'delimiter.twig' }, + { startIndex: 2, type: '' }, + { startIndex: 3, type: 'keyword.twig' }, + { startIndex: 11, type: '' }, + { startIndex: 12, type: 'delimiter.twig' }, + { startIndex: 14, type: 'string.twig' }, + { startIndex: 22, type: 'delimiter.twig' }, + { startIndex: 24, type: '' }, + { startIndex: 25, type: 'keyword.twig' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'delimiter.twig' } + ] + } + ] + ] +); diff --git a/monaco-languages/src/twig/twig.ts b/monaco-languages/src/twig/twig.ts new file mode 100644 index 00000000..f6aad693 --- /dev/null +++ b/monaco-languages/src/twig/twig.ts @@ -0,0 +1,432 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import type { languages } from '../fillers/monaco-editor-core'; + +export const conf: languages.LanguageConfiguration = { + wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g, + + comments: { + blockComment: ['{#', '#}'] + }, + + brackets: [ + ['{#', '#}'], + ['{%', '%}'], + ['{{', '}}'], + ['(', ')'], + ['[', ']'], + + // HTML + [''], + ['<', '>'] + ], + + autoClosingPairs: [ + { open: '{# ', close: ' #}' }, + { open: '{% ', close: ' %}' }, + { open: '{{ ', close: ' }}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + { open: "'", close: "'" } + ], + + surroundingPairs: [ + { open: '"', close: '"' }, + { open: "'", close: "'" }, + + // HTML + { open: '<', close: '>' } + ] +}; + +export const language = { + defaultToken: '', + tokenPostfix: '', + ignoreCase: true, + + keywords: [ + // (opening) tags + 'apply', + 'autoescape', + 'block', + 'deprecated', + 'do', + 'embed', + 'extends', + 'flush', + 'for', + 'from', + 'if', + 'import', + 'include', + 'macro', + 'sandbox', + 'set', + 'use', + 'verbatim', + 'with', + // closing tags + 'endapply', + 'endautoescape', + 'endblock', + 'endembed', + 'endfor', + 'endif', + 'endmacro', + 'endsandbox', + 'endset', + 'endwith', + // literals + 'true', + 'false' + ], + + tokenizer: { + root: [ + // whitespace + [/\s+/], + + // Twig Tag Delimiters + [/{#/, 'comment.twig', '@commentState'], + [/{%[-~]?/, 'delimiter.twig', '@blockState'], + [/{{[-~]?/, 'delimiter.twig', '@variableState'], + + // HTML + [/)/, + ['delimiter.html', 'tag.html', '', 'delimiter.html'] + ], + [/(<)(script)/, ['delimiter.html', { token: 'tag.html', next: '@script' }]], + [/(<)(style)/, ['delimiter.html', { token: 'tag.html', next: '@style' }]], + [ + /(<)((?:[\w\-]+:)?[\w\-]+)/, + ['delimiter.html', { token: 'tag.html', next: '@otherTag' }] + ], + [ + /(<\/)((?:[\w\-]+:)?[\w\-]+)/, + ['delimiter.html', { token: 'tag.html', next: '@otherTag' }] + ], + [/|>=|<=/, 'operators.twig'], + // operators - comparison (words) + [/(starts with|ends with|matches)(\s+)/, ['operators.twig', '']], + // operators - containment + [/(in)(\s+)/, ['operators.twig', '']], + // operators - test + [/(is)(\s+)/, ['operators.twig', '']], + // operators - misc + [/\||~|:|\.{1,2}|\?{1,2}/, 'operators.twig'], + // names + [ + /[^\W\d][\w]*/, + { + cases: { + '@keywords': 'keyword.twig', + '@default': 'variable.twig' + } + } + ], + // numbers + [/\d+(\.\d+)?/, 'number.twig'], + // punctuation + [/\(|\)|\[|\]|{|}|,/, 'delimiter.twig'], + // strings + [/"([^#"\\]*(?:\\.[^#"\\]*)*)"|\'([^\'\\]*(?:\\.[^\'\\]*)*)\'/, 'string.twig'], + // opening double quoted string + [/"/, 'string.twig', '@stringState'], + + // misc syntactic constructs + // These are not operators per se, but for the purposes of lexical analysis we + // can treat them as such. + // arrow functions + [/=>/, 'operators.twig'], + // assignment + [/=/, 'operators.twig'] + ], + + /** + * HTML + */ + doctype: [ + [/[^>]+/, 'metatag.content.html'], + [/>/, 'metatag.html', '@pop'] + ], + + comment: [ + [/-->/, 'comment.html', '@pop'], + [/[^-]+/, 'comment.content.html'], + [/./, 'comment.content.html'] + ], + + otherTag: [ + [/\/?>/, 'delimiter.html', '@pop'], + [/"([^"]*)"/, 'attribute.value.html'], + [/'([^']*)'/, 'attribute.value.html'], + [/[\w\-]+/, 'attribute.name.html'], + [/=/, 'delimiter.html'], + [/[ \t\r\n]+/] // whitespace + ], + + // -- BEGIN + + + + + + + diff --git a/monaco-typescript/test/custom-worker.js b/monaco-typescript/test/custom-worker.js new file mode 100644 index 00000000..3652f3c9 --- /dev/null +++ b/monaco-typescript/test/custom-worker.js @@ -0,0 +1,59 @@ +// This example uses @typescript/vfs to create a virtual TS program +// which can do work on a bg thread. + +// This version of the vfs edits the global scope (in the case of a webworker, this is 'self') +importScripts('https://unpkg.com/@typescript/vfs@1.3.0/dist/vfs.globals.js'); + +/** @type { import("@typescript/vfs") } */ +const tsvfs = globalThis.tsvfs; + +/** @type {import("../src/tsWorker").CustomTSWebWorkerFactory }*/ +const worker = (TypeScriptWorker, ts, libFileMap) => { + return class MonacoTSWorker extends TypeScriptWorker { + // Adds a custom function to the webworker + async getDTSEmitForFile(fileName) { + const result = await this.getEmitOutput(fileName); + const firstDTS = result.outputFiles.find((o) => o.name.endsWith('.d.ts')); + return (firstDTS && firstDTS.text) || ''; + } + + async printAST(fileName) { + console.log('Creating virtual TS project'); + const compilerOptions = this.getCompilationSettings(); + const fsMap = new Map(); + for (const key of Object.keys(libFileMap)) { + fsMap.set(key, '/' + libFileMap[key]); + } + + const thisCode = await this.getScriptText(fileName); + fsMap.set('index.ts', thisCode); + + console.log('Starting up TS program'); + const system = tsvfs.createSystem(fsMap); + const host = tsvfs.createVirtualCompilerHost(system, compilerOptions, ts); + + const program = ts.createProgram({ + rootNames: [...fsMap.keys()], + options: compilerOptions, + host: host.compilerHost + }); + + // Now I can look at the AST for the .ts file too + const mainSrcFile = program.getSourceFile('index.ts'); + let miniAST = 'SourceFile'; + + const recurse = (parent, depth) => { + if (depth > 5) return; + ts.forEachChild(parent, (node) => { + const spaces = ' '.repeat(depth + 1); + miniAST += `\n${spaces}${ts.SyntaxKind[node.kind]}`; + recurse(node, depth + 1); + }); + }; + recurse(mainSrcFile, 0); + return miniAST; + } + }; +}; + +self.customTSWorkerFactory = worker; diff --git a/monaco-typescript/test/index.html b/monaco-typescript/test/index.html new file mode 100644 index 00000000..e28d7459 --- /dev/null +++ b/monaco-typescript/test/index.html @@ -0,0 +1,210 @@ + + + + + + + + +

Monaco Editor TypeScript test page

+ +
+

Compiler settings

+
+ + + + + + + + + + diff --git a/monaco-typescript/test/inlayHints.html b/monaco-typescript/test/inlayHints.html new file mode 100644 index 00000000..a1d70174 --- /dev/null +++ b/monaco-typescript/test/inlayHints.html @@ -0,0 +1,219 @@ + + + + + + + + +

Monaco Editor TypeScript test page

+ +
+

Inlay Hints options

+
+ + + + + + + + + +