@mirascript/monaco 0.1.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 (95) hide show
  1. package/dist/basic/index.d.ts +6 -0
  2. package/dist/basic/index.d.ts.map +1 -0
  3. package/dist/basic/index.js +10 -0
  4. package/dist/basic/index.js.map +6 -0
  5. package/dist/basic/language-configuration.d.ts +5 -0
  6. package/dist/basic/language-configuration.d.ts.map +1 -0
  7. package/dist/basic/tokens-provider.d.ts +4 -0
  8. package/dist/basic/tokens-provider.d.ts.map +1 -0
  9. package/dist/chunk-CEFEXBF7.js +65 -0
  10. package/dist/chunk-CEFEXBF7.js.map +6 -0
  11. package/dist/chunk-PTNWRTNM.js +474 -0
  12. package/dist/chunk-PTNWRTNM.js.map +6 -0
  13. package/dist/constants.d.ts +20 -0
  14. package/dist/constants.d.ts.map +1 -0
  15. package/dist/contribute.d.ts +3 -0
  16. package/dist/contribute.d.ts.map +1 -0
  17. package/dist/index.d.ts +26 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +83 -0
  20. package/dist/index.js.map +6 -0
  21. package/dist/lsp/compile-result.d.ts +150 -0
  22. package/dist/lsp/compile-result.d.ts.map +1 -0
  23. package/dist/lsp/diagnostics.d.ts +5 -0
  24. package/dist/lsp/diagnostics.d.ts.map +1 -0
  25. package/dist/lsp/index.d.ts +21 -0
  26. package/dist/lsp/index.d.ts.map +1 -0
  27. package/dist/lsp/index.js +2285 -0
  28. package/dist/lsp/index.js.map +6 -0
  29. package/dist/lsp/providers/base.d.ts +21 -0
  30. package/dist/lsp/providers/base.d.ts.map +1 -0
  31. package/dist/lsp/providers/code-action-provider.d.ts +12 -0
  32. package/dist/lsp/providers/code-action-provider.d.ts.map +1 -0
  33. package/dist/lsp/providers/color-provider.d.ts +10 -0
  34. package/dist/lsp/providers/color-provider.d.ts.map +1 -0
  35. package/dist/lsp/providers/completion-item-provider.d.ts +21 -0
  36. package/dist/lsp/providers/completion-item-provider.d.ts.map +1 -0
  37. package/dist/lsp/providers/definition-reference-provider.d.ts +16 -0
  38. package/dist/lsp/providers/definition-reference-provider.d.ts.map +1 -0
  39. package/dist/lsp/providers/document-highlight-provider.d.ts +12 -0
  40. package/dist/lsp/providers/document-highlight-provider.d.ts.map +1 -0
  41. package/dist/lsp/providers/document-symbol-provider.d.ts +10 -0
  42. package/dist/lsp/providers/document-symbol-provider.d.ts.map +1 -0
  43. package/dist/lsp/providers/formatter-provider.d.ts +18 -0
  44. package/dist/lsp/providers/formatter-provider.d.ts.map +1 -0
  45. package/dist/lsp/providers/hover-provider.d.ts +12 -0
  46. package/dist/lsp/providers/hover-provider.d.ts.map +1 -0
  47. package/dist/lsp/providers/inlay-hints-provider.d.ts +10 -0
  48. package/dist/lsp/providers/inlay-hints-provider.d.ts.map +1 -0
  49. package/dist/lsp/providers/range-provider.d.ts +10 -0
  50. package/dist/lsp/providers/range-provider.d.ts.map +1 -0
  51. package/dist/lsp/providers/rename-provider.d.ts +12 -0
  52. package/dist/lsp/providers/rename-provider.d.ts.map +1 -0
  53. package/dist/lsp/providers/semantic-tokens-provider.d.ts +12 -0
  54. package/dist/lsp/providers/semantic-tokens-provider.d.ts.map +1 -0
  55. package/dist/lsp/providers/signature-help-provider.d.ts +12 -0
  56. package/dist/lsp/providers/signature-help-provider.d.ts.map +1 -0
  57. package/dist/lsp/utils.d.ts +37 -0
  58. package/dist/lsp/utils.d.ts.map +1 -0
  59. package/dist/lsp/worker-helper.d.ts +5 -0
  60. package/dist/lsp/worker-helper.d.ts.map +1 -0
  61. package/dist/lsp/worker.d.ts +22 -0
  62. package/dist/lsp/worker.d.ts.map +1 -0
  63. package/dist/lsp/worker.js +62 -0
  64. package/dist/lsp/worker.js.map +6 -0
  65. package/dist/monaco-api.d.ts +16 -0
  66. package/dist/monaco-api.d.ts.map +1 -0
  67. package/package.json +39 -0
  68. package/src/basic/index.ts +11 -0
  69. package/src/basic/language-configuration.ts +90 -0
  70. package/src/basic/tokens-provider.ts +358 -0
  71. package/src/constants.ts +56 -0
  72. package/src/contribute.ts +18 -0
  73. package/src/index.ts +71 -0
  74. package/src/lsp/compile-result.ts +518 -0
  75. package/src/lsp/diagnostics.ts +83 -0
  76. package/src/lsp/index.ts +84 -0
  77. package/src/lsp/providers/base.ts +40 -0
  78. package/src/lsp/providers/code-action-provider.ts +28 -0
  79. package/src/lsp/providers/color-provider.ts +129 -0
  80. package/src/lsp/providers/completion-item-provider.ts +497 -0
  81. package/src/lsp/providers/definition-reference-provider.ts +107 -0
  82. package/src/lsp/providers/document-highlight-provider.ts +71 -0
  83. package/src/lsp/providers/document-symbol-provider.ts +65 -0
  84. package/src/lsp/providers/formatter-provider.ts +81 -0
  85. package/src/lsp/providers/hover-provider.ts +150 -0
  86. package/src/lsp/providers/inlay-hints-provider.ts +121 -0
  87. package/src/lsp/providers/range-provider.ts +37 -0
  88. package/src/lsp/providers/rename-provider.ts +144 -0
  89. package/src/lsp/providers/semantic-tokens-provider.ts +166 -0
  90. package/src/lsp/providers/signature-help-provider.ts +119 -0
  91. package/src/lsp/utils.ts +322 -0
  92. package/src/lsp/worker-helper.ts +119 -0
  93. package/src/lsp/worker.ts +83 -0
  94. package/src/monaco-api.js +66 -0
  95. package/src/monaco-api.ts +18 -0
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@mirascript/monaco",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Monaco Editor integration for Mirascript.",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "@mirascript/dev": "./src/index.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./basic": {
14
+ "@mirascript/dev": "./src/basic/index.ts",
15
+ "default": "./dist/basic/index.js"
16
+ },
17
+ "./lsp": {
18
+ "@mirascript/dev": "./src/lsp/index.ts",
19
+ "default": "./dist/lsp/index.js"
20
+ }
21
+ },
22
+ "imports": {
23
+ "#lsp/worker": {
24
+ "@mirascript/dev": "./src/lsp/worker.ts",
25
+ "default": "./dist/lsp/worker.js"
26
+ }
27
+ },
28
+ "dependencies": {
29
+ "@mirascript/wasm": "~0.1.0",
30
+ "@mirascript/mirascript": "~0.1.0"
31
+ },
32
+ "peerDependencies": {
33
+ "monaco-editor": ">= 0.0.40 < 0.53.0"
34
+ },
35
+ "scripts": {
36
+ "build": "pnpm clean && tsc && node ./esbuild.config.js",
37
+ "clean": "rimraf dist"
38
+ }
39
+ }
@@ -0,0 +1,11 @@
1
+ import { ready } from '@mirascript/wasm';
2
+ import type { IDisposable } from '../monaco-api.js';
3
+ import { setLanguageConfiguration, configuration } from './language-configuration.js';
4
+ import { registerMiraScriptTokensProvider } from './tokens-provider.js';
5
+
6
+ export { configuration };
7
+ /** 注册 */
8
+ export async function registerBasic(): Promise<IDisposable[]> {
9
+ await ready;
10
+ return [...setLanguageConfiguration(), ...registerMiraScriptTokensProvider()];
11
+ }
@@ -0,0 +1,90 @@
1
+ import { type IDisposable, languages } from '../monaco-api.js';
2
+ import { MAX_VERBATIM_LENGTH } from '../constants.js';
3
+
4
+ /** 缩进配置 */
5
+ function indentAction(action: keyof typeof languages.IndentAction): { indentAction: languages.IndentAction } {
6
+ if (languages == null) {
7
+ // vscode
8
+ return {
9
+ indent: action[0]?.toLowerCase() + action.slice(1),
10
+ } as unknown as { indentAction: languages.IndentAction };
11
+ }
12
+ return { indentAction: languages.IndentAction[action] };
13
+ }
14
+
15
+ export const configuration = (): languages.LanguageConfiguration => ({
16
+ comments: {
17
+ lineComment: '//',
18
+ blockComment: ['/*', '*/'],
19
+ },
20
+ brackets: [
21
+ ...Array.from({ length: MAX_VERBATIM_LENGTH }).flatMap((_, i): languages.CharacterPair[] => {
22
+ const prefix = '$'.repeat(MAX_VERBATIM_LENGTH - i - 1);
23
+ return [
24
+ [`${prefix}{`, '}'],
25
+ [`${prefix}(`, ')'],
26
+ ];
27
+ }),
28
+ ['[', ']'],
29
+ ],
30
+ wordPattern: /(-?\d+\.\w+([+-]\w*)?)|([^`~!#%^&*()\-=+[{\]}\\|;:'",.<>/?\s]+)/g,
31
+ autoClosingPairs: [
32
+ { open: '{', close: '}' },
33
+ { open: '[', close: ']' },
34
+ { open: '(', close: ')' },
35
+ { open: '"', close: '"', notIn: ['string'] },
36
+ { open: "'", close: "'", notIn: ['string', 'comment'] },
37
+ { open: '`', close: '`', notIn: ['string', 'comment'] },
38
+ { open: '/**', close: ' */', notIn: ['string'] },
39
+ ],
40
+ onEnterRules: [
41
+ {
42
+ // e.g. /** | */
43
+ beforeText: /^\s*\/\*\*(?!\/)([^*]|\*(?!\/))*$/,
44
+ afterText: /^\s*\*\/$/,
45
+ action: {
46
+ ...indentAction('IndentOutdent'),
47
+ appendText: ' * ',
48
+ },
49
+ },
50
+ {
51
+ // e.g. /** ...|
52
+ beforeText: /^\s*\/\*\*(?!\/)([^*]|\*(?!\/))*$/,
53
+ action: {
54
+ ...indentAction('None'),
55
+ appendText: ' * ',
56
+ },
57
+ },
58
+ {
59
+ // e.g. * ...|
60
+ beforeText: /^(\t|( {2}))* \*( ([^*]|\*(?!\/))*)?$/,
61
+ action: {
62
+ ...indentAction('None'),
63
+ appendText: '* ',
64
+ },
65
+ },
66
+ {
67
+ // e.g. */|
68
+ beforeText: /^(\t|( {2}))* \*\/\s*$/,
69
+ action: {
70
+ ...indentAction('None'),
71
+ removeText: 1,
72
+ },
73
+ },
74
+ ],
75
+ autoCloseBefore: '*/%^ &| ><= )}] ;,?: \'"` \n\t ~#\\',
76
+ folding: {
77
+ markers: {
78
+ start: /^\s*\/\/#?\s*?region\b/gu,
79
+ end: /^\s*\/\/#?\s*?endregion\b/gu,
80
+ },
81
+ },
82
+ });
83
+
84
+ /** 注册语言配置 */
85
+ export function setLanguageConfiguration(): IDisposable[] {
86
+ return [
87
+ languages.setLanguageConfiguration('mirascript', configuration()),
88
+ languages.setLanguageConfiguration('mirascript-template', configuration()),
89
+ ];
90
+ }
@@ -0,0 +1,358 @@
1
+ import { languages, type IDisposable } from '../monaco-api.js';
2
+ import {
3
+ REG_WHITESPACE,
4
+ REG_ORDINAL,
5
+ REG_OCT,
6
+ REG_BIN,
7
+ REG_HEX,
8
+ REG_NUMBER,
9
+ REG_IDENTIFIER,
10
+ DOC_HEADER,
11
+ MAX_VERBATIM_LENGTH,
12
+ constantKeywords,
13
+ controlKeywords,
14
+ keywords,
15
+ numericKeywords,
16
+ } from '../constants.js';
17
+
18
+ /** 匹配 identifier */
19
+ function identifierCases(
20
+ data?: Partial<languages.IExpandedMonarchLanguageAction>,
21
+ defaultToken = 'variable',
22
+ ): Record<string, languages.IExpandedMonarchLanguageAction> {
23
+ return {
24
+ '@numericKeywords': { ...data, token: `constant.numeric` },
25
+ '@constantKeywords': { ...data, token: `constant.language` },
26
+ '@controlKeywords': { ...data, token: `keyword.control` },
27
+ '@keywords': { ...data, token: `keyword` },
28
+ '[@]+.*': { ...data, token: `variable.other.constant` },
29
+ '~it': { ...data, token: `variable.other.constant.emphasis` },
30
+ '@default': { ...data, token: defaultToken },
31
+ };
32
+ }
33
+
34
+ /** 生成 TokensProvider */
35
+ function getTokensProvider(mode: string): languages.IMonarchLanguage {
36
+ return {
37
+ ignoreCase: false,
38
+ unicode: true,
39
+ includeLF: false,
40
+ brackets: [
41
+ { open: '{', close: '}', token: 'delimiter.curly' },
42
+ { open: '[', close: ']', token: 'delimiter.square' },
43
+ { open: '(', close: ')', token: 'delimiter.parenthesis' },
44
+ ],
45
+ defaultToken: 'invalid',
46
+
47
+ whitespace: REG_WHITESPACE,
48
+ identifier: REG_IDENTIFIER,
49
+ docHeader: DOC_HEADER,
50
+
51
+ keywords: keywords(),
52
+ controlKeywords: controlKeywords(),
53
+ constantKeywords: constantKeywords(),
54
+ numericKeywords: numericKeywords(),
55
+
56
+ inlineDocParam: /\(parameter(?: pattern)?\)/,
57
+
58
+ start: mode === 'template' ? 'root_template' : 'root',
59
+ tokenPostfix: '.mirascript',
60
+ tokenizer: {
61
+ root: [
62
+ [/^(?=\0)/, '', '@doc_mode'],
63
+ [/^\/\*\*@docHeader\*\*\/$/, 'comment.doc', '@doc_mode'],
64
+ [/[[\](){}]/, '@brackets'],
65
+ { include: '@common' },
66
+ ],
67
+ root_template: [
68
+ [/[^$]+/, 'string'],
69
+ [/(?=\$)/, '', '@string_interpolation.$S3'],
70
+ [/[$]/, 'string'],
71
+ ],
72
+ common: [
73
+ [/(@identifier)(@whitespace*)(\??:)(?!:)/, ['support.type.property-name', '', 'delimiter']],
74
+ [
75
+ /(fn)(@whitespace+)(@identifier)(?=$|@whitespace|[[({,;])/,
76
+ ['keyword', '', { cases: identifierCases(undefined, 'entity.name.function') }],
77
+ ],
78
+ [
79
+ /(for)(@whitespace+)(mut)(@whitespace+)(@identifier)(@whitespace+)(in)/,
80
+ ['keyword.control', '', 'keyword', '', { cases: identifierCases() }, '', 'keyword.control'],
81
+ ],
82
+ [
83
+ /(for)(@whitespace+)(@identifier)(@whitespace+)(in)/,
84
+ ['keyword.control', '', { cases: identifierCases() }, '', 'keyword.control'],
85
+ ],
86
+ [
87
+ /(\.)(@whitespace*)(\d+)/,
88
+ [
89
+ 'delimiter',
90
+ '',
91
+ {
92
+ cases: {
93
+ [REG_ORDINAL.source]: 'number.ordinal',
94
+ '@default': 'number.float',
95
+ },
96
+ },
97
+ ],
98
+ ],
99
+ [
100
+ /(\.)(@whitespace*)(@identifier)(@whitespace*)(!?)(@whitespace*(?=\())/,
101
+ ['delimiter', '', 'entity.name.function', '', 'delimiter', ''],
102
+ ],
103
+ [/(\.)(@whitespace*)(@identifier)/, ['delimiter', '', 'variable']],
104
+ [
105
+ /(@identifier)(@whitespace*(?=\())/,
106
+ [
107
+ {
108
+ cases: identifierCases(undefined, `entity.name.function`),
109
+ },
110
+ '',
111
+ ],
112
+ ],
113
+ { include: '@whitespace' },
114
+ { include: '@string' },
115
+ [/(@identifier)/, { cases: identifierCases() }],
116
+ [REG_OCT, 'number.octal'],
117
+ [REG_BIN, 'number.binary'],
118
+ [REG_HEX, 'number.hex'],
119
+ [
120
+ REG_NUMBER,
121
+ {
122
+ cases: {
123
+ [REG_ORDINAL.source]: 'number.ordinal',
124
+ '@default': 'number.float',
125
+ },
126
+ },
127
+ ],
128
+ [/(\.\.|\?:|[-+=/~?:;,.!@$%^&|*<>])/, 'delimiter'],
129
+ [REG_ORDINAL, 'number.ordinal'],
130
+ ],
131
+ whitespace: [
132
+ [/(@whitespace)+/, ''],
133
+ [/\/\/.*$/, 'comment.line'],
134
+ [/\/\*{2}/, 'comment.doc', '@doc_comment'],
135
+ [/\/\*/, 'comment.block', '@block_comment'],
136
+ ],
137
+ string: [
138
+ [/["'`]/, { token: 'string.quote.open', next: '@string_normal.$#', bracket: '@open' }],
139
+ [
140
+ /(@+)(["'`])/,
141
+ { token: 'string.quote.open.$2$1.raw', next: '@string_verbatim.$2$1.$1', bracket: '@open' },
142
+ ],
143
+ ],
144
+ string_normal: [
145
+ [/[^'"`\\$]+/, 'string'],
146
+ { include: '@string_escape' },
147
+ [/(?=\$)/, '', '@string_interpolation.'],
148
+ [
149
+ /['"`]/,
150
+ {
151
+ cases: {
152
+ '$S2==$#': { token: 'string.quote.close', next: '@pop', bracket: '@close' },
153
+ '@default': 'string',
154
+ },
155
+ },
156
+ ],
157
+ ],
158
+ string_verbatim: [
159
+ [/[^'"`$]+/, 'string'],
160
+ [/(?=\$)/, '', '@string_interpolation.$S3'],
161
+ [
162
+ /(['"`]@+)/,
163
+ {
164
+ cases: {
165
+ '$S2==$#': { token: 'string.quote.close.raw.$#', next: '@pop', bracket: '@close' },
166
+ '@default': 'string',
167
+ },
168
+ },
169
+ ],
170
+ [/['"`$]/, 'string'],
171
+ ],
172
+ string_escape: [
173
+ [/\\([\\'"`$rntbfv0])/, 'string.escape'],
174
+ [/\\u\{([0-9a-fA-F]+)\}/, 'string.escape.unicode'],
175
+ [/\\x([0-9a-fA-F]{2})/, 'string.escape.ascii'],
176
+ [/\\./, { token: 'string.escape.invalid' }],
177
+ ],
178
+ ...Object.fromEntries(
179
+ Array.from({ length: MAX_VERBATIM_LENGTH }, (_, i) => {
180
+ const dollarCount = i === 0 ? 1 : i;
181
+ const dollarRegex = `\\\${${dollarCount}}`;
182
+ return [
183
+ `string_interpolation.${'@'.repeat(i)}`,
184
+ [
185
+ [
186
+ `(${dollarRegex})(${REG_IDENTIFIER.source})`,
187
+ ['punctuation.section.embedded', { cases: identifierCases({ next: '@pop' }) }],
188
+ ],
189
+ [
190
+ `(${dollarRegex}\\{)`,
191
+ {
192
+ token: 'punctuation.section.embedded',
193
+ bracket: '@open',
194
+ next: '@braced',
195
+ },
196
+ ],
197
+ [
198
+ `(${dollarRegex}\\()`,
199
+ {
200
+ token: 'punctuation.section.embedded',
201
+ bracket: '@open',
202
+ next: '@parenthesized',
203
+ },
204
+ ],
205
+ [`\\\${0,${dollarCount}}`, 'string', '@pop'],
206
+ ['', '', '@pop'],
207
+ ],
208
+ ];
209
+ }),
210
+ ),
211
+ string_interpolation: [[/\$*/, 'string', '@pop']],
212
+
213
+ braced: [
214
+ [/\{/, { token: '@brackets', next: '@push' }],
215
+ [/\}/, { token: '@brackets', next: '@pop' }],
216
+ [/[[\]()]/, '@brackets'],
217
+ { include: '@common' },
218
+ ],
219
+ parenthesized: [
220
+ [/\(/, { token: '@brackets', next: '@push' }],
221
+ [/\)/, { token: '@brackets', next: '@pop' }],
222
+ [/[[\]{}]/, '@brackets'],
223
+ { include: '@common' },
224
+ ],
225
+ bracketed: [
226
+ [/\[/, { token: '@brackets', next: '@push' }],
227
+ [/\]/, { token: '@brackets', next: '@pop' }],
228
+ [/[(){}]/, '@brackets'],
229
+ { include: '@common' },
230
+ ],
231
+
232
+ block_comment: [
233
+ [/\*\//, { token: 'comment.block', next: '@pop' }],
234
+ [/[^*]+/, { token: 'comment.block' }],
235
+ [/\*/, { token: 'comment.block' }],
236
+ ],
237
+
238
+ doc_comment: [
239
+ [/\*\//, { token: 'comment.doc', next: '@pop' }],
240
+ [/^(\s*)\*(?!\/)/, { token: 'comment.doc' }],
241
+ [/\\\*(?!\/)/, { token: 'comment.doc.escape' }],
242
+ [/@(param|returns)/, { token: 'entity.name.tag.doc' }],
243
+ [/\*{2}(\S|\S.*?\S)\*{2}(?!\/)/, { token: 'comment.strong' }],
244
+ [/\*(\S|\S.*?\S)\*(?!\/)/, { token: 'comment.emphasis' }],
245
+ [/[^*@\\]+/, { token: 'comment.doc' }],
246
+ [/[*@\\]/, { token: 'comment.doc' }],
247
+ ],
248
+
249
+ doc_mode: [
250
+ // inline doc, start with `\0`
251
+ [
252
+ /^(\0@inlineDocParam)(@whitespace+)(\.\.|)(mut)(@whitespace+)(@identifier)/,
253
+ ['entity.name.label', '', 'delimiter', 'keyword.mut', '', 'variable.emphasis'],
254
+ ],
255
+ [
256
+ /^(\0@inlineDocParam)(@whitespace+)(\.\.|)(@identifier)/,
257
+ ['entity.name.label', '', 'delimiter', 'variable.other.constant.emphasis'],
258
+ ],
259
+ [/^(\0\(@identifier\))(@whitespace+)/, ['entity.name.label', '']],
260
+
261
+ [
262
+ /(@identifier)(@whitespace*)(:)(@whitespace*)(\/\*@whitespace*<)(extern )([.\w]*Function)(>@whitespace*\*\/)/,
263
+ [
264
+ 'entity.name.function.doc',
265
+ '',
266
+ 'delimiter',
267
+ '',
268
+ 'comment.doc',
269
+ 'type',
270
+ 'entity.name.label',
271
+ 'comment.doc',
272
+ ],
273
+ ],
274
+ [
275
+ /(@identifier)(@whitespace*)(:)(@whitespace*)(\/\*@whitespace*<)(function )([.\w]*)(>@whitespace*\*\/)/,
276
+ [
277
+ 'entity.name.function.doc',
278
+ '',
279
+ 'delimiter',
280
+ '',
281
+ 'comment.doc',
282
+ 'type',
283
+ 'entity.name.label',
284
+ 'comment.doc',
285
+ ],
286
+ ],
287
+ [/(@identifier)(@whitespace*)(:)(@whitespace+)/, ['support.type.property-name', '', 'delimiter', '']],
288
+ [
289
+ /(\/\*@whitespace*<)(\w+@whitespace*)([.\w]*)(>@whitespace*\*\/)/,
290
+ ['comment.doc', 'type', 'entity.name.label', 'comment.doc'],
291
+ ],
292
+ [/(\s*)(\(module\))(\s*)(@identifier)/, ['', 'entity.name.label', '', 'entity.name.namespace']],
293
+
294
+ [/(fn)(@whitespace+)(@identifier)$/, ['keyword.fn.doc', '', 'entity.name.function.doc']],
295
+ [
296
+ /(fn)(@whitespace+)(@identifier)(\()(\.\.)(\))$/,
297
+ ['keyword.fn.doc', '', 'entity.name.function.doc', '@brackets', 'delimiter', '@brackets'],
298
+ ],
299
+ [/fn/, 'keyword.fn.doc', '@fn_doc'],
300
+ [
301
+ /(let)(@whitespace+)(mut)(@whitespace+)(@identifier)/,
302
+ [{ token: 'keyword.$1' }, '', 'keyword.mut', '', { token: 'variable', next: '@root' }],
303
+ ],
304
+ [
305
+ /(let|const)(@whitespace+)(@identifier)/,
306
+ [{ token: 'keyword.$1' }, '', { token: 'variable.other.constant', next: '@root' }],
307
+ ],
308
+ { include: '@common' },
309
+ [/[[\](){}]/, '@brackets'],
310
+ ],
311
+ fn_doc: [
312
+ [/(@identifier)(\()/, ['entity.name.function.doc', '@brackets']],
313
+ [/@whitespace+/, ''],
314
+ [
315
+ /(\.\.|)(@identifier)(\s*)(:|,|\))/,
316
+ [
317
+ 'delimiter',
318
+ 'variable.emphasis.doc',
319
+ '',
320
+ {
321
+ cases: {
322
+ ':': { token: 'delimiter', next: '@type_doc' },
323
+ '\\)': '@brackets',
324
+ '@default': 'delimiter',
325
+ },
326
+ },
327
+ ],
328
+ ],
329
+ [/[()]/, '@brackets'],
330
+ [/(->)/, 'delimiter', '@type_doc'],
331
+ [/;/, { token: 'delimiter', next: '@pop', goBack: 1 }],
332
+ ],
333
+ type_doc: [
334
+ { include: '@type_doc_common' },
335
+ [/[,)]/, 'delimiter', '@pop'],
336
+ [/;/, { token: 'delimiter', next: '@pop', goBack: 1 }],
337
+ ],
338
+ type_doc_inner: [{ include: '@type_doc_common' }, [/[,;]/, 'delimiter']],
339
+ type_doc_common: [
340
+ [/fn\b/, 'type', '@fn_doc'],
341
+ [/(type)(\()(@identifier)(\))/, ['type', '@brackets', 'variable.emphasis.doc', '@brackets']],
342
+ [/@identifier/, 'type'],
343
+ [/[[(]/, '@brackets', '@type_doc_inner'],
344
+ [/[\])]/, '@brackets', '@pop'],
345
+ [/[&|.]/, 'delimiter'],
346
+ [/@whitespace+/, ''],
347
+ ],
348
+ },
349
+ };
350
+ }
351
+
352
+ /** 注册 Mirascript 的 TokensProvider */
353
+ export function registerMiraScriptTokensProvider(): IDisposable[] {
354
+ return [
355
+ languages.setMonarchTokensProvider('mirascript', getTokensProvider('script')),
356
+ languages.setMonarchTokensProvider('mirascript-template', getTokensProvider('template')),
357
+ ];
358
+ }
@@ -0,0 +1,56 @@
1
+ import { constants } from '@mirascript/mirascript/subtle';
2
+ import { wasm } from '@mirascript/wasm';
3
+
4
+ /** 所有 MiraScript 关键字 */
5
+ export let keywords = (): readonly string[] => {
6
+ const kw = wasm.keywords();
7
+ Object.freeze(kw);
8
+ keywords = () => kw;
9
+ return kw;
10
+ };
11
+
12
+ /** MiraScript 控制流关键字 */
13
+ export let controlKeywords = (): readonly string[] => {
14
+ const kw = wasm.control_keywords();
15
+ Object.freeze(kw);
16
+ controlKeywords = () => kw;
17
+ return kw;
18
+ };
19
+
20
+ /** MiraScript 数值字面量关键字 */
21
+ export let numericKeywords = (): readonly string[] => {
22
+ const kw = wasm.numeric_keywords();
23
+ Object.freeze(kw);
24
+ numericKeywords = () => kw;
25
+ return kw;
26
+ };
27
+
28
+ /** MiraScript 字面量关键字 */
29
+ export let constantKeywords = (): readonly string[] => {
30
+ const kw = wasm.constant_keywords();
31
+ Object.freeze(kw);
32
+ constantKeywords = () => kw;
33
+ return kw;
34
+ };
35
+
36
+ /** MiraScript 保留字关键字 */
37
+ export let reservedKeywords = (): readonly string[] => {
38
+ const kw = wasm.reserved_keywords();
39
+ Object.freeze(kw);
40
+ reservedKeywords = () => kw;
41
+ return kw;
42
+ };
43
+
44
+ export const { REG_IDENTIFIER, REG_ORDINAL } = constants;
45
+
46
+ export const REG_WHITESPACE = /[ \t\v\f\r\n]/u;
47
+ export const REG_HEX = /0[xX][a-fA-F0-9_]*[a-fA-F0-9]/;
48
+ export const REG_OCT = /0[oO][0-7_]*[0-7]/;
49
+ export const REG_BIN = /0[bB][01_]*[01]/;
50
+ export const REG_NUMBER = /\d[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?[\d_]*\d)?/u;
51
+
52
+ // Special characters
53
+ export const DOC_HEADER = ' 𝙼𝚒𝚛𝚊𝚂𝚌𝚛𝚒𝚙𝚝 𝙶𝚕𝚘𝚋𝚊𝚕 𝙳𝚎𝚏𝚒𝚗𝚒𝚝𝚒𝚘𝚗𝚜 ';
54
+
55
+ /** 基础语言服务支持的最大插值字符串 `$` 数量 */
56
+ export const MAX_VERBATIM_LENGTH = 16;
@@ -0,0 +1,18 @@
1
+ import { languages } from './monaco-api.js';
2
+
3
+ /** 注册语言 */
4
+ export function registerContribution(): void {
5
+ languages.register({
6
+ id: 'mirascript',
7
+ extensions: ['.mira'],
8
+ aliases: ['MiraScript', 'mirascript', 'mira'],
9
+ mimetypes: ['text/x-mirascript'],
10
+ });
11
+
12
+ languages.register({
13
+ id: 'mirascript-template',
14
+ extensions: ['.miratpl'],
15
+ aliases: ['MiraScriptTemplate', 'mirascript-template', 'miratpl'],
16
+ mimetypes: ['text/x-mirascript-template'],
17
+ });
18
+ }
package/src/index.ts ADDED
@@ -0,0 +1,71 @@
1
+ import type { VmContext } from '@mirascript/mirascript';
2
+ import { type editor, languages, registerMonacoApi, type IDisposable, type MonacoApi } from './monaco-api.js';
3
+ import { registerContribution } from './contribute.js';
4
+
5
+ /** 提供全局变量信息 */
6
+ export type VmContextProvider = (model: editor.ITextModel) => languages.ProviderResult<VmContext>;
7
+
8
+ /** 加载器 */
9
+ export class MiraScriptMonacoLoader implements IDisposable {
10
+ constructor(readonly contextProvider?: VmContextProvider) {
11
+ registerContribution();
12
+
13
+ const _loadBasicFeatures = () => void this.loadBasicFeatures();
14
+ const _loadFullFeatures = () => void this.loadLSPFeatures();
15
+
16
+ languages.onLanguageEncountered('mirascript', _loadBasicFeatures);
17
+ languages.onLanguage('mirascript', _loadFullFeatures);
18
+
19
+ languages.onLanguageEncountered('mirascript-template', _loadBasicFeatures);
20
+ languages.onLanguage('mirascript-template', _loadFullFeatures);
21
+ }
22
+ private _basicFeaturesLoaded = false;
23
+ private _lspFeaturesLoaded = false;
24
+ /** 加载基础功能 */
25
+ async loadBasicFeatures(): Promise<void> {
26
+ try {
27
+ const { registerBasic } = await import('./basic/index.js');
28
+ if (this._basicFeaturesLoaded || this.disposed) return;
29
+ this._basicFeaturesLoaded = true;
30
+ this.disposables.push(...(await registerBasic()));
31
+ } catch (error) {
32
+ // eslint-disable-next-line no-console
33
+ console.error('Failed to load MiraScript basic features:', error);
34
+ }
35
+ }
36
+ /** 加载 LSP 功能 */
37
+ async loadLSPFeatures(): Promise<void> {
38
+ try {
39
+ const basic = this.loadBasicFeatures();
40
+ const { registerLSP } = await import('./lsp/index.js');
41
+ await basic; // 确保基础功能已加载
42
+ if (this._lspFeaturesLoaded || this.disposed) return;
43
+ this._lspFeaturesLoaded = true;
44
+ this.disposables.push(...(await registerLSP(this.contextProvider)));
45
+ } catch (error) {
46
+ // eslint-disable-next-line no-console
47
+ console.error('Failed to load MiraScript LSP features:', error);
48
+ }
49
+ }
50
+
51
+ private readonly disposables: IDisposable[] = [];
52
+ private disposed = false;
53
+ /** @inheritdoc */
54
+ dispose(): void {
55
+ if (this.disposed) {
56
+ throw new Error('MiraScriptMonacoLoader has already been disposed.');
57
+ }
58
+ this.disposed = true;
59
+ for (const d of this.disposables.splice(0)) {
60
+ d.dispose();
61
+ }
62
+ }
63
+ }
64
+ export { registerMonacoApi, registerContribution };
65
+ /**
66
+ * 注册 MiraScript Monaco 编辑器扩展。
67
+ */
68
+ export function registerMiraScript(monacoApi: MonacoApi, globalProvider?: VmContextProvider): MiraScriptMonacoLoader {
69
+ registerMonacoApi(monacoApi);
70
+ return new MiraScriptMonacoLoader(globalProvider);
71
+ }