@bhsd/codemirror-mediawiki 2.3.2 → 2.3.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/README.md +19 -0
- package/dist/codemirror.d.ts +9 -1
- package/dist/main.min.js +14 -14
- package/dist/mediawiki.d.ts +1 -1
- package/dist/mw.min.js +1 -1
- package/dist/mw.min.js.map +3 -3
- package/i18n/en.json +12 -3
- package/i18n/zh-hans.json +12 -3
- package/i18n/zh-hant.json +12 -3
- package/mediawiki.css +12 -0
- package/mw/base.ts +3 -4
- package/mw/config.ts +4 -1
- package/mw/msg.ts +22 -1
- package/mw/openLinks.ts +4 -1
- package/mw/preference.ts +1 -4
- package/package.json +4 -6
- package/dist/config.d.ts +0 -130
- package/dist/escape.d.ts +0 -2
- package/dist/fold.d.ts +0 -11
- package/dist/main.min.js.map +0 -7
- package/dist/plugins.d.ts +0 -3
- package/src/codemirror.ts +0 -521
- package/src/config.ts +0 -215
- package/src/escape.ts +0 -28
- package/src/fold.ts +0 -128
- package/src/mediawiki.ts +0 -1304
package/src/config.ts
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author MusikAnimal and others
|
|
3
|
-
* @license GPL-2.0-or-later
|
|
4
|
-
* @link https://gerrit.wikimedia.org/g/mediawiki/extensions/CodeMirror
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {Tag} from '@lezer/highlight';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Configuration for the MediaWiki highlighting mode for CodeMirror.
|
|
11
|
-
*/
|
|
12
|
-
export const modeConfig = {
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* All HTML/XML tags permitted in MediaWiki Core.
|
|
16
|
-
*
|
|
17
|
-
* @see https://www.mediawiki.org/wiki/Extension:CodeMirror#Extension_integration
|
|
18
|
-
*/
|
|
19
|
-
permittedHtmlTags: [
|
|
20
|
-
'b',
|
|
21
|
-
'bdi',
|
|
22
|
-
'bdo',
|
|
23
|
-
'del',
|
|
24
|
-
'i',
|
|
25
|
-
'ins',
|
|
26
|
-
'u',
|
|
27
|
-
'font',
|
|
28
|
-
'big',
|
|
29
|
-
'small',
|
|
30
|
-
'sub',
|
|
31
|
-
'sup',
|
|
32
|
-
'h1',
|
|
33
|
-
'h2',
|
|
34
|
-
'h3',
|
|
35
|
-
'h4',
|
|
36
|
-
'h5',
|
|
37
|
-
'h6',
|
|
38
|
-
'cite',
|
|
39
|
-
'code',
|
|
40
|
-
'em',
|
|
41
|
-
's',
|
|
42
|
-
'strike',
|
|
43
|
-
'strong',
|
|
44
|
-
'tt',
|
|
45
|
-
'var',
|
|
46
|
-
'div',
|
|
47
|
-
'center',
|
|
48
|
-
'blockquote',
|
|
49
|
-
'q',
|
|
50
|
-
'ol',
|
|
51
|
-
'ul',
|
|
52
|
-
'dl',
|
|
53
|
-
'table',
|
|
54
|
-
'caption',
|
|
55
|
-
'pre',
|
|
56
|
-
'ruby',
|
|
57
|
-
'rb',
|
|
58
|
-
'rp',
|
|
59
|
-
'rt',
|
|
60
|
-
'rtc',
|
|
61
|
-
'p',
|
|
62
|
-
'span',
|
|
63
|
-
'abbr',
|
|
64
|
-
'dfn',
|
|
65
|
-
'kbd',
|
|
66
|
-
'samp',
|
|
67
|
-
'data',
|
|
68
|
-
'time',
|
|
69
|
-
'mark',
|
|
70
|
-
'br',
|
|
71
|
-
'wbr',
|
|
72
|
-
'hr',
|
|
73
|
-
'li',
|
|
74
|
-
'dt',
|
|
75
|
-
'dd',
|
|
76
|
-
'td',
|
|
77
|
-
'th',
|
|
78
|
-
'tr',
|
|
79
|
-
'noinclude',
|
|
80
|
-
'includeonly',
|
|
81
|
-
'onlyinclude',
|
|
82
|
-
'img',
|
|
83
|
-
'meta',
|
|
84
|
-
'link',
|
|
85
|
-
],
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* HTML tags that are only self-closing.
|
|
89
|
-
*/
|
|
90
|
-
implicitlyClosedHtmlTags: [
|
|
91
|
-
'br',
|
|
92
|
-
'hr',
|
|
93
|
-
'wbr',
|
|
94
|
-
'img',
|
|
95
|
-
'meta',
|
|
96
|
-
'link',
|
|
97
|
-
],
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Mapping of MediaWiki-esque token identifiers to a standardized lezer highlighting tag.
|
|
101
|
-
* Values are one of the default highlighting tags.
|
|
102
|
-
*
|
|
103
|
-
* Once we allow use of other themes, we may want to tweak these values for aesthetic reasons.
|
|
104
|
-
*
|
|
105
|
-
* @see https://lezer.codemirror.net/docs/ref/#highlight.tags
|
|
106
|
-
* @internal
|
|
107
|
-
*/
|
|
108
|
-
tags: {
|
|
109
|
-
apostrophes: 'mw-apostrophes',
|
|
110
|
-
apostrophesBold: 'mw-apostrophes-bold',
|
|
111
|
-
apostrophesItalic: 'mw-apostrophes-italic',
|
|
112
|
-
comment: 'mw-comment',
|
|
113
|
-
doubleUnderscore: 'mw-double-underscore',
|
|
114
|
-
extLink: 'mw-extlink',
|
|
115
|
-
extLinkBracket: 'mw-extlink-bracket',
|
|
116
|
-
extLinkProtocol: 'mw-extlink-protocol',
|
|
117
|
-
extLinkText: 'mw-extlink-text',
|
|
118
|
-
hr: 'mw-hr',
|
|
119
|
-
htmlTagAttribute: 'mw-htmltag-attribute',
|
|
120
|
-
htmlTagBracket: 'mw-htmltag-bracket',
|
|
121
|
-
htmlTagName: 'mw-htmltag-name',
|
|
122
|
-
linkBracket: 'mw-link-bracket',
|
|
123
|
-
linkDelimiter: 'mw-link-delimiter',
|
|
124
|
-
linkText: 'mw-link-text',
|
|
125
|
-
linkToSection: 'mw-link-tosection',
|
|
126
|
-
list: 'mw-list',
|
|
127
|
-
parserFunction: 'mw-parserfunction',
|
|
128
|
-
parserFunctionBracket: 'mw-parserfunction-bracket',
|
|
129
|
-
parserFunctionDelimiter: 'mw-parserfunction-delimiter',
|
|
130
|
-
parserFunctionName: 'mw-parserfunction-name',
|
|
131
|
-
sectionHeader: 'mw-section-header',
|
|
132
|
-
sectionHeader1: 'mw-section-1',
|
|
133
|
-
sectionHeader2: 'mw-section-2',
|
|
134
|
-
sectionHeader3: 'mw-section-3',
|
|
135
|
-
sectionHeader4: 'mw-section-4',
|
|
136
|
-
sectionHeader5: 'mw-section-5',
|
|
137
|
-
sectionHeader6: 'mw-section-6',
|
|
138
|
-
signature: 'mw-signature',
|
|
139
|
-
tableBracket: 'mw-table-bracket',
|
|
140
|
-
tableDefinition: 'mw-table-definition',
|
|
141
|
-
tableDelimiter: 'mw-table-delimiter',
|
|
142
|
-
template: 'mw-template',
|
|
143
|
-
templateArgumentName: 'mw-template-argument-name',
|
|
144
|
-
templateBracket: 'mw-template-bracket',
|
|
145
|
-
templateDelimiter: 'mw-template-delimiter',
|
|
146
|
-
templateName: 'mw-template-name',
|
|
147
|
-
templateVariable: 'mw-templatevariable',
|
|
148
|
-
templateVariableBracket: 'mw-templatevariable-bracket',
|
|
149
|
-
templateVariableName: 'mw-templatevariable-name',
|
|
150
|
-
section: 'mw-section',
|
|
151
|
-
em: 'mw-em',
|
|
152
|
-
error: 'mw-error',
|
|
153
|
-
extGround: 'mw-ext-ground',
|
|
154
|
-
ext2Ground: 'mw-ext2-ground',
|
|
155
|
-
ext2LinkGround: 'mw-ext2-link-ground',
|
|
156
|
-
ext3Ground: 'mw-ext3-ground',
|
|
157
|
-
ext3LinkGround: 'mw-ext3-link-ground',
|
|
158
|
-
extLinkGround: 'mw-ext-link-ground',
|
|
159
|
-
extTag: 'mw-exttag',
|
|
160
|
-
extTagAttribute: 'mw-exttag-attribute',
|
|
161
|
-
extTagBracket: 'mw-exttag-bracket',
|
|
162
|
-
extTagName: 'mw-exttag-name',
|
|
163
|
-
freeExtLink: 'mw-free-extlink',
|
|
164
|
-
freeExtLinkProtocol: 'mw-free-extlink-protocol',
|
|
165
|
-
htmlEntity: 'mw-html-entity',
|
|
166
|
-
link: 'mw-link',
|
|
167
|
-
linkGround: 'mw-link-ground',
|
|
168
|
-
linkPageName: 'mw-link-pagename',
|
|
169
|
-
pageName: 'mw-pagename',
|
|
170
|
-
skipFormatting: 'mw-skipformatting',
|
|
171
|
-
strong: 'mw-strong',
|
|
172
|
-
tableCaption: 'mw-table-caption',
|
|
173
|
-
templateExtGround: 'mw-template-ext-ground',
|
|
174
|
-
templateExt2Ground: 'mw-template-ext2-ground',
|
|
175
|
-
templateExt2LinkGround: 'mw-template-ext2-link-ground',
|
|
176
|
-
templateExt3Ground: 'mw-template-ext3-ground',
|
|
177
|
-
templateExt3LinkGround: 'mw-template-ext3-link-ground',
|
|
178
|
-
templateExtLinkGround: 'mw-template-ext-link-ground',
|
|
179
|
-
templateGround: 'mw-template-ground',
|
|
180
|
-
templateLinkGround: 'mw-template-link-ground',
|
|
181
|
-
templateVariableDelimiter: 'mw-templatevariable-delimiter',
|
|
182
|
-
template2ExtGround: 'mw-template2-ext-ground',
|
|
183
|
-
template2Ext2Ground: 'mw-template2-ext2-ground',
|
|
184
|
-
template2Ext3Ground: 'mw-template2-ext3-ground',
|
|
185
|
-
templatet2Ext2LinkGround: 'mw-template2-ext2-link-ground',
|
|
186
|
-
template2Ext3LinkGround: 'mw-template2-ext3-link-ground',
|
|
187
|
-
template2ExtLinkGround: 'mw-template2-ext-link-ground',
|
|
188
|
-
template2Ground: 'mw-template2-ground',
|
|
189
|
-
template2LinkGround: 'mw-template2-link-ground',
|
|
190
|
-
template3ExtGround: 'mw-template3-ext-ground',
|
|
191
|
-
template3Ext2Ground: 'mw-template3-ext2-ground',
|
|
192
|
-
template3Ext3Ground: 'mw-template3-ext3-ground',
|
|
193
|
-
template3ExtLinkGround: 'mw-template3-ext-link-ground',
|
|
194
|
-
template3Ext2LinkGround: 'mw-template3-ext2-link-ground',
|
|
195
|
-
template3Ext3LinkGround: 'mw-template3-ext3-link-ground',
|
|
196
|
-
template3Ground: 'mw-template3-ground',
|
|
197
|
-
template3LinkGround: 'mw-template3-link-ground',
|
|
198
|
-
},
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* These are custom tokens (a.k.a. tags) that aren't mapped to any of the standardized tags.
|
|
202
|
-
*
|
|
203
|
-
* TODO: pass parent Tags in Tag.define() where appropriate for better theming.
|
|
204
|
-
*
|
|
205
|
-
* @see https://codemirror.net/docs/ref/#language.StreamParser.tokenTable
|
|
206
|
-
* @see https://lezer.codemirror.net/docs/ref/#highlight.Tag%5Edefine
|
|
207
|
-
*/
|
|
208
|
-
get tokenTable(): Record<string, Tag> {
|
|
209
|
-
const table: Record<string, Tag> = {};
|
|
210
|
-
for (const className of Object.values(this.tags)) {
|
|
211
|
-
table[className] = Tag.define();
|
|
212
|
-
}
|
|
213
|
-
return table;
|
|
214
|
-
},
|
|
215
|
-
};
|
package/src/escape.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {CodeMirror6} from './codemirror';
|
|
2
|
-
import type {KeyBinding, Command} from '@codemirror/view';
|
|
3
|
-
|
|
4
|
-
const entity = {'"': 'quot', "'": 'apos', '<': 'lt', '>': 'gt', '&': 'amp', ' ': 'nbsp'};
|
|
5
|
-
const convert = (func: (str: string) => string): Command => (view): true => {
|
|
6
|
-
CodeMirror6.replaceSelections(view, func);
|
|
7
|
-
return true;
|
|
8
|
-
},
|
|
9
|
-
escapeHTML = convert(str => [...str].map(c => {
|
|
10
|
-
if (c in entity) {
|
|
11
|
-
return `&${entity[c as keyof typeof entity]};`;
|
|
12
|
-
}
|
|
13
|
-
const code = c.codePointAt(0)!;
|
|
14
|
-
return code < 256 ? `&#${code};` : `&#x${code.toString(16)};`;
|
|
15
|
-
}).join('')),
|
|
16
|
-
escapeURI = convert(str => {
|
|
17
|
-
if (str.includes('%')) {
|
|
18
|
-
try {
|
|
19
|
-
return decodeURIComponent(str);
|
|
20
|
-
} catch {}
|
|
21
|
-
}
|
|
22
|
-
return encodeURIComponent(str);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export const keyMap: KeyBinding[] = [
|
|
26
|
-
{key: 'Mod-[', run: escapeHTML},
|
|
27
|
-
{key: 'Mod-]', run: escapeURI},
|
|
28
|
-
];
|
package/src/fold.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
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
|
-
};
|