wikiparser-node 0.7.0-m → 0.7.1-b

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 (78) hide show
  1. package/bundle/bundle.min.js +40 -0
  2. package/extensions/editor.css +60 -0
  3. package/extensions/editor.js +324 -0
  4. package/extensions/ui.css +119 -0
  5. package/package.json +11 -9
  6. package/config/default.json +0 -832
  7. package/config/llwiki.json +0 -595
  8. package/config/minimum.json +0 -142
  9. package/config/moegirl.json +0 -684
  10. package/config/zhwiki.json +0 -803
  11. package/index.js +0 -73
  12. package/lib/element.js +0 -137
  13. package/lib/node.js +0 -226
  14. package/lib/text.js +0 -124
  15. package/lib/title.js +0 -53
  16. package/mixin/hidden.js +0 -18
  17. package/parser/brackets.js +0 -119
  18. package/parser/commentAndExt.js +0 -61
  19. package/parser/converter.js +0 -45
  20. package/parser/externalLinks.js +0 -32
  21. package/parser/hrAndDoubleUnderscore.js +0 -37
  22. package/parser/html.js +0 -41
  23. package/parser/links.js +0 -93
  24. package/parser/list.js +0 -58
  25. package/parser/magicLinks.js +0 -40
  26. package/parser/quotes.js +0 -63
  27. package/parser/table.js +0 -113
  28. package/src/arg.js +0 -89
  29. package/src/atom/hidden.js +0 -11
  30. package/src/atom/index.js +0 -26
  31. package/src/attribute.js +0 -253
  32. package/src/attributes.js +0 -150
  33. package/src/charinsert.js +0 -41
  34. package/src/converter.js +0 -70
  35. package/src/converterFlags.js +0 -97
  36. package/src/converterRule.js +0 -75
  37. package/src/extLink.js +0 -60
  38. package/src/gallery.js +0 -101
  39. package/src/hasNowiki/index.js +0 -32
  40. package/src/hasNowiki/pre.js +0 -28
  41. package/src/heading.js +0 -83
  42. package/src/html.js +0 -133
  43. package/src/imageParameter.js +0 -106
  44. package/src/imagemap.js +0 -140
  45. package/src/imagemapLink.js +0 -29
  46. package/src/index.js +0 -389
  47. package/src/link/category.js +0 -13
  48. package/src/link/file.js +0 -125
  49. package/src/link/galleryImage.js +0 -62
  50. package/src/link/index.js +0 -115
  51. package/src/magicLink.js +0 -68
  52. package/src/nested/choose.js +0 -23
  53. package/src/nested/combobox.js +0 -22
  54. package/src/nested/index.js +0 -69
  55. package/src/nested/references.js +0 -22
  56. package/src/nowiki/comment.js +0 -47
  57. package/src/nowiki/dd.js +0 -13
  58. package/src/nowiki/doubleUnderscore.js +0 -26
  59. package/src/nowiki/hr.js +0 -22
  60. package/src/nowiki/index.js +0 -34
  61. package/src/nowiki/list.js +0 -13
  62. package/src/nowiki/noinclude.js +0 -14
  63. package/src/nowiki/quote.js +0 -55
  64. package/src/onlyinclude.js +0 -39
  65. package/src/paramTag/index.js +0 -66
  66. package/src/parameter.js +0 -97
  67. package/src/syntax.js +0 -23
  68. package/src/table/index.js +0 -46
  69. package/src/table/td.js +0 -119
  70. package/src/table/tr.js +0 -74
  71. package/src/tagPair/ext.js +0 -118
  72. package/src/tagPair/include.js +0 -36
  73. package/src/tagPair/index.js +0 -76
  74. package/src/transclude.js +0 -323
  75. package/util/base.js +0 -17
  76. package/util/diff.js +0 -76
  77. package/util/lint.js +0 -54
  78. package/util/string.js +0 -60
