wikiplus-highlight 2.7.5 → 2.8.1
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 +39 -5
- package/bump.sh +23 -13
- package/dist/main.min.js +1 -1
- package/dist/main.min.js.map +1 -1
- package/fold.js +179 -0
- package/i18n/en.json +8 -2
- package/i18n/zh-hans.json +8 -2
- package/i18n/zh-hant.json +8 -2
- package/jsconfig.json +8 -0
- package/main.js +130 -85
- package/matchtags.js +51 -26
- package/package.json +7 -3
- package/search.js +37 -11
package/matchtags.js
CHANGED
|
@@ -10,12 +10,16 @@
|
|
|
10
10
|
const {Pos, cmpPos} = CodeMirror;
|
|
11
11
|
|
|
12
12
|
const tagStart = /<(\/?)([A-Z_a-z]\w*)/g,
|
|
13
|
-
voidTags = ['br', 'wbr', 'hr', 'img']
|
|
13
|
+
voidTags = ['br', 'wbr', 'hr', 'img'],
|
|
14
|
+
maxScanLines = 1000;
|
|
14
15
|
|
|
15
16
|
class Iter {
|
|
17
|
+
/**
|
|
18
|
+
* @param {CodeMirror.Editor} cm
|
|
19
|
+
* @param {CodeMirror.Position} pos
|
|
20
|
+
*/
|
|
16
21
|
constructor(cm, pos) {
|
|
17
|
-
const {line, ch} = pos
|
|
18
|
-
{state: {matchTags: {maxScanLines = 1000}}} = cm;
|
|
22
|
+
const {line, ch} = pos;
|
|
19
23
|
this.line = line;
|
|
20
24
|
this.ch = ch;
|
|
21
25
|
this.cm = cm;
|
|
@@ -29,6 +33,7 @@
|
|
|
29
33
|
return /\b(?:mw-(?:html|ext)tag|tag\b)/.test(type);
|
|
30
34
|
}
|
|
31
35
|
|
|
36
|
+
/** @param {number} ch */
|
|
32
37
|
bracketAt(ch) {
|
|
33
38
|
const type = this.cm.getTokenTypeAt(Pos(this.line, ch + 1));
|
|
34
39
|
return /\b(?:mw-(?:html|ext)tag-)?bracket\b/.test(type);
|
|
@@ -61,14 +66,11 @@
|
|
|
61
66
|
if (gt === -1) {
|
|
62
67
|
return;
|
|
63
68
|
}
|
|
69
|
+
this.ch = gt + 1;
|
|
64
70
|
if (!this.bracketAt(gt)) {
|
|
65
|
-
this.ch = gt + 1;
|
|
66
71
|
continue;
|
|
67
72
|
}
|
|
68
|
-
|
|
69
|
-
const selfClose = lastSlash > -1 && !/\S/.test(this.text.slice(lastSlash + 1, gt));
|
|
70
|
-
this.ch = gt + 1;
|
|
71
|
-
return selfClose ? 'selfClose' : 'regular';
|
|
73
|
+
return this.text[gt - 1] === '/' ? 'selfClose' : 'regular';
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
|
|
@@ -135,8 +137,9 @@
|
|
|
135
137
|
}
|
|
136
138
|
}
|
|
137
139
|
|
|
140
|
+
/** @param {string} tag */
|
|
138
141
|
findMatchingClose(tag) {
|
|
139
|
-
const stack = [];
|
|
142
|
+
const /** @type {string[]} */ stack = [];
|
|
140
143
|
for (;;) {
|
|
141
144
|
const next = this.toNextTag();
|
|
142
145
|
if (!next) {
|
|
@@ -172,8 +175,9 @@
|
|
|
172
175
|
}
|
|
173
176
|
}
|
|
174
177
|
|
|
178
|
+
/** @param {string} tag */
|
|
175
179
|
findMatchingOpen(tag) {
|
|
176
|
-
const stack = [];
|
|
180
|
+
const /** @type {string[]} */ stack = [];
|
|
177
181
|
for (;;) {
|
|
178
182
|
const prev = this.toPrevTag();
|
|
179
183
|
if (!prev) {
|
|
@@ -210,7 +214,7 @@
|
|
|
210
214
|
}
|
|
211
215
|
}
|
|
212
216
|
|
|
213
|
-
CodeMirror.defineExtension('findMatchingTag', function(pos) {
|
|
217
|
+
CodeMirror.defineExtension('findMatchingTag', /** @param {CodeMirror.Position} pos */ function(pos) {
|
|
214
218
|
let iter = new Iter(this, pos);
|
|
215
219
|
if (!iter.isTag()) {
|
|
216
220
|
return;
|
|
@@ -234,20 +238,32 @@
|
|
|
234
238
|
return {open: here, close: iter.findMatchingClose(tag), at: 'open'};
|
|
235
239
|
});
|
|
236
240
|
|
|
237
|
-
CodeMirror.defineExtension(
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
241
|
+
CodeMirror.defineExtension(
|
|
242
|
+
'findEnclosingTag',
|
|
243
|
+
/**
|
|
244
|
+
* @param {CodeMirror.Position} pos
|
|
245
|
+
* @param {string} tag
|
|
246
|
+
*/
|
|
247
|
+
function(pos, tag) {
|
|
248
|
+
const iter = new Iter(this, pos);
|
|
249
|
+
const open = iter.findMatchingOpen(tag);
|
|
250
|
+
if (!open) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const forward = new Iter(this, pos);
|
|
254
|
+
const close = forward.findMatchingClose(open.tag);
|
|
255
|
+
if (close) {
|
|
256
|
+
return {open, close};
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
);
|
|
249
260
|
|
|
250
|
-
|
|
261
|
+
/**
|
|
262
|
+
* Used by addon/edit/closetag.js
|
|
263
|
+
* @param {CodeMirror.Editor} cm
|
|
264
|
+
* @param {CodeMirror.Position} pos
|
|
265
|
+
* @param {string} name
|
|
266
|
+
*/
|
|
251
267
|
CodeMirror.scanForClosingTag = function(cm, pos, name) {
|
|
252
268
|
const iter = new Iter(cm, pos);
|
|
253
269
|
return iter.findMatchingClose(name);
|
|
@@ -259,12 +275,12 @@
|
|
|
259
275
|
clear(cm);
|
|
260
276
|
}
|
|
261
277
|
if (val) {
|
|
262
|
-
cm.state.matchTags = typeof val === 'object' ? val : {};
|
|
263
278
|
cm.on('cursorActivity', doMatchTags);
|
|
264
279
|
doMatchTags(cm);
|
|
265
280
|
}
|
|
266
281
|
});
|
|
267
282
|
|
|
283
|
+
/** @param {CodeMirror.Editor} cm */
|
|
268
284
|
function clear(cm) {
|
|
269
285
|
if (cm.state.tagHit) {
|
|
270
286
|
cm.state.tagHit.clear();
|
|
@@ -276,13 +292,22 @@
|
|
|
276
292
|
cm.state.tagOther = null;
|
|
277
293
|
}
|
|
278
294
|
|
|
295
|
+
/** @param {CodeMirror.Editor} cm */
|
|
279
296
|
function doMatchTags(cm) {
|
|
280
297
|
cm.operation(() => {
|
|
281
298
|
clear(cm);
|
|
282
299
|
if (cm.somethingSelected()) {
|
|
283
300
|
return;
|
|
284
301
|
}
|
|
285
|
-
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* @typedef {object} matchingTag
|
|
305
|
+
* @property {string} at
|
|
306
|
+
* @property {CodeMirror.MarkerRange} open
|
|
307
|
+
* @property {CodeMirror.MarkerRange} close
|
|
308
|
+
*/
|
|
309
|
+
|
|
310
|
+
const /** @type {matchingTag}} */ match = cm.findMatchingTag(cm.getCursor());
|
|
286
311
|
if (!match) {
|
|
287
312
|
return;
|
|
288
313
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikiplus-highlight",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.1",
|
|
4
4
|
"description": "A plugin for the MediaWiki front-end add-on \"Wikiplus\"",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"mediawiki",
|
|
15
|
-
"
|
|
15
|
+
"codemirror",
|
|
16
16
|
"wikiplus"
|
|
17
17
|
],
|
|
18
18
|
"author": "Bhsd",
|
|
@@ -20,5 +20,9 @@
|
|
|
20
20
|
"bugs": {
|
|
21
21
|
"url": "https://github.com/bhsd-harry/Wikiplus-highlight/issues"
|
|
22
22
|
},
|
|
23
|
-
"homepage": "https://github.com/bhsd-harry/Wikiplus-highlight#readme"
|
|
23
|
+
"homepage": "https://github.com/bhsd-harry/Wikiplus-highlight#readme",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"eslint": "^8.8.0",
|
|
26
|
+
"uglify-js": "^3.15.5"
|
|
27
|
+
}
|
|
24
28
|
}
|
package/search.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @author Bhsd <https://github.com/bhsd-harry>
|
|
3
|
-
* @license
|
|
3
|
+
* @license GPL-3.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
(() => {
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} key
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
9
13
|
const msg = key => mw.msg(`wphl-${key}`);
|
|
10
14
|
|
|
11
15
|
// Prepare elements
|
|
@@ -42,18 +46,19 @@
|
|
|
42
46
|
text: msg('addon-search'),
|
|
43
47
|
});
|
|
44
48
|
|
|
45
|
-
const escapeRegExp = mw.util.escapeRegExp || mw.RegExp.escape;
|
|
46
|
-
const overlay = {token: () => {}};
|
|
49
|
+
const /** @type {(str: string) => string} */ escapeRegExp = mw.util.escapeRegExp || mw.RegExp.escape;
|
|
50
|
+
const /** @type {{token: (stream: CodeMirror.StringStream) => string}} */ overlay = {token: () => {}};
|
|
47
51
|
|
|
48
52
|
/**
|
|
49
53
|
* 根据搜索字符串生成高亮
|
|
54
|
+
* @param {string|RegExp} str
|
|
50
55
|
*/
|
|
51
56
|
const token = str => {
|
|
52
|
-
let initial;
|
|
57
|
+
let /** @type {RegExp} */ initial;
|
|
53
58
|
if (typeof str === 'string') {
|
|
54
59
|
initial = RegExp(`[^${escapeRegExp(str[0])}]`, 'i');
|
|
55
60
|
}
|
|
56
|
-
return stream => {
|
|
61
|
+
return /** @param {CodeMirror.StringStream} stream */ stream => {
|
|
57
62
|
if (stream.match(str, true, true)) {
|
|
58
63
|
return 'search';
|
|
59
64
|
}
|
|
@@ -69,10 +74,23 @@
|
|
|
69
74
|
$search.css('background-color', '').off('input', onInput);
|
|
70
75
|
};
|
|
71
76
|
|
|
77
|
+
/**
|
|
78
|
+
* @typedef {object} SearchCursor
|
|
79
|
+
* @property {() => boolean} findNext
|
|
80
|
+
* @property {() => boolean} findPrevious
|
|
81
|
+
* @property {() => CodeMirror.Position} from
|
|
82
|
+
* @property {() => CodeMirror.Position} to
|
|
83
|
+
*/
|
|
84
|
+
|
|
72
85
|
// keyboard event handler of $search
|
|
73
|
-
let lastPtn,
|
|
86
|
+
let /** @type {string|RegExp} */ lastPtn,
|
|
87
|
+
/** @type {SearchCursor} */ cursor;
|
|
88
|
+
/**
|
|
89
|
+
* @param {CodeMirror.Editor} cm
|
|
90
|
+
* @param {boolean} dir
|
|
91
|
+
*/
|
|
74
92
|
const findNext = (cm, dir) => {
|
|
75
|
-
let ptn = $search.val();
|
|
93
|
+
let /** @type {string|RegExp} */ ptn = $search.val();
|
|
76
94
|
if (!ptn) {
|
|
77
95
|
return;
|
|
78
96
|
}
|
|
@@ -119,27 +137,35 @@
|
|
|
119
137
|
.scrollIntoView({behavior: 'smooth'});
|
|
120
138
|
};
|
|
121
139
|
|
|
122
|
-
|
|
140
|
+
/**
|
|
141
|
+
* click event handler of $searchClose
|
|
142
|
+
* @param {CodeMirror.Editor} cm
|
|
143
|
+
*/
|
|
123
144
|
const reset = cm => {
|
|
124
145
|
cm.removeOverlay(overlay);
|
|
125
146
|
$searchContainer.hide();
|
|
126
147
|
lastPtn = '';
|
|
127
148
|
};
|
|
128
149
|
|
|
150
|
+
/** @param {CodeMirror.Editor} doc */
|
|
129
151
|
CodeMirror.commands.findForward = doc => {
|
|
130
152
|
findNext(doc, true);
|
|
131
153
|
};
|
|
154
|
+
/** @param {CodeMirror.Editor} doc */
|
|
132
155
|
CodeMirror.commands.findBackward = doc => {
|
|
133
156
|
findNext(doc, false);
|
|
134
157
|
};
|
|
135
158
|
|
|
136
|
-
const {name} = $.client.profile(),
|
|
159
|
+
const /** @type {{name: string}} */ {name} = $.client.profile(),
|
|
137
160
|
focus = name === 'safari'
|
|
138
|
-
? cm => {
|
|
161
|
+
? /** @param {CodeMirror.Editor} cm */ cm => {
|
|
139
162
|
cm.focus();
|
|
140
163
|
}
|
|
141
164
|
: () => {};
|
|
142
|
-
mw.hook('wiki-codemirror').add(cm => {
|
|
165
|
+
mw.hook('wiki-codemirror').add(/** @param {CodeMirror.Editor} cm */ cm => {
|
|
166
|
+
if (!cm.getOption('styleSelectedText')) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
143
169
|
const $textarea = $(cm.getWrapperElement()).prev('#Wikiplus-Quickedit');
|
|
144
170
|
if ($textarea.length === 0) {
|
|
145
171
|
return;
|