tjs-lang 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CONTEXT.md +594 -0
  2. package/LICENSE +190 -0
  3. package/README.md +220 -0
  4. package/bin/benchmarks.ts +351 -0
  5. package/bin/dev.ts +205 -0
  6. package/bin/docs.js +170 -0
  7. package/bin/install-cursor.sh +71 -0
  8. package/bin/install-vscode.sh +71 -0
  9. package/bin/select-local-models.d.ts +1 -0
  10. package/bin/select-local-models.js +28 -0
  11. package/bin/select-local-models.ts +31 -0
  12. package/demo/autocomplete.test.ts +232 -0
  13. package/demo/docs.json +186 -0
  14. package/demo/examples.test.ts +598 -0
  15. package/demo/index.html +91 -0
  16. package/demo/src/autocomplete.ts +482 -0
  17. package/demo/src/capabilities.ts +859 -0
  18. package/demo/src/demo-nav.ts +2097 -0
  19. package/demo/src/examples.test.ts +161 -0
  20. package/demo/src/examples.ts +476 -0
  21. package/demo/src/imports.test.ts +196 -0
  22. package/demo/src/imports.ts +421 -0
  23. package/demo/src/index.ts +639 -0
  24. package/demo/src/module-store.ts +635 -0
  25. package/demo/src/module-sw.ts +132 -0
  26. package/demo/src/playground.ts +949 -0
  27. package/demo/src/service-host.ts +389 -0
  28. package/demo/src/settings.ts +440 -0
  29. package/demo/src/style.ts +280 -0
  30. package/demo/src/tjs-playground.ts +1605 -0
  31. package/demo/src/ts-examples.ts +478 -0
  32. package/demo/src/ts-playground.ts +1092 -0
  33. package/demo/static/favicon.svg +30 -0
  34. package/demo/static/photo-1.jpg +0 -0
  35. package/demo/static/photo-2.jpg +0 -0
  36. package/demo/static/texts/ai-history.txt +9 -0
  37. package/demo/static/texts/coffee-origins.txt +9 -0
  38. package/demo/static/texts/renewable-energy.txt +9 -0
  39. package/dist/index.js +256 -0
  40. package/dist/index.js.map +37 -0
  41. package/dist/tjs-batteries.js +4 -0
  42. package/dist/tjs-batteries.js.map +15 -0
  43. package/dist/tjs-full.js +256 -0
  44. package/dist/tjs-full.js.map +37 -0
  45. package/dist/tjs-transpiler.js +220 -0
  46. package/dist/tjs-transpiler.js.map +21 -0
  47. package/dist/tjs-vm.js +4 -0
  48. package/dist/tjs-vm.js.map +14 -0
  49. package/docs/CNAME +1 -0
  50. package/docs/favicon.svg +30 -0
  51. package/docs/index.html +91 -0
  52. package/docs/index.js +10468 -0
  53. package/docs/index.js.map +92 -0
  54. package/docs/photo-1.jpg +0 -0
  55. package/docs/photo-1.webp +0 -0
  56. package/docs/photo-2.jpg +0 -0
  57. package/docs/photo-2.webp +0 -0
  58. package/docs/texts/ai-history.txt +9 -0
  59. package/docs/texts/coffee-origins.txt +9 -0
  60. package/docs/texts/renewable-energy.txt +9 -0
  61. package/docs/tjs-lang.svg +31 -0
  62. package/docs/tosijs-agent.svg +31 -0
  63. package/editors/README.md +325 -0
  64. package/editors/ace/ajs-mode.js +328 -0
  65. package/editors/ace/ajs-mode.ts +269 -0
  66. package/editors/ajs-syntax.ts +212 -0
  67. package/editors/build-grammars.ts +510 -0
  68. package/editors/codemirror/ajs-language.js +287 -0
  69. package/editors/codemirror/ajs-language.ts +1447 -0
  70. package/editors/codemirror/autocomplete.test.ts +531 -0
  71. package/editors/codemirror/component.ts +404 -0
  72. package/editors/monaco/ajs-monarch.js +243 -0
  73. package/editors/monaco/ajs-monarch.ts +225 -0
  74. package/editors/tjs-syntax.ts +115 -0
  75. package/editors/vscode/language-configuration.json +37 -0
  76. package/editors/vscode/package.json +65 -0
  77. package/editors/vscode/syntaxes/ajs-injection.tmLanguage.json +107 -0
  78. package/editors/vscode/syntaxes/ajs.tmLanguage.json +252 -0
  79. package/editors/vscode/syntaxes/tjs.tmLanguage.json +333 -0
  80. package/package.json +83 -0
  81. package/src/cli/commands/check.ts +41 -0
  82. package/src/cli/commands/convert.ts +133 -0
  83. package/src/cli/commands/emit.ts +260 -0
  84. package/src/cli/commands/run.ts +68 -0
  85. package/src/cli/commands/test.ts +194 -0
  86. package/src/cli/commands/types.ts +20 -0
  87. package/src/cli/create-app.ts +236 -0
  88. package/src/cli/playground.ts +250 -0
  89. package/src/cli/tjs.ts +166 -0
  90. package/src/cli/tjsx.ts +160 -0
  91. package/tjs-lang.svg +31 -0
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Monaco Editor Monarch Tokenizer for AsyncJS
3
+ *
4
+ * Usage:
5
+ * ```typescript
6
+ * import * as monaco from 'monaco-editor'
7
+ * import { languageId, languageConfiguration, monarchLanguage } from 'tjs-lang/editors/monaco/ajs-monarch'
8
+ *
9
+ * monaco.languages.register({ id: languageId })
10
+ * monaco.languages.setLanguageConfiguration(languageId, languageConfiguration)
11
+ * monaco.languages.setMonarchTokensProvider(languageId, monarchLanguage)
12
+ * ```
13
+ */
14
+
15
+ import type * as Monaco from 'monaco-editor'
16
+ import { KEYWORDS, FORBIDDEN_KEYWORDS, TYPE_CONSTRUCTORS } from '../ajs-syntax'
17
+
18
+ export const languageId = 'ajs'
19
+
20
+ export const languageConfiguration: Monaco.languages.LanguageConfiguration = {
21
+ comments: {
22
+ lineComment: '//',
23
+ blockComment: ['/*', '*/'],
24
+ },
25
+ brackets: [
26
+ ['{', '}'],
27
+ ['[', ']'],
28
+ ['(', ')'],
29
+ ],
30
+ autoClosingPairs: [
31
+ { open: '{', close: '}' },
32
+ { open: '[', close: ']' },
33
+ { open: '(', close: ')' },
34
+ { open: "'", close: "'", notIn: ['string', 'comment'] },
35
+ { open: '"', close: '"', notIn: ['string', 'comment'] },
36
+ { open: '`', close: '`', notIn: ['string', 'comment'] },
37
+ ],
38
+ surroundingPairs: [
39
+ { open: '{', close: '}' },
40
+ { open: '[', close: ']' },
41
+ { open: '(', close: ')' },
42
+ { open: "'", close: "'" },
43
+ { open: '"', close: '"' },
44
+ { open: '`', close: '`' },
45
+ ],
46
+ folding: {
47
+ markers: {
48
+ start: /^\s*\/\/\s*#region\b/,
49
+ end: /^\s*\/\/\s*#endregion\b/,
50
+ },
51
+ },
52
+ }
53
+
54
+ export const monarchLanguage: Monaco.languages.IMonarchLanguage = {
55
+ defaultToken: 'source',
56
+ ignoreCase: false,
57
+
58
+ // Good parts - standard keywords (from shared definition)
59
+ keywords: [...KEYWORDS],
60
+
61
+ // Bad parts - forbidden in AsyncJS (from shared definition)
62
+ forbidden: [...FORBIDDEN_KEYWORDS],
63
+
64
+ // Built-in type constructors used as factories (from shared definition)
65
+ typeKeywords: [...TYPE_CONSTRUCTORS],
66
+
67
+ operators: [
68
+ '=',
69
+ '>',
70
+ '<',
71
+ '!',
72
+ '~',
73
+ '?',
74
+ ':',
75
+ '==',
76
+ '<=',
77
+ '>=',
78
+ '!=',
79
+ '&&',
80
+ '||',
81
+ '++',
82
+ '--',
83
+ '+',
84
+ '-',
85
+ '*',
86
+ '/',
87
+ '&',
88
+ '|',
89
+ '^',
90
+ '%',
91
+ '<<',
92
+ '>>',
93
+ '>>>',
94
+ '+=',
95
+ '-=',
96
+ '*=',
97
+ '/=',
98
+ '&=',
99
+ '|=',
100
+ '^=',
101
+ '%=',
102
+ '<<=',
103
+ '>>=',
104
+ '>>>=',
105
+ ],
106
+
107
+ symbols: /[=><!~?:&|+\-*\/\^%]+/,
108
+
109
+ escapes:
110
+ /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
111
+
112
+ tokenizer: {
113
+ root: [
114
+ // Identifiers and keywords
115
+ [
116
+ /[a-zA-Z_$][\w$]*/,
117
+ {
118
+ cases: {
119
+ '@forbidden': 'invalid', // Red squiggly for bad parts
120
+ '@keywords': 'keyword',
121
+ '@typeKeywords': 'type.identifier',
122
+ '@default': 'identifier',
123
+ },
124
+ },
125
+ ],
126
+
127
+ // Whitespace
128
+ { include: '@whitespace' },
129
+
130
+ // Delimiters and operators
131
+ [/[{}()\[\]]/, '@brackets'],
132
+ [
133
+ /@symbols/,
134
+ {
135
+ cases: {
136
+ '@operators': 'operator',
137
+ '@default': '',
138
+ },
139
+ },
140
+ ],
141
+
142
+ // Numbers
143
+ [/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
144
+ [/0[xX][0-9a-fA-F]+/, 'number.hex'],
145
+ [/\d+/, 'number'],
146
+
147
+ // Delimiter: after number because of .\d floats
148
+ [/[;,.]/, 'delimiter'],
149
+
150
+ // Strings
151
+ [/'/, { token: 'string.quote', bracket: '@open', next: '@stringSingle' }],
152
+ [/"/, { token: 'string.quote', bracket: '@open', next: '@stringDouble' }],
153
+ [
154
+ /`/,
155
+ {
156
+ token: 'string.quote',
157
+ bracket: '@open',
158
+ next: '@stringBacktick',
159
+ },
160
+ ],
161
+ ],
162
+
163
+ stringSingle: [
164
+ [/[^\\']+/, 'string'],
165
+ [/@escapes/, 'string.escape'],
166
+ [/\\./, 'string.escape.invalid'],
167
+ [/'/, { token: 'string.quote', bracket: '@close', next: '@pop' }],
168
+ ],
169
+
170
+ stringDouble: [
171
+ [/[^\\"]+/, 'string'],
172
+ [/@escapes/, 'string.escape'],
173
+ [/\\./, 'string.escape.invalid'],
174
+ [/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }],
175
+ ],
176
+
177
+ stringBacktick: [
178
+ [/[^\\`$]+/, 'string'],
179
+ [/@escapes/, 'string.escape'],
180
+ [/\\./, 'string.escape.invalid'],
181
+ [
182
+ /\$\{/,
183
+ {
184
+ token: 'delimiter.bracket',
185
+ next: '@stringTemplateExpression',
186
+ },
187
+ ],
188
+ [/`/, { token: 'string.quote', bracket: '@close', next: '@pop' }],
189
+ ],
190
+
191
+ stringTemplateExpression: [
192
+ [/[^}]+/, 'identifier'],
193
+ [/\}/, { token: 'delimiter.bracket', next: '@pop' }],
194
+ ],
195
+
196
+ whitespace: [
197
+ [/[ \t\r\n]+/, 'white'],
198
+ [/\/\*\*(?!\/)/, 'comment.doc', '@docComment'],
199
+ [/\/\*/, 'comment', '@comment'],
200
+ [/\/\/.*$/, 'comment'],
201
+ ],
202
+
203
+ comment: [
204
+ [/[^\/*]+/, 'comment'],
205
+ [/\*\//, 'comment', '@pop'],
206
+ [/[\/*]/, 'comment'],
207
+ ],
208
+
209
+ docComment: [
210
+ [/@\w+/, 'comment.doc.tag'],
211
+ [/[^\/*]+/, 'comment.doc'],
212
+ [/\*\//, 'comment.doc', '@pop'],
213
+ [/[\/*]/, 'comment.doc'],
214
+ ],
215
+ },
216
+ }
217
+
218
+ /**
219
+ * Register AsyncJS language with Monaco editor
220
+ */
221
+ export function registerAjsLanguage(monaco: typeof Monaco): void {
222
+ monaco.languages.register({ id: languageId })
223
+ monaco.languages.setLanguageConfiguration(languageId, languageConfiguration)
224
+ monaco.languages.setMonarchTokensProvider(languageId, monarchLanguage)
225
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * TJS (Typed JavaScript) Syntax Definitions
3
+ *
4
+ * Extends AsyncJS syntax with:
5
+ * - test/mock/unsafe keywords
6
+ * - Return type annotation (-> Type)
7
+ * - Markdown in non-JSDoc comments
8
+ */
9
+
10
+ import {
11
+ KEYWORDS as AJS_KEYWORDS,
12
+ FORBIDDEN_KEYWORDS as AJS_FORBIDDEN,
13
+ TYPE_CONSTRUCTORS as AJS_TYPE_CONSTRUCTORS,
14
+ OPERATORS as AJS_OPERATORS,
15
+ } from './ajs-syntax'
16
+
17
+ /**
18
+ * TJS-specific keywords (in addition to AJS)
19
+ */
20
+ export const TJS_KEYWORDS = [
21
+ 'test', // inline tests
22
+ 'mock', // test setup blocks
23
+ 'unsafe', // exception-catching blocks
24
+ 'async', // TJS allows async (unlike sandboxed AJS)
25
+ 'await',
26
+ ] as const
27
+
28
+ /**
29
+ * All TJS keywords
30
+ */
31
+ export const KEYWORDS = [...AJS_KEYWORDS, ...TJS_KEYWORDS] as const
32
+
33
+ /**
34
+ * TJS forbidden keywords (fewer than AJS - TJS is less restrictive)
35
+ * TJS allows: async/await, throw, import/export
36
+ */
37
+ export const FORBIDDEN_KEYWORDS = AJS_FORBIDDEN.filter(
38
+ (k) => !['async', 'await', 'throw', 'import', 'export'].includes(k)
39
+ ) as readonly string[]
40
+
41
+ /**
42
+ * Type constructors (same as AJS plus TJS-specific)
43
+ */
44
+ export const TYPE_CONSTRUCTORS = [
45
+ ...AJS_TYPE_CONSTRUCTORS,
46
+ 'expect', // test assertions
47
+ 'assert', // simple assertions
48
+ ] as const
49
+
50
+ /**
51
+ * TJS operators (same as AJS plus return type arrow)
52
+ */
53
+ export const OPERATORS = [...AJS_OPERATORS, '->'] as const
54
+
55
+ /**
56
+ * TJS-specific syntax patterns
57
+ */
58
+ export const TJS_PATTERNS = {
59
+ // Return type annotation: -> Type
60
+ returnType: /\)\s*->\s*(\{[^}]+\}|'[^']*'|"[^"]*"|\[[^\]]*\]|\w+)/,
61
+
62
+ // Unsafe function marker: function name(! or function name(!
63
+ unsafeFunction: /function\s+(\w+)\s*\(\s*!/,
64
+
65
+ // Test block: test('description') { ... }
66
+ testBlock: /test\s*\(\s*(['"`])([^'"`]*)\1\s*\)\s*\{/,
67
+
68
+ // Mock block: mock { ... }
69
+ mockBlock: /mock\s*\{/,
70
+
71
+ // Unsafe block: unsafe { ... }
72
+ unsafeBlock: /unsafe\s*\{/,
73
+
74
+ // Colon type annotation: name: 'type' or name: 0
75
+ colonType:
76
+ /([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:\s*('[^']*'|"[^"]*"|\d+|\{[^}]*\}|\[[^\]]*\]|true|false|null)/,
77
+ }
78
+
79
+ /**
80
+ * Markdown elements to highlight in comments
81
+ * (for non-JSDoc block comments)
82
+ */
83
+ export const MARKDOWN_PATTERNS = {
84
+ // Headers: # ## ###
85
+ header: /^(\s*)(#{1,6})\s+(.*)$/m,
86
+
87
+ // Bold: **text** or __text__
88
+ bold: /(\*\*|__)([^*_]+)\1/,
89
+
90
+ // Italic: *text* or _text_
91
+ italic: /(\*|_)([^*_]+)\1/,
92
+
93
+ // Code: `code`
94
+ inlineCode: /`([^`]+)`/,
95
+
96
+ // Links: [text](url)
97
+ link: /\[([^\]]+)\]\(([^)]+)\)/,
98
+
99
+ // Lists: - item or * item or 1. item
100
+ listItem: /^(\s*)([*\-]|\d+\.)\s+/m,
101
+ }
102
+
103
+ /**
104
+ * Questions/Notes:
105
+ *
106
+ * Q1: Should markdown highlighting be in all comments or just /* ... *\/?
107
+ * Current plan: Only non-JSDoc block comments (/* without **)
108
+ *
109
+ * Q2: How deep should markdown parsing go?
110
+ * Current: Basic patterns (headers, bold, italic, code, links)
111
+ * Could add: code blocks, tables, etc.
112
+ *
113
+ * Q3: Should we generate separate TJS grammar files or extend AJS?
114
+ * Current plan: Extend - TJS is a superset
115
+ */
@@ -0,0 +1,37 @@
1
+ {
2
+ "comments": {
3
+ "lineComment": "//",
4
+ "blockComment": ["/*", "*/"]
5
+ },
6
+ "brackets": [
7
+ ["{", "}"],
8
+ ["[", "]"],
9
+ ["(", ")"]
10
+ ],
11
+ "autoClosingPairs": [
12
+ { "open": "{", "close": "}" },
13
+ { "open": "[", "close": "]" },
14
+ { "open": "(", "close": ")" },
15
+ { "open": "'", "close": "'", "notIn": ["string", "comment"] },
16
+ { "open": "\"", "close": "\"", "notIn": ["string", "comment"] },
17
+ { "open": "`", "close": "`", "notIn": ["string", "comment"] }
18
+ ],
19
+ "surroundingPairs": [
20
+ ["{", "}"],
21
+ ["[", "]"],
22
+ ["(", ")"],
23
+ ["'", "'"],
24
+ ["\"", "\""],
25
+ ["`", "`"]
26
+ ],
27
+ "folding": {
28
+ "markers": {
29
+ "start": "^\\s*//\\s*#region\\b",
30
+ "end": "^\\s*//\\s*#endregion\\b"
31
+ }
32
+ },
33
+ "indentationRules": {
34
+ "increaseIndentPattern": "^.*\\{[^}]*$",
35
+ "decreaseIndentPattern": "^\\s*\\}"
36
+ }
37
+ }
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "tjs-lang-ajs",
3
+ "displayName": "AsyncJS (tjs-lang)",
4
+ "description": "Syntax highlighting for AsyncJS - ajs`...` template literals and .ajs files",
5
+ "version": "0.1.0",
6
+ "publisher": "tosijs",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/tonioloewald/tjs-lang"
10
+ },
11
+ "engines": {
12
+ "vscode": "^1.75.0"
13
+ },
14
+ "categories": [
15
+ "Programming Languages"
16
+ ],
17
+ "contributes": {
18
+ "configurationDefaults": {
19
+ "editor.tokenColorCustomizations": {
20
+ "textMateRules": [
21
+ {
22
+ "scope": "invalid.illegal.ajs",
23
+ "settings": {
24
+ "foreground": "#ff0000",
25
+ "fontStyle": "bold underline"
26
+ }
27
+ }
28
+ ]
29
+ }
30
+ },
31
+ "languages": [
32
+ {
33
+ "id": "ajs",
34
+ "aliases": [
35
+ "AsyncJS",
36
+ "ajs"
37
+ ],
38
+ "extensions": [
39
+ ".ajs"
40
+ ],
41
+ "configuration": "./language-configuration.json"
42
+ }
43
+ ],
44
+ "grammars": [
45
+ {
46
+ "language": "ajs",
47
+ "scopeName": "source.ajs",
48
+ "path": "./syntaxes/ajs.tmLanguage.json"
49
+ },
50
+ {
51
+ "scopeName": "inline.ajs.injection",
52
+ "path": "./syntaxes/ajs-injection.tmLanguage.json",
53
+ "injectTo": [
54
+ "source.js",
55
+ "source.ts",
56
+ "source.tsx",
57
+ "source.jsx"
58
+ ],
59
+ "embeddedLanguages": {
60
+ "meta.embedded.block.ajs": "javascript"
61
+ }
62
+ }
63
+ ]
64
+ }
65
+ }
@@ -0,0 +1,107 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
3
+ "name": "AsyncJS Injection",
4
+ "scopeName": "inline.ajs.injection",
5
+ "injectionSelector": "L:source.js, L:source.ts, L:source.tsx, L:source.jsx",
6
+ "patterns": [
7
+ {
8
+ "begin": "(ajs|transpile)\\s*(`)",
9
+ "beginCaptures": {
10
+ "1": { "name": "entity.name.function.tagged-template.js" },
11
+ "2": { "name": "punctuation.definition.string.template.begin.js" }
12
+ },
13
+ "end": "(`)",
14
+ "endCaptures": {
15
+ "1": { "name": "punctuation.definition.string.template.end.js" }
16
+ },
17
+ "contentName": "meta.embedded.block.ajs",
18
+ "patterns": [
19
+ { "include": "#template-substitution" },
20
+ { "include": "#ajs-content" }
21
+ ]
22
+ }
23
+ ],
24
+ "repository": {
25
+ "template-substitution": {
26
+ "begin": "(\\$\\{)",
27
+ "beginCaptures": {
28
+ "1": { "name": "punctuation.definition.template-expression.begin.js" }
29
+ },
30
+ "end": "(\\})",
31
+ "endCaptures": {
32
+ "1": { "name": "punctuation.definition.template-expression.end.js" }
33
+ },
34
+ "contentName": "meta.template.expression.js",
35
+ "patterns": [{ "include": "source.ts" }]
36
+ },
37
+ "ajs-content": {
38
+ "patterns": [
39
+ { "include": "#forbidden" },
40
+ { "include": "#function-def" },
41
+ { "include": "#keywords" },
42
+ { "include": "#strings" },
43
+ { "include": "#numbers" },
44
+ { "include": "#comments" },
45
+ { "include": "#operators" }
46
+ ]
47
+ },
48
+ "forbidden": {
49
+ "patterns": [
50
+ {
51
+ "match": "\\b(new|class|async|await|var|this|super|extends|implements|interface|type|yield|import|export|require)\\b",
52
+ "name": "invalid.illegal.ajs"
53
+ },
54
+ {
55
+ "comment": "Ternary operator ? - not supported (but allow ?. optional chaining)",
56
+ "match": "\\?(?![.:])",
57
+ "name": "invalid.illegal.ajs"
58
+ }
59
+ ]
60
+ },
61
+ "function-def": {
62
+ "match": "\\b(function)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)",
63
+ "captures": {
64
+ "1": { "name": "storage.type.function.js" },
65
+ "2": { "name": "entity.name.function.js" }
66
+ }
67
+ },
68
+ "keywords": {
69
+ "match": "\\b(function|return|if|else|while|for|of|in|try|catch|finally|throw|let|const|true|false|null)\\b",
70
+ "name": "keyword.control.js"
71
+ },
72
+ "strings": {
73
+ "patterns": [
74
+ {
75
+ "begin": "'",
76
+ "end": "'",
77
+ "name": "string.quoted.single.js",
78
+ "patterns": [
79
+ { "match": "\\\\.", "name": "constant.character.escape.js" }
80
+ ]
81
+ },
82
+ {
83
+ "begin": "\"",
84
+ "end": "\"",
85
+ "name": "string.quoted.double.js",
86
+ "patterns": [
87
+ { "match": "\\\\.", "name": "constant.character.escape.js" }
88
+ ]
89
+ }
90
+ ]
91
+ },
92
+ "numbers": {
93
+ "match": "\\b\\d+(\\.\\d+)?\\b",
94
+ "name": "constant.numeric.js"
95
+ },
96
+ "comments": {
97
+ "patterns": [
98
+ { "match": "//.*$", "name": "comment.line.double-slash.js" },
99
+ { "begin": "/\\*", "end": "\\*/", "name": "comment.block.js" }
100
+ ]
101
+ },
102
+ "operators": {
103
+ "match": "=>|&&|\\|\\||===?|!==?|>=?|<=?|[+\\-*/%=]",
104
+ "name": "keyword.operator.js"
105
+ }
106
+ }
107
+ }