@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.
- package/dist/codemirror.d.ts +2 -1
- package/dist/codemirror.js +5 -5
- package/dist/constants.d.ts +2 -1
- package/dist/constants.js +1 -1
- package/dist/css.js +2 -2
- package/dist/escape.js +9 -10
- package/dist/fold.d.ts +5 -8
- package/dist/fold.js +18 -18
- package/dist/hover.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/inlay.js +2 -2
- package/dist/javascript.d.ts +1 -1
- package/dist/javascript.js +8 -4
- package/dist/json.d.ts +8 -0
- package/dist/json.js +101 -0
- package/dist/keymap.d.ts +8 -1
- package/dist/keymap.js +89 -7
- package/dist/lilypond.d.ts +14 -0
- package/dist/lilypond.js +240 -0
- package/dist/lint.js +2 -2
- package/dist/lintsource.d.ts +1 -1
- package/dist/lintsource.js +7 -7
- package/dist/lua.d.ts +1 -1
- package/dist/lua.js +39 -63
- package/dist/main.min.js +32 -31
- package/dist/matchBrackets.d.ts +3 -11
- package/dist/matchBrackets.js +51 -39
- package/dist/matchTag.d.ts +5 -5
- package/dist/matchTag.js +4 -4
- package/dist/math.d.ts +3 -0
- package/dist/math.js +58 -0
- package/dist/mediawiki.d.ts +2 -3
- package/dist/mediawiki.js +34 -26
- package/dist/mw.min.js +33 -32
- package/dist/ref.d.ts +2 -2
- package/dist/ref.js +5 -5
- package/dist/signature.js +13 -13
- package/dist/static.d.ts +7 -0
- package/dist/static.js +7 -0
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +9 -3
- package/dist/token.d.ts +10 -6
- package/dist/token.js +54 -20
- package/dist/util.d.ts +35 -10
- package/dist/util.js +43 -15
- package/dist/wiki.min.js +33 -32
- package/i18n/en.json +1 -1
- package/i18n/zh-hans.json +1 -1
- package/i18n/zh-hant.json +1 -1
- package/package.json +8 -10
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/codemirror.js
CHANGED
|
@@ -5,7 +5,7 @@ import { defaultKeymap, historyKeymap, history, redo, indentWithTab, insertNewli
|
|
|
5
5
|
import { search, searchKeymap } from '@codemirror/search';
|
|
6
6
|
import { linter, lintGutter } from '@codemirror/lint';
|
|
7
7
|
import elt from 'crelt';
|
|
8
|
-
import {
|
|
8
|
+
import { baseData, panelSelector, panelsSelector, diagnosticSelector, noDetectionLangs } from './constants.js';
|
|
9
9
|
import { light } from './theme.js';
|
|
10
10
|
import { nextDiagnostic } from './lint.js';
|
|
11
11
|
export const plain = () => [
|
|
@@ -62,10 +62,10 @@ export const replaceSelections = (view, func) => {
|
|
|
62
62
|
/** CodeMirror 6 editor */
|
|
63
63
|
export class CodeMirror6 {
|
|
64
64
|
static get CDN() {
|
|
65
|
-
return
|
|
65
|
+
return baseData.CDN;
|
|
66
66
|
}
|
|
67
67
|
static set CDN(url) {
|
|
68
|
-
|
|
68
|
+
baseData.CDN = url;
|
|
69
69
|
}
|
|
70
70
|
#textarea;
|
|
71
71
|
#language = new Compartment();
|
|
@@ -301,10 +301,10 @@ export class CodeMirror6 {
|
|
|
301
301
|
const diagnostics = (await source(state)).map((diagnostic) => ({
|
|
302
302
|
...diagnostic,
|
|
303
303
|
renderMessage(view) {
|
|
304
|
-
const span = elt('span', { class: diagnosticSelector.slice(1) }, diagnostic.renderMessage?.(view) ??
|
|
304
|
+
const span = elt('span', { class: diagnosticSelector.slice(1) }, diagnostic.renderMessage?.call(this, view) ?? this.message);
|
|
305
305
|
span.addEventListener('click', () => {
|
|
306
306
|
view.dispatch({
|
|
307
|
-
selection: { anchor:
|
|
307
|
+
selection: { anchor: this.from, head: this.to },
|
|
308
308
|
});
|
|
309
309
|
view.focus();
|
|
310
310
|
});
|
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
|
|
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
|
@@ -3,7 +3,7 @@ import { EditorSelection } from '@codemirror/state';
|
|
|
3
3
|
import { indentMore, indentLess } from '@codemirror/commands';
|
|
4
4
|
import { getLSP } from '@bhsd/browser';
|
|
5
5
|
import elt from 'crelt';
|
|
6
|
-
import {
|
|
6
|
+
import { baseData } from './constants.js';
|
|
7
7
|
import { replaceSelections, menuRegistry, } from './codemirror.js';
|
|
8
8
|
import { sliceDoc, toConfigGetter, } from './util.js';
|
|
9
9
|
const entity = { '"': 'quot', "'": 'apos', '<': 'lt', '>': 'gt', '&': 'amp', ' ': 'nbsp' };
|
|
@@ -60,17 +60,16 @@ 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) => {
|
|
73
|
-
const lsp = getLSP(view, false, getConfig,
|
|
72
|
+
const lsp = getLSP(view, false, getConfig, baseData.CDN);
|
|
74
73
|
if (lsp && 'provideRefactoringAction' in lsp && view.state.selection.ranges.some(({ empty }) => !empty)) {
|
|
75
74
|
void escapeWiki(view, lsp);
|
|
76
75
|
return true;
|
|
@@ -99,7 +98,7 @@ menuRegistry.push({
|
|
|
99
98
|
handlerBase(view, e);
|
|
100
99
|
});
|
|
101
100
|
items = [btnHTML, btnURI];
|
|
102
|
-
const lsp = getLSP(view, false, cm.getWikiConfig,
|
|
101
|
+
const lsp = getLSP(view, false, cm.getWikiConfig, baseData.CDN);
|
|
103
102
|
if (lsp && 'provideRefactoringAction' in lsp) {
|
|
104
103
|
const btnWiki = elt('div', 'Escape with magic words');
|
|
105
104
|
btnWiki.addEventListener('click', e => {
|
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
|
/**
|
|
@@ -17,7 +14,7 @@ export declare const updateSelection: AnchorUpdate, updateAll: AnchorUpdate;
|
|
|
17
14
|
* @param refOnly 是否仅检查`<ref>`标签
|
|
18
15
|
* @test
|
|
19
16
|
*/
|
|
20
|
-
export declare const
|
|
17
|
+
export declare const foldableInline: (state: EditorState, posOrNode: number | SyntaxNode, tree?: Tree | null, refOnly?: boolean) => DocRange | false;
|
|
21
18
|
/**
|
|
22
19
|
* 折叠所有模板
|
|
23
20
|
* @param state
|
|
@@ -31,7 +28,7 @@ export declare const foldable: (state: EditorState, posOrNode: number | SyntaxNo
|
|
|
31
28
|
* @test
|
|
32
29
|
*/
|
|
33
30
|
export declare const traverse: (state: EditorState, tree: Tree, effects: StateEffect<DocRange>[], node: SyntaxNode | null, end: number, anchor: number, update: AnchorUpdate, refOnly?: boolean) => number;
|
|
34
|
-
declare class
|
|
31
|
+
declare class MyFoldMarker extends GutterMarker {
|
|
35
32
|
readonly open: boolean;
|
|
36
33
|
constructor(open: boolean);
|
|
37
34
|
eq(other: this): boolean;
|
|
@@ -48,7 +45,7 @@ export declare const foldableLine: ({ state, viewportLineBlocks }: EditorView, {
|
|
|
48
45
|
* @param view
|
|
49
46
|
* @test
|
|
50
47
|
*/
|
|
51
|
-
export declare const buildMarkers: (view: EditorView) => RangeSet<
|
|
48
|
+
export declare const buildMarkers: (view: EditorView) => RangeSet<MyFoldMarker>;
|
|
52
49
|
/**
|
|
53
50
|
* 生成折叠命令
|
|
54
51
|
* @param refOnly 是否仅检查`<ref>`标签
|
|
@@ -62,7 +59,7 @@ export declare const unfoldRef: Command;
|
|
|
62
59
|
* @param view
|
|
63
60
|
* @test
|
|
64
61
|
*/
|
|
65
|
-
export declare const
|
|
62
|
+
export declare const mySelectedLines: (view: EditorView) => BlockInfo[];
|
|
66
63
|
/**
|
|
67
64
|
* Fold the template at the selection/cursor
|
|
68
65
|
* @param view
|
package/dist/fold.js
CHANGED
|
@@ -47,7 +47,7 @@ const refNames = new Set(['ref', 'references']);
|
|
|
47
47
|
* @param refOnly 是否仅检查`<ref>`标签
|
|
48
48
|
* @test
|
|
49
49
|
*/
|
|
50
|
-
export const
|
|
50
|
+
export const foldableInline = (state, posOrNode, tree, refOnly = false) => {
|
|
51
51
|
if (typeof posOrNode === 'number') {
|
|
52
52
|
tree = ensureSyntaxTree(state, posOrNode);
|
|
53
53
|
}
|
|
@@ -141,7 +141,7 @@ const foldSelector = '.cm-tooltip-fold';
|
|
|
141
141
|
* @param state
|
|
142
142
|
*/
|
|
143
143
|
const create = (state) => {
|
|
144
|
-
const { head } = state.selection.main, range =
|
|
144
|
+
const { head } = state.selection.main, range = foldableInline(state, head);
|
|
145
145
|
if (range) {
|
|
146
146
|
const { from, to } = range;
|
|
147
147
|
let folded = false;
|
|
@@ -207,7 +207,7 @@ export const traverse = (state, tree, effects, node, end, anchor, update, refOnl
|
|
|
207
207
|
while (node && (node.from < end
|
|
208
208
|
|| node.from === end
|
|
209
209
|
&& !(isTemplateBracket(node) && sliceDoc(state, node).startsWith('}}')))) {
|
|
210
|
-
const range =
|
|
210
|
+
const range = foldableInline(state, node, tree, refOnly);
|
|
211
211
|
if (range) {
|
|
212
212
|
effects.push(foldEffect.of(range));
|
|
213
213
|
node = tree.resolve(range.to, 1);
|
|
@@ -219,7 +219,7 @@ export const traverse = (state, tree, effects, node, end, anchor, update, refOnl
|
|
|
219
219
|
}
|
|
220
220
|
return anchor;
|
|
221
221
|
};
|
|
222
|
-
class
|
|
222
|
+
class MyFoldMarker extends GutterMarker {
|
|
223
223
|
constructor(open) {
|
|
224
224
|
super();
|
|
225
225
|
this.open = open;
|
|
@@ -231,8 +231,8 @@ class FoldMarker extends GutterMarker {
|
|
|
231
231
|
return elt('span', { title: state.phrase(this.open ? 'Fold line' : 'Unfold line') }, this.open ? '⌄' : '›');
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
|
-
const canFold = /* @__PURE__ */ new
|
|
235
|
-
const
|
|
234
|
+
const canFold = /* @__PURE__ */ new MyFoldMarker(true), canUnfold = /* @__PURE__ */ new MyFoldMarker(false);
|
|
235
|
+
const myFindFold = ({ state }, line) => {
|
|
236
236
|
let found;
|
|
237
237
|
state.field(foldState, false)?.between(line.from, line.to, (from, to) => {
|
|
238
238
|
if (!found && to === line.to) {
|
|
@@ -323,7 +323,7 @@ export const buildMarkers = (view) => {
|
|
|
323
323
|
const builder = new RangeSetBuilder();
|
|
324
324
|
for (const line of view.viewportLineBlocks) {
|
|
325
325
|
let mark;
|
|
326
|
-
if (
|
|
326
|
+
if (myFindFold(view, line)) {
|
|
327
327
|
mark = canUnfold;
|
|
328
328
|
}
|
|
329
329
|
else if (foldableLine(view, line)) {
|
|
@@ -393,7 +393,7 @@ export const unfoldRef = (view) => {
|
|
|
393
393
|
* @param view
|
|
394
394
|
* @test
|
|
395
395
|
*/
|
|
396
|
-
export const
|
|
396
|
+
export const mySelectedLines = (view) => {
|
|
397
397
|
const lines = [];
|
|
398
398
|
for (const { head } of view.state.selection.ranges) {
|
|
399
399
|
if (lines.some(({ from, to }) => from <= head && to >= head)) {
|
|
@@ -403,7 +403,7 @@ export const selectedLines = (view) => {
|
|
|
403
403
|
}
|
|
404
404
|
return lines;
|
|
405
405
|
};
|
|
406
|
-
const
|
|
406
|
+
const myFoldCode = (view, line) => {
|
|
407
407
|
const range = foldableLine(view, line);
|
|
408
408
|
if (range) {
|
|
409
409
|
view.dispatch({ effects: foldEffect.of(range) });
|
|
@@ -411,8 +411,8 @@ const foldCode = (view, line) => {
|
|
|
411
411
|
}
|
|
412
412
|
return false;
|
|
413
413
|
};
|
|
414
|
-
const
|
|
415
|
-
const folded =
|
|
414
|
+
const myUnfoldCode = (view, line) => {
|
|
415
|
+
const folded = myFindFold(view, line);
|
|
416
416
|
return folded && unfoldEffect.of(folded);
|
|
417
417
|
};
|
|
418
418
|
/**
|
|
@@ -437,8 +437,8 @@ export const foldAt = view => {
|
|
|
437
437
|
if (effects.length > 0) {
|
|
438
438
|
return execute(view, effects, anchor);
|
|
439
439
|
}
|
|
440
|
-
for (const line of
|
|
441
|
-
if (
|
|
440
|
+
for (const line of mySelectedLines(view)) {
|
|
441
|
+
if (myFoldCode(view, line)) {
|
|
442
442
|
return true;
|
|
443
443
|
}
|
|
444
444
|
}
|
|
@@ -515,8 +515,8 @@ export const mediawikiFold = /* @__PURE__ */ (() => [
|
|
|
515
515
|
view.dispatch({ effects, selection });
|
|
516
516
|
return true;
|
|
517
517
|
}
|
|
518
|
-
for (const line of
|
|
519
|
-
const effect =
|
|
518
|
+
for (const line of mySelectedLines(view)) {
|
|
519
|
+
const effect = myUnfoldCode(view, line);
|
|
520
520
|
if (effect) {
|
|
521
521
|
effects.push(effect);
|
|
522
522
|
}
|
|
@@ -537,16 +537,16 @@ export const mediawikiFold = /* @__PURE__ */ (() => [
|
|
|
537
537
|
return view.plugin(markers)?.markers ?? RangeSet.empty;
|
|
538
538
|
},
|
|
539
539
|
initialSpacer() {
|
|
540
|
-
return new
|
|
540
|
+
return new MyFoldMarker(false);
|
|
541
541
|
},
|
|
542
542
|
domEventHandlers: {
|
|
543
543
|
click(view, line) {
|
|
544
|
-
const effects =
|
|
544
|
+
const effects = myUnfoldCode(view, line);
|
|
545
545
|
if (effects) {
|
|
546
546
|
view.dispatch({ effects });
|
|
547
547
|
return true;
|
|
548
548
|
}
|
|
549
|
-
return
|
|
549
|
+
return myFoldCode(view, line);
|
|
550
550
|
},
|
|
551
551
|
},
|
|
552
552
|
}),
|
package/dist/hover.js
CHANGED
|
@@ -2,7 +2,7 @@ import { hoverTooltip, EditorView } from '@codemirror/view';
|
|
|
2
2
|
import { ensureSyntaxTree } from '@codemirror/language';
|
|
3
3
|
import { getLSP, loadScript, } from '@bhsd/browser';
|
|
4
4
|
import { tokens } from './config.js';
|
|
5
|
-
import {
|
|
5
|
+
import { baseData, hoverSelector, bgDark } from './constants.js';
|
|
6
6
|
import { indexToPos, posToIndex, createTooltipView, toConfigGetter, escHTML, sliceDoc, findTemplateName, } from './util.js';
|
|
7
7
|
const code = `${hoverSelector} code`;
|
|
8
8
|
/**
|
|
@@ -58,13 +58,13 @@ export default (articlePath, templatedata) => (cm) => {
|
|
|
58
58
|
hoverTooltip(async (view, pos, side) => {
|
|
59
59
|
const { state } = view, { doc } = state;
|
|
60
60
|
const { paramSuggest, tags } = cm.langConfig;
|
|
61
|
-
let hover = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath),
|
|
61
|
+
let hover = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), baseData.CDN)?.provideHover(doc.toString(), indexToPos(doc, pos));
|
|
62
62
|
if (!hover && paramSuggest && 'templatedata' in tags) {
|
|
63
63
|
// eslint-disable-next-line require-atomic-updates
|
|
64
64
|
hover = await getHoverFromApi(state, pos, side, paramSuggest, templatedata);
|
|
65
65
|
}
|
|
66
66
|
if (hover) {
|
|
67
|
-
const { CDN = '' } =
|
|
67
|
+
const { CDN = '' } = baseData;
|
|
68
68
|
await loadScript(`${CDN}${CDN && '/'}npm/marked/lib/marked.umd.js`, 'marked', true);
|
|
69
69
|
const { end } = hover.range;
|
|
70
70
|
return {
|
package/dist/index.d.ts
CHANGED
|
@@ -159,4 +159,4 @@ export declare const registerLanguage: (name: string, lang: (config?: unknown) =
|
|
|
159
159
|
*/
|
|
160
160
|
export declare const registerLanguageCore: (name: string, lang: (config?: unknown) => LanguageSupport, lintSource?: LintSourceGetter) => void;
|
|
161
161
|
export declare const registerTheme: (name: string, theme: Extension) => void;
|
|
162
|
-
export { nord } from './theme.js';
|
|
162
|
+
export { nordDark as nord } from './theme.js';
|
package/dist/index.js
CHANGED
package/dist/inlay.js
CHANGED
|
@@ -2,7 +2,7 @@ import { StateField, StateEffect } from '@codemirror/state';
|
|
|
2
2
|
import { Decoration, EditorView, WidgetType, ViewPlugin } from '@codemirror/view';
|
|
3
3
|
import { getLSP } from '@bhsd/browser';
|
|
4
4
|
import elt from 'crelt';
|
|
5
|
-
import {
|
|
5
|
+
import { baseData } from './constants.js';
|
|
6
6
|
import { posToIndex, toConfigGetter, } from './util.js';
|
|
7
7
|
const cls = 'cm-inlay-hint';
|
|
8
8
|
class InlayHintWidget extends WidgetType {
|
|
@@ -54,7 +54,7 @@ export default (articlePath) => (cm) => {
|
|
|
54
54
|
field,
|
|
55
55
|
ViewPlugin.define(view => {
|
|
56
56
|
const timer = setInterval(() => {
|
|
57
|
-
if (getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath),
|
|
57
|
+
if (getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), baseData.CDN)) {
|
|
58
58
|
clearInterval(timer);
|
|
59
59
|
void update({ view, docChanged: true });
|
|
60
60
|
}
|
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/javascript.js
CHANGED
|
@@ -6,7 +6,7 @@ import { builtin } from './javascript-globals.js';
|
|
|
6
6
|
import { doctagMark } from './constants.js';
|
|
7
7
|
import { markDocTagType, pushDecoration } from './util.js';
|
|
8
8
|
export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
|
|
9
|
-
const globalsMark = Decoration.mark({ class: 'cm-globals' }), builtinGlobals = new Set(Object.keys(builtin));
|
|
9
|
+
const globalsMark = Decoration.mark({ class: 'cm-globals' }), varMark = Decoration.mark({ class: 'cm-doctag-var' }), builtinGlobals = new Set(Object.keys(builtin));
|
|
10
10
|
/**
|
|
11
11
|
* 忽略JavaScript正则表达式中的括号匹配
|
|
12
12
|
* @param state
|
|
@@ -61,14 +61,18 @@ export const markGlobalsAndDocTag = (tree, visibleRanges, state, cm) => {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
else if (type.is('BlockComment') && /^\/\*{2}(?!\*)/u.test(name)) {
|
|
64
|
-
const comment = name.slice(2), mtAll = comment.matchAll(/^[ \t]*\*\s*(@[a-z]+)(\s+\{
|
|
64
|
+
const comment = name.slice(2), pos = f + 2, mtAll = comment.matchAll(/^[ \t]*\*\s*(@[a-z]+)(\s+\{)?|\{(@[a-z]+)/dgimu);
|
|
65
65
|
for (const mt of mtAll) {
|
|
66
66
|
if (mt[3]) {
|
|
67
67
|
const [start, end] = mt.indices[3];
|
|
68
|
-
pushDecoration(decorations, doctagMark,
|
|
68
|
+
pushDecoration(decorations, doctagMark, pos + start, pos + end);
|
|
69
69
|
}
|
|
70
70
|
else {
|
|
71
|
-
markDocTagType(decorations,
|
|
71
|
+
const index = markDocTagType(decorations, pos, mt), m = /^\s+([a-z_]\w*)\s+-/diu.exec(comment.slice(index));
|
|
72
|
+
if (m) {
|
|
73
|
+
const [start, end] = m.indices[1];
|
|
74
|
+
pushDecoration(decorations, varMark, pos + index + start, pos + index + end);
|
|
75
|
+
}
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
}
|
package/dist/json.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StreamParser, StringStream } from '@codemirror/language';
|
|
2
|
+
declare interface State {
|
|
3
|
+
tokenize: Tokenizer;
|
|
4
|
+
wb: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare type Tokenizer = (stream: StringStream, state: State) => string;
|
|
7
|
+
export declare const jsonBasic: StreamParser<State>, jsonc: StreamParser<State>;
|
|
8
|
+
export {};
|
package/dist/json.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { inComment } from './util.js';
|
|
2
|
+
const eatNumber = (stream, state) => {
|
|
3
|
+
if (stream.match(/^\d+(?:\.\d+)?(?:e[+-]?\d+)?/iu)) {
|
|
4
|
+
state.wb = false;
|
|
5
|
+
return /* #164 */ 'number';
|
|
6
|
+
}
|
|
7
|
+
state.wb = true;
|
|
8
|
+
return '';
|
|
9
|
+
};
|
|
10
|
+
const mkJson = (jsoncMode) => {
|
|
11
|
+
// Tokenizer
|
|
12
|
+
const inBase = (stream, state) => {
|
|
13
|
+
if (stream.eatSpace()) {
|
|
14
|
+
state.wb = true;
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
const ch = stream.next();
|
|
18
|
+
switch (ch) {
|
|
19
|
+
case '{':
|
|
20
|
+
case '}':
|
|
21
|
+
state.wb = true;
|
|
22
|
+
return 'brace';
|
|
23
|
+
case '[':
|
|
24
|
+
case ']':
|
|
25
|
+
state.wb = true;
|
|
26
|
+
return 'squareBracket';
|
|
27
|
+
case ':':
|
|
28
|
+
case ',':
|
|
29
|
+
state.wb = true;
|
|
30
|
+
return 'separator';
|
|
31
|
+
case '/':
|
|
32
|
+
state.wb = true;
|
|
33
|
+
if (jsoncMode) {
|
|
34
|
+
if (stream.eat('/')) {
|
|
35
|
+
stream.skipToEnd();
|
|
36
|
+
return /* #940 */ 'comment';
|
|
37
|
+
}
|
|
38
|
+
else if (stream.eat('*')) {
|
|
39
|
+
state.tokenize = inJsoncComment;
|
|
40
|
+
return 'comment';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return '';
|
|
44
|
+
case '"': {
|
|
45
|
+
state.wb = true;
|
|
46
|
+
let escaped = false, next = stream.next();
|
|
47
|
+
while (next) {
|
|
48
|
+
if (!escaped && next === '"') {
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
escaped = !escaped && next === '\\';
|
|
52
|
+
next = stream.next();
|
|
53
|
+
}
|
|
54
|
+
return stream.match(/^\s*:/u, false)
|
|
55
|
+
? /* #00c */ 'propertyName.definition'
|
|
56
|
+
: /* #a11 */ 'string';
|
|
57
|
+
}
|
|
58
|
+
case '-':
|
|
59
|
+
if (state.wb) {
|
|
60
|
+
return eatNumber(stream, state);
|
|
61
|
+
}
|
|
62
|
+
state.wb = true;
|
|
63
|
+
return '';
|
|
64
|
+
default:
|
|
65
|
+
if (state.wb) {
|
|
66
|
+
if (/\d/u.test(ch)) {
|
|
67
|
+
stream.backUp(1);
|
|
68
|
+
return eatNumber(stream, state);
|
|
69
|
+
}
|
|
70
|
+
else if (ch === 'n' && stream.match(/^ull\b/u)) {
|
|
71
|
+
state.wb = false;
|
|
72
|
+
return /* #708 */ 'null';
|
|
73
|
+
}
|
|
74
|
+
else if (ch === 't' && stream.match(/^rue\b/u)
|
|
75
|
+
|| ch === 'f' && stream.match(/^alse\b/u)) {
|
|
76
|
+
state.wb = false;
|
|
77
|
+
return /* #219 */ 'bool';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
state.wb = !/[\w$]/u.test(ch);
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const inJsoncComment = inComment(inBase, '*/');
|
|
85
|
+
// Interface
|
|
86
|
+
return {
|
|
87
|
+
startState() {
|
|
88
|
+
return {
|
|
89
|
+
tokenize: inBase,
|
|
90
|
+
wb: true,
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
token(stream, state) {
|
|
94
|
+
if (stream.sol()) {
|
|
95
|
+
state.wb = true;
|
|
96
|
+
}
|
|
97
|
+
return state.tokenize(stream, state);
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
export const jsonBasic = mkJson(), jsonc = mkJson(true);
|
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 快捷键设置
|
|
@@ -9,6 +16,6 @@ import type { KeymapConfig } from './keybindings';
|
|
|
9
16
|
* @param opt.splitlines 是否分行
|
|
10
17
|
* @test
|
|
11
18
|
*/
|
|
12
|
-
export declare const
|
|
19
|
+
export declare const getWikiKeymap: ({ key, pre, post, splitlines }: KeymapConfig) => KeyBinding;
|
|
13
20
|
declare const _default: KeyBinding[];
|
|
14
21
|
export default _default;
|
package/dist/keymap.js
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
import { EditorSelection } from '@codemirror/state';
|
|
2
|
+
import { syntaxTree } from '@codemirror/language';
|
|
2
3
|
import { keybindings, encapsulateLines } from './keybindings.js';
|
|
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));
|
|
3
48
|
/**
|
|
4
49
|
* 生成keymap
|
|
5
50
|
* @param opt 快捷键设置
|
|
@@ -9,21 +54,58 @@ import { keybindings, encapsulateLines } from './keybindings.js';
|
|
|
9
54
|
* @param opt.splitlines 是否分行
|
|
10
55
|
* @test
|
|
11
56
|
*/
|
|
12
|
-
export const
|
|
57
|
+
export const getWikiKeymap = ({ key, pre = '', post = '', splitlines }) => ({
|
|
13
58
|
key,
|
|
14
59
|
run(view) {
|
|
15
|
-
const { state } = view;
|
|
16
|
-
view.dispatch(state.changeByRange(({ from, to }) => {
|
|
60
|
+
const { state } = view, tree = syntaxTree(state);
|
|
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
|
+
}
|
|
86
|
+
}
|
|
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
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
17
99
|
if (splitlines) {
|
|
18
|
-
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);
|
|
19
101
|
return {
|
|
20
102
|
range: EditorSelection.range(start, start + insert.length),
|
|
21
103
|
changes: { from: start, to: end, insert },
|
|
22
104
|
};
|
|
23
105
|
}
|
|
24
|
-
const insert =
|
|
106
|
+
const insert = before + state.sliceDoc(from, to) + after, head = from + insert.length;
|
|
25
107
|
return {
|
|
26
|
-
range: EditorSelection.cursor(
|
|
108
|
+
range: EditorSelection.cursor(empty ? from + before.length : head),
|
|
27
109
|
changes: { from, to, insert },
|
|
28
110
|
};
|
|
29
111
|
}));
|
|
@@ -31,4 +113,4 @@ export const getKeymap = ({ key, pre = '', post = '', splitlines }) => ({
|
|
|
31
113
|
},
|
|
32
114
|
preventDefault: true,
|
|
33
115
|
});
|
|
34
|
-
export default keybindings.map(
|
|
116
|
+
export default keybindings.map(getWikiKeymap);
|