wikilint 2.28.1 → 2.29.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.
Files changed (51) hide show
  1. package/data/ext/ThirdPartyNotices.txt +33 -0
  2. package/data/ext/mapframe.json +489 -2
  3. package/dist/base.d.mts +4 -2
  4. package/dist/base.d.ts +4 -2
  5. package/dist/base.js +1 -0
  6. package/dist/base.mjs +2 -1
  7. package/dist/bin/config.js +1 -1
  8. package/dist/index.d.ts +2 -1
  9. package/dist/index.js +23 -2
  10. package/dist/lib/document.d.ts +23 -7
  11. package/dist/lib/document.js +7 -27
  12. package/dist/lib/element.js +1 -1
  13. package/dist/lib/lintConfig.js +2 -0
  14. package/dist/lib/lsp.d.ts +1 -12
  15. package/dist/lib/lsp.js +41 -75
  16. package/dist/lib/node.js +23 -20
  17. package/dist/lib/title.d.ts +3 -1
  18. package/dist/lib/title.js +37 -9
  19. package/dist/mixin/elementLike.js +14 -9
  20. package/dist/parser/commentAndExt.js +30 -26
  21. package/dist/parser/links.js +4 -3
  22. package/dist/parser/redirect.js +1 -1
  23. package/dist/parser/selector.js +6 -8
  24. package/dist/src/arg.js +2 -2
  25. package/dist/src/attribute.js +27 -0
  26. package/dist/src/attributes.js +1 -1
  27. package/dist/src/converter.js +6 -3
  28. package/dist/src/imageParameter.d.ts +3 -1
  29. package/dist/src/imageParameter.js +18 -3
  30. package/dist/src/index.d.ts +8 -0
  31. package/dist/src/index.js +21 -28
  32. package/dist/src/link/file.js +7 -7
  33. package/dist/src/link/galleryImage.js +1 -1
  34. package/dist/src/link/redirectTarget.js +1 -1
  35. package/dist/src/multiLine/gallery.js +2 -2
  36. package/dist/src/multiLine/imagemap.js +3 -4
  37. package/dist/src/multiLine/paramTag.js +2 -2
  38. package/dist/src/nowiki/index.js +59 -2
  39. package/dist/src/table/base.js +1 -2
  40. package/dist/src/table/index.js +1 -2
  41. package/dist/src/transclude.js +3 -3
  42. package/dist/util/constants.js +3 -1
  43. package/dist/util/debug.js +1 -1
  44. package/dist/util/search.js +16 -0
  45. package/dist/util/sharable.js +27 -3
  46. package/dist/util/sharable.mjs +28 -4
  47. package/i18n/en.json +2 -0
  48. package/i18n/zh-hans.json +2 -0
  49. package/i18n/zh-hant.json +2 -0
  50. package/package.json +5 -3
  51. package/data/ext/maplink.json +0 -4
@@ -8,6 +8,21 @@ const common_1 = require("@bhsd/common");
8
8
  const lint_1 = require("../../util/lint");
9
9
  const index_1 = __importDefault(require("../../index"));
10
10
  const base_1 = require("./base");
11
+ /* NOT FOR BROWSER ONLY */
12
+ const constants_1 = require("../../util/constants");
13
+ const document_1 = require("../../lib/document");
14
+ /** @ignore */
15
+ const updateLocation = ({ startIndex, startLine, startCol, endIndex, endLine, endCol }, { offset, line, column }, n) => {
16
+ const index = startIndex + offset - n;
17
+ if (index < startIndex) {
18
+ return [startIndex, startLine, startCol];
19
+ }
20
+ else if (index > endIndex) {
21
+ return [endIndex, endLine, endCol];
22
+ }
23
+ return [index, startLine + line - 1, (line === 1 ? startCol - n : 0) + column - 1];
24
+ };
25
+ /* NOT FOR BROWSER ONLY END */
11
26
  const getLintRegex = /* #__PURE__ */ (0, common_1.getRegex)(name => new RegExp(String.raw `<\s*(?:/\s*)${name === 'nowiki' ? '' : '?'}(${name})\b`, 'giu'));
12
27
  const voidExt = new Set(['languages', 'section', 'templatestyles']);
13
28
  /**
@@ -27,7 +42,10 @@ class NowikiToken extends base_1.NowikiBaseToken {
27
42
  /** @private */
