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,510 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Build script for editor grammars
4
+ *
5
+ * Generates JSON grammar files from the TypeScript source of truth (ajs-syntax.ts).
6
+ * Run with: bun editors/build-grammars.ts
7
+ */
8
+
9
+ import { KEYWORDS, FORBIDDEN_KEYWORDS, TYPE_CONSTRUCTORS } from './ajs-syntax'
10
+ import {
11
+ KEYWORDS as TJS_KEYWORDS,
12
+ FORBIDDEN_KEYWORDS as TJS_FORBIDDEN,
13
+ TYPE_CONSTRUCTORS as TJS_TYPE_CONSTRUCTORS,
14
+ TJS_PATTERNS,
15
+ } from './tjs-syntax'
16
+ import { writeFileSync, readFileSync } from 'fs'
17
+ import { join, dirname } from 'path'
18
+
19
+ const editorsDir = dirname(new URL(import.meta.url).pathname)
20
+
21
+ // VSCode TextMate grammar
22
+ function buildVSCodeGrammar() {
23
+ const grammarPath = join(editorsDir, 'vscode/syntaxes/ajs.tmLanguage.json')
24
+
25
+ // Build regex patterns from arrays
26
+ const forbiddenPattern = `\\\\b(${FORBIDDEN_KEYWORDS.join('|')})\\\\b`
27
+ const keywordsPattern = `\\\\b(${KEYWORDS.filter(
28
+ (k) => !['true', 'false', 'null', 'undefined'].includes(k)
29
+ ).join('|')})\\\\b`
30
+ const constantsPattern = `\\\\b(true|false|null|undefined)\\\\b`
31
+
32
+ const grammar = {
33
+ $schema:
34
+ 'https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json',
35
+ name: 'AsyncJS',
36
+ scopeName: 'source.ajs',
37
+ patterns: [
38
+ { include: '#comments' },
39
+ { include: '#strings' },
40
+ { include: '#function-def' },
41
+ { include: '#forbidden' },
42
+ { include: '#keywords' },
43
+ { include: '#builtins' },
44
+ { include: '#type-parameters' },
45
+ { include: '#numbers' },
46
+ { include: '#operators' },
47
+ ],
48
+ repository: {
49
+ 'function-def': {
50
+ begin: '\\b(function)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*\\(',
51
+ beginCaptures: {
52
+ '1': { name: 'keyword.control.ajs' },
53
+ '2': { name: 'entity.name.function.ajs' },
54
+ },
55
+ end: '\\)',
56
+ patterns: [{ include: '#type-parameters' }, { include: '#comments' }],
57
+ },
58
+ 'type-parameters': {
59
+ patterns: [
60
+ {
61
+ comment: "Required parameter with type: name: 'string' or name: 0",
62
+ match:
63
+ '([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*(:)\\s*(\'[^\']*\'|"[^"]*"|\\d+|\\{[^}]*\\}|\\[[^\\]]*\\]|true|false|null)',
64
+ captures: {
65
+ '1': { name: 'variable.parameter.ajs' },
66
+ '2': { name: 'punctuation.separator.ajs' },
67
+ '3': { name: 'support.type.ajs' },
68
+ },
69
+ },
70
+ {
71
+ comment: 'Optional parameter with default: name = value',
72
+ match:
73
+ '([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*(=)\\s*(?=null\\s*&&|\'|"|\\d|\\{|\\[|true|false|null)',
74
+ captures: {
75
+ '1': { name: 'variable.parameter.ajs' },
76
+ '2': { name: 'keyword.operator.assignment.ajs' },
77
+ },
78
+ },
79
+ {
80
+ comment: 'Simple parameter name',
81
+ match: '([a-zA-Z_$][a-zA-Z0-9_$]*)(?=\\s*[,)])',
82
+ captures: {
83
+ '1': { name: 'variable.parameter.ajs' },
84
+ },
85
+ },
86
+ ],
87
+ },
88
+ forbidden: {
89
+ comment: 'Auto-generated from editors/ajs-syntax.ts FORBIDDEN_KEYWORDS',
90
+ patterns: [
91
+ {
92
+ match: forbiddenPattern,
93
+ name: 'invalid.illegal.forbidden.ajs',
94
+ },
95
+ ],
96
+ },
97
+ keywords: {
98
+ comment: 'Auto-generated from editors/ajs-syntax.ts KEYWORDS',
99
+ patterns: [
100
+ {
101
+ match: keywordsPattern,
102
+ name: 'keyword.control.ajs',
103
+ },
104
+ {
105
+ match: constantsPattern,
106
+ name: 'constant.language.ajs',
107
+ },
108
+ ],
109
+ },
110
+ builtins: {
111
+ comment: 'Auto-generated from editors/ajs-syntax.ts TYPE_CONSTRUCTORS',
112
+ patterns: [
113
+ {
114
+ match: `\\\\b(${TYPE_CONSTRUCTORS.join('|')})\\\\b`,
115
+ name: 'support.class.ajs',
116
+ },
117
+ ],
118
+ },
119
+ strings: {
120
+ patterns: [
121
+ {
122
+ name: 'string.quoted.single.ajs',
123
+ begin: "'",
124
+ end: "'",
125
+ patterns: [
126
+ { name: 'constant.character.escape.ajs', match: '\\\\.' },
127
+ ],
128
+ },
129
+ {
130
+ name: 'string.quoted.double.ajs',
131
+ begin: '"',
132
+ end: '"',
133
+ patterns: [
134
+ { name: 'constant.character.escape.ajs', match: '\\\\.' },
135
+ ],
136
+ },
137
+ {
138
+ name: 'string.template.ajs',
139
+ begin: '`',
140
+ end: '`',
141
+ patterns: [
142
+ { name: 'constant.character.escape.ajs', match: '\\\\.' },
143
+ {
144
+ name: 'meta.template.expression.ajs',
145
+ begin: '\\$\\{',
146
+ end: '\\}',
147
+ beginCaptures: {
148
+ '0': {
149
+ name: 'punctuation.definition.template-expression.begin.ajs',
150
+ },
151
+ },
152
+ endCaptures: {
153
+ '0': {
154
+ name: 'punctuation.definition.template-expression.end.ajs',
155
+ },
156
+ },
157
+ patterns: [
158
+ { include: '#forbidden' },
159
+ { include: '#keywords' },
160
+ { include: '#builtins' },
161
+ { include: '#numbers' },
162
+ { include: '#operators' },
163
+ ],
164
+ },
165
+ ],
166
+ },
167
+ ],
168
+ },
169
+ numbers: {
170
+ patterns: [
171
+ {
172
+ match: '\\b\\d+\\.\\d+([eE][+-]?\\d+)?\\b',
173
+ name: 'constant.numeric.float.ajs',
174
+ },
175
+ {
176
+ match: '\\b\\d+\\b',
177
+ name: 'constant.numeric.integer.ajs',
178
+ },
179
+ ],
180
+ },
181
+ operators: {
182
+ patterns: [
183
+ {
184
+ match: '\\?\\?|&&|\\|\\||!|===|!==|==|!=|>=|<=|>|<',
185
+ name: 'keyword.operator.logical.ajs',
186
+ },
187
+ {
188
+ match: '\\+|\\-|\\*|\\/|%|\\*\\*',
189
+ name: 'keyword.operator.arithmetic.ajs',
190
+ },
191
+ {
192
+ match: '=',
193
+ name: 'keyword.operator.assignment.ajs',
194
+ },
195
+ {
196
+ match: '\\?\\.?',
197
+ name: 'keyword.operator.optional.ajs',
198
+ },
199
+ ],
200
+ },
201
+ comments: {
202
+ patterns: [
203
+ {
204
+ name: 'comment.line.double-slash.ajs',
205
+ match: '//.*$',
206
+ },
207
+ {
208
+ name: 'comment.block.documentation.ajs',
209
+ begin: '/\\*\\*',
210
+ end: '\\*/',
211
+ patterns: [
212
+ {
213
+ match: '@(param|returns?|description|example)\\b',
214
+ name: 'keyword.other.documentation.ajs',
215
+ },
216
+ ],
217
+ },
218
+ {
219
+ name: 'comment.block.ajs',
220
+ begin: '/\\*',
221
+ end: '\\*/',
222
+ },
223
+ ],
224
+ },
225
+ },
226
+ }
227
+
228
+ writeFileSync(grammarPath, JSON.stringify(grammar, null, 2) + '\n')
229
+ console.log(`Generated: ${grammarPath}`)
230
+ }
231
+
232
+ // Monaco and Ace use TypeScript directly, so just verify they import correctly
233
+ function verifyTypeScriptGrammars() {
234
+ // These will fail at import time if broken
235
+ try {
236
+ require('./monaco/ajs-monarch')
237
+ console.log('Verified: monaco/ajs-monarch.ts imports correctly')
238
+ } catch (e) {
239
+ console.error('Failed to import monaco/ajs-monarch.ts:', e)
240
+ }
241
+
242
+ try {
243
+ require('./ace/ajs-mode')
244
+ console.log('Verified: ace/ajs-mode.ts imports correctly')
245
+ } catch (e) {
246
+ console.error('Failed to import ace/ajs-mode.ts:', e)
247
+ }
248
+
249
+ try {
250
+ require('./codemirror/ajs-language')
251
+ console.log('Verified: codemirror/ajs-language.ts imports correctly')
252
+ } catch (e) {
253
+ console.error('Failed to import codemirror/ajs-language.ts:', e)
254
+ }
255
+ }
256
+
257
+ // TJS VSCode grammar (extends AJS)
258
+ function buildTJSVSCodeGrammar() {
259
+ const grammarPath = join(editorsDir, 'vscode/syntaxes/tjs.tmLanguage.json')
260
+
261
+ // Build regex patterns from TJS arrays
262
+ const forbiddenPattern = `\\\\b(${TJS_FORBIDDEN.join('|')})\\\\b`
263
+ const keywordsPattern = `\\\\b(${TJS_KEYWORDS.filter(
264
+ (k) => !['true', 'false', 'null', 'undefined'].includes(k)
265
+ ).join('|')})\\\\b`
266
+ const constantsPattern = `\\\\b(true|false|null|undefined)\\\\b`
267
+
268
+ const grammar = {
269
+ $schema:
270
+ 'https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json',
271
+ name: 'TJS',
272
+ scopeName: 'source.tjs',
273
+ patterns: [
274
+ { include: '#comments' },
275
+ { include: '#strings' },
276
+ { include: '#test-block' },
277
+ { include: '#mock-block' },
278
+ { include: '#unsafe-block' },
279
+ { include: '#function-def' },
280
+ { include: '#return-type' },
281
+ { include: '#forbidden' },
282
+ { include: '#keywords' },
283
+ { include: '#builtins' },
284
+ { include: '#type-parameters' },
285
+ { include: '#numbers' },
286
+ { include: '#operators' },
287
+ ],
288
+ repository: {
289
+ 'test-block': {
290
+ begin: '\\b(test)\\s*\\(\\s*([\'"`])([^\'"`]*)(\\2)\\s*\\)\\s*\\{',
291
+ beginCaptures: {
292
+ '1': { name: 'keyword.control.test.tjs' },
293
+ '2': { name: 'punctuation.definition.string.begin.tjs' },
294
+ '3': { name: 'string.quoted.test-description.tjs' },
295
+ '4': { name: 'punctuation.definition.string.end.tjs' },
296
+ },
297
+ end: '\\}',
298
+ patterns: [{ include: '$self' }],
299
+ },
300
+ 'mock-block': {
301
+ begin: '\\b(mock)\\s*\\{',
302
+ beginCaptures: {
303
+ '1': { name: 'keyword.control.mock.tjs' },
304
+ },
305
+ end: '\\}',
306
+ patterns: [{ include: '$self' }],
307
+ },
308
+ 'unsafe-block': {
309
+ begin: '\\b(unsafe)\\s*\\{',
310
+ beginCaptures: {
311
+ '1': { name: 'keyword.control.unsafe.tjs' },
312
+ },
313
+ end: '\\}',
314
+ patterns: [{ include: '$self' }],
315
+ },
316
+ 'return-type': {
317
+ match:
318
+ '\\)\\s*(->)\\s*(\\{[^}]+\\}|\'[^\']*\'|"[^"]*"|\\[[^\\]]*\\]|\\w+)',
319
+ captures: {
320
+ '1': { name: 'keyword.operator.return-type.tjs' },
321
+ '2': { name: 'support.type.return.tjs' },
322
+ },
323
+ },
324
+ 'function-def': {
325
+ begin: '\\b(async\\s+)?(function)\\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*\\(',
326
+ beginCaptures: {
327
+ '1': { name: 'keyword.control.async.tjs' },
328
+ '2': { name: 'keyword.control.tjs' },
329
+ '3': { name: 'entity.name.function.tjs' },
330
+ },
331
+ end: '\\)',
332
+ patterns: [{ include: '#type-parameters' }, { include: '#comments' }],
333
+ },
334
+ 'type-parameters': {
335
+ patterns: [
336
+ {
337
+ comment: "Required parameter with type: name: 'string' or name: 0",
338
+ match:
339
+ '([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*(:)\\s*(\'[^\']*\'|"[^"]*"|\\d+|\\{[^}]*\\}|\\[[^\\]]*\\]|true|false|null)',
340
+ captures: {
341
+ '1': { name: 'variable.parameter.tjs' },
342
+ '2': { name: 'punctuation.separator.type.tjs' },
343
+ '3': { name: 'support.type.tjs' },
344
+ },
345
+ },
346
+ {
347
+ comment: 'Optional parameter with default: name = value',
348
+ match:
349
+ '([a-zA-Z_$][a-zA-Z0-9_$]*)\\s*(=)\\s*(?=null\\s*&&|\'|"|\\d|\\{|\\[|true|false|null)',
350
+ captures: {
351
+ '1': { name: 'variable.parameter.tjs' },
352
+ '2': { name: 'keyword.operator.assignment.tjs' },
353
+ },
354
+ },
355
+ {
356
+ comment: 'Simple parameter name',
357
+ match: '([a-zA-Z_$][a-zA-Z0-9_$]*)(?=\\s*[,)])',
358
+ captures: {
359
+ '1': { name: 'variable.parameter.tjs' },
360
+ },
361
+ },
362
+ ],
363
+ },
364
+ forbidden: {
365
+ patterns: [
366
+ {
367
+ match: forbiddenPattern,
368
+ name: 'invalid.illegal.forbidden.tjs',
369
+ },
370
+ ],
371
+ },
372
+ keywords: {
373
+ patterns: [
374
+ {
375
+ match: keywordsPattern,
376
+ name: 'keyword.control.tjs',
377
+ },
378
+ {
379
+ match: constantsPattern,
380
+ name: 'constant.language.tjs',
381
+ },
382
+ ],
383
+ },
384
+ builtins: {
385
+ patterns: [
386
+ {
387
+ match: `\\\\b(${TJS_TYPE_CONSTRUCTORS.join('|')})\\\\b`,
388
+ name: 'support.class.tjs',
389
+ },
390
+ ],
391
+ },
392
+ strings: {
393
+ patterns: [
394
+ {
395
+ name: 'string.quoted.single.tjs',
396
+ begin: "'",
397
+ end: "'",
398
+ patterns: [
399
+ { name: 'constant.character.escape.tjs', match: '\\\\.' },
400
+ ],
401
+ },
402
+ {
403
+ name: 'string.quoted.double.tjs',
404
+ begin: '"',
405
+ end: '"',
406
+ patterns: [
407
+ { name: 'constant.character.escape.tjs', match: '\\\\.' },
408
+ ],
409
+ },
410
+ {
411
+ name: 'string.template.tjs',
412
+ begin: '`',
413
+ end: '`',
414
+ patterns: [
415
+ { name: 'constant.character.escape.tjs', match: '\\\\.' },
416
+ {
417
+ name: 'meta.template.expression.tjs',
418
+ begin: '\\$\\{',
419
+ end: '\\}',
420
+ beginCaptures: {
421
+ '0': {
422
+ name: 'punctuation.definition.template-expression.begin.tjs',
423
+ },
424
+ },
425
+ endCaptures: {
426
+ '0': {
427
+ name: 'punctuation.definition.template-expression.end.tjs',
428
+ },
429
+ },
430
+ patterns: [{ include: '$self' }],
431
+ },
432
+ ],
433
+ },
434
+ ],
435
+ },
436
+ numbers: {
437
+ patterns: [
438
+ {
439
+ match: '\\b\\d+\\.\\d+([eE][+-]?\\d+)?\\b',
440
+ name: 'constant.numeric.float.tjs',
441
+ },
442
+ { match: '\\b\\d+\\b', name: 'constant.numeric.integer.tjs' },
443
+ ],
444
+ },
445
+ operators: {
446
+ patterns: [
447
+ { match: '->', name: 'keyword.operator.return-type.tjs' },
448
+ {
449
+ match: '\\?\\?|&&|\\|\\||!|===|!==|==|!=|>=|<=|>|<',
450
+ name: 'keyword.operator.logical.tjs',
451
+ },
452
+ {
453
+ match: '\\+|\\-|\\*|\\/|%|\\*\\*',
454
+ name: 'keyword.operator.arithmetic.tjs',
455
+ },
456
+ { match: '=', name: 'keyword.operator.assignment.tjs' },
457
+ { match: '\\?\\.?', name: 'keyword.operator.optional.tjs' },
458
+ ],
459
+ },
460
+ comments: {
461
+ patterns: [
462
+ { name: 'comment.line.double-slash.tjs', match: '//.*$' },
463
+ {
464
+ name: 'comment.block.documentation.tjs',
465
+ begin: '/\\*\\*',
466
+ end: '\\*/',
467
+ patterns: [
468
+ {
469
+ match: '@(param|returns?|description|example)\\b',
470
+ name: 'keyword.other.documentation.tjs',
471
+ },
472
+ ],
473
+ },
474
+ {
475
+ comment:
476
+ 'Non-JSDoc block comments - could add markdown highlighting here',
477
+ name: 'comment.block.markdown.tjs',
478
+ begin: '/\\*(?!\\*)',
479
+ end: '\\*/',
480
+ patterns: [
481
+ {
482
+ match: '(^|\\s)(#{1,6})\\s+.*$',
483
+ name: 'markup.heading.markdown.tjs',
484
+ },
485
+ { match: '\\*\\*[^*]+\\*\\*', name: 'markup.bold.markdown.tjs' },
486
+ { match: '`[^`]+`', name: 'markup.inline.raw.markdown.tjs' },
487
+ ],
488
+ },
489
+ ],
490
+ },
491
+ },
492
+ }
493
+
494
+ writeFileSync(grammarPath, JSON.stringify(grammar, null, 2) + '\n')
495
+ console.log(`Generated: ${grammarPath}`)
496
+ }
497
+
498
+ // Main
499
+ console.log('Building editor grammars from ajs-syntax.ts...\n')
500
+ console.log(`KEYWORDS: ${KEYWORDS.length} items`)
501
+ console.log(`FORBIDDEN_KEYWORDS: ${FORBIDDEN_KEYWORDS.length} items`)
502
+ console.log(`TYPE_CONSTRUCTORS: ${TYPE_CONSTRUCTORS.length} items\n`)
503
+
504
+ console.log(`TJS_KEYWORDS: ${TJS_KEYWORDS.length} items`)
505
+ console.log(`TJS_FORBIDDEN: ${TJS_FORBIDDEN.length} items`)
506
+ console.log(`TJS_TYPE_CONSTRUCTORS: ${TJS_TYPE_CONSTRUCTORS.length} items\n`)
507
+
508
+ buildVSCodeGrammar()
509
+ buildTJSVSCodeGrammar()
510
+ console.log('\nDone!')