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/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
- const lastSlash = this.text.lastIndexOf('/', gt);
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('findEnclosingTag', function(pos, tag) {
238
- const iter = new Iter(this, pos);
239
- const open = iter.findMatchingOpen(tag);
240
- if (!open) {
241
- return;
242
- }
243
- const forward = new Iter(this, pos);
244
- const close = forward.findMatchingClose(open.tag);
245
- if (close) {
246
- return {open, close};
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
- // Used by addon/edit/closetag.js
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
- const match = cm.findMatchingTag(cm.getCursor());
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.7.5",
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
- "mediawiki-gadget",
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: GPL-3.0
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; // @type {(function|undefined)}
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, cursor;
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
- // click event handler of $searchClose
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;