wikiparser-node 0.10.0 → 0.11.0-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 (93) hide show
  1. package/README.md +44 -32
  2. package/bundle/bundle.min.js +38 -0
  3. package/config/.schema.json +1 -19
  4. package/config/default.json +1 -2
  5. package/config/llwiki.json +1 -36
  6. package/config/minimum.json +135 -0
  7. package/config/moegirl.json +1 -45
  8. package/config/zhwiki.json +1 -467
  9. package/extensions/base.js +154 -0
  10. package/extensions/editor.css +63 -0
  11. package/extensions/editor.js +183 -0
  12. package/extensions/highlight.js +40 -0
  13. package/extensions/ui.css +119 -0
  14. package/i18n/zh-hans.json +1 -1
  15. package/i18n/zh-hant.json +1 -1
  16. package/package.json +16 -11
  17. package/index.js +0 -333
  18. package/lib/element.js +0 -611
  19. package/lib/node.js +0 -770
  20. package/lib/ranges.js +0 -130
  21. package/lib/text.js +0 -263
  22. package/lib/title.js +0 -83
  23. package/mixin/attributeParent.js +0 -117
  24. package/mixin/fixedToken.js +0 -40
  25. package/mixin/hidden.js +0 -21
  26. package/mixin/singleLine.js +0 -31
  27. package/mixin/sol.js +0 -54
  28. package/parser/brackets.js +0 -126
  29. package/parser/commentAndExt.js +0 -59
  30. package/parser/converter.js +0 -46
  31. package/parser/externalLinks.js +0 -33
  32. package/parser/hrAndDoubleUnderscore.js +0 -49
  33. package/parser/html.js +0 -42
  34. package/parser/links.js +0 -94
  35. package/parser/list.js +0 -59
  36. package/parser/magicLinks.js +0 -41
  37. package/parser/quotes.js +0 -64
  38. package/parser/selector.js +0 -177
  39. package/parser/table.js +0 -114
  40. package/src/arg.js +0 -207
  41. package/src/atom/hidden.js +0 -13
  42. package/src/atom/index.js +0 -43
  43. package/src/attribute.js +0 -470
  44. package/src/attributes.js +0 -453
  45. package/src/charinsert.js +0 -97
  46. package/src/converter.js +0 -176
  47. package/src/converterFlags.js +0 -284
  48. package/src/converterRule.js +0 -256
  49. package/src/extLink.js +0 -180
  50. package/src/gallery.js +0 -149
  51. package/src/hasNowiki/index.js +0 -44
  52. package/src/hasNowiki/pre.js +0 -40
  53. package/src/heading.js +0 -134
  54. package/src/html.js +0 -254
  55. package/src/imageParameter.js +0 -303
  56. package/src/imagemap.js +0 -199
  57. package/src/imagemapLink.js +0 -41
  58. package/src/index.js +0 -932
  59. package/src/link/category.js +0 -44
  60. package/src/link/file.js +0 -287
  61. package/src/link/galleryImage.js +0 -120
  62. package/src/link/index.js +0 -388
  63. package/src/magicLink.js +0 -149
  64. package/src/nested/choose.js +0 -24
  65. package/src/nested/combobox.js +0 -23
  66. package/src/nested/index.js +0 -93
  67. package/src/nested/references.js +0 -23
  68. package/src/nowiki/comment.js +0 -71
  69. package/src/nowiki/dd.js +0 -59
  70. package/src/nowiki/doubleUnderscore.js +0 -56
  71. package/src/nowiki/hr.js +0 -41
  72. package/src/nowiki/index.js +0 -56
  73. package/src/nowiki/list.js +0 -16
  74. package/src/nowiki/noinclude.js +0 -28
  75. package/src/nowiki/quote.js +0 -69
  76. package/src/onlyinclude.js +0 -64
  77. package/src/paramTag/index.js +0 -89
  78. package/src/paramTag/inputbox.js +0 -35
  79. package/src/parameter.js +0 -239
  80. package/src/syntax.js +0 -91
  81. package/src/table/index.js +0 -983
  82. package/src/table/td.js +0 -338
  83. package/src/table/tr.js +0 -319
  84. package/src/tagPair/ext.js +0 -145
  85. package/src/tagPair/include.js +0 -50
  86. package/src/tagPair/index.js +0 -126
  87. package/src/transclude.js +0 -843
  88. package/tool/index.js +0 -1202
  89. package/util/base.js +0 -17
  90. package/util/debug.js +0 -73
  91. package/util/diff.js +0 -76
  92. package/util/lint.js +0 -55
  93. package/util/string.js +0 -126