package/parser/table.js DELETED
@@ -1,113 +0,0 @@
1
- 'use strict';
2
-
3
- const Parser = require('..'),
4
- AstText = require('../lib/text'),
5
- Token = require('../src'),
6
- TableToken = require('../src/table'),
7
- TrToken = require('../src/table/tr'),
8
- TdToken = require('../src/table/td'),
9
- DdToken = require('../src/nowiki/dd');
10
-
11
- /**
12
- * 解析表格,注意`tr`和`td`包含开头的换行
13
- * @param {Token & {firstChild: AstText}} root 根节点
14
- * @param {accum} accum
15
- */
16
- const parseTable = ({firstChild: {data}, type, name}, config = Parser.getConfig(), accum = []) => {
17
- const /** @type {TrToken[]} */ stack = [],
18
- lines = data.split('\n');
19
- let out = type === 'root' || type === 'parameter-value' || type === 'ext-inner' && name === 'poem'
20
- ? ''
21
- : `\n${lines.shift()}`;
22
-
23
- /**
24
- * 向表格中插入纯文本
25
- * @param {string} str 待插入的文本
26
- * @param {TrToken} top 当前解析的表格或表格行
27
- */
28
- const push = (str, top) => {
29
- if (!top) {
30
- out += str;
31
- return;
32
- }
33
- const /** @type {Token}} */ {lastChild} = top;
34
- if (lastChild.constructor === Token) {
35
- lastChild.setText(String(lastChild) + str);
36
- } else {
37
- const token = new Token(str, config, true, accum);
38
- token.type = 'table-inter';
39
- top.insertAt(token.setAttribute('stage', 3));
40
- }
41
- };
42
- for (const outLine of lines) {
43
- let top = stack.pop();
44
- const [spaces] = /^(?:\s|\0\d+c\x7F)*/u.exec(outLine),
45
- line = outLine.slice(spaces.length),
46
- matchesStart = /^(:*)((?:\s|\0\d+c\x7F)*)(\{\||\{(?:\0\d+c\x7F)*\0\d+!\x7F|\0\d+\{\x7F)(.*)$/u.exec(line);
47
- if (matchesStart) {
48
- while (top && top.type !== 'td') {
49
- top = stack.pop();
50
- }
51
- const [, indent, moreSpaces, tableSyntax, attr] = matchesStart;
52
- if (indent) {
53
- new DdToken(indent, config, accum);
54
- }
55
- push(`\n${spaces}${indent && `\0${accum.length - 1}d\x7F`}${moreSpaces}\0${accum.length}b\x7F`, top);
56
- const table = new TableToken(tableSyntax, attr, config, accum);
57
- stack.push(...top ? [top] : [], table);
58
- continue;
59
- } else if (!top) {
60
- out += `\n${outLine}`;
61
- continue;
62
- }
63
- const matches = // eslint-disable-line operator-linebreak
64
- /^(?:(\|\}|\0\d+!\x7F\}|\0\d+\}\x7F)|(\|-+|\0\d+!\x7F-+|\0\d+-\x7F-*)(?!-)|(!|(?:\||\0\d+!\x7F)\+?))(.*)$/u
65
- .exec(line);
66
- if (!matches) {
67
- push(`\n${outLine}`, top);
68
- stack.push(...top ? [top] : []);
69
- continue;
70
- }
71
- const [, closing, row, cell, attr] = matches;
72
- if (closing) {
73
- while (!(top instanceof TableToken)) {
74
- top = stack.pop();
75
- }
76
- top.close(`\n${spaces}${closing}`, true);
77
- push(attr, stack.at(-1));
78
- } else if (row) {
79
- if (top.type === 'td') {
80
- top = stack.pop();
81
- }
82
- if (top.type === 'tr') {
83
- top = stack.pop();
84
- }
85
- const tr = new TrToken(`\n${spaces}${row}`, attr, config, accum);
86
- stack.push(top, tr);
87
- top.insertAt(tr);
88
- } else {
89
- if (top.type === 'td') {
90
- top = stack.pop();
91
- }
92
- const regex = cell === '!'
93
- ? /!!|(?:\||\0\d+!\x7F){2}|\0\d+\+\x7F/gu
94
- : /(?:\||\0\d+!\x7F){2}|\0\d+\+\x7F/gu;
95
- let mt = regex.exec(attr),
96
- lastIndex = 0,
97
- lastSyntax = `\n${spaces}${cell}`;
98
- while (mt) {
99
- const td = new TdToken(lastSyntax, attr.slice(lastIndex, mt.index), config, accum);
100
- top.insertAt(td);
101
- ({lastIndex} = regex);
102
- [lastSyntax] = mt;
103
- mt = regex.exec(attr);
104
- }
105
- const td = new TdToken(lastSyntax, attr.slice(lastIndex), config, accum);
106
- stack.push(top, td);
107
- top.insertAt(td);
108
- }
109
- }
110
- return out.slice(1);
111
- };
112
-
113
- module.exports = parseTable;
package/src/arg.js DELETED
@@ -1,89 +0,0 @@
1
- 'use strict';
2
-
3
- const {text} = require('../util/string'),
4
- {generateForSelf, generateForChild} = require('../util/lint'),
5
- Parser = require('..'),
6
- Token = require('.');
7
-
8
- /**
9
- * `{{{}}}`包裹的参数
10
- * @classdesc `{childNodes: [AtomToken, ?Token, ...HiddenToken]}`
11
- */
12
- class ArgToken extends Token {
13
- type = 'arg';
14
-
15
- /** default */
16
- get default() {
17
- return this.childNodes[1]?.text() ?? false;
18
- }
19
-
20
- /**
21
- * @param {string[]} parts 以'|'分隔的各部分
22
- * @param {accum} accum
23
- * @complexity `n`
24
- */
25
- constructor(parts, config = Parser.getConfig(), accum = []) {
26
- super(undefined, config, true, accum, {
27
- });
28
- for (let i = 0; i < parts.length; i++) {
29
- if (i === 0 || i > 1) {
30
- const AtomToken = i === 0 ? require('./atom') : require('./atom/hidden');
31
- const token = new AtomToken(parts[i], i === 0 ? 'arg-name' : undefined, config, accum, {
32
- });
33
- super.insertAt(token);
34
- } else {
35
- const token = new Token(parts[i], config, true, accum);
36
- token.type = 'arg-default';
37
- super.insertAt(token.setAttribute('stage', 2));
38
- }
39
- }
40
- }
41
-
42
- /**
43
- * @override
44
- */
45
- toString(selector) {
46
- return `{{{${super.toString(selector, '|')}}}}`;
47
- }
48
-
49
- /**
50
- * @override
51
- * @returns {string}
52
- */
53
- text() {
54
- return `{{{${text(this.childNodes.slice(0, 2), '|')}}}}`;
55
- }
56
-
57
- /** @override */
58
- getPadding() {
59
- return 3;
60
- }
61
-
62
- /** @override */
63
- getGaps() {
64
- return 1;
65
- }
66
-
67
- /**
68
- * @override
69
- * @param {number} start 起始位置
70
- * @returns {LintError[]}
71
- */
72
- lint(start = 0) {
73
- if (!this.getAttribute('include')) {
74
- return [generateForSelf(this, {start}, '未预期的模板参数')];
75
- }
76
- const {childNodes: [argName, argDefault, ...rest]} = this,
77
- errors = argName.lint(start + 3);
78
- if (argDefault) {
79
- errors.push(...argDefault.lint(start + 4 + String(argName).length));
80
- }
81
- if (rest.length > 0) {
82
- const rect = {start, ...this.getRootNode().posFromIndex(start)};
83
- errors.push(...rest.map(child => generateForChild(child, rect, '三重括号内的不可见部分')));
84
- }
85
- return errors;
86
- }
87
- }
88
-
89
- module.exports = ArgToken;
@@ -1,11 +0,0 @@
1
- 'use strict';
2
-
3
- const hidden = require('../../mixin/hidden'),
4
- AtomToken = require('.');
5
-
6
- /** 不可见的节点 */
7
- class HiddenToken extends hidden(AtomToken) {
8
- type = 'hidden';
9
- }
10
-
11
- module.exports = HiddenToken;
package/src/atom/index.js DELETED
@@ -1,26 +0,0 @@
1
- 'use strict';
2
-
3
- const Parser = require('../..'),
4
- Token = require('..');
5
-
6
- /**
7
- * 不会被继续解析的plain Token
8
- * @classdesc `{childNodes: ...AstText|Token}`
9
- */
10
- class AtomToken extends Token {
11
- type = 'plain';
12
-
13
- /**
14
- * @param {string} wikitext wikitext
15
- * @param {string|undefined} type Token.type
16
- * @param {accum} accum
17
- */
18
- constructor(wikitext, type, config = Parser.getConfig(), accum = [], acceptable = undefined) {
19
- super(wikitext, config, true, accum, acceptable);
20
- if (type) {
21
- this.type = type;
22
- }
23
- }
24
- }
25
-
26
- module.exports = AtomToken;
package/src/attribute.js DELETED
@@ -1,253 +0,0 @@
1
- 'use strict';
2
-
3
- const {generateForChild} = require('../util/lint'),
4
- {removeComment} = require('../util/string'),
5
- Parser = require('..'),
6
- Token = require('.'),
7
- AtomToken = require('./atom');
8
-
9
- const commonHtmlAttrs = new Set([
10
- 'id',
11
- 'class',
12
- 'style',
13
- 'lang',
14
- 'dir',
15
- 'title',
16
- 'tabindex',
17
- 'aria-describedby',
18
- 'aria-flowto',
19
- 'aria-hidden',
20
- 'aria-label',
21
- 'aria-labelledby',
22
- 'aria-owns',
23
- 'role',
24
- 'about',
25
- 'property',
26
- 'resource',
27
- 'datatype',
28
- 'typeof',
29
- 'itemid',
30
- 'itemprop',
31
- 'itemref',
32
- 'itemscope',
33
- 'itemtype',
34
- ]),
35
- blockAttrs = new Set(['align']),
36
- citeAttrs = new Set(['cite']),
37
- citeAndAttrs = new Set(['cite', 'datetime']),
38
- widthAttrs = new Set(['width']),
39
- tdAttrs = new Set(
40
- ['align', 'valign', 'abbr', 'axis', 'headers', 'scope', 'rowspan', 'colspan', 'width', 'height', 'bgcolor'],
41
- ),
42
- typeAttrs = new Set(['type']),
43
- htmlAttrs = {
44
- div: blockAttrs,
45
- h1: blockAttrs,
46
- h2: blockAttrs,
47
- h3: blockAttrs,
48
- h4: blockAttrs,
49
- h5: blockAttrs,
50
- h6: blockAttrs,
51
- blockquote: citeAttrs,
52
- q: citeAttrs,
53
- p: blockAttrs,
54
- br: new Set(['clear']),
55
- pre: widthAttrs,
56
- ins: citeAndAttrs,
57
- del: citeAndAttrs,
58
- ul: typeAttrs,
59
- ol: new Set(['type', 'start', 'reversed']),
60
- li: new Set(['type', 'value']),
61
- table: new Set(
62
- ['summary', 'width', 'border', 'frame', 'rules', 'cellspacing', 'cellpadding', 'align', 'bgcolor'],
63
- ),
64
- caption: blockAttrs,
65
- tr: new Set(['bgcolor', 'align', 'valign']),
66
- td: tdAttrs,
67
- th: tdAttrs,
68
- img: new Set(['alt', 'src', 'width', 'height', 'srcset']),
69
- font: new Set(['size', 'color', 'face']),
70
- hr: widthAttrs,
71
- rt: new Set(['rbspan']),
72
- data: new Set(['value']),
73
- time: new Set(['datetime']),
74
- meta: new Set(['itemprop', 'content']),
75
- link: new Set(['itemprop', 'href', 'title']),
76
- gallery: new Set(['mode', 'showfilename', 'caption', 'perrow', 'widths', 'heights', 'showthumbnails', 'type']),
77
- poem: new Set(['compact', 'align']),
78
- categorytree: new Set(['align', 'hideroot', 'onlyroot', 'depth', 'mode', 'hideprefix']),
79
- combooption: new Set(['name', 'for', 'inline', 'align']),
80
- },
81
- empty = new Set(),
82
- extAttrs = {
83
- nowiki: empty,
84
- indicator: new Set(['name']),
85
- langconvert: new Set(['from', 'to']),
86
- ref: new Set(['group', 'name', 'extends', 'follow', 'dir']),
87
- references: new Set(['group', 'responsive']),
88
- charinsert: new Set(['label']),
89
- choose: new Set(['uncached', 'before', 'after']),
90
- option: new Set(['weight']),
91
- imagemap: empty,
92
- inputbox: empty,
93
- templatestyles: new Set(['src', 'wrapper']),
94
- dynamicpagelist: empty,
95
- poll: new Set(['id', 'show-results-before-voting']),
96
- sm2: typeAttrs,
97
- flashmp3: typeAttrs,
98
- tab: new Set([
99
- 'nested',
100
- 'name',
101
- 'index',
102
- 'class',
103
- 'block',
104
- 'inline',
105
- 'openname',
106
- 'closename',
107
- 'collapsed',
108
- 'dropdown',
109
- 'style',
110
- 'bgcolor',
111
- 'container',
112
- 'id',
113
- 'title',
114
- ]),
115
- tabs: new Set(['plain', 'class', 'container', 'id', 'title', 'style']),
116
- combobox: new Set(['placeholder', 'value', 'id', 'class', 'text', 'dropdown', 'style']),
117
- },
118
- insecureStyle = new RegExp(
119
- `${
120
- 'expression'
121
- }|${
122
- '(?:filter|accelerator|-o-link(?:-source)?|-o-replace)\\s*:'
123
- }|${
124
- '(?:url|image(?:-set)?)\\s*\\('
125
- }|${
126
- 'attr\\s*\\([^)]+[\\s,]url'
127
- }`,
128
- 'u',
129
- );
130
-
131
- /**
132
- * 扩展和HTML标签属性
133
- * @classdesc `{childNodes: [AtomToken, Token|AtomToken]}`
134
- */
135
- class AttributeToken extends Token {
136
- #equal;
137
- #quotes;
138
-
139
- /** 引号是否匹配 */
140
- get balanced() {
141
- return !this.#equal || this.#quotes[0] === this.#quotes[1];
142
- }
143
-
144
- /** getValue()的getter */
145
- get value() {
146
- return this.getValue();
147
- }
148
-
149
- /**
150
- * @param {'ext-attr'|'html-attr'|'table-attr'} type 标签类型
151
- * @param {string} key 属性名
152
- * @param {string} equal 等号
153
- * @param {string} value 属性值
154
- * @param {string[]} quotes 引号
155
- * @param {accum} accum
156
- */
157
- constructor(type, key, equal = '', value = '', quotes = [], config = Parser.getConfig(), accum = []) {
158
- const keyToken = new AtomToken(key, 'attr-key', config, accum, {
159
- }),
160
- valueToken = key === 'title'
161
- ? new Token(value, config, true, accum, {
162
- }).setAttribute('type', 'attr-value').setAttribute('stage', Parser.MAX_STAGE - 1)
163
- : new AtomToken(value, 'attr-value', config, accum, {
164
- });
165
- super(undefined, config, true, accum);
166
- this.type = type;
167
- this.append(keyToken, valueToken);
168
- this.#equal = equal;
169
- this.#quotes = quotes;
170
- this.setAttribute('name', removeComment(key).trim().toLowerCase());
171
- }
172
-
173
- /** @override */
174
- afterBuild() {
175
- if (this.#equal.includes('\0')) {
176
- this.#equal = this.getAttribute('buildFromStr')(this.#equal, 'string');
177
- }
178
- this.setAttribute('name', this.firstChild.text().trim().toLowerCase());
179
- }
180
-
181
- /**
182
- * @override
183
- * @returns {string}
184
- */
185
- toString(selector) {
186
- const [quoteStart = '', quoteEnd = ''] = this.#quotes;
187
- return this.#equal
188
- ? `${super.toString(selector, `${this.#equal}${quoteStart}`)}${quoteEnd}`
189
- : this.firstChild.toString(selector);
190
- }
191
-
192
- /**
193
- * @override
194
- * @returns {string}
195
- */
196
- text() {
197
- return this.#equal ? `${super.text(`${this.#equal.trim()}"`)}"` : this.firstChild.text();
198
- }
199
-
200
- /** @override */
201
- getGaps() {
202
- return this.#equal ? this.#equal.length + (this.#quotes[0]?.length ?? 0) : 0;
203
- }
204
-
205
- /** @override */
206
- print() {
207
- const [quoteStart = '', quoteEnd = ''] = this.#quotes;
208
- return this.#equal ? super.print({sep: `${this.#equal}${quoteStart}`, post: quoteEnd}) : super.print();
209
- }
210
-
211
- /**
212
- * @override
213
- * @param {number} start 起始位置
214
- */
215
- lint(start = 0) {
216
- const errors = super.lint(start),
217
- {balanced, firstChild, lastChild, type, name, parentNode, value} = this,
218
- tagName = parentNode?.name;
219
- let rect;
220
- if (!balanced) {
221
- const root = this.getRootNode();
222
- rect = {start, ...root.posFromIndex(start)};
223
- const e = generateForChild(lastChild, rect, '未闭合的引号', 'warning'),
224
- startIndex = e.startIndex - 1,
225
- startCol = e.startCol - 1;
226
- errors.push({...e, startIndex, startCol, excerpt: String(root).slice(startIndex, startIndex + 50)});
227
- }
228
- if (!/\{\{[^{]+\}\}/u.test(name) && (
229
- type === 'ext-attr' && !(tagName in htmlAttrs) && extAttrs[tagName] && !extAttrs[tagName].has(name)
230
- || (type === 'html-attr' || type === 'table-attr' || tagName in htmlAttrs) && !htmlAttrs[tagName]?.has(name)
231
- && !/^(?:xmlns:[\w:.-]+|data-[^:]*)$/u.test(name)
232
- && (tagName === 'meta' || tagName === 'link' || !commonHtmlAttrs.has(name))
233
- )) {
234
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
235
- errors.push(generateForChild(firstChild, rect, '非法的属性名'));
236
- } else if (name === 'style' && typeof value === 'string' && insecureStyle.test(value)) {
237
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
238
- errors.push(generateForChild(lastChild, rect, '不安全的样式'));
239
- }
240
- return errors;
241
- }
242
-
243
- /** 获取属性值 */
244
- getValue() {
245
- if (this.#equal) {
246
- const value = this.lastChild.text();
247
- return value;
248
- }
249
- return true;
250
- }
251
- }
252
-
253
- module.exports = AttributeToken;
package/src/attributes.js DELETED
@@ -1,150 +0,0 @@
1
- 'use strict';
2
-
3
- const {generateForSelf, generateForChild} = require('../util/lint'),
4
- {removeComment} = require('../util/string'),
5
- Parser = require('..'),
6
- Token = require('.'),
7
- AtomToken = require('./atom'),
8
- AttributeToken = require('./attribute');
9
-
10
- /**
11
- * 扩展和HTML标签属性
12
- * @classdesc `{childNodes: ...AtomToken|AttributeToken}`
13
- */
14
- class AttributesToken extends Token {
15
- /**
16
- * @param {string} attr 标签属性
17
- * @param {'ext-attrs'|'html-attrs'|'table-attrs'} type 标签类型
18
- * @param {string} name 标签名
19
- * @param {accum} accum
20
- */
21
- constructor(attr, type, name, config = Parser.getConfig(), accum = []) {
22
- super(undefined, config, true, accum, {
23
- });
24
- this.type = type;
25
- this.setAttribute('name', name);
26
- if (attr) {
27
- const regex = new RegExp(
28
- `([^\\s/](?:(?!\0\\d+~\x7F)[^\\s/=])*)` // 属性名
29
- + '(?:'
30
- + '((?:\\s|\0\\d+c\x7F)*' // `=`前的空白字符
31
- + '(?:=|\0\\d+~\x7F)' // `=`
32
- + '(?:\\s|\0\\d+c\x7F)*)' // `=`后的空白字符
33
- + `(?:(["'])(.*?)(\\3|$)|(\\S*))` // 属性值
34
- + ')?',
35
- 'gsu',
36
- );
37
- let out = '',
38
- mt = regex.exec(attr),
39
- lastIndex = 0;
40
- const insertDirty = /** 插入无效属性 */ () => {
41
- if (out) {
42
- super.insertAt(new AtomToken(out, `${type.slice(0, -1)}-dirty`, config, accum, {
43
- }));
44
- out = '';
45
- }
46
- };
47
- while (mt) {
48
- const {index, 0: full, 1: key, 2: equal, 3: quoteStart, 4: quoted, 5: quoteEnd, 6: unquoted} = mt;
49
- out += attr.slice(lastIndex, index);
50
- if (/^(?:[\w:]|\0\d+[t!~{}+-]\x7F)(?:[\w:.-]|\0\d+[t!~{}+-]\x7F)*$/u.test(removeComment(key).trim())) {
51
- const value = quoted ?? unquoted,
52
- quotes = [quoteStart, quoteEnd],
53
- token = new AttributeToken(type.slice(0, -1), key, equal, value, quotes, config, accum);
54
- insertDirty();
55
- super.insertAt(token);
56
- } else {
57
- out += full;
58
- }
59
- ({lastIndex} = regex);
60
- mt = regex.exec(attr);
61
- }
62
- out += attr.slice(lastIndex);
63
- insertDirty();
64
- }
65
- }
66
-
67
- /**
68
- * @override
69
- * @this {AttributesToken & {parentNode: TdToken}}
70
- */
71
- afterBuild() {
72
- const TdToken = require('./table/td');
73
- if (this.type === 'table-attrs') {
74
- this.setAttribute('name', this.parentNode?.subtype === 'caption' ? 'caption' : this.parentNode?.type);
75
- }
76
- }
77
-
78
- /**
79
- * 所有指定属性名的AttributeToken
80
- * @param {string} key 属性名
81
- * @returns {AttributeToken[]}
82
- */
83
- getAttrTokens(key) {
84
- return this.childNodes.filter(
85
- child => child instanceof AttributeToken && child.name === key.toLowerCase().trim(),
86
- );
87
- }
88
-
89
- /**
90
- * 制定属性名的最后一个AttributeToken
91
- * @param {string} key 属性名
92
- */
93
- getAttrToken(key) {
94
- const tokens = this.getAttrTokens(key);
95
- return tokens.at(-1);
96
- }
97
-
98
- /**
99
- * 获取标签属性
100
- * @param {string} key 属性键
101
- */
102
- getAttr(key) {
103
- return this.getAttrToken(key)?.getValue();
104
- }
105
-
106
- /**
107
- * @override
108
- * @this {AttributesToken & {parentNode: HtmlToken}}
109
- * @param {number} start 起始位置
110
- */
111
- lint(start = 0) {
112
- const HtmlToken = require('./html');
113
- const errors = super.lint(start),
114
- {parentNode: {closing}, length, childNodes} = this,
115
- /** @type {Record<string, AttributeToken[]>} */ attrs = {},
116
- /** @type {Set<string>} */ duplicated = new Set();
117
- let rect;
118
- if (closing && this.text().trim()) {
119
- rect = {start, ...this.getRootNode().posFromIndex(start)};
120
- errors.push(generateForSelf(this, rect, '位于闭合标签的属性'));
121
- }
122
- for (let i = 0; i < length; i++) {
123
- const /** @type {AtomToken|AttributeToken} */ attr = childNodes[i];
124
- if (attr instanceof AtomToken && attr.text().trim()) {
125
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
126
- errors.push({
127
- ...generateForChild(attr, rect, '包含无效属性'),
128
- excerpt: childNodes.slice(i).map(String).join('').slice(0, 50),
129
- });
130
- } else if (attr instanceof AttributeToken) {
131
- const {name} = attr;
132
- if (name in attrs) {
133
- duplicated.add(name);
134
- attrs[name].push(attr);
135
- } else if (name !== 'class') {
136
- attrs[name] = [attr];
137
- }
138
- }
139
- }
140
- if (duplicated.size > 0) {
141
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
142
- for (const key of duplicated) {
143
- errors.push(...attrs[key].map(attr => generateForChild(attr, rect, `重复的${key}属性`)));
144
- }
145
- }
146
- return errors;
147
- }
148
- }
149
-
150
- module.exports = AttributesToken;
package/src/charinsert.js DELETED
@@ -1,41 +0,0 @@
1
- 'use strict';
2
-
3
- const Parser = require('..'),
4
- Token = require('.'),
5
- HasNowikiToken = require('./hasNowiki');
6
-
7
- /**
8
- * `<charinsert>`
9
- * @classdesc `{childNodes: [...HasNowikiToken]}`
10
- */
11
- class CharinsertToken extends Token {
12
- type = 'ext-inner';
13
- name = 'charinsert';
14
-
15
- /**
16
- * @param {string} wikitext wikitext
17
- * @param {accum} accum
18
- */
19
- constructor(wikitext, config = Parser.getConfig(), accum = []) {
20
- super(undefined, config, true, accum, {
21
- });
22
- const SingleLineHasNowikiToken = HasNowikiToken;
23
- this.append(
24
- ...wikitext.split('\n').map(str => new SingleLineHasNowikiToken(str, 'charinsert-line', config, accum)),
25
- );
26
- }
27
-
28
- /**
29
- * @override
30
- */
31
- toString(selector) {
32
- return super.toString(selector, '\n');
33
- }
34
-
35
- /** @override */
36
- getGaps() {
37
- return 1;
38
- }
39
- }
40
-
41
- module.exports = CharinsertToken;