wikiplus-highlight 2.21.0 → 2.22.5

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/matchtags.js CHANGED
@@ -7,16 +7,17 @@
7
7
  (() => {
8
8
  'use strict';
9
9
 
10
- const {Pos, cmpPos} = CodeMirror;
10
+ const {Pos, cmpPos, Init} = CodeMirror;
11
11
 
12
- const tagStart = /<(\/?)([A-Z_a-z]\w*)/g,
12
+ const tagStart = /<(\/?)([_a-z]\w*)/giu,
13
13
  voidTags = ['br', 'wbr', 'hr', 'img'],
14
14
  maxScanLines = 1000;
15
15
 
16
+ /** @ignore */
16
17
  class Iter {
17
18
  /**
18
19
  * @param {CodeMirror.Editor} cm
19
- * @param {CodeMirror.Position} pos
20
+ * @param {CodeMirror.Position} pos 当前位置
20
21
  */
21
22
  constructor(cm, pos) {
22
23
  const {line, ch} = pos;
@@ -28,21 +29,25 @@
28
29
  this.max = Math.min(line + maxScanLines - 1, cm.lastLine());
29
30
  }
30
31
 
32
+ /** 是否是标签 */
31
33
  isTag() {
32
34
  const type = this.cm.getTokenTypeAt(Pos(this.line, this.ch));
33
- return /\b(?:mw-(?:html|ext)tag|tag\b)/.test(type);
35
+ return /\b(?:mw-(?:html|ext)tag|tag\b)/u.test(type);
34
36
  }
35
37
 
36
- /** @param {number} ch */
38
+ /**
39
+ * 判断是否是括号
40
+ * @param {number} ch 列号
41
+ */
37
42
  bracketAt(ch) {
38
43
  const type = this.cm.getTokenTypeAt(Pos(this.line, ch + 1));
39
- return /\b(?:mw-(?:html|ext)tag-)?bracket\b/.test(type);
44
+ return /\b(?:mw-(?:html|ext)tag-)?bracket\b/u.test(type);
40
45
  }
41
46
 
42
47
  /** Jump to the start of the next line */
43
48
  nextLine() {
44
49
  if (this.line >= this.max) {
45
- return;
50
+ return false;
46
51
  }
47
52
  this.ch = 0;
48
53
  this.text = this.cm.getLine(++this.line);
@@ -52,7 +57,7 @@
52
57
  /** Jump to the end of the previous line */
53
58
  prevLine() {
54
59
  if (this.line <= this.min) {
55
- return;
60
+ return false;
56
61
  }
57
62
  this.text = this.cm.getLine(--this.line);
58
63
  this.ch = this.text.length;
@@ -64,7 +69,7 @@
64
69
  for (;;) {
65
70
  const gt = this.text.indexOf('>', this.ch);
66
71
  if (gt === -1) {
67
- return;
72
+ return undefined;
68
73
  }
69
74
  this.ch = gt + 1;
70
75
  if (!this.bracketAt(gt)) {
@@ -79,7 +84,7 @@
79
84
  for (;;) {
80
85
  const lt = this.ch ? this.text.lastIndexOf('<', this.ch - 1) : -1;
81
86
  if (lt === -1) {
82
- return;
87
+ return undefined;
83
88
  }
84
89
  if (!this.bracketAt(lt)) {
85
90
  this.ch = lt;
@@ -103,7 +108,7 @@
103
108
  if (this.nextLine()) {
104
109
  continue;
105
110
  } else {
106
- return;
111
+ return undefined;
107
112
  }
108
113
  }
109
114
  if (!this.bracketAt(found.index)) {
@@ -123,7 +128,7 @@
123
128
  if (this.prevLine()) {
124
129
  continue;
125
130
  } else {
126
- return;
131
+ return undefined;
127
132
  }
128
133
  }
129
134
  if (!this.bracketAt(gt)) {
@@ -131,14 +136,16 @@
131
136
  continue;
132
137
  }
133
138
  const lastSlash = this.text.lastIndexOf('/', gt);
134
- const selfClose = lastSlash > -1 && !/\S/.test(this.text.slice(lastSlash + 1, gt));
139
+ const selfClose = lastSlash > -1 && !/\S/u.test(this.text.slice(lastSlash + 1, gt));
135
140
  this.ch = gt + 1;
136
141
  return selfClose ? 'selfClose' : 'regular';
137
142
  }
138
143
  }
139
144
 
145
+ // eslint-disable-next-line jsdoc/require-returns-check
140
146
  /**
141
- * @param {string} tag
147
+ * 搜索匹配的闭合标签
148
+ * @param {string} tag 标签名
142
149
  * @returns {CodeMirror.MatchingTag}
143
150
  */
144
151
  findMatchingClose(tag) {
@@ -146,13 +153,13 @@
146
153
  for (;;) {
147
154
  const next = this.toNextTag();
148
155
  if (!next) {
149
- return;
156
+ return undefined;
150
157
  }
151
158
  const start = this.ch - next[0].length,
152
159
  end = this.toTagEnd(),
153
160
  tagName = next[2].toLowerCase();
154
161
  if (!end) {
155
- return;
162
+ return undefined;
156
163
  }
157
164
  if (end === 'selfClose' || voidTags.includes(tagName)) {
158
165
  continue;
@@ -174,8 +181,10 @@
174
181
  }
175
182
  }
176
183
 
184
+ // eslint-disable-next-line jsdoc/require-returns-check
177
185
  /**
178
- * @param {string|undefined} tag
186
+ * 搜索匹配的开启标签
187
+ * @param {string|undefined} tag 标签名
179
188
  * @returns {CodeMirror.MatchingTag}
180
189
  */
181
190
  findMatchingOpen(tag) {
@@ -183,12 +192,12 @@
183
192
  for (;;) {
184
193
  const prev = this.toPrevTag();
185
194
  if (!prev) {
186
- return;
195
+ return undefined;
187
196
  }
188
- const end = this.ch,
197
+ const {ch: end} = this,
189
198
  start = this.toTagStart();
190
199
  if (!start) {
191
- return;
200
+ return undefined;
192
201
  }
193
202
  const tagName = start[2].toLowerCase();
194
203
  if (prev === 'selfClose' || voidTags.includes(tagName)) {
@@ -205,6 +214,7 @@
205
214
  }
206
215
  }
207
216
  if (i < 0 && (!tag || tag === tagName)) {
217
+ // eslint-disable-next-line unicorn/consistent-destructuring
208
218
  return {tag: tagName, from: Pos(this.line, this.ch), to: Pos(this.line, end)};
209
219
  }
210
220
  }
@@ -214,17 +224,22 @@
214
224
 
215
225
  CodeMirror.defineExtension(
216
226
  'findMatchingTag',
217
- /** @type {function(this: CodeMirror.Editor, CodeMirror.Position): CodeMirror.MatchingTagPair} */
227
+
228
+ /**
229
+ * @this {CodeMirror.Editor}
230
+ * @param {CodeMirror.Position} pos 当前位置
231
+ * @returns {CodeMirror.MatchingTagPair}
232
+ */
218
233
  function(pos) {
219
234
  let iter = new Iter(this, pos);
220
235
  if (!iter.isTag()) {
221
- return;
236
+ return undefined;
222
237
  }
223
238
  const end = iter.toTagEnd(),
224
239
  to = end && Pos(iter.line, iter.ch);
225
240
  const start = end && iter.toTagStart();
226
241
  if (!start || cmpPos(iter, pos) > 0) {
227
- return;
242
+ return undefined;
228
243
  }
229
244
  const tag = start[2].toLowerCase(),
230
245
  here = {from: Pos(iter.line, iter.ch), to, tag};
@@ -242,29 +257,36 @@
242
257
 
243
258
  CodeMirror.defineExtension(
244
259
  'findEnclosingTag',
245
- /** @type {function(this: CodeMirror.Editor, CodeMirror.Position, string): CodeMirror.MatchingTagPair} */
260
+
261
+ /**
262
+ * @this {CodeMirror.Editor}
263
+ * @param {CodeMirror.Position} pos
264
+ * @param {string} tag
265
+ * @returns {CodeMirror.MatchingTagPair}
266
+ */
246
267
  function(pos, tag) {
247
- const iter = new Iter(this, pos);
248
- const open = iter.findMatchingOpen(tag);
268
+ const iter = new Iter(this, pos),
269
+ open = iter.findMatchingOpen(tag);
249
270
  if (!open) {
250
- return;
271
+ return undefined;
251
272
  }
252
- const forward = new Iter(this, pos);
253
- const close = forward.findMatchingClose(open.tag);
273
+ const forward = new Iter(this, pos),
274
+ close = forward.findMatchingClose(open.tag);
254
275
  if (close) {
255
276
  return {open, close};
256
277
  }
278
+ return undefined;
257
279
  },
258
280
  );
259
281
 
260
282
  /** Used by addon/edit/closetag.js */
261
- CodeMirror.scanForClosingTag = function(cm, pos, name) {
283
+ CodeMirror.scanForClosingTag = (cm, pos, tagName) => {
262
284
  const iter = new Iter(cm, pos);
263
- return iter.findMatchingClose(name);
285
+ return iter.findMatchingClose(tagName);
264
286
  };
265
287
 
266
288
  CodeMirror.defineOption('matchTags', false, (cm, val, old) => {
267
- if (old && old !== CodeMirror.Init) {
289
+ if (old && old !== Init) {
268
290
  cm.off('cursorActivity', doMatchTags);
269
291
  clear(cm);
270
292
  }
@@ -274,8 +296,11 @@
274
296
  }
275
297
  });
276
298
 
277
- /** @param {CodeMirror.EditorWithMatchingTags} cm */
278
- function clear(cm) {
299
+ /**
300
+ * 清除高亮
301
+ * @param {CodeMirror.EditorWithMatchingTags} cm
302
+ */
303
+ const clear = cm => {
279
304
  if (cm.state.tagHit) {
280
305
  cm.state.tagHit.clear();
281
306
  }
@@ -284,10 +309,13 @@
284
309
  }
285
310
  cm.state.tagHit = null;
286
311
  cm.state.tagOther = null;
287
- }
312
+ };
288
313
 
289
- /** @param {CodeMirror.EditorWithMatchingTags} cm */
290
- function doMatchTags(cm) {
314
+ /**
315
+ * 搜索并高亮匹配的标签
316
+ * @param {CodeMirror.EditorWithMatchingTags} cm
317
+ */
318
+ const doMatchTags = cm => {
291
319
  cm.operation(() => {
292
320
  clear(cm);
293
321
  if (cm.somethingSelected()) {
@@ -310,7 +338,7 @@
310
338
  cm.state.tagOther = cm.markText(other.from, other.to, {className: 'cm-matchingtag'});
311
339
  }
312
340
  });
313
- }
341
+ };
314
342
 
315
343
  mw.loader.addStyleTag(
316
344
  '.cm-matchingtag{background-color:#c9ffc8}'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiplus-highlight",
3
- "version": "2.21.0",
3
+ "version": "2.22.5",
4
4
  "description": "A plugin for the MediaWiki front-end add-on \"Wikiplus\"",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -24,6 +24,10 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "eslint": "^8.8.0",
27
+ "eslint-plugin-promise": "^6.1.1",
28
+ "eslint-plugin-es-x": "^5.4.0",
29
+ "eslint-plugin-regexp": "^1.11.0",
30
+ "eslint-plugin-jsdoc": "^1.0.0",
27
31
  "http-server": "^14.1.0",
28
32
  "types-mediawiki": "^1.2.0",
29
33
  "uglify-js": "^3.15.5"
package/search.js CHANGED
@@ -6,7 +6,10 @@
6
6
  (() => {
7
7
  'use strict';
8
8
 
9
- /** @param {string} key */
9
+ /**
10
+ * I18N消息
11
+ * @param {string} key 消息键
12
+ */
10
13
  const msg = key => mw.msg(`wphl-${key}`);
11
14
 
12
15
  // Prepare elements
@@ -21,15 +24,20 @@
21
24
  $searchBtn = $('<span>', {class: 'Wikiplus-Btn', html: msg('addon-search')});
22
25
 
23
26
  const escapeRegExp = mw.util.escapeRegExp || mw.RegExp.escape;
24
- const /** @type {CodeMirror.Mode<undefined>} */ overlay = {token: () => {}};
27
+ const /** @type {CodeMirror.Mode<undefined>} */ overlay = {token: /** @override */ () => {}};
25
28
 
26
29
  /**
27
30
  * 根据搜索字符串生成高亮
28
- * @param {string|RegExp} str
31
+ * @param {string|RegExp} str 搜索字符串
29
32
  */
30
33
  const token = str => {
31
- const initial = typeof str === 'string' ? RegExp(`[^${escapeRegExp(str[0])}]`, 'i') : null;
32
- return /** @param {CodeMirror.StringStream} stream */ stream => {
34
+ const initial = typeof str === 'string' ? new RegExp(`[^${escapeRegExp(str[0])}]`, 'iu') : null;
35
+
36
+ /**
37
+ * @override
38
+ * @param {CodeMirror.StringStream} stream
39
+ */
40
+ return stream => {
33
41
  if (stream.match(str, true, true)) {
34
42
  return 'search';
35
43
  }
@@ -37,6 +45,7 @@
37
45
  if (initial) {
38
46
  stream.eatWhile(initial);
39
47
  }
48
+ return undefined;
40
49
  };
41
50
  };
42
51
 
@@ -50,7 +59,7 @@
50
59
  /**
51
60
  * keyboard event handler of `$search`
52
61
  * @param {CodeMirror.Editor} cm
53
- * @param {boolean} dir
62
+ * @param {boolean} dir 搜索方向
54
63
  */
55
64
  const findNext = (cm, dir) => {
56
65
  let /** @type {string|RegExp} */ ptn = $search.val();
@@ -58,10 +67,10 @@
58
67
  return;
59
68
  }
60
69
 
61
- if (typeof ptn === 'string' && /^\/.+\/i?$/.test(ptn)) {
70
+ if (typeof ptn === 'string' && /^\/.+\/i?$/u.test(ptn)) {
62
71
  ptn = ptn.endsWith('i')
63
- ? RegExp(ptn.slice(1, -2), 'i')
64
- : RegExp(ptn.slice(1, -1));
72
+ ? new RegExp(ptn.slice(1, -2), 'iu')
73
+ : new RegExp(ptn.slice(1, -1), 'u');
65
74
  }
66
75
  if (ptn !== lastPtn) {
67
76
  cm.removeOverlay(overlay);
@@ -76,7 +85,7 @@
76
85
  cursor = cm.getSearchCursor(ptn, {line: 0, ch: 0}, {caseFold: true});
77
86
  } else {
78
87
  const lastLine = cm.lastLine(),
79
- lastCh = cm.getLine(lastLine).length;
88
+ {length: lastCh} = cm.getLine(lastLine);
80
89
  cursor = cm.getSearchCursor(ptn, {line: lastLine, ch: lastCh}, {caseFold: true});
81
90
  }
82
91
  result = dir ? cursor.findNext() : cursor.findPrevious();
@@ -109,10 +118,10 @@
109
118
  lastPtn = '';
110
119
  };
111
120
 
112
- CodeMirror.commands.findForward = doc => {
121
+ CodeMirror.commands.findForward = /** 向后搜索 */ doc => {
113
122
  findNext(doc, true);
114
123
  };
115
- CodeMirror.commands.findBackward = doc => {
124
+ CodeMirror.commands.findBackward = /** 向前搜索 */ doc => {
116
125
  findNext(doc, false);
117
126
  };
118
127
 
@@ -144,9 +153,10 @@
144
153
  reset(cm);
145
154
  }
146
155
  });
147
- cm.addKeyMap(CodeMirror.keyMap.default === CodeMirror.keyMap.pcDefault
148
- ? {'Ctrl-F': findNew, 'Ctrl-G': 'findForward', 'Shift-Ctrl-G': 'findBackward'}
149
- : {'Cmd-F': findNew, 'Cmd-G': 'findForward', 'Shift-Cmd-G': 'findBackward'},
156
+ cm.addKeyMap(
157
+ CodeMirror.keyMap.default === CodeMirror.keyMap.pcDefault
158
+ ? {'Ctrl-F': findNew, 'Ctrl-G': 'findForward', 'Shift-Ctrl-G': 'findBackward'}
159
+ : {'Cmd-F': findNew, 'Cmd-G': 'findForward', 'Shift-Cmd-G': 'findBackward'},
150
160
  );
151
161
  });
152
162