wikiparser-node 0.9.2-b → 0.10.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 (90) hide show
  1. package/README.md +40 -0
  2. package/config/.schema.json +134 -0
  3. package/config/default.json +832 -0
  4. package/config/llwiki.json +630 -0
  5. package/config/moegirl.json +729 -0
  6. package/config/zhwiki.json +1269 -0
  7. package/i18n/zh-hans.json +1 -0
  8. package/i18n/zh-hant.json +1 -0
  9. package/index.js +333 -0
  10. package/lib/element.js +611 -0
  11. package/lib/node.js +770 -0
  12. package/lib/ranges.js +130 -0
  13. package/lib/text.js +263 -0
  14. package/lib/title.js +83 -0
  15. package/mixin/attributeParent.js +117 -0
  16. package/mixin/fixedToken.js +40 -0
  17. package/mixin/hidden.js +21 -0
  18. package/mixin/singleLine.js +31 -0
  19. package/mixin/sol.js +54 -0
  20. package/package.json +49 -47
  21. package/parser/brackets.js +126 -0
  22. package/parser/commentAndExt.js +59 -0
  23. package/parser/converter.js +46 -0
  24. package/parser/externalLinks.js +33 -0
  25. package/parser/hrAndDoubleUnderscore.js +49 -0
  26. package/parser/html.js +42 -0
  27. package/parser/links.js +94 -0
  28. package/parser/list.js +59 -0
  29. package/parser/magicLinks.js +41 -0
  30. package/parser/quotes.js +64 -0
  31. package/parser/selector.js +177 -0
  32. package/parser/table.js +114 -0
  33. package/src/arg.js +207 -0
  34. package/src/atom/hidden.js +13 -0
  35. package/src/atom/index.js +43 -0
  36. package/src/attribute.js +470 -0
  37. package/src/attributes.js +453 -0
  38. package/src/charinsert.js +97 -0
  39. package/src/converter.js +176 -0
  40. package/src/converterFlags.js +284 -0
  41. package/src/converterRule.js +256 -0
  42. package/src/extLink.js +180 -0
  43. package/src/gallery.js +149 -0
  44. package/src/hasNowiki/index.js +44 -0
  45. package/src/hasNowiki/pre.js +40 -0
  46. package/src/heading.js +134 -0
  47. package/src/html.js +254 -0
  48. package/src/imageParameter.js +303 -0
  49. package/src/imagemap.js +199 -0
  50. package/src/imagemapLink.js +41 -0
  51. package/src/index.js +932 -0
  52. package/src/link/category.js +44 -0
  53. package/src/link/file.js +287 -0
  54. package/src/link/galleryImage.js +120 -0
  55. package/src/link/index.js +388 -0
  56. package/src/magicLink.js +149 -0
  57. package/src/nested/choose.js +24 -0
  58. package/src/nested/combobox.js +23 -0
  59. package/src/nested/index.js +93 -0
  60. package/src/nested/references.js +23 -0
  61. package/src/nowiki/comment.js +71 -0
  62. package/src/nowiki/dd.js +59 -0
  63. package/src/nowiki/doubleUnderscore.js +56 -0
  64. package/src/nowiki/hr.js +41 -0
  65. package/src/nowiki/index.js +56 -0
  66. package/src/nowiki/list.js +16 -0
  67. package/src/nowiki/noinclude.js +28 -0
  68. package/src/nowiki/quote.js +69 -0
  69. package/src/onlyinclude.js +64 -0
  70. package/src/paramTag/index.js +89 -0
  71. package/src/paramTag/inputbox.js +35 -0
  72. package/src/parameter.js +239 -0
  73. package/src/syntax.js +91 -0
  74. package/src/table/index.js +983 -0
  75. package/src/table/td.js +338 -0
  76. package/src/table/tr.js +319 -0
  77. package/src/tagPair/ext.js +145 -0
  78. package/src/tagPair/include.js +50 -0
  79. package/src/tagPair/index.js +126 -0
  80. package/src/transclude.js +843 -0
  81. package/tool/index.js +1202 -0
  82. package/util/base.js +17 -0
  83. package/util/debug.js +73 -0
  84. package/util/diff.js +76 -0
  85. package/util/lint.js +55 -0
  86. package/util/string.js +126 -0
  87. package/bundle/bundle.min.js +0 -38
  88. package/extensions/editor.css +0 -62
  89. package/extensions/editor.js +0 -328
  90. package/extensions/ui.css +0 -119
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ const hidden = require('../../mixin/hidden'),
4
+ {generateForSelf} = require('../../util/lint'),
5
+ Parser = require('../..'),
6
+ NowikiToken = require('.');
7
+
8
+ /**
9
+ * HTML注释,不可见
10
+ * @classdesc `{childNodes: [AstText]}`
11
+ */
12
+ class CommentToken extends hidden(NowikiToken) {
13
+ type = 'comment';
14
+ closed;
15
+
16
+ /** 内部wikitext */
17
+ get innerText() {
18
+ return String(this.firstChild);
19
+ }
20
+
21
+ /**
22
+ * @param {string} wikitext wikitext
23
+ * @param {boolean} closed 是否闭合
24
+ * @param {accum} accum
25
+ */
26
+ constructor(wikitext, closed = true, config = Parser.getConfig(), accum = []) {
27
+ super(wikitext, config, accum);
28
+ this.closed = closed;
29
+ Object.defineProperty(this, 'closed', {enumerable: false});
30
+ }
31
+
32
+ /** @override */
33
+ getPadding() {
34
+ return 4;
35
+ }
36
+
37
+ /** @override */
38
+ print() {
39
+ return super.print({pre: '<!--', post: this.closed ? '-->' : ''});
40
+ }
41
+
42
+ /**
43
+ * @override
44
+ * @param {number} start 起始位置
45
+ */
46
+ lint(start = this.getAbsoluteIndex()) {
47
+ return this.closed ? [] : [generateForSelf(this, {start}, 'unclosed HTML comment')];
48
+ }
49
+
50
+ /**
51
+ * @override
52
+ * @param {string} selector
53
+ */
54
+ toString(selector) {
55
+ if (!this.closed && this.nextSibling) {
56
+ Parser.error('自动闭合HTML注释', this);
57
+ this.closed = true;
58
+ }
59
+ return selector && this.matches(selector)
60
+ ? ''
61
+ : `<!--${String(this.firstChild)}${this.closed ? '-->' : ''}`;
62
+ }
63
+
64
+ /** @override */
65
+ cloneNode() {
66
+ return Parser.run(() => new CommentToken(String(this.firstChild), this.closed, this.getAttribute('config')));
67
+ }
68
+ }
69
+
70
+ Parser.classes.CommentToken = __filename;
71
+ module.exports = CommentToken;
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ const Parser = require('../..'),
4
+ NowikiToken = require('.');
5
+
6
+ /**
7
+ * :
8
+ * @classdesc `{childNodes: [AstText]}`
9
+ */
10
+ class DdToken extends NowikiToken {
11
+ type = 'dd';
12
+
13
+ /** 是否包含<dt> */
14
+ get dt() {
15
+ return String(this).includes(';');
16
+ }
17
+
18
+ /** 是否包含<ul> */
19
+ get ul() {
20
+ return String(this).includes('*');
21
+ }
22
+
23
+ /** 是否包含<ol> */
24
+ get ol() {
25
+ return String(this).includes('#');
26
+ }
27
+
28
+ /** 缩进数 */
29
+ get indent() {
30
+ return String(this).split(':').length - 1;
31
+ }
32
+
33
+ set indent(indent) {
34
+ if (this.type === 'dd') {
35
+ if (!Number.isInteger(indent)) {
36
+ this.typeError('set indent', 'Number');
37
+ } else if (indent < 0) {
38
+ throw new RangeError(`indent 应为自然数!${indent}`);
39
+ }
40
+ this.setText(':'.repeat(indent));
41
+ }
42
+ }
43
+
44
+ /**
45
+ * @override
46
+ * @param {string} str 新文本
47
+ * @throws `RangeError` 错误的列表语法
48
+ */
49
+ setText(str) {
50
+ const src = this.type === 'dd' ? ':' : ';:*#';
51
+ if (new RegExp(`[^${src}]`, 'u').test(str)) {
52
+ throw new RangeError(`${this.constructor.name} 仅能包含${[...src].map(c => `"${c}"`).join('、')}!`);
53
+ }
54
+ return super.setText(str);
55
+ }
56
+ }
57
+
58
+ Parser.classes.DdToken = __filename;
59
+ module.exports = DdToken;
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const hidden = require('../../mixin/hidden'),
4
+ Parser = require('../..'),
5
+ NowikiToken = require('.');
6
+
7
+ /**
8
+ * 状态开关
9
+ * @classdesc `{childNodes: [AstText]}`
10
+ */
11
+ class DoubleUnderscoreToken extends hidden(NowikiToken) {
12
+ type = 'double-underscore';
13
+
14
+ /** @override */
15
+ getPadding() {
16
+ return 2;
17
+ }
18
+
19
+ /** @override */
20
+ print() {
21
+ return super.print({pre: '__', post: '__'});
22
+ }
23
+
24
+ /**
25
+ * @override
26
+ * @param {string} selector
27
+ */
28
+ toString(selector) {
29
+ return selector && this.matches(selector) ? '' : `__${String(this.firstChild)}__`;
30
+ }
31
+
32
+ /**
33
+ * @param {string} word 状态开关名
34
+ * @param {accum} accum
35
+ */
36
+ constructor(word, config = Parser.getConfig(), accum = []) {
37
+ super(word, config, accum);
38
+ this.setAttribute('name', word.toLowerCase());
39
+ }
40
+
41
+ /** @override */
42
+ cloneNode() {
43
+ return Parser.run(() => new DoubleUnderscoreToken(String(this.firstChild), this.getAttribute('config')));
44
+ }
45
+
46
+ /**
47
+ * @override
48
+ * @throws `Error` 禁止修改
49
+ */
50
+ setText() {
51
+ throw new Error(`禁止修改 ${this.constructor.name}!`);
52
+ }
53
+ }
54
+
55
+ Parser.classes.DoubleUnderscoreToken = __filename;
56
+ module.exports = DoubleUnderscoreToken;
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ const Parser = require('../..'),
4
+ sol = require('../../mixin/sol'),
5
+ NowikiToken = require('.');
6
+
7
+ /**
8
+ * `<hr>`
9
+ * @classdesc `{childNodes: [AstText]}`
10
+ */
11
+ class HrToken extends sol(NowikiToken) {
12
+ type = 'hr';
13
+
14
+ /**
15
+ * @param {number} n 字符串长度
16
+ * @param {accum} accum
17
+ */
18
+ constructor(n, config = Parser.getConfig(), accum = []) {
19
+ super('-'.repeat(n), config, accum);
20
+ }
21
+
22
+ /** @override */
23
+ cloneNode() {
24
+ return Parser.run(() => new HrToken(String(this).length, this.getAttribute('config')));
25
+ }
26
+
27
+ /**
28
+ * @override
29
+ * @param {string} str 新文本
30
+ * @throws `RangeError` 错误的\<hr\>语法
31
+ */
32
+ setText(str) {
33
+ if (str.length < 4 || /[^-]/u.test(str)) {
34
+ throw new RangeError('<hr>总是写作不少于4个的连续"-"!');
35
+ }
36
+ return super.setText(str);
37
+ }
38
+ }
39
+
40
+ Parser.classes.HrToken = __filename;
41
+ module.exports = HrToken;
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const {generateForSelf} = require('../../util/lint'),
4
+ fixedToken = require('../../mixin/fixedToken'),
5
+ Parser = require('../..'),
6
+ AstText = require('../../lib/text'),
7
+ Token = require('..');
8
+
9
+ /**
10
+ * 纯文字Token,不会被解析
11
+ * @classdesc `{childNodes: [AstText]}`
12
+ */
13
+ class NowikiToken extends fixedToken(Token) {
14
+ type = 'ext-inner';
15
+
16
+ /**
17
+ * @param {string} wikitext wikitext
18
+ * @param {accum} accum
19
+ */
20
+ constructor(wikitext, config = Parser.getConfig(), accum = []) {
21
+ super(wikitext, config, true, accum);
22
+ }
23
+
24
+ /**
25
+ * @override
26
+ * @param {number} start 起始位置
27
+ */
28
+ lint(start = this.getAbsoluteIndex()) {
29
+ const {type, name} = this;
30
+ return type === 'ext-inner' && (name === 'templatestyles' || name === 'section') && String(this)
31
+ ? [generateForSelf(this, {start}, Parser.msg('nothing should be in <$1>', name))]
32
+ : super.lint(start);
33
+ }
34
+
35
+ /**
36
+ * @override
37
+ * @this {NowikiToken & {firstChild: AstText, constructor: typeof NowikiToken}}
38
+ */
39
+ cloneNode() {
40
+ const {constructor, firstChild: {data}, type} = this,
41
+ token = Parser.run(() => new constructor(data, this.getAttribute('config')));
42
+ token.type = type;
43
+ return token;
44
+ }
45
+
46
+ /**
47
+ * @override
48
+ * @param {string} str 新文本
49
+ */
50
+ setText(str) {
51
+ return super.setText(str, 0);
52
+ }
53
+ }
54
+
55
+ Parser.classes.NowikiToken = __filename;
56
+ module.exports = NowikiToken;
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ const sol = require('../../mixin/sol'),
4
+ Parser = require('../..'),
5
+ DdToken = require('./dd');
6
+
7
+ /**
8
+ * ;:*#
9
+ * @classdesc `{childNodes: [AstText]}`
10
+ */
11
+ class ListToken extends sol(DdToken) {
12
+ type = 'list';
13
+ }
14
+
15
+ Parser.classes.ListToken = __filename;
16
+ module.exports = ListToken;
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ const hidden = require('../../mixin/hidden'),
4
+ Parser = require('../..'),
5
+ NowikiToken = require('.');
6
+
7
+ /**
8
+ * `<noinclude>`和`</noinclude>`,不可进行任何更改
9
+ * @classdesc `{childNodes: [AstText]}`
10
+ */
11
+ class NoincludeToken extends hidden(NowikiToken) {
12
+ type = 'noinclude';
13
+
14
+ /**
15
+ * @override
16
+ * @param {string} str 新文本
17
+ * @throws `Error` 不可更改
18
+ */
19
+ setText(str) {
20
+ if (/^<\/?(?:(?:no|only)include|includeonly)(?:\s.*)?\/?>$/isu.test(String(this))) {
21
+ throw new Error(`${this.constructor.name} 不可更改文字内容!`);
22
+ }
23
+ return super.setText(str);
24
+ }
25
+ }
26
+
27
+ Parser.classes.NoincludeToken = __filename;
28
+ module.exports = NoincludeToken;
@@ -0,0 +1,69 @@
1
+ 'use strict';
2
+
3
+ const {generateForSelf} = require('../../util/lint'),
4
+ Parser = require('../..'),
5
+ AstText = require('../../lib/text'),
6
+ NowikiToken = require('.');
7
+
8
+ /**
9
+ * `<hr>`
10
+ * @classdesc `{childNodes: [AstText]}`
11
+ */
12
+ class QuoteToken extends NowikiToken {
13
+ type = 'quote';
14
+
15
+ /**
16
+ * @param {number} n 字符串长度
17
+ * @param {accum} accum
18
+ */
19
+ constructor(n, config = Parser.getConfig(), accum = []) {
20
+ super(`'`.repeat(n), config, accum);
21
+ this.setAttribute('name', String(n));
22
+ }
23
+
24
+ /**
25
+ * @override
26
+ * @this {AstText}
27
+ * @param {number} start 起始位置
28
+ */
29
+ lint(start = this.getAbsoluteIndex()) {
30
+ const {previousSibling, nextSibling} = this,
31
+ message = Parser.msg('lonely "$1"', `'`),
32
+ /** @type {LintError[]} */ errors = [];
33
+ let refError, wikitext;
34
+ if (previousSibling?.type === 'text' && previousSibling.data.endsWith(`'`)) {
35
+ refError = generateForSelf(this, {start}, message);
36
+ wikitext = String(this.getRootNode());
37
+ const {startIndex: endIndex, startLine: endLine, startCol: endCol} = refError,
38
+ [{length}] = previousSibling.data.match(/(?<!')'+$/u),
39
+ startIndex = start - length,
40
+ excerpt = wikitext.slice(startIndex, startIndex + 50);
41
+ errors.push({...refError, startIndex, endIndex, startCol: endCol - length, endLine, endCol, excerpt});
42
+ }
43
+ if (nextSibling?.type === 'text' && nextSibling.data[0] === `'`) {
44
+ refError ||= generateForSelf(this, {start}, message);
45
+ wikitext ||= String(this.getRootNode());
46
+ const {endIndex: startIndex, endLine: startLine, endCol: startCol} = refError,
47
+ [{length}] = nextSibling.data.match(/^'+/u),
48
+ endIndex = startIndex + length,
49
+ excerpt = wikitext.slice(Math.max(0, endIndex - 50), endIndex);
50
+ errors.push({...refError, startIndex, endIndex, startLine, startCol, endCol: startCol + length, excerpt});
51
+ }
52
+ return errors;
53
+ }
54
+
55
+ /**
56
+ * @override
57
+ * @param {string} str 新文本
58
+ * @throws `RangeError` 错误的单引号语法
59
+ */
60
+ setText(str) {
61
+ if (str === `''` || str === `'''` || str === `'''''`) {
62
+ return super.setText(str);
63
+ }
64
+ throw new RangeError(`${this.constructor.name} 的内部文本只能为连续 2/3/5 个"'"!`);
65
+ }
66
+ }
67
+
68
+ Parser.classes.QuoteToken = __filename;
69
+ module.exports = QuoteToken;
@@ -0,0 +1,64 @@
1
+ 'use strict';
2
+
3
+ const Parser = require('..'),
4
+ Token = require('.');
5
+
6
+ /**
7
+ * 嵌入时的`<onlyinclude>`
8
+ * @classdesc `{childNodes: ...AstText|Token}`
9
+ */
10
+ class OnlyincludeToken extends Token {
11
+ type = 'onlyinclude';
12
+
13
+ /** 内部wikitext */
14
+ get innerText() {
15
+ return this.text();
16
+ }
17
+
18
+ /**
19
+ * @param {string} inner 标签内部wikitext
20
+ * @param {accum} accum
21
+ */
22
+ constructor(inner, config = Parser.getConfig(), accum = []) {
23
+ super(inner, config, true, accum);
24
+ }
25
+
26
+ /**
27
+ * @override
28
+ * @param {string} selector
29
+ */
30
+ toString(selector) {
31
+ return selector && this.matches(selector) ? '' : `<onlyinclude>${super.toString(selector)}</onlyinclude>`;
32
+ }
33
+
34
+ /** @override */
35
+ getPadding() {
36
+ return 13;
37
+ }
38
+
39
+ /** @override */
40
+ print() {
41
+ return super.print({
42
+ pre: '<span class="wpb-ext">&lt;onlyinclude&gt;</span>',
43
+ post: '<span class="wpb-ext">&lt;/onlyinclude&gt;</span>',
44
+ });
45
+ }
46
+
47
+ /** @override */
48
+ isPlain() {
49
+ return true;
50
+ }
51
+
52
+ /** @override */
53
+ cloneNode() {
54
+ const cloned = this.cloneChildNodes();
55
+ return Parser.run(() => {
56
+ const token = new OnlyincludeToken(undefined, this.getAttribute('config'));
57
+ token.append(...cloned);
58
+ return token;
59
+ });
60
+ }
61
+ }
62
+
63
+ Parser.classes.OnlyincludeToken = __filename;
64
+ module.exports = OnlyincludeToken;
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ const {generateForChild} = require('../../util/lint'),
4
+ singleLine = require('../../mixin/singleLine'),
5
+ Parser = require('../..'),
6
+ Token = require('..'),
7
+ AtomToken = require('../atom');
8
+
9
+ /**
10
+ * `<inputbox>`
11
+ * @classdesc `{childNodes: ...AtomToken}`
12
+ */
13
+ class ParamTagToken extends Token {
14
+ type = 'ext-inner';
15
+
16
+ /**
17
+ * @param {string} wikitext wikitext
18
+ * @param {accum} accum
19
+ */
20
+ constructor(wikitext, config = Parser.getConfig(), accum = []) {
21
+ super(undefined, config, true, accum, {
22
+ SingleLineAtomToken: ':',
23
+ });
24
+ if (wikitext) {
25
+ const SingleLineAtomToken = singleLine(AtomToken);
26
+ this.append(
27
+ ...wikitext.split('\n').map(line => new SingleLineAtomToken(line, 'param-line', config, accum, {
28
+ AstText: ':',
29
+ })),
30
+ );
31
+ }
32
+ }
33
+
34
+ /**
35
+ * @override
36
+ * @param {string} selector
37
+ */
38
+ toString(selector) {
39
+ return super.toString(selector, '\n');
40
+ }
41
+
42
+ /** @override */
43
+ text() {
44
+ return super.text('\n');
45
+ }
46
+
47
+ /** @override */
48
+ getGaps() {
49
+ return 1;
50
+ }
51
+
52
+ /** @override */
53
+ print() {
54
+ return super.print({sep: '\n'});
55
+ }
56
+
57
+ /**
58
+ * @override
59
+ * @param {number} start 起始位置
60
+ */
61
+ lint(start = this.getAbsoluteIndex()) {
62
+ let /** @type {{top: number, left: number}} */ rect;
63
+ return this.childNodes.filter(child => {
64
+ const {childNodes} = child,
65
+ i = childNodes.findIndex(({type}) => type !== 'text'),
66
+ str = (i >= 0 ? childNodes.slice(0, i).map(String).join('') : String(child)).trim();
67
+ return str && !(i >= 0 ? /^[a-z]+(?:\[\])?\s*(?:=|$)/iu : /^[a-z]+(?:\[\])?\s*=/iu).test(str);
68
+ }).map(child => {
69
+ rect ||= {start, ...this.getRootNode().posFromIndex(start)};
70
+ return generateForChild(child, rect, Parser.msg('invalid parameter of $1', this.name));
71
+ });
72
+ }
73
+
74
+ /**
75
+ * @override
76
+ * @this {ParamTagToken & {constructor: typeof ParamTagToken}}
77
+ */
78
+ cloneNode() {
79
+ const cloned = this.cloneChildNodes();
80
+ return Parser.run(() => {
81
+ const token = new this.constructor(undefined, this.getAttribute('config'));
82
+ token.append(...cloned);
83
+ return token;
84
+ });
85
+ }
86
+ }
87
+
88
+ Parser.classes.ParamTagToken = __filename;
89
+ module.exports = ParamTagToken;
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ const parseBrackets = require('../../parser/brackets'),
4
+ singleLine = require('../../mixin/singleLine'),
5
+ Parser = require('../..'),
6
+ ParamTagToken = require('.'),
7
+ AtomToken = require('../atom');
8
+
9
+ /**
10
+ * `<inputbox>`
11
+ * @classdesc `{childNodes: ...SingleLineAtomToken}`
12
+ */
13
+ class InputboxToken extends ParamTagToken {
14
+ name = 'inputbox';
15
+
16
+ /**
17
+ * @param {string} wikitext wikitext
18
+ * @param {accum} accum
19
+ */
20
+ constructor(wikitext, config = Parser.getConfig(), accum = []) {
21
+ super(undefined, config, accum);
22
+ wikitext = parseBrackets(wikitext, config, accum);
23
+ accum.splice(accum.indexOf(this), 1);
24
+ accum.push(this);
25
+ if (wikitext) {
26
+ const SingleLineAtomToken = singleLine(AtomToken);
27
+ this.append(...wikitext.split('\n').map(line => new SingleLineAtomToken(line, 'param-line', config, accum, {
28
+ AstText: ':', ArgToken: ':', TranscludeToken: ':',
29
+ })));
30
+ }
31
+ }
32
+ }
33
+
34
+ Parser.classes.InputboxToken = __filename;
35
+ module.exports = InputboxToken;