@bhsd/codemirror-mediawiki 3.12.1 → 3.12.3

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 (51) hide show
  1. package/dist/codemirror.d.ts +2 -1
  2. package/dist/codemirror.js +5 -5
  3. package/dist/constants.d.ts +2 -1
  4. package/dist/constants.js +1 -1
  5. package/dist/css.js +2 -2
  6. package/dist/escape.js +9 -10
  7. package/dist/fold.d.ts +5 -8
  8. package/dist/fold.js +18 -18
  9. package/dist/hover.js +3 -3
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/inlay.js +2 -2
  13. package/dist/javascript.d.ts +1 -1
  14. package/dist/javascript.js +8 -4
  15. package/dist/json.d.ts +8 -0
  16. package/dist/json.js +101 -0
  17. package/dist/keymap.d.ts +8 -1
  18. package/dist/keymap.js +89 -7
  19. package/dist/lilypond.d.ts +14 -0
  20. package/dist/lilypond.js +240 -0
  21. package/dist/lint.js +2 -2
  22. package/dist/lintsource.d.ts +1 -1
  23. package/dist/lintsource.js +7 -7
  24. package/dist/lua.d.ts +1 -1
  25. package/dist/lua.js +39 -63
  26. package/dist/main.min.js +32 -31
  27. package/dist/matchBrackets.d.ts +3 -11
  28. package/dist/matchBrackets.js +51 -39
  29. package/dist/matchTag.d.ts +5 -5
  30. package/dist/matchTag.js +4 -4
  31. package/dist/math.d.ts +3 -0
  32. package/dist/math.js +58 -0
  33. package/dist/mediawiki.d.ts +2 -3
  34. package/dist/mediawiki.js +34 -26
  35. package/dist/mw.min.js +33 -32
  36. package/dist/ref.d.ts +2 -2
  37. package/dist/ref.js +5 -5
  38. package/dist/signature.js +13 -13
  39. package/dist/static.d.ts +7 -0
  40. package/dist/static.js +7 -0
  41. package/dist/theme.d.ts +1 -1
  42. package/dist/theme.js +9 -3
  43. package/dist/token.d.ts +10 -6
  44. package/dist/token.js +54 -20
  45. package/dist/util.d.ts +35 -10
  46. package/dist/util.js +43 -15
  47. package/dist/wiki.min.js +33 -32
  48. package/i18n/en.json +1 -1
  49. package/i18n/zh-hans.json +1 -1
  50. package/i18n/zh-hant.json +1 -1
  51. package/package.json +8 -10