@@ -0,0 +1,183 @@
1
+ 'use strict';
2
+
3
+ (() => {
4
+ const /** @type {{wikiparse: import('../typings/extension')}} */ {wikiparse} = window,
5
+ {MAX_STAGE, print} = wikiparse;
6
+
7
+ /** 用于打印AST */
8
+ class Printer {
9
+ /**
10
+ * @param {HTMLDivElement} preview 置于下层的代码高亮
11
+ * @param {HTMLTextAreaElement} textbox 置于上层的文本框
12
+ * @param {boolean} include 是否嵌入
13
+ */
14
+ constructor(preview, textbox, include) {
15
+ this.id = wikiparse.id++;
16
+ this.preview = preview;
17
+ this.textbox = textbox;
18
+ this.include = Boolean(include);
19
+ /** @type {[number, string, string][]} */ this.root = [];
20
+ /** @type {Promise<void>} */ this.running = undefined;
21
+ this.viewportChanged = false;
22
+ /** @type {[number, string]} */ this.ticks = [0, undefined];
23
+ }
24
+
25
+ /** 倒计时 */
26
+ tick() {
27
+ setTimeout(() => {
28
+ const {ticks} = this;
29
+ if (ticks[0] > 0) {
30
+ ticks[0] -= 500;
31
+ this[ticks[0] <= 0 ? ticks[1] : 'tick']();
32
+ }
33
+ }, 500);
34
+ }
35
+
36
+ /**
37
+ * 用于debounce
38
+ * @param {number} delay 延迟
39
+ * @param {string} method 方法
40
+ */
41
+ queue(delay, method) {
42
+ const {ticks} = this,
43
+ [state] = ticks;
44
+ if (state <= 0 || method === 'coarsePrint' || ticks[1] !== 'coarsePrint') {
45
+ ticks[0] = delay;
46
+ ticks[1] = method;
47
+ if (state <= 0) {
48
+ this.tick();
49
+ }
50
+ }
51
+ }
52
+
53
+ /** 渲染 */
54
+ paint() {
55
+ this.preview.innerHTML = `<span class="wpb-root">${
56
+ this.root.map(([,, printed]) => printed).join('')
57
+ }</span> `;
58
+ this.preview.scrollTop = this.textbox.scrollTop;
59
+ this.preview.classList.remove('active');
60
+ this.textbox.style.color = 'transparent';
61
+ }
62
+
63
+ /** 初步解析 */
64
+ async coarsePrint() {
65
+ if (this.running) {
66
+ return undefined;
67
+ }
68
+ const {include, textbox: {value}} = this,
69
+ parsed = await print(value, include, 2, this.id);
70
+ if (this.include !== include || this.textbox.value !== value) {
71
+ this.running = undefined;
72
+ this.running = this.coarsePrint();
73
+ return this.running;
74
+ }
75
+ this.root = parsed;
76
+ this.paint();
77
+ this.running = undefined;
78
+ this.running = this.finePrint();
79
+ return this.running;
80
+ }
81
+
82
+ /** 根据可见范围精细解析 */
83
+ async finePrint() {
84
+ if (this.running) {
85
+ this.viewportChanged = true;
86
+ return undefined;
87
+ }
88
+ this.viewportChanged = false;
89
+ const {
90
+ root,
91
+ preview: {scrollHeight, offsetHeight: parentHeight, scrollTop, children: [rootNode]},
92
+ include,
93
+ textbox: {value},
94
+ } = this;
95
+ let text = value,
96
+ start = 0,
97
+ {length: end} = root;
98
+ if (scrollHeight > parentHeight) {
99
+ const /** @type {HTMLElement[]} */ childNodes = [...rootNode.childNodes],
100
+ headings = childNodes.filter(({className}) => className === 'wpb-heading'),
101
+ {length} = headings;
102
+ if (length > 0) {
103
+ let i = headings.findIndex(({offsetTop, offsetHeight}) => offsetTop + offsetHeight > scrollTop);
104
+ i = i === -1 ? length : i;
105
+ let j = headings.slice(i).findIndex(({offsetTop}) => offsetTop >= scrollTop + parentHeight);
106
+ j = j === -1 ? length : i + j;
107
+ start = i ? childNodes.indexOf(headings[i - 1]) : 0;
108
+ while (i <= j && root[start][0] === MAX_STAGE) {
109
+ start = childNodes.indexOf(headings[i++]);
110
+ }
111
+ end = j === length ? end : childNodes.indexOf(headings[j]);
112
+ while (i <= j && root[end - 1][0] === MAX_STAGE) {
113
+ end = childNodes.indexOf(headings[--j]);
114
+ }
115
+ text = root.slice(start, end).map(([, str]) => str).join('');
116
+ }
117
+ }
118
+ if (start === end) {
119
+ this.running = undefined;
120
+ return undefined;
121
+ }
122
+ const parsed = await print(text, include, MAX_STAGE, this.id);
123
+ if (this.include === include && this.textbox.value === value) {
124
+ this.root.splice(start, end - start, ...parsed);
125
+ this.paint();
126
+ this.running = undefined;
127
+ if (this.viewportChanged) {
128
+ this.running = this.finePrint();
129
+ }
130
+ } else {
131
+ this.running = undefined;
132
+ this.running = this.coarsePrint();
133
+ }
134
+ return this.running;
135
+ }
136
+ }
137
+
138
+ /**
139
+ * 高亮textarea
140
+ * @param {HTMLTextAreaElement} textbox textarea元素
141
+ * @param {boolean} include 是否嵌入
142
+ * @throws `TypeError` 不是textarea
143
+ */
144
+ const edit = (textbox, include) => {
145
+ if (!(textbox instanceof HTMLTextAreaElement)) {
146
+ throw new TypeError('wikiparse.edit方法仅可用于textarea元素!');
147
+ }
148
+ const preview = document.createElement('div'),
149
+ container = document.createElement('div'),
150
+ printer = new Printer(preview, textbox, include);
151
+ preview.id = 'wikiPretty';
152
+ preview.classList.add('wikiparser', 'active');
153
+ container.classList.add('wikiparse-container');
154
+ textbox.replaceWith(container);
155
+ textbox.classList.add('wikiparsed');
156
+ container.append(preview, textbox);
157
+
158
+ textbox.addEventListener('input', ({isComposing}) => {
159
+ if (!isComposing) {
160
+ printer.queue(2000, 'coarsePrint');
161
+ }
162
+ textbox.style.color = '';
163
+ preview.classList.add('active');
164
+ });
165
+ textbox.addEventListener('scroll', () => {
166
+ if (preview.scrollHeight > preview.offsetHeight && !preview.classList.contains('active')) {
167
+ preview.scrollTop = textbox.scrollTop;
168
+ printer.queue(500, 'finePrint');
169
+ }
170
+ });
171
+ textbox.addEventListener('keydown', e => {
172
+ if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
173
+ e.preventDefault();
174
+ printer.ticks[0] = 0;
175
+ printer.running = printer.coarsePrint();
176
+ }
177
+ });
178
+ printer.running = printer.coarsePrint();
179
+ return printer;
180
+ };
181
+
182
+ Object.assign(wikiparse, {edit, Printer});
183
+ })();
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ (() => {
4
+ const /** @type {{wikiparse: import('../typings/extension')}} */ {wikiparse} = window;
5
+
6
+ /**
7
+ * 高亮代码块
8
+ * @param {HTMLElement} ele 代码块
9
+ * @param {boolean} linenums 是否添加行号
10
+ * @param {number} start 起始行号
11
+ */
12
+ const highlight = async (ele, linenums, start = 1) => {
13
+ if (ele.classList.contains('highlighted')) {
14
+ return;
15
+ }
16
+ const html = (await wikiparse.print(ele.innerText)).map(([,, printed]) => printed).join('');
17
+ ele.classList.add('highlighted');
18
+ if (linenums) {
19
+ // 添加行号。这里不使用<table>排版,而是使用<ol>
20
+ const lines = html.split('\n').map((line, i) => {
21
+ const li = document.createElement('li');
22
+ li.id = `L${i + start}`;
23
+ li.innerHTML = line;
24
+ return li;
25
+ });
26
+ if (!lines[lines.length - 1].textContent) {
27
+ lines.pop();
28
+ }
29
+ const ol = document.createElement('ol');
30
+ ol.start = start;
31
+ ol.style.paddingLeft = `${(lines.length + start - 1).toString().length + 2.5}ch`;
32
+ ol.append(...lines);
33
+ ele.replaceChildren(ol);
34
+ } else {
35
+ ele.innerHTML = html;
36
+ }
37
+ };
38
+
39
+ wikiparse.highlight = highlight;
40
+ })();
@@ -0,0 +1,119 @@
1
+ .wikiparser {
2
+ white-space: pre-wrap;
3
+ overflow-wrap: break-word;
4
+ font-family: monospace;
5
+ }
6
+
7
+ .wpb-error {
8
+ text-decoration: underline wavy #f00 1px;
9
+ }
10
+ .wpb-hidden, .wpb-table-inter, .wpb-table-inter span {
11
+ color: #f00;
12
+ font-weight: normal;
13
+ text-decoration: underline wavy 1px;
14
+ }
15
+
16
+ .wpb-noinclude, .wpb-include, .wpb-comment {
17
+ color: #72777d;
18
+ font-weight: normal;
19
+ }
20
+ .wpb-comment {
21
+ font-style: italic;
22
+ }
23
+
24
+ .wpb-ext, .wpb-html {
25
+ color: #14866d;
26
+ font-weight: bold;
27
+ }
28
+ .wpb-ext-attrs, .wpb-html-attrs {
29
+ font-weight: normal;
30
+ }
31
+ .wpb-ext-attr > .wpb-attr-value, .wpb-html-attr > .wpb-attr-value {
32
+ color: #179b1c;
33
+ }
34
+ .wpb-ext-inner {
35
+ color: initial;
36
+ font-weight: normal;
37
+ background-color: rgba(0, 0, 0, .03);
38
+ }
39
+
40
+ .wpb-arg {
41
+ color: #ac6600;
42
+ font-weight: bold;
43
+ }
44
+ .wpb-arg-default {
45
+ color: #ad9300;
46
+ font-weight: normal;
47
+ }
48
+
49
+ .wpb-template {
50
+ color: #80c;
51
+ font-weight: bold;
52
+ background-color: rgba(119, 0, 170, .03);
53
+ }
54
+ .wpb-magic-word {
55
+ color: #d33;
56
+ font-weight: bold;
57
+ background-color: rgba(170, 17, 17, .03);
58
+ }
59
+ .wpb-invoke-module, .wpb-invoke-function {
60
+ color: #dd5d33;
61
+ font-weight: normal;
62
+ }
63
+ .wpb-parameter {
64
+ color: initial;
65
+ font-weight: normal;
66
+ }
67
+ .wpb-template > .wpb-parameter > .wpb-parameter-key,
68
+ .wpb-invoke-function ~ .wpb-parameter > .wpb-parameter-key {
69
+ color: #b0c;
70
+ }
71
+
72
+ .wpb-heading, .wpb-image-parameter {
73
+ color: #0076dd;
74
+ }
75
+ .wpb-heading-title {
76
+ color: initial;
77
+ font-weight: bold;
78
+ }
79
+
80
+ .wpb-table, .wpb-tr, .wpb-td {
81
+ color: #d08;
82
+ font-weight: bold;
83
+ }
84
+ .wpb-table-attrs {
85
+ font-weight: normal;
86
+ }
87
+ .wpb-table-attr > .wpb-attr-value {
88
+ color: #f500d4;
89
+ }
90
+ .wpb-td-inner {
91
+ color: initial;
92
+ font-weight: normal;
93
+ }
94
+
95
+ .wpb-double-underscore, .wpb-hr, .wpb-quote, .wpb-list, .wpb-dd {
96
+ color: #0076dd;
97
+ font-weight: bold;
98
+ background-color: #eee;
99
+ }
100
+
101
+ .wpb-link, .wpb-category, .wpb-file, .wpb-gallery-image, .wpb-imagemap-image,
102
+ .wpb-ext-link, .wpb-free-ext-link {
103
+ color: #000aaa;
104
+ background-color: rgba(34, 17, 153, .03);
105
+ }
106
+ .wpb-link-text, .wpb-image-caption, .wpb-ext-link-text {
107
+ color: initial;
108
+ }
109
+
110
+ .wpb-converter {
111
+ color: #b68;
112
+ font-weight: bold;
113
+ }
114
+ .wpb-converter-rule {
115
+ font-weight: normal;
116
+ }
117
+ .wpb-converter-rule-from, .wpb-converter-rule-to, .wpb-converter-noconvert {
118
+ color: initial;
119
+ }
package/i18n/zh-hans.json CHANGED
@@ -42,4 +42,4 @@
42
42
  "unnecessary URL encoding in an internal link": "内链中不必要的URL编码",
