@bhsd/codemirror-mediawiki 3.12.2 → 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.
- package/dist/codemirror.d.ts +2 -1
- package/dist/constants.d.ts +2 -1
- package/dist/constants.js +1 -1
- package/dist/css.js +2 -2
- package/dist/escape.js +6 -7
- package/dist/fold.d.ts +1 -4
- package/dist/javascript.d.ts +1 -1
- package/dist/json.js +17 -24
- package/dist/keymap.d.ts +7 -0
- package/dist/keymap.js +82 -15
- package/dist/lilypond.d.ts +14 -0
- package/dist/lilypond.js +240 -0
- package/dist/lintsource.d.ts +1 -1
- package/dist/lua.d.ts +1 -1
- package/dist/lua.js +32 -56
- package/dist/main.min.js +32 -32
- package/dist/matchBrackets.js +6 -8
- package/dist/math.d.ts +3 -0
- package/dist/math.js +58 -0
- package/dist/mediawiki.d.ts +1 -1
- package/dist/mediawiki.js +30 -17
- package/dist/mw.min.js +36 -36
- package/dist/static.d.ts +4 -0
- package/dist/static.js +4 -0
- package/dist/token.d.ts +5 -4
- package/dist/token.js +40 -19
- package/dist/util.d.ts +32 -8
- package/dist/util.js +36 -9
- package/dist/wiki.min.js +36 -36
- package/i18n/en.json +1 -1
- package/i18n/zh-hans.json +1 -1
- package/i18n/zh-hant.json +1 -1
- package/package.json +5 -4
package/dist/codemirror.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import type { Extension, StateField } from '@codemirror/state';
|
|
|
4
4
|
import type { SyntaxNode } from '@lezer/common';
|
|
5
5
|
import type { ConfigGetter } from '@bhsd/browser';
|
|
6
6
|
import type { ConfigData } from 'wikiparser-node';
|
|
7
|
-
import type {
|
|
7
|
+
import type { foldHandler } from './fold';
|
|
8
|
+
import type { DocRange } from './util';
|
|
8
9
|
import type { detectIndent } from './indent';
|
|
9
10
|
import type { Option, LiveOption } from './linter';
|
|
10
11
|
import type { LintSource, LintSources, LintSourceGetter } from './lintsource';
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Decoration } from '@codemirror/view';
|
|
2
|
-
|
|
2
|
+
import type { Completion } from '@codemirror/autocomplete';
|
|
3
|
+
export declare const baseData: Record<'CDN', string | undefined>, extData: Record<string, Set<string>>, extCompletion: Record<string, Completion[]>, hoverSelector = ".cm-tooltip-hover-mw", diagnosticSelector = ".cm-diagnosticText-clickable", panelSelector = ".cm-panel", panelsSelector = ".cm-panels", actionSelector = ".cm-diagnosticAction", doctagMark: Decoration, typeMark: Decoration, noDetectionLangs: Set<string>, bgDark = "#4c566a", matchingCls = "cm-matchingTag", nonmatchingCls = "cm-nonmatchingTag";
|
|
3
4
|
export declare const isWMF: boolean;
|
|
4
5
|
export declare const isMac: boolean;
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Decoration } from '@codemirror/view';
|
|
2
2
|
import { wmf } from '@bhsd/common';
|
|
3
|
-
export const baseData = { CDN: undefined }, hoverSelector = '.cm-tooltip-hover-mw', diagnosticSelector = '.cm-diagnosticText-clickable', panelSelector = '.cm-panel', panelsSelector = '.cm-panels', actionSelector = '.cm-diagnosticAction', doctagMark = /* @__PURE__ */ Decoration.mark({ class: 'cm-doctag' }), typeMark = /* @__PURE__ */ Decoration.mark({ class: 'cm-doctag-type' }), noDetectionLangs = new Set(['plain', 'mediawiki']), bgDark = '#4c566a', matchingCls = 'cm-matchingTag', nonmatchingCls = 'cm-nonmatchingTag';
|
|
3
|
+
export const baseData = { CDN: undefined }, extData = {}, extCompletion = {}, hoverSelector = '.cm-tooltip-hover-mw', diagnosticSelector = '.cm-diagnosticText-clickable', panelSelector = '.cm-panel', panelsSelector = '.cm-panels', actionSelector = '.cm-diagnosticAction', doctagMark = /* @__PURE__ */ Decoration.mark({ class: 'cm-doctag' }), typeMark = /* @__PURE__ */ Decoration.mark({ class: 'cm-doctag-type' }), noDetectionLangs = new Set(['plain', 'mediawiki']), bgDark = '#4c566a', matchingCls = 'cm-matchingTag', nonmatchingCls = 'cm-nonmatchingTag';
|
|
4
4
|
export const isWMF = /* @__PURE__ */ (() => typeof location === 'object'
|
|
5
5
|
&& new RegExp(String.raw `\.(?:${wmf})\.org$`, 'u').test(location.hostname))();
|
|
6
6
|
export const isMac = /* @__PURE__ */ (() => {
|
package/dist/css.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cssLanguage, cssCompletionSource } from '@codemirror/lang-css';
|
|
2
2
|
import { LanguageSupport, syntaxTree } from '@codemirror/language';
|
|
3
|
-
import { sliceDoc } from './util.js';
|
|
4
|
-
const cssWideKeywords = /* @__PURE__ */ (
|
|
3
|
+
import { sliceDoc, getCompletions } from './util.js';
|
|
4
|
+
const cssWideKeywords = /* @__PURE__ */ getCompletions(['revert', 'revert-layer']);
|
|
5
5
|
/**
|
|
6
6
|
* CSS completion source with dialect-specific adjustments.
|
|
7
7
|
* @param dialect 是否是sanitized-css
|
package/dist/escape.js
CHANGED
|
@@ -60,13 +60,12 @@ escapeWiki = async (view, lsp) => {
|
|
|
60
60
|
}
|
|
61
61
|
view.dispatch(state.changeByRange(range => {
|
|
62
62
|
const insert = replacements.get(range);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
};
|
|
63
|
+
return insert === undefined
|
|
64
|
+
? { range }
|
|
65
|
+
: {
|
|
66
|
+
range: EditorSelection.range(range.from, range.from + insert.length),
|
|
67
|
+
changes: { from: range.from, to: range.to, insert },
|
|
68
|
+
};
|
|
70
69
|
}));
|
|
71
70
|
};
|
|
72
71
|
const escapeWikiCommand = (view, getConfig) => {
|
package/dist/fold.d.ts
CHANGED
|
@@ -3,10 +3,7 @@ import { RangeSet } from '@codemirror/state';
|
|
|
3
3
|
import type { BlockInfo, Command } from '@codemirror/view';
|
|
4
4
|
import type { EditorState, StateEffect, Extension } from '@codemirror/state';
|
|
5
5
|
import type { SyntaxNode, Tree } from '@lezer/common';
|
|
6
|
-
|
|
7
|
-
from: number;
|
|
8
|
-
to: number;
|
|
9
|
-
}
|
|
6
|
+
import type { DocRange } from './util';
|
|
10
7
|
declare type AnchorUpdate = (pos: number, range: DocRange) => number;
|
|
11
8
|
export declare const updateSelection: AnchorUpdate, updateAll: AnchorUpdate;
|
|
12
9
|
/**
|
package/dist/javascript.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Extension, EditorState } from '@codemirror/state';
|
|
2
2
|
import type { DecorationSet } from '@codemirror/view';
|
|
3
3
|
import type { Tree } from '@lezer/common';
|
|
4
|
-
import type { DocRange } from './
|
|
4
|
+
import type { DocRange } from './util';
|
|
5
5
|
import type { CodeMirror6 } from './codemirror';
|
|
6
6
|
export declare const jsCompletion: Extension;
|
|
7
7
|
/**
|
package/dist/json.js
CHANGED
|
@@ -1,25 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { inComment } from './util.js';
|
|
2
|
+
const eatNumber = (stream, state) => {
|
|
2
3
|
if (stream.match(/^\d+(?:\.\d+)?(?:e[+-]?\d+)?/iu)) {
|
|
3
4
|
state.wb = false;
|
|
4
|
-
return 'number';
|
|
5
|
+
return /* #164 */ 'number';
|
|
5
6
|
}
|
|
6
7
|
state.wb = true;
|
|
7
8
|
return '';
|
|
8
9
|
};
|
|
9
10
|
const mkJson = (jsoncMode) => {
|
|
10
11
|
// Tokenizer
|
|
11
|
-
const
|
|
12
|
-
if (stream.skipTo('*/')) {
|
|
13
|
-
stream.next();
|
|
14
|
-
stream.next();
|
|
15
|
-
state.tokenize = tokenBase;
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
stream.skipToEnd();
|
|
19
|
-
}
|
|
20
|
-
return 'comment';
|
|
21
|
-
};
|
|
22
|
-
const tokenBase = (stream, state) => {
|
|
12
|
+
const inBase = (stream, state) => {
|
|
23
13
|
if (stream.eatSpace()) {
|
|
24
14
|
state.wb = true;
|
|
25
15
|
return '';
|
|
@@ -43,11 +33,11 @@ const mkJson = (jsoncMode) => {
|
|
|
43
33
|
if (jsoncMode) {
|
|
44
34
|
if (stream.eat('/')) {
|
|
45
35
|
stream.skipToEnd();
|
|
46
|
-
return 'comment';
|
|
36
|
+
return /* #940 */ 'comment';
|
|
47
37
|
}
|
|
48
38
|
else if (stream.eat('*')) {
|
|
49
|
-
state.tokenize =
|
|
50
|
-
return
|
|
39
|
+
state.tokenize = inJsoncComment;
|
|
40
|
+
return 'comment';
|
|
51
41
|
}
|
|
52
42
|
}
|
|
53
43
|
return '';
|
|
@@ -61,39 +51,42 @@ const mkJson = (jsoncMode) => {
|
|
|
61
51
|
escaped = !escaped && next === '\\';
|
|
62
52
|
next = stream.next();
|
|
63
53
|
}
|
|
64
|
-
return stream.match(/^\s*:/u, false)
|
|
54
|
+
return stream.match(/^\s*:/u, false)
|
|
55
|
+
? /* #00c */ 'propertyName.definition'
|
|
56
|
+
: /* #a11 */ 'string';
|
|
65
57
|
}
|
|
66
58
|
case '-':
|
|
67
59
|
if (state.wb) {
|
|
68
|
-
return
|
|
60
|
+
return eatNumber(stream, state);
|
|
69
61
|
}
|
|
70
62
|
state.wb = true;
|
|
71
63
|
return '';
|
|
72
64
|
default:
|
|
73
65
|
if (state.wb) {
|
|
74
|
-
if (ch
|
|
66
|
+
if (/\d/u.test(ch)) {
|
|
75
67
|
stream.backUp(1);
|
|
76
|
-
return
|
|
68
|
+
return eatNumber(stream, state);
|
|
77
69
|
}
|
|
78
70
|
else if (ch === 'n' && stream.match(/^ull\b/u)) {
|
|
79
71
|
state.wb = false;
|
|
80
|
-
return 'null';
|
|
72
|
+
return /* #708 */ 'null';
|
|
81
73
|
}
|
|
82
74
|
else if (ch === 't' && stream.match(/^rue\b/u)
|
|
83
75
|
|| ch === 'f' && stream.match(/^alse\b/u)) {
|
|
84
76
|
state.wb = false;
|
|
85
|
-
return 'bool';
|
|
77
|
+
return /* #219 */ 'bool';
|
|
86
78
|
}
|
|
87
79
|
}
|
|
88
80
|
state.wb = !/[\w$]/u.test(ch);
|
|
89
81
|
return '';
|
|
90
82
|
}
|
|
91
83
|
};
|
|
84
|
+
const inJsoncComment = inComment(inBase, '*/');
|
|
92
85
|
// Interface
|
|
93
86
|
return {
|
|
94
87
|
startState() {
|
|
95
88
|
return {
|
|
96
|
-
tokenize:
|
|
89
|
+
tokenize: inBase,
|
|
97
90
|
wb: true,
|
|
98
91
|
};
|
|
99
92
|
},
|
package/dist/keymap.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { KeyBinding } from '@codemirror/view';
|
|
2
|
+
import type { EditorState } from '@codemirror/state';
|
|
3
|
+
import type { Tree } from '@lezer/common';
|
|
2
4
|
import type { KeymapConfig } from './keybindings';
|
|
5
|
+
/**
|
|
6
|
+
* @ignore
|
|
7
|
+
* @test
|
|
8
|
+
*/
|
|
9
|
+
export declare const getExtNames: (state: EditorState, tree: Tree, pos: number, side: 1 | -1) => string[];
|
|
3
10
|
/**
|
|
4
11
|
* 生成keymap
|
|
5
12
|
* @param opt 快捷键设置
|
package/dist/keymap.js
CHANGED
|
@@ -1,7 +1,50 @@
|
|
|
1
1
|
import { EditorSelection } from '@codemirror/state';
|
|
2
2
|
import { syntaxTree } from '@codemirror/language';
|
|
3
3
|
import { keybindings, encapsulateLines } from './keybindings.js';
|
|
4
|
-
|
|
4
|
+
import { getTag } from './matchTag.js';
|
|
5
|
+
import { sliceDoc, getExtTags } from './util.js';
|
|
6
|
+
/**
|
|
7
|
+
* @ignore
|
|
8
|
+
* @test
|
|
9
|
+
*/
|
|
10
|
+
export const getExtNames = (state, tree, pos, side) => {
|
|
11
|
+
const node = tree.resolveInner(pos, side), { name } = node;
|
|
12
|
+
if (name === 'Document') {
|
|
13
|
+
const { doc } = state, end = side === 1 ? 'to' : 'from';
|
|
14
|
+
let line = doc.lineAt(pos);
|
|
15
|
+
if (line[end] === pos) {
|
|
16
|
+
const { lines } = doc;
|
|
17
|
+
for (let { number } = line; number > 0 && number <= lines; number -= side) {
|
|
18
|
+
line = doc.line(number);
|
|
19
|
+
if (line.length > 0) {
|
|
20
|
+
return getExtNames(state, tree, line[end], -side);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
const ext = name.includes('mw-tag-') ? getExtTags(name.split('_')) : [];
|
|
27
|
+
if (name.includes('mw-exttag-bracket')) {
|
|
28
|
+
const bracket = sliceDoc(state, node), { from } = node;
|
|
29
|
+
// `<score>`、`<maplink>`和`<mapfram>`内部均不可包含其他扩展标签,所以可以省略一些情形
|
|
30
|
+
if (side === 1 ? bracket === '</' && from === pos : bracket === '>') {
|
|
31
|
+
// 在扩展标签旁,如 `・</score>` 或 `<maplink>・`
|
|
32
|
+
const sibling = node[side === 1 ? 'nextSibling' : 'prevSibling'], tag = sibling && getTag(state, sibling);
|
|
33
|
+
if (tag && (side === 1 || !tag.closing)) {
|
|
34
|
+
ext.push(tag.name);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (bracket === '></' && from + 1 === pos) {
|
|
38
|
+
// 扩展标签内尚无内容,如 `<score>・</score>`
|
|
39
|
+
const { prevSibling } = node, tag = prevSibling && getTag(state, prevSibling);
|
|
40
|
+
if (tag) {
|
|
41
|
+
ext.push(tag.name);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return ext;
|
|
46
|
+
};
|
|
47
|
+
const isExtRange = (from, to, empty, names) => names.some(name => empty ? from.includes(name) || to.includes(name) : from.includes(name) && to.includes(name));
|
|
5
48
|
/**
|
|
6
49
|
* 生成keymap
|
|
7
50
|
* @param opt 快捷键设置
|
|
@@ -15,30 +58,54 @@ export const getWikiKeymap = ({ key, pre = '', post = '', splitlines }) => ({
|
|
|
15
58
|
key,
|
|
16
59
|
run(view) {
|
|
17
60
|
const { state } = view, tree = syntaxTree(state);
|
|
18
|
-
view.dispatch(state.changeByRange(({ from, to }) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
61
|
+
view.dispatch(state.changeByRange(({ from, to, empty }) => {
|
|
62
|
+
let before = pre, after = post;
|
|
63
|
+
if (key === 'Mod-/') {
|
|
64
|
+
const fromExt = getExtNames(state, tree, from, 1), toExt = getExtNames(state, tree, to, -1);
|
|
65
|
+
if (isExtRange(fromExt, toExt, empty, ['maplink', 'mapframe'])) {
|
|
66
|
+
// JSONC comment
|
|
67
|
+
if (empty) {
|
|
68
|
+
before = '//';
|
|
69
|
+
after = '';
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
before = '/* ';
|
|
73
|
+
after = ' */';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (isExtRange(fromExt, toExt, empty, ['score-scheme'])) {
|
|
77
|
+
// LilyPond scheme comment
|
|
78
|
+
if (empty) {
|
|
79
|
+
before = ';';
|
|
80
|
+
after = '';
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
before = '#! ';
|
|
84
|
+
after = ' !#';
|
|
85
|
+
}
|
|
26
86
|
}
|
|
27
|
-
else {
|
|
28
|
-
|
|
29
|
-
|
|
87
|
+
else if (isExtRange(fromExt, toExt, empty, ['score'])) {
|
|
88
|
+
// LilyPond comment
|
|
89
|
+
if (empty) {
|
|
90
|
+
before = '%';
|
|
91
|
+
after = '';
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
before = '%{ ';
|
|
95
|
+
after = ' %}';
|
|
96
|
+
}
|
|
30
97
|
}
|
|
31
98
|
}
|
|
32
99
|
if (splitlines) {
|
|
33
|
-
const start = state.doc.lineAt(from).from, end = state.doc.lineAt(to).to, insert = encapsulateLines(state.sliceDoc(start, end),
|
|
100
|
+
const start = state.doc.lineAt(from).from, end = state.doc.lineAt(to).to, insert = encapsulateLines(state.sliceDoc(start, end), before, after);
|
|
34
101
|
return {
|
|
35
102
|
range: EditorSelection.range(start, start + insert.length),
|
|
36
103
|
changes: { from: start, to: end, insert },
|
|
37
104
|
};
|
|
38
105
|
}
|
|
39
|
-
const insert =
|
|
106
|
+
const insert = before + state.sliceDoc(from, to) + after, head = from + insert.length;
|
|
40
107
|
return {
|
|
41
|
-
range: EditorSelection.cursor(
|
|
108
|
+
range: EditorSelection.cursor(empty ? from + before.length : head),
|
|
42
109
|
changes: { from, to, insert },
|
|
43
110
|
};
|
|
44
111
|
}));
|
|
@@ -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 {};
|
package/dist/lilypond.js
ADDED
|
@@ -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/lintsource.d.ts
CHANGED
|
@@ -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 './
|
|
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>;
|
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 './
|
|
6
|
+
import type { DocRange } from './util';
|
|
7
7
|
/**
|
|
8
8
|
* 高亮显示LDoc标签
|
|
9
9
|
* @ignore
|