@@ -0,0 +1,14 @@
1
+ import type { StreamParser, StringStream } from '@codemirror/language';
2
+ declare interface State {
3
+ tokenize: Tokenizer;
4
+ /** 只用于Scheme */
5
+ parens: number;
6
+ /** 只用于歌词 */
7
+ braces: number;
8
+ /** 只用于歌词 */
9
+ spaced: boolean;
10
+ lyrics: boolean;
11
+ }
12
+ declare type Tokenizer = (stream: StringStream, state: State) => string;
13
+ export declare const lilypond: StreamParser<State>;
14
+ export {};
@@ -0,0 +1,240 @@
1
+ import { inComment, getCompletions } from './util.js';
2
+ import { extData, extCompletion } from './constants.js';
3
+ let scoreFetch;
4
+ const inString = (parent) => (stream, state) => {
5
+ let escaped = false, next = stream.next();
6
+ while (next) {
7
+ if (!escaped && next === '"') {
8
+ state.tokenize = parent;
9
+ return /* #a11 */ 'string';
10
+ }
11
+ escaped = !escaped && next === '\\';
12
+ next = stream.next();
13
+ }
14
+ return /* #a11 */ 'string';
15
+ };
16
+ const inScheme = (parent) => {
17
+ const style = 'mw-tag-score-scheme';
18
+ const tokenizer = (stream, state) => {
19
+ if (stream.eatSpace()) {
20
+ return style;
21
+ }
22
+ const ch = stream.next();
23
+ switch (ch) {
24
+ case '(':
25
+ state.parens++;
26
+ return style;
27
+ case ')':
28
+ state.parens--;
29
+ if (state.parens === 0) {
30
+ state.tokenize = parent;
31
+ return 'separator';
32
+ }
33
+ return style;
34
+ case '"':
35
+ state.tokenize = inString(tokenizer);
36
+ return /* #a11 */ `string ${style}`;
37
+ case ';':
38
+ stream.skipToEnd();
39
+ return /* #940 */ `comment ${style}`;
40
+ case '#':
41
+ if (stream.eat('!')) {
42
+ state.tokenize = inComment(tokenizer, '!#');
43
+ return /* #940 */ `comment ${style}`;
44
+ }
45
+ // fall through
46
+ default:
47
+ return style;
48
+ }
49
+ };
50
+ return tokenizer;
51
+ };
52
+ const eatHash = (stream, state, ch, parent) => {
53
+ if (stream.match(/^#[tf]/u)) {
54
+ return /* #219 */ 'bool';
55
+ }
56
+ else if (ch === '#' && stream.match(/^(?:\d+|#x[\da-f]*)/iu)) {
57
+ return /* #a11 */ 'character';
58
+ }
59
+ else if (stream.eat('(')) {
60
+ state.tokenize = inScheme(parent);
61
+ state.parens = 1;
62
+ return 'separator';
63
+ }
64
+ return stream.match(/^\s*[-_a-z][-\w]*/iu) ? 'variableName.local' : 'operator';
65
+ };
66
+ const eatQuote = (state, parent) => {
67
+ state.tokenize = inString(parent);
68
+ return /* #a11 */ 'string';
69
+ };
70
+ const eatPercent = (stream, state, parent) => {
71
+ if (stream.eat('{')) {
72
+ state.tokenize = inComment(parent, '%}');
73
+ return /* #940 */ 'comment';
74
+ }
75
+ stream.skipToEnd();
76
+ return /* #940 */ 'comment';
77
+ };
78
+ const lyricsCommands = new Set(['addlyrics', 'lyricmode', 'lyrics', 'lyricsto']), setCommands = new Set(['set', 'override']), unsetCommands = new Set(['unset', 'revert', 'tweak']), newCommands = new Set(['new', 'context']);
79
+ const eatCommand = (stream, state, parent, base) => {
80
+ const mt = stream.match(/^[a-z](?:[a-z]|-+(?=[a-z]))*/iu), cmd = mt?.[0], isUnset = unsetCommands.has(cmd), isNew = newCommands.has(cmd);
81
+ if (base && lyricsCommands.has(cmd)) {
82
+ state.lyrics = true;
83
+ }
84
+ else if (isUnset || isNew || setCommands.has(cmd)) {
85
+ state.tokenize = inAssignment(parent, isUnset ? -1 : 1, isNew);
86
+ }
87
+ return mt && extData['score']?.has(`\\${cmd}`) !== false ? /* #708 */ 'keyword' : '';
88
+ };
89
+ const inAssignment = (parent, step, cls) => (stream, state) => {
90
+ if (stream.eatSpace()) {
91
+ return '';
92
+ }
93
+ else if (step === 0) {
94
+ stream.eat('=');
95
+ state.tokenize = parent;
96
+ return 'operator';
97
+ }
98
+ stream.match(/^[a-z][-\w.]*/iu);
99
+ state.tokenize = step === 1 ? inAssignment(parent, 0) : parent;
100
+ return cls ? /* #167 */ 'className' : /* #00f */ 'variableName.definition';
101
+ };
102
+ const inBase = (stream, state) => {
103
+ if (stream.eatSpace()) {
104
+ return '';
105
+ }
106
+ const ch = stream.next();
107
+ switch (ch) {
108
+ case '-':
109
+ return stream.eat(/[->.+_!^]/u) ? 'operator' : 'punctuation';
110
+ case '#':
111
+ case '$':
112
+ return eatHash(stream, state, ch, inBase);
113
+ case '"':
114
+ return eatQuote(state, inBase);
115
+ case '%':
116
+ return eatPercent(stream, state, inBase);
117
+ case '/':
118
+ stream.eat('+');
119
+ return 'punctuation';
120
+ case '\\':
121
+ if (stream.eat(/[-<>!]/u)) {
122
+ return 'operator';
123
+ }
124
+ else if (stream.eat(/[()[\]]/u)) {
125
+ return 'squareBracket';
126
+ }
127
+ return stream.eat(/[\\=]/u) ? 'punctuation' : eatCommand(stream, state, inBase, true);
128
+ case '}':
129
+ state.lyrics = false;
130
+ return 'squareBracket';
131
+ case '{':
132
+ if (state.lyrics) {
133
+ state.lyrics = false;
134
+ state.braces = 1;
135
+ state.spaced = true;
136
+ state.tokenize = inLyrics;
137
+ }
138
+ return 'squareBracket';
139
+ default:
140
+ if (/[<>()[\]]/u.test(ch)) {
141
+ return 'squareBracket';
142
+ }
143
+ else if (/[:|~^_=]/u.test(ch)) {
144
+ return 'punctuation';
145
+ }
146
+ else if (/[',.!?]/u.test(ch)) {
147
+ return 'operator';
148
+ }
149
+ else if (/\d/u.test(ch)) {
150
+ stream.match(/^\d*(?:[./]\d+)?/u);
151
+ return /* #164 */ 'number';
152
+ }
153
+ else if (/[a-z]/iu.test(ch)) {
154
+ stream.match(/^(?:[a-z]|[-_\d]+(?=[a-z]))+/iu);
155
+ return /^(?:[rs]|[a-g](?:is)*(?:ih)*|[a-g]?(?:es)*(?:eh)*)$/u.test(stream.current())
156
+ ? ''
157
+ : /* #219 */ 'atom';
158
+ }
159
+ return '';
160
+ }
161
+ };
162
+ const inLyrics = (stream, state) => {
163
+ if (stream.eatSpace()) {
164
+ state.spaced = true;
165
+ return '';
166
+ }
167
+ else if (stream.sol()) {
168
+ state.spaced = true;
169
+ }
170
+ const ch = stream.next();
171
+ switch (ch) {
172
+ case '-':
173
+ if (state.spaced && stream.match(/^-(?=\s)/u)) {
174
+ return 'punctuation';
175
+ }
176
+ state.spaced = false;
177
+ return 'string';
178
+ case '_':
179
+ case '~':
180
+ case '|':
181
+ state.spaced = false;
182
+ return 'punctuation';
183
+ case '#':
184
+ case '$':
185
+ state.spaced = false;
186
+ return eatHash(stream, state, ch, inLyrics);
187
+ case '"':
188
+ state.spaced = true;
189
+ return eatQuote(state, inLyrics);
190
+ case '%':
191
+ state.spaced = true;
192
+ return eatPercent(stream, state, inLyrics);
193
+ case '\\':
194
+ if (stream.eat(/[<>!\\]/u)) {
195
+ state.spaced = true;
196
+ return '';
197
+ }
198
+ state.spaced = false;
199
+ return eatCommand(stream, state, inLyrics);
200
+ case '{':
201
+ case '}':
202
+ state.braces += ch === '{' ? 1 : -1;
203
+ if (state.braces) {
204
+ state.spaced = true;
205
+ }
206
+ else {
207
+ state.tokenize = inBase;
208
+ }
209
+ return 'squareBracket';
210
+ default:
211
+ state.spaced = false;
212
+ if (/\d/u.test(ch)) {
213
+ stream.eatWhile(/\d/u);
214
+ return /* #164 */ 'number';
215
+ }
216
+ stream.eatWhile(/[^\s\d_~{}#$"%\\]/u);
217
+ return /* #a11 */ 'string';
218
+ }
219
+ };
220
+ export const lilypond = {
221
+ startState() {
222
+ if (typeof wikiparse === 'object') {
223
+ scoreFetch ??= (async () => {
224
+ const data = await (await fetch(`${wikiparse.CDN}/data/ext/score.json`)).json();
225
+ extData['score'] = new Set(data.flatMap(item => item.split('.')));
226
+ extCompletion['score'] = getCompletions(data.filter(s => s.startsWith('\\')), 'keyword');
227
+ })();
228
+ }
229
+ return {
230
+ tokenize: inBase,
231
+ parens: 0,
232
+ braces: 0,
233
+ lyrics: false,
234
+ spaced: false,
235
+ };
236
+ },
237
+ token(stream, state) {
238
+ return state.tokenize(stream, state);
239
+ },
240
+ };
package/dist/lint.js CHANGED
@@ -1,4 +1,4 @@
1
- const findDiagnostic = (deco, head, anchor = head) => {
1
+ const myFindDiagnostic = (deco, head, anchor = head) => {
2
2
  let found;
3
3
  deco.between(head, Infinity, (_, __, { spec: { diagnostics } }) => {
4
4
  const next = diagnostics.sort((a, b) => a.from - b.from || a.to - b.to)
@@ -16,7 +16,7 @@ const findDiagnostic = (deco, head, anchor = head) => {
16
16
  * @param cm CodeMirror6 实例
17
17
  */
18
18
  export const nextDiagnostic = (cm) => {
19
- const view = cm.view, { state } = view, { diagnostics } = state.field(cm.getLintExtension()[2][0]), { from, to } = state.selection.main, next = findDiagnostic(diagnostics, from, to) ?? findDiagnostic(diagnostics, 0);
19
+ const view = cm.view, { state } = view, { diagnostics } = state.field(cm.getLintExtension()[2][0]), { from, to } = state.selection.main, next = myFindDiagnostic(diagnostics, from, to) ?? myFindDiagnostic(diagnostics, 0);
20
20
  if (!next || next.from === from && next.to === to) {
21
21
  return false;
22
22
  }
@@ -3,7 +3,7 @@ import type { Text, EditorState } from '@codemirror/state';
3
3
  import type { Language } from '@codemirror/language';
4
4
  import type { Diagnostic, Action } from '@codemirror/lint';
5
5
  import type { Option, LiveOption } from './linter';
6
- import type { DocRange } from './fold';
6
+ import type { DocRange } from './util';
7
7
  export type LintSource<T = unknown> = ((state: EditorState) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>) & {
8
8
  config?: T;
9
9
  fixer?: (doc: Text, rule?: string) => string | Promise<string>;
@@ -4,7 +4,7 @@ import { javascriptLanguage } from '@codemirror/lang-javascript';
4
4
  import { sanitizeInlineStyle, lintJSON } from '@bhsd/common';
5
5
  import { getWikiLinter, getJsLinter, getCssLinter, getLuaLinter, stylelintRepo, eslintRepo, luacheckRepo, isStylelintConfig, } from './linter.js';
6
6
  import { posToIndex, toConfigGetter, } from './util.js';
7
- import { base } from './constants.js';
7
+ import { baseData } from './constants.js';
8
8
  import { vue } from './javascript-globals.js';
9
9
  /**
10
10
  * 获取Linter选项
@@ -67,7 +67,7 @@ const wikiLintSource = async (wikiLint, text, opt, doc, f = 0, t) => (await wiki
67
67
  * @test
68
68
  */
69
69
  export const getWikiLintSource = (articlePath) => async (opt, v) => {
70
- const options = { ...await getOpt(opt), cdn: base.CDN };
70
+ const options = { ...await getOpt(opt), cdn: baseData.CDN };
71
71
  if (articlePath) {
72
72
  options.getConfig = toConfigGetter(options.getConfig, articlePath);
73
73
  }
@@ -113,7 +113,7 @@ const jsLintSource = (esLint, code, opt, doc, f = 0, t) => esLint(code, opt)
113
113
  * @test
114
114
  */
115
115
  export const getJsLintSource = async (opt) => {
116
- const { CDN } = base, esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
116
+ const { CDN } = baseData, esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
117
117
  const lintSource = async ({ doc }) => jsLintSource(esLint, doc.toString(), await getOpt(opt), doc);
118
118
  lintSource.fixer = (doc, rule) => esLint.fixer(doc.toString(), rule);
119
119
  Object.defineProperty(lintSource, 'config', {
@@ -156,7 +156,7 @@ const cssLintSource = async (styleLint, code, opt, doc, f = 0, t) => {
156
156
  * @test
157
157
  */
158
158
  export const getCssLintSource = async (opt) => {
159
- const { CDN } = base, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`);
159
+ const { CDN } = baseData, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`);
160
160
  const lintSource = async ({ doc }) => cssLintSource(styleLint, doc.toString(), await getOpt(opt), doc);
161
161
  lintSource.fixer = async (doc, rule) => styleLint.fixer(doc.toString(), rule);
162
162
  Object.defineProperty(lintSource, 'config', {
@@ -180,7 +180,7 @@ const stylelintConfigVue = /* #__PURE__ */ (() => ({
180
180
  }))();
181
181
  /** @implements */
182
182
  const getVueOrHtmlLintSource = (rules, globals) => async (opt) => {
183
- const { CDN } = base, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`), esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
183
+ const { CDN } = baseData, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`), esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
184
184
  const lintSource = async (state) => {
185
185
  const { doc } = state, option = await getOpt(opt, true) ?? {};
186
186
  let js = option['js'], css = option['css'];
@@ -228,7 +228,7 @@ export const getVueLintSource = /* #__PURE__ */ getVueOrHtmlLintSource(stylelint
228
228
  * @test
229
229
  */
230
230
  export const getHTMLLintSource = async (opt, view, language) => {
231
- const vueLintSource = await getVueOrHtmlLintSource()(opt), wikiLint = await getWikiLinter({ include: false, ...await getOpt(opt), cdn: base.CDN }, view);
231
+ const vueLintSource = await getVueOrHtmlLintSource()(opt), wikiLint = await getWikiLinter({ include: false, ...await getOpt(opt), cdn: baseData.CDN }, view);
232
232
  const lintSource = async (state) => {
233
233
  const { doc } = state, option = await getOpt(opt, true) ?? {}, wiki = option['wiki'];
234
234
  return [
@@ -255,7 +255,7 @@ export const getJsonLintSource = () => ({ doc }) => lintJSON(doc.toString())
255
255
  * @test
256
256
  */
257
257
  export const getLuaLintSource = async () => {
258
- const { CDN } = base, luaLint = await getLuaLinter(CDN && `${CDN}/${luacheckRepo}`);
258
+ const { CDN } = baseData, luaLint = await getLuaLinter(CDN && `${CDN}/${luacheckRepo}`);
259
259
  return async ({ doc }) => (await luaLint(doc.toString()))
260
260
  .map(({ line, column, end_column, msg: message, severity }) => ({
261
261
  source: 'Luacheck',
package/dist/lua.d.ts CHANGED
@@ -3,7 +3,7 @@ import { LanguageSupport } from '@codemirror/language';
3
3
  import type { ViewUpdate, DecorationSet } from '@codemirror/view';
4
4
  import type { EditorState } from '@codemirror/state';
5
5
  import type { Tree } from '@lezer/common';
6
- import type { DocRange } from './fold';
6
+ import type { DocRange } from './util';
7
7
  /**
8
8
  * 高亮显示LDoc标签
9
9
  * @ignore
package/dist/lua.js CHANGED
@@ -4,7 +4,7 @@ import { ViewPlugin, Decoration } from '@codemirror/view';
4
4
  import { syntaxTree, LanguageSupport, StreamLanguage, foldService, HighlightStyle, syntaxHighlighting, } from '@codemirror/language';
5
5
  import { snippetCompletion } from '@codemirror/autocomplete';
6
6
  import { tags } from '@lezer/highlight';
7
- import { leadingSpaces, sliceDoc, markDocTagType } from './util.js';
7
+ import { leadingSpaces, sliceDoc, markDocTagType, getCompletions } from './util.js';
8
8
  import { lightHighlightStyle } from './theme.js';
9
9
  const map = {
10
10
  1: 'constant',
@@ -218,12 +218,9 @@ const map = {
218
218
  },
219
219
  ext: 4,
220
220
  },
221
- }, builtin = ['false', 'nil', 'true'], builtins = builtin.map(label => ({ label, type: 'constant' })), tables = [
222
- '_G',
223
- ...Object.keys(globals),
224
- ].map(label => ({ label, type: 'namespace' })), constants = [
221
+ }, luaBuiltin = ['false', 'nil', 'true'], luaBuiltins = getCompletions(luaBuiltin, 'constant'), tables = getCompletions(['_G', ...Object.keys(globals)], 'namespace'), constants = [
225
222
  { label: '_VERSION', type: 'constant' },
226
- ...[
223
+ ...getCompletions([
227
224
  'assert',
228
225
  'error',
229
226
  'getfenv',
@@ -243,22 +240,15 @@ const map = {
243
240
  'unpack',
244
241
  'xpcall',
245
242
  'require',
246
- ].map(label => ({ label, type: 'function' })),
247
- ], binary = [
248
- 'and',
249
- 'or',
250
- 'in',
251
- ].map(label => ({ label, type: 'keyword' })), unary = [
252
- ...[
253
- 'not',
254
- 'function',
255
- ].map(label => ({ label, type: 'keyword' })),
243
+ ], 'function'),
244
+ ], binary = getCompletions(['and', 'or', 'in']), unary = [
245
+ ...getCompletions(['not', 'function']),
256
246
  snippetCompletion('function ${name}(${})\n\t${}\nend', {
257
247
  label: 'function',
258
248
  detail: 'definition',
259
249
  type: 'keyword',
260
250
  }),
261
- ], blocks = [
251
+ ], blocks = getCompletions([
262
252
  'break',
263
253
  'elseif',
264
254
  'return',
@@ -268,14 +258,14 @@ const map = {
268
258
  'do',
269
259
  'until',
270
260
  'goto',
271
- ].map(label => ({ label, type: 'keyword' })), keywords = [
272
- ...[
261
+ ]), luaKeywords = [
262
+ ...getCompletions([
273
263
  'if',
274
264
  'while',
275
265
  'repeat',
276
266
  'for',
277
267
  'local',
278
- ].map(label => ({ label, type: 'keyword' })),
268
+ ]),
279
269
  snippetCompletion('if ${condition} then\n\t${}\nend', {
280
270
  label: 'if',
281
271
  detail: 'block',
@@ -306,14 +296,14 @@ const map = {
306
296
  detail: 'in loop',
307
297
  type: 'keyword',
308
298
  }),
309
- ], types = new Set(['variableName', 'variableName.standard', 'keyword']), lang = StreamLanguage.define(lua);
299
+ ], excludedTypes = new Set(['variableName', 'variableName.standard', 'keyword']), lang = StreamLanguage.define(lua);
310
300
  /**
311
301
  * @implements
312
302
  * @test
313
303
  */
314
304
  const source = context => {
315
305
  const { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1);
316
- if (!types.has(node.name)) {
306
+ if (!excludedTypes.has(node.name)) {
317
307
  return null;
318
308
  }
319
309
  const match = context.matchBefore(/(?:(?:^|\S|\.\.)\s+|^|[^\w\s]|\.\.)\w+$|\.{1,2}$/u);
@@ -358,57 +348,43 @@ const source = context => {
358
348
  };
359
349
  }
360
350
  break;
361
- case '..':
362
- case '+':
363
- case '-':
364
- case '*':
365
- case '/':
366
- case '%':
367
- case '^':
368
- case '&':
369
- case '|':
370
- case '~':
371
- case '<':
372
- case '>':
373
- case '[':
374
- return {
375
- from,
376
- options: [...constants, ...tables],
377
- validFor,
378
- };
379
- case '=':
380
- case '{':
381
- case '(':
382
- case ',':
383
- return {
384
- from,
385
- options: [...builtins, ...constants, ...tables, ...unary],
386
- validFor,
387
- };
388
- case '}':
389
- case ']':
390
- case ')':
391
- return {
392
- from,
393
- options: [...binary, ...blocks],
394
- validFor,
395
- };
396
351
  case ';':
397
352
  case '':
398
353
  return {
399
354
  from,
400
- options: [...keywords, ...blocks, ...unary, ...constants, ...tables, ...builtins],
355
+ options: [...luaKeywords, ...blocks, ...unary, ...constants, ...tables, ...luaBuiltins],
401
356
  validFor,
402
357
  };
403
358
  default:
404
- if (pre !== char) {
359
+ if (/\.\.|[-+*/%^&|~<>[]/u.test(char)) {
360
+ return {
361
+ from,
362
+ options: [...constants, ...tables],
363
+ validFor,
364
+ };
365
+ }
366
+ else if (/[={(,]/u.test(char)) {
367
+ return {
368
+ from,
369
+ options: [...luaBuiltins, ...constants, ...tables, ...unary],
370
+ validFor,
371
+ };
372
+ }
373
+ else if (/[}\])]/u.test(char)) {
374
+ return {
375
+ from,
376
+ options: [...binary, ...blocks],
377
+ validFor,
378
+ };
379
+ }
380
+ else if (pre !== char) {
405
381
  const { prevSibling } = node;
406
382
  return {
407
383
  from,
408
384
  options: prevSibling?.name !== 'keyword'
409
- || builtin.includes(sliceDoc(state, prevSibling))
385
+ || luaBuiltin.includes(sliceDoc(state, prevSibling))
410
386
  ? [...binary, ...blocks]
411
- : [...builtins, ...constants, ...tables, ...unary, ...blocks],
387
+ : [...luaBuiltins, ...constants, ...tables, ...unary, ...blocks],
412
388
  validFor,
413
389
  };
414
390
  }
@@ -455,9 +431,9 @@ export const markDocTag = (tree, visibleRanges, state) => {
455
431
  || firstLine.startsWith('---')
456
432
  && !(firstLine.endsWith('--') && /[^-]/u.test(firstLine))) {
457
433
  while (node.name === 'comment') {
458
- const comment = sliceDoc(state, node), mt = /^\s*(?:-{2,}\s*)?(@[a-z]+)(\s+\{(?!\}))?/diu.exec(comment);
434
+ const comment = sliceDoc(state, node), mt = /^\s*(?:-{2,}\s*)?(@[a-z]+)(\s+\{)?/diu.exec(comment);
459
435
  if (mt) {
460
- markDocTagType(decorations, node.from, mt);
436
+ markDocTagType(decorations, node.from, mt, 1);
461
437
  }
462
438
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
463
439
  const { nextSibling } = node;