28
43
  lint(start = this.getAbsoluteIndex()) {
29
44
  LINT: { // eslint-disable-line no-unused-labels
30
- const { name } = this, rule = 'void-ext', { lintConfig } = index_1.default, s = lintConfig.getSeverity(rule, name);
45
+ const { name,
46
+ /* NOT FOR BROWSER ONLY */
47
+ innerText, previousSibling, } = this, { lintConfig } = index_1.default;
48
+ let rule = 'void-ext', s = lintConfig.getSeverity(rule, name);
31
49
  if (s && this.#lint()) {
32
50
  const e = (0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('nothing-in', name), s);
33
51
  if (lintConfig.computeEditInfo) {
@@ -35,7 +53,46 @@ class NowikiToken extends base_1.NowikiBaseToken {
35
53
  }
36
54
  return [e];
37
55
  }
38
- return super.lint(start, getLintRegex(name));
56
+ const errors = super.lint(start, getLintRegex(name));
57
+ /* NOT FOR BROWSER ONLY */
58
+ rule = 'invalid-math';
59
+ s = lintConfig.getSeverity(rule);
60
+ if (s && document_1.texvcjs && constants_1.mathTags.has(name)) {
61
+ const isChem = name !== 'math', display = previousSibling?.getAttr('display') ?? 'block';
62
+ let tex = innerText, n = 0;
63
+ if (isChem) {
64
+ tex = String.raw `\ce{${tex}}`;
65
+ n = 4;
66
+ }
67
+ switch (display) {
68
+ case 'block':
69
+ tex = String.raw `{\displaystyle ${tex}}`;
70
+ n += 15;
71
+ break;
72
+ case 'inline':
73
+ tex = String.raw `{\textstyle ${tex}}`;
74
+ n += 12;
75
+ break;
76
+ case 'linebreak':
77
+ tex = String.raw `\[ ${tex} \]`;
78
+ n += 3;
79
+ // no default
80
+ }
81
+ const result = document_1.texvcjs.check(tex, {
82
+ usemhchem: isChem || Boolean(previousSibling?.hasAttr('chem')),
83
+ });
84
+ if (result.status !== '+') {
85
+ const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'chem-required', s);
86
+ if (result.status !== 'C') {
87
+ const { error: { message, location } } = result, [endIndex, endLine, endCol] = updateLocation(e, location.end, n);
88
+ [e.startIndex, e.startLine, e.startCol] = updateLocation(e, location.start, n);
89
+ Object.assign(e, { endIndex, endLine, endCol, message });
90
+ }
91
+ errors.push(e);
92
+ }
93
+ }
94
+ /* NOT FOR BROWSER ONLY END */
95
+ return errors;
39
96
  }
40
97
  }
41
98
  }
@@ -51,8 +51,7 @@ const escapeTable = (syntax) => {
51
51
  const wikitext = syntax.childNodes.map(child => child.type === 'text'
52
52
  ? child.data.replace(/\|\|/gu, '{{!!}}')
53
53
  .replace(/\|/gu, '{{!}}')
54
- : child.toString()).join(''), { childNodes } = index_1.default
55
- .parse(wikitext, syntax.getAttribute('include'), 2, syntax.getAttribute('config'));
54
+ : child.toString()).join(''), { childNodes } = index_1.default.parseWithRef(wikitext, syntax, 2);
56
55
  syntax.safeReplaceChildren(childNodes);
57
56
  };
58
57
  /**
@@ -140,9 +140,8 @@ let TableToken = (() => {
140
140
  * @param syntax syntax of the table end / 表格结尾语法
141
141
  */
142
142
  close(syntax = '\n|}', halfParsed) {
143
- const config = this.getAttribute('config'), accum = this.getAttribute('accum');
144
143
  debug_1.Shadow.run(() => {
145
- const token = new syntax_1.SyntaxToken(halfParsed ? syntax : undefined, 'table-syntax', config, accum);
144
+ const token = new syntax_1.SyntaxToken(halfParsed ? syntax : undefined, 'table-syntax', this.getAttribute('config'), this.getAttribute('accum'));
146
145
  super.insertAt(token);
147
146
  });
148
147
  }
@@ -219,7 +219,7 @@ let TranscludeToken = (() => {
219
219
  }
220
220
  /** 获取模板或模块名 */
221
221
  #getTitle() {
222
- const isTemplate = this.type === 'template', title = this.normalizeTitle(this.childNodes[isTemplate ? 0 : 1].text(), isTemplate ? 10 : 828, { temporary: true });
222
+ const isTemplate = this.type === 'template', title = this.normalizeTitle((isTemplate ? '' : 'Module:') + this.childNodes[isTemplate ? 0 : 1].text(), 10, { temporary: true, ...!isTemplate && { page: '' } });
223
223
  return title;
224
224
  }