43
43
  "useless fragment": "多余的fragment",
44
44
  "vertical-alignment": "垂直对齐"
45
- }
45
+ }
package/i18n/zh-hant.json CHANGED
@@ -42,4 +42,4 @@
42
42
  "unnecessary URL encoding in an internal link": "內部連結中不必要的URL編碼",
43
43
  "useless fragment": "多餘的fragment",
44
44
  "vertical-alignment": "垂直對齊"
45
- }
45
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiparser-node",
3
- "version": "0.10.0",
3
+ "version": "0.11.0-b",
4
4
  "description": "A Node.js parser for MediaWiki markup with AST",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -14,34 +14,39 @@
14
14
  "license": "GPL-3.0",
15
15
  "author": "Bhsd",
16
16
  "files": [
17
- "/index.js",
17
+ "/bundle/bundle.min.js",
18
+ "/extensions/",
19
+ "!/extensions/gh-page.*",
20
+ "!/extensions/.eslintrc.json",
18
21
  "/config/",
19
- "/i18n/",
20
- "/lib/",
21
- "/mixin/",
22
- "/parser/",
23
- "/src/",
24
- "/tool/",
25
- "/util/"
22
+ "/i18n/"
26
23
  ],
24
+ "browser": "/bundle/bundle.min.js",
27
25
  "repository": {
28
26
  "type": "git",
29
27
  "url": "git+https://github.com/bhsd-harry/wikiparser-node.git"
30
28
  },
