@bhsd/codemirror-mediawiki 2.2.2 → 2.3.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.
- package/README.md +4 -0
- package/dist/fold.d.ts +11 -0
- package/dist/main.min.js +12 -12
- package/dist/main.min.js.map +4 -4
- package/dist/mw.min.js +1 -1
- package/dist/mw.min.js.map +3 -3
- package/i18n/en.json +5 -2
- package/i18n/zh-hans.json +5 -2
- package/i18n/zh-hant.json +5 -2
- package/mw/base.ts +8 -4
- package/mw/msg.ts +50 -5
- package/mw/preference.ts +1 -1
- package/package.json +2 -1
- package/src/codemirror.ts +18 -4
- package/src/fold.ts +128 -0
- package/src/mediawiki.ts +4 -1
package/src/fold.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {EditorView, showTooltip} from '@codemirror/view';
|
|
2
|
+
import {StateField} from '@codemirror/state';
|
|
3
|
+
import {foldEffect, syntaxTree, foldState} from '@codemirror/language';
|
|
4
|
+
import type {Tooltip} from '@codemirror/view';
|
|
5
|
+
import type {EditorState} from '@codemirror/state';
|
|
6
|
+
import type {SyntaxNode} from '@lezer/common';
|
|
7
|
+
|
|
8
|
+
const isBracket = (node: SyntaxNode): boolean => node.type.name.includes('-template-bracket'),
|
|
9
|
+
isTemplate = (node: SyntaxNode): boolean => /-template[a-z\d-]+ground/u.test(node.type.name) && !isBracket(node),
|
|
10
|
+
isDelimiter = (node: SyntaxNode): boolean => /-template-delimiter/u.test(node.type.name);
|
|
11
|
+
|
|
12
|
+
const MaxScanDist = 10_000;
|
|
13
|
+
|
|
14
|
+
const foldable = (state: EditorState): {from: number, to: number} | false => {
|
|
15
|
+
const {selection: {main: {head}}} = state,
|
|
16
|
+
tree = syntaxTree(state);
|
|
17
|
+
let node = tree.resolve(head, -1);
|
|
18
|
+
if (!isTemplate(node)) {
|
|
19
|
+
node = tree.resolve(head, 1);
|
|
20
|
+
if (!isTemplate(node)) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
let {prevSibling, nextSibling} = node,
|
|
25
|
+
stack = 1,
|
|
26
|
+
delimiter: SyntaxNode | null = isDelimiter(node) ? node : null;
|
|
27
|
+
while (nextSibling && nextSibling.to - head < MaxScanDist) {
|
|
28
|
+
if (isBracket(nextSibling)) {
|
|
29
|
+
stack += state.sliceDoc(nextSibling.from, nextSibling.from + 1) === '{' ? 1 : -1;
|
|
30
|
+
if (stack === 0) {
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
} else if (!delimiter && isDelimiter(nextSibling)) {
|
|
34
|
+
delimiter = nextSibling;
|
|
35
|
+
}
|
|
36
|
+
({nextSibling} = nextSibling);
|
|
37
|
+
}
|
|
38
|
+
if (!nextSibling) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
stack = -1;
|
|
42
|
+
while (prevSibling && head - prevSibling.from < MaxScanDist) {
|
|
43
|
+
if (isBracket(prevSibling)) {
|
|
44
|
+
stack += state.sliceDoc(prevSibling.from, prevSibling.from + 1) === '{' ? 1 : -1;
|
|
45
|
+
if (stack === 0) {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
} else if (isDelimiter(prevSibling)) {
|
|
49
|
+
delimiter = prevSibling;
|
|
50
|
+
}
|
|
51
|
+
({prevSibling} = prevSibling);
|
|
52
|
+
}
|
|
53
|
+
if (delimiter) {
|
|
54
|
+
return {from: delimiter.from, to: nextSibling.from};
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 寻找匹配的括号并折叠
|
|
61
|
+
* @param view EditorView
|
|
62
|
+
*/
|
|
63
|
+
export const fold = (view: EditorView): boolean => {
|
|
64
|
+
const {state} = view,
|
|
65
|
+
range = foldable(state);
|
|
66
|
+
if (range) {
|
|
67
|
+
view.dispatch({effects: foldEffect.of(range)});
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const create = (state: EditorState): Tooltip | null => {
|
|
74
|
+
const range = foldable(state);
|
|
75
|
+
if (range) {
|
|
76
|
+
const {from, to} = range;
|
|
77
|
+
let folded = false;
|
|
78
|
+
state.field(foldState).between(from, to, (i, j) => {
|
|
79
|
+
if (i === from && j === to) {
|
|
80
|
+
folded = true;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return folded // eslint-disable-line @typescript-eslint/no-unnecessary-condition
|
|
84
|
+
? null
|
|
85
|
+
: {
|
|
86
|
+
pos: state.selection.main.head,
|
|
87
|
+
above: true,
|
|
88
|
+
create: (): {dom: HTMLElement} => {
|
|
89
|
+
const dom = document.createElement('div');
|
|
90
|
+
dom.className = 'cm-tooltip-fold';
|
|
91
|
+
dom.textContent = '\uff0d';
|
|
92
|
+
dom.title = 'Fold template parameters';
|
|
93
|
+
dom.dataset['from'] = String(from);
|
|
94
|
+
dom.dataset['to'] = String(to);
|
|
95
|
+
return {dom};
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const cursorTooltipField = StateField.define<Tooltip | null>({
|
|
103
|
+
create,
|
|
104
|
+
update(tooltip, {state, docChanged, selection}) {
|
|
105
|
+
return docChanged || selection ? create(state) : tooltip;
|
|
106
|
+
},
|
|
107
|
+
provide(f) {
|
|
108
|
+
return showTooltip.from(f);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
export const cursorTooltipTheme = EditorView.baseTheme({
|
|
113
|
+
'.cm-tooltip-fold': {
|
|
114
|
+
cursor: 'pointer',
|
|
115
|
+
lineHeight: 1.2,
|
|
116
|
+
padding: '0 1px',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export const handler = (view: EditorView) => (e: MouseEvent): void => {
|
|
121
|
+
const dom = (e.target as Element).closest<HTMLElement>('.cm-tooltip-fold');
|
|
122
|
+
if (dom) {
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
const {dataset: {from, to}} = dom;
|
|
125
|
+
view.dispatch({effects: foldEffect.of({from: Number(from), to: Number(to)})});
|
|
126
|
+
dom.remove();
|
|
127
|
+
}
|
|
128
|
+
};
|
package/src/mediawiki.ts
CHANGED
|
@@ -1196,7 +1196,10 @@ class MediaWiki {
|
|
|
1196
1196
|
|
|
1197
1197
|
tokenTable: this.tokenTable,
|
|
1198
1198
|
|
|
1199
|
-
languageData: {
|
|
1199
|
+
languageData: {
|
|
1200
|
+
commentTokens: {block: {open: '<!--', close: '-->'}},
|
|
1201
|
+
closeBrackets: {brackets: ['(', '[', '{', '"']},
|
|
1202
|
+
},
|
|
1200
1203
|
};
|
|
1201
1204
|
}
|
|
1202
1205
|
|