225
225
  /** @private */
@@ -310,7 +310,7 @@ let TranscludeToken = (() => {
310
310
  const duplicatedArgs = this.getDuplicatedArgs()
311
311
  .filter(([, parameter]) => !parameter[0].querySelector('ext')), msg = 'duplicate-parameter';
312
312
  for (const [, args] of duplicatedArgs) {
313
- errors.push(...args.map(arg => {
313
+ Array.prototype.push.apply(errors, args.map(arg => {
314
314
  const e = (0, lint_1.generateForChild)(arg, rect, rule, msg, s);
315
315
  if (computeEditInfo) {
316
316
  e.suggestions = [(0, lint_1.fixByRemove)(e, -1)];
@@ -442,7 +442,7 @@ let TranscludeToken = (() => {
442
442
  else {
443
443
  try {
444
444
  const possibleValues = first.getPossibleValues();
445
- queue.splice(i, 1, ...possibleValues);
445
+ Array.prototype.splice.apply(queue, [i, 1, ...possibleValues]);
446
446
  i += possibleValues.length;
447
447
  }
448
448
  catch {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.enMsg = exports.BuildMethod = exports.MAX_STAGE = void 0;
3
+ exports.mathTags = exports.enMsg = exports.BuildMethod = exports.MAX_STAGE = void 0;
4
4
  exports.MAX_STAGE = 11;
5
5
  var BuildMethod;
6
6
  (function (BuildMethod) {
@@ -9,3 +9,5 @@ var BuildMethod;
9
9
  })(BuildMethod || (exports.BuildMethod = BuildMethod = {}));
10
10
  // eslint-disable-next-line n/no-missing-require
11
11
  exports.enMsg = (() => require('../../i18n/en.json'))();
12
+ /* NOT FOR BROWSER ONLY */
13
+ exports.mathTags = new Set(['math', 'chem', 'ce']);
@@ -43,7 +43,7 @@ const setChildNodes = (parent, position, deleteCount, inserted = []) => {
43
43
  nodes = inserted;
44
44
  }
45
45
  else {
46
- removed = nodes.splice(position, deleteCount, ...inserted);
46
+ removed = Array.prototype.splice.apply(nodes, [position, deleteCount, ...inserted]);
47
47
  }
48
48
  for (let i = 0; i < inserted.length; i++) {
49
49
  const node = inserted[i];
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const binary_search_1 = __importDefault(require("binary-search"));
7
+ /**
8
+ * 二分法查找索引
9
+ * @param haystack 数组
10
+ * @param needle 目标值
11
+ * @param comparator 比较函数
12
+ */
13
+ exports.default = (haystack, needle, comparator) => {
14
+ const found = (0, binary_search_1.default)(haystack, needle, comparator);
15
+ return found < 0 ? ~found : found; // eslint-disable-line no-bitwise
16
+ };
@@ -15,6 +15,17 @@ const blockAttrs = new Set(['align']), citeAttrs = new Set(['cite']), citeAndAtt
15
15
  'copy',
16
16
  'highlight',
17
17
  'start',
18
+ ]), weightAttrs = new Set(['weight']), mapAttrs = new Set([
19
+ 'width',
20
+ 'height',
21
+ 'zoom',
22
+ 'latitude',
23
+ 'longitude',
24
+ 'align',
25
+ 'mapstyle',
26
+ 'lang',
27
+ 'alt',
28
+ 'text',
18
29
  ]), empty = new Set();
19
30
  exports.commonHtmlAttrs = new Set([
20
31
  'id',
@@ -100,14 +111,13 @@ exports.commonHtmlAttrs = new Set([
100
111
  references: new Set(['group', 'responsive']),
101
112
  charinsert: new Set(['label']),
102
113
  choose: new Set(['uncached', 'before', 'after']),
103
- option: new Set(['weight']),
114
+ option: weightAttrs,
115
+ choicetemplate: weightAttrs,
104
116
  imagemap: empty,
105
117
  inputbox: empty,
106
118
  templatestyles: new Set(['src', 'wrapper']),
107
119
  dynamicpagelist: empty,
108
120
  poll: new Set(['id', 'show-results-before-voting']),
109
- sm2: typeAttrs,
110
- flashmp3: typeAttrs,
111
121
  score: new Set([
112
122
  'line_width_inches',
113
123
  'lang',
@@ -170,6 +180,20 @@ exports.commonHtmlAttrs = new Set([
170
180
  timeline: new Set(['method', 'font']),
171
181
  quiz: new Set(['display', 'shuffleanswers', 'points', 'shuffle', 'case']),
172
182
  languages: empty,
183
+ mapframe: new Set([...mapAttrs, 'frameless']),
184
+ maplink: new Set([...mapAttrs, 'class']),
185
+ rss: new Set([
186
+ 'template',
187
+ 'templatename',
188
+ 'max',
189
+ 'highlight',
190
+ 'filter',
191
+ 'filterout',
192
+ 'reverse',
193
+ 'date',
194
+ 'item-max-length',
195
+ ]),
196
+ 'page-collection': new Set(['lang', 'name', 'description', 'end-date']),
173
197
  }))(), exports.obsoleteAttrs = (() => ({
174
198
  table: obsoleteTableAttrs,
175
199
  td: new Set([...obsoleteTdAttrs, 'scope']),
@@ -13,6 +13,17 @@ const blockAttrs = /* @__PURE__ */ new Set(["align"]), citeAttrs = /* @__PURE__
13
13
  "copy",
14
14
  "highlight",
15
15
  "start"
16
+ ]), weightAttrs = /* @__PURE__ */ new Set(["weight"]), mapAttrs = /* @__PURE__ */ new Set([
17
+ "width",
18
+ "height",
19
+ "zoom",
20
+ "latitude",
21
+ "longitude",
22
+ "align",
23
+ "mapstyle",
24
+ "lang",
25
+ "alt",
26
+ "text"
16
27
  ]), empty = /* @__PURE__ */ new Set();
17
28
  const commonHtmlAttrs = /* @__PURE__ */ new Set([
18
29
  "id",
@@ -98,14 +109,13 @@ const commonHtmlAttrs = /* @__PURE__ */ new Set([
98
109
  references: /* @__PURE__ */ new Set(["group", "responsive"]),
99
110
  charinsert: /* @__PURE__ */ new Set(["label"]),
100
111
  choose: /* @__PURE__ */ new Set(["uncached", "before", "after"]),
101
- option: /* @__PURE__ */ new Set(["weight"]),
112
+ option: weightAttrs,
113
+ choicetemplate: weightAttrs,
102
114
  imagemap: empty,
103
115
  inputbox: empty,
104
116
  templatestyles: /* @__PURE__ */ new Set(["src", "wrapper"]),
105
117
  dynamicpagelist: empty,
106
118
  poll: /* @__PURE__ */ new Set(["id", "show-results-before-voting"]),
107
- sm2: typeAttrs,
108
- flashmp3: typeAttrs,
109
119
  score: /* @__PURE__ */ new Set([
110
120
  "line_width_inches",
111
121
  "lang",
@@ -167,7 +177,21 @@ const commonHtmlAttrs = /* @__PURE__ */ new Set([
167
177
  templatedata: empty,
168
178
  timeline: /* @__PURE__ */ new Set(["method", "font"]),
169
179
  quiz: /* @__PURE__ */ new Set(["display", "shuffleanswers", "points", "shuffle", "case"]),
170
- languages: empty
180
+ languages: empty,
181
+ mapframe: /* @__PURE__ */ new Set([...mapAttrs, "frameless"]),
182
+ maplink: /* @__PURE__ */ new Set([...mapAttrs, "class"]),
183
+ rss: /* @__PURE__ */ new Set([
184
+ "template",
185
+ "templatename",
186
+ "max",
187
+ "highlight",
188
+ "filter",
189
+ "filterout",
190
+ "reverse",
191
+ "date",
192
+ "item-max-length"
193
+ ]),
194
+ "page-collection": /* @__PURE__ */ new Set(["lang", "name", "description", "end-date"])
171
195
  }))(), obsoleteAttrs = /* @__PURE__ */ (() => ({
172
196
  table: obsoleteTableAttrs,
173
197
  td: /* @__PURE__ */ new Set([...obsoleteTdAttrs, "scope"]),
package/i18n/en.json CHANGED
@@ -2,6 +2,7 @@
2
2
  "attributes-of-closing-tag": "attributes of a closing tag",
3
3
  "bold-apostrophes": "bold apostrophes",
4
4
  "bold-in-header": "bold text in a section header",
5
+ "chem-required": "chem attribute required",
5
6
  "close": null,
6
7
  "closing-and-self-closing": "tag that is both closing and self-closing",
7
8
  "comment": null,
@@ -39,6 +40,7 @@
39
40
  "invalid-isbn": "invalid ISBN",
40
41
  "invalid-parameter": "invalid parameter of <$1>",
41
42
  "invalid-self-closing": "invalid self-closing tag",
43
+ "invalid-thumb": "invalid thumbnail filename",
42
44
  "invalid-url": "invalid URL",
43
45
  "invisible-triple-braces": "invisible content inside triple braces",
44
46
  "italic-apostrophes": "italic apostrophes",
package/i18n/zh-hans.json CHANGED
@@ -2,6 +2,7 @@
2
2
  "attributes-of-closing-tag": "闭合标签的属性",
3
3
  "bold-apostrophes": "粗体单引号",
4
4
  "bold-in-header": "章节标题中的粗体文本",
5
+ "chem-required": "需要chem属性",
5
6
  "close": "闭合",
6
7
  "closing-and-self-closing": "同时闭合和自封闭的标签",
7
8
  "comment": "注释",
@@ -39,6 +40,7 @@
39
40
  "invalid-isbn": "无效的ISBN",
40
41
  "invalid-parameter": "<$1>的无效参数",
41
42
  "invalid-self-closing": "无效自封闭标签",
43
+ "invalid-thumb": "无效的缩略图文件名",
42
44
  "invalid-url": "无效的URL",
43
45
  "invisible-triple-braces": "三重括号内的不可见部分",
44
46
  "italic-apostrophes": "斜体单引号",
package/i18n/zh-hant.json CHANGED
@@ -2,6 +2,7 @@
2
2
  "attributes-of-closing-tag": "結束標籤的屬性",
3
3
  "bold-apostrophes": "粗體撇號",
4
4
  "bold-in-header": "章節標題中的粗體文本",
5
+ "chem-required": "需要chem屬性",
5
6
  "close": "閉合",
6
7
  "closing-and-self-closing": "同時閉合和自封閉的標籤",
7
8
  "comment": "註解",
@@ -39,6 +40,7 @@
39
40
  "invalid-isbn": "無效的ISBN",
40
41
  "invalid-parameter": "<$1>的無效參數",
41
42
  "invalid-self-closing": "無效自封閉標籤",
43
+ "invalid-thumb": "無效的縮略圖檔名",
42
44
  "invalid-url": "無效的URL",
43
45
  "invisible-triple-braces": "三重括號內的不可見部分",
44
46
  "italic-apostrophes": "斜體撇號",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.28.1",
3
+ "version": "2.29.0",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -52,6 +52,7 @@
52
52
  "test:unit": "mocha dist/test/test.js",
53
53
  "test:parser": "mocha dist/test/parserTests.js",
54
54
  "test": "npm run test:unit && npm run test:parser",
55
+ "test:ci": "LSP=0 npm test",
55
56
  "test:end": "pkill -x http-server",
56
57
  "test:real": "node dist/test/real.js"
57
58
  },
@@ -71,13 +72,14 @@
71
72
  "@bhsd/cm-util": "^0.1.0",
72
73
  "@bhsd/common": "^1.0.1",
73
74
  "@bhsd/stylelint-util": "^0.1.0",
75
+ "binary-search": "^1.3.6",
74
76
  "vscode-languageserver-types": "^3.17.5"
75
77
  },
76
78
  "optionalDependencies": {
77
79
  "chalk": "^4.1.2",
78
80
  "color-name": "^2.0.0",
79
81
  "entities": "^6.0.0",
80
- "mathjax": "^3.2.2",
82
+ "mathoid-texvcjs": "^0.5.4",
81
83
  "minimatch": "^10.0.1",
82
84
  "stylelint": "^16.25.0",
83
85
  "vscode-css-languageservice": "^6.3.7",
@@ -86,7 +88,7 @@
86
88
  },
87
89
  "devDependencies": {
88
90
  "@bhsd/code-standard": "^1.2.0",
89
- "@bhsd/test-util": "^0.1.0",
91
+ "@bhsd/test-util": "^0.2.1",
90
92
  "@stylistic/eslint-plugin": "^3.1.0",
91
93
  "@types/color-name": "^2.0.0",
92
94
  "@types/color-rgba": "^2.1.3",
@@ -1,4 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$ref": "https://geojson.org/schema/GeoJSON.json"
4
- }