31
29
  "scripts": {
32
- "test": "eslint . && ajv -s config/.schema.json -d 'config/*.json' --strict=true --strict-required=false && node test/test.js",
30
+ "test": "rm bundle/*.js; webpack && eslint . && ajv -s config/.schema.json -d 'config/*.json' --strict=true --strict-required=false && stylelint extensions/*.css",
33
31
  "real": "node test/real.js",
34
- "single": "node --prof test/single.js && node --prof-process isolate-0x*-v8.log > test/processed.txt && rm isolate-0x*-v8.log"
32
+ "single": "node test/single.js"
35
33
  },
36
34
  "devDependencies": {
37
35
  "@types/node": "^17.0.23",
36
+ "webpack-cli": "^4.10.0",
37
+ "webpack": "^5.73.0",
38
+ "esbuild-loader": "^2.20.0",
38
39
  "eslint": "^8.30.0",
39
40
  "eslint-plugin-n": "^15.6.0",
41
+ "eslint-plugin-es-x": "^5.4.0",
40
42
  "eslint-plugin-regexp": "^1.11.0",
41
43
  "eslint-plugin-unicorn": "^45.0.2",
42
44
  "eslint-plugin-jsdoc": "^1.0.0",
43
45
  "eslint-plugin-json-es": "^1.5.7",
44
46
  "eslint-plugin-eslint-comments": "^3.2.0",
47
+ "typescript": "^4.6.3",
48
+ "@typescript-eslint/eslint-plugin": "^5.47.1",
49
+ "@typescript-eslint/parser": "^5.47.1",
45
50
  "ajv-cli": "^5.0.0",
46
51
  "request": "^2.88.2"
47
52
  },