wikilint 2.16.3 → 2.16.4

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.
@@ -63,7 +63,7 @@ export declare abstract class AstNode implements AstNodeBase {
63
63
  * 是否是某种类型的节点
64
64
  * @param type 节点类型
65
65
  */
66
- is<T extends Token>(type: string): this is T;
66
+ is<T extends Token>(type: TokenTypes): this is T;
67
67
  /** 获取所有行的wikitext和起止位置 */
68
68
  getLines(): [string, number, number][];
69
69
  }
package/dist/lib/node.js CHANGED
@@ -3,13 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AstNode = void 0;
4
4
  /* eslint-disable @typescript-eslint/no-base-to-string */
5
5
  const lint_1 = require("../util/lint");
6
- /**
7
- * 获取子节点相对于父节点的字符位置
8
- * @param j 子节点序号
9
- * @param parent 父节点
10
- */
11
- const getIndex = (j, parent) => parent.childNodes.slice(0, j).reduce((acc, cur, i) => acc + cur.toString().length + parent.getGaps(i), 0)
12
- + parent.getAttribute('padding');
6
+ const debug_1 = require("../util/debug");
13
7
  /** 类似Node */
14
8
  class AstNode {
15
9
  childNodes = [];
@@ -19,6 +13,7 @@ class AstNode {
19
13
  #lines;
20
14
  #root;
21
15
  #aIndex;
16
+ #rIndex = {};
22
17
  /** 首位子节点 */
23
18
  get firstChild() {
24
19
  return this.childNodes[0];
@@ -125,9 +120,21 @@ class AstNode {
125
120
  getRelativeIndex(j) {
126
121
  if (j === undefined) {
127
122
  const { parentNode } = this;
128
- return parentNode ? getIndex(parentNode.childNodes.indexOf(this), parentNode) : 0;
123
+ return parentNode
124
+ ? parentNode.getRelativeIndex(parentNode.childNodes.indexOf(this))
125
+ : 0;
129
126
  }
130
- return getIndex(j, this);
127
+ return (0, lint_1.cache)(this.#rIndex[j], () => {
128
+ const { childNodes } = this, n = j + (j < 0 ? childNodes.length : 0);
129
+ let acc = this.getAttribute('padding');
130
+ for (let i = 0; i < n; i++) {
131
+ this.#rIndex[i] = [debug_1.Shadow.rev, acc];
132
+ acc += childNodes[i].toString().length + this.getGaps(i);
133
+ }
134
+ return acc;
135
+ }, value => {
136
+ this.#rIndex[j] = value;
137
+ });
131
138
  }
132
139
  /** 获取当前节点的绝对位置 */
133
140
  getAbsoluteIndex() {
@@ -28,4 +28,9 @@ export declare class Title {
28
28
  constructor(title: string, defaultNs: number, config: Config, decode: boolean, selfLink: boolean);
29
29
  /** 检测是否是重定向 */
30
30
  getRedirection(): [boolean, string];
31
+ /**
32
+ * 生成URL
33
+ * @param articlePath 条目路径
34
+ */
35
+ getUrl(articlePath?: string): string;
31
36
  }
package/dist/lib/title.js CHANGED
@@ -6,6 +6,7 @@ const string_1 = require("../util/string");
6
6
  class Title {
7
7
  #main;
8
8
  #namespaces;
9
+ #path;
9
10
  #ns;
10
11
  #fragment;
11
12
  interwiki = '';
@@ -100,6 +101,10 @@ class Title {
100
101
  encoded: { enumerable: false, writable: false },
101
102
  });
102
103
  this.#namespaces = config.namespaces;
104
+ this.#path = config.articlePath || '/wiki/$1';
105
+ if (!this.#path.includes('$1')) {
106
+ this.#path += `${this.#path.endsWith('/') ? '' : '/'}$1`;
107
+ }
103
108
  }
104
109
  /** @private */
105
110
  toString(display) {
@@ -119,5 +124,29 @@ class Title {
119
124
  setFragment(fragment) {
120
125
  this.#fragment = fragment;
121
126
  }
127
+ /**
128
+ * 生成URL
129
+ * @param articlePath 条目路径
130
+ */
131
+ getUrl(articlePath) {
132
+ LSP: { // eslint-disable-line no-unused-labels
133
+ if (typeof articlePath === 'string') {
134
+ this.#path = articlePath || '/wiki/$1';
135
+ if (!this.#path.includes('$1')) {
136
+ this.#path += `${this.#path.endsWith('/') ? '' : '/'}$1`;
137
+ }
138
+ }
139
+ const { title, fragment } = this;
140
+ if (title) {
141
+ return this.#path.replace('$1', encodeURIComponent(title)
142
+ + (fragment === undefined
143
+ ? ''
144
+ : `#${encodeURIComponent(
145
+ // eslint-disable-next-line @stylistic/comma-dangle
146
+ fragment)}`));
147
+ }
148
+ return fragment === undefined ? '' : `#${encodeURIComponent(fragment)}`;
149
+ }
150
+ }
122
151
  }
123
152
  exports.Title = Title;
@@ -12,12 +12,12 @@ const attributesParent = (i = 0) => (constructor, _) => {
12
12
  /** 子节点含有AttributesToken的类 */
13
13
  class AttributesParent extends constructor {
14
14
  /** AttributesToken子节点 */
15
- get #attributesChild() {
15
+ #getAttributesChild() {
16
16
  return this.childNodes[i];
17
17
  }
18
18
  /** @implements */
19
19
  getAttr(key) {
20
- return this.#attributesChild.getAttr(key);
20
+ return this.#getAttributesChild().getAttr(key);
21
21
  }
22
22
  }
23
23
  (0, debug_1.mixin)(AttributesParent, constructor);
@@ -16,10 +16,6 @@ class HeadingToken extends index_2.Token {
16
16
  get type() {
17
17
  return 'heading';
18
18
  }
19
- /** 标题格式的等号 */
20
- get #equals() {
21
- return '='.repeat(this.level);
22
- }
23
19
  /** 标题层级 */
24
20
  get level() {
25
21
  return this.#level;
@@ -37,14 +33,18 @@ class HeadingToken extends index_2.Token {
37
33
  const trail = new syntax_1.SyntaxToken(input[1], /^\s*$/u, 'heading-trail', config, accum, {});
38
34
  this.append(token, trail);
39
35
  }
36
+ /** 标题格式的等号 */
37
+ #getEquals() {
38
+ return '='.repeat(this.level);
39
+ }
40
40
  /** @private */
41
41
  toString(skip) {
42
- const equals = this.#equals;
42
+ const equals = this.#getEquals();
43
43
  return equals + this.firstChild.toString(skip) + equals + this.lastChild.toString(skip);
44
44
  }
45
45
  /** @private */
46
46
  text() {
47
- const equals = this.#equals;
47
+ const equals = this.#getEquals();
48
48
  return equals + this.firstChild.text() + equals;
49
49
  }
50
50
  /** @private */
@@ -1,6 +1,9 @@
1
1
  import { Token } from './index';
2
2
  import type { Config, LintError } from '../base';
3
+ import type { AttributesParentBase } from '../mixin/attributesParent';
3
4
  import type { AttributesToken } from '../internal';
5
+ export interface HtmlToken extends AttributesParentBase {
6
+ }
4
7
  /**
5
8
  * HTML标签
6
9
  * @classdesc `{childNodes: [AttributesToken]}`
package/dist/src/html.js CHANGED
@@ -1,9 +1,44 @@
1
1
  "use strict";
2
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
4
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
5
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
7
+ var _, done = false;
8
+ for (var i = decorators.length - 1; i >= 0; i--) {
9
+ var context = {};
10
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
11
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
12
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
13
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
14
+ if (kind === "accessor") {
15
+ if (result === void 0) continue;
16
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
17
+ if (_ = accept(result.get)) descriptor.get = _;
18
+ if (_ = accept(result.set)) descriptor.set = _;
19
+ if (_ = accept(result.init)) initializers.unshift(_);
20
+ }
21
+ else if (_ = accept(result)) {
22
+ if (kind === "field") initializers.unshift(_);
23
+ else descriptor[key] = _;
24
+ }
25
+ }
26
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
27
+ done = true;
28
+ };
29
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
30
+ var useValue = arguments.length > 2;
31
+ for (var i = 0; i < initializers.length; i++) {
32
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
33
+ }
34
+ return useValue ? value : void 0;
35
+ };
2
36
  Object.defineProperty(exports, "__esModule", { value: true });
3
37
  exports.HtmlToken = void 0;
4
38
  const lint_1 = require("../util/lint");
5
39
  const string_1 = require("../util/string");
6
40
  const rect_1 = require("../lib/rect");
41
+ const attributesParent_1 = require("../mixin/attributesParent");
7
42
  const index_1 = require("./index");
8
43
  const magicWords = new Set(['if', 'ifeq', 'ifexpr', 'ifexist', 'iferror', 'switch']), formattingTags = new Set([
9
44
  'b',
@@ -36,165 +71,181 @@ const magicWords = new Set(['if', 'ifeq', 'ifexpr', 'ifexist', 'iferror', 'switc
36
71
  * HTML标签
37
72
  * @classdesc `{childNodes: [AttributesToken]}`
38
73
  */
39
- class HtmlToken extends index_1.Token {
40
- #closing;
41
- #selfClosing;
42
- #tag;
43
- get type() {
44
- return 'html';
45
- }
46
- /** 是否自封闭 */
47
- get selfClosing() {
48
- return this.#selfClosing;
49
- }
50
- /** 是否是闭合标签 */
51
- get closing() {
52
- return this.#closing;
53
- }
54
- /**
55
- * @param name 标签名
56
- * @param attr 标签属性
57
- * @param closing 是否闭合
58
- * @param selfClosing 是否自封闭
59
- */
60
- constructor(name, attr, closing, selfClosing, config, accum) {
61
- super(undefined, config, accum);
62
- this.insertAt(attr);
63
- this.setAttribute('name', name.toLowerCase());
64
- this.#closing = closing;
65
- this.#selfClosing = selfClosing;
66
- this.#tag = name;
67
- }
68
- /** @private */
69
- toString(skip) {
70
- return `<${this.closing ? '/' : ''}${this.#tag}${super.toString(skip)}${this.#selfClosing ? '/' : ''}>`;
71
- }
72
- /** @private */
73
- text() {
74
- const { closing, } = this, tag = this.#tag + (closing ? '' : super.text());
75
- return `<${closing ? '/' : ''}${tag}${this.#selfClosing ? '/' : ''}>`;
76
- }
77
- /** @private */
78
- getAttribute(key) {
79
- return key === 'padding'
80
- ? this.#tag.length + (this.closing ? 2 : 1)
81
- : super.getAttribute(key);
82
- }
83
- /** @private */
84
- lint(start = this.getAbsoluteIndex(), re) {
85
- const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start);
86
- if (this.name === 'h1' && !this.closing) {
87
- const e = (0, lint_1.generateForSelf)(this, rect, 'h1', '<h1>');
88
- e.suggestions = [{ desc: 'h2', range: [start + 2, start + 3], text: '2' }];
89
- errors.push(e);
74
+ let HtmlToken = (() => {
75
+ let _classDecorators = [(0, attributesParent_1.attributesParent)()];
76
+ let _classDescriptor;
77
+ let _classExtraInitializers = [];
78
+ let _classThis;
79
+ let _classSuper = index_1.Token;
80
+ var HtmlToken = class extends _classSuper {
81
+ static { _classThis = this; }
82
+ static {
83
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
84
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
85
+ HtmlToken = _classThis = _classDescriptor.value;
86
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
87
+ __runInitializers(_classThis, _classExtraInitializers);
90
88
  }
91
- if (this.closest('table-attrs')) {
92
- const e = (0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'HTML tag in table attributes');
93
- e.fix = { desc: 'remove', range: [start, e.endIndex], text: '' };
94
- errors.push(e);
89
+ #closing;
90
+ #selfClosing;
91
+ #tag;
92
+ get type() {
93
+ return 'html';
95
94
  }
96
- try {
97
- this.findMatchingTag();
95
+ /** 是否自封闭 */
96
+ get selfClosing() {
97
+ return this.#selfClosing;
98
98
  }
99
- catch (e) {
100
- if (e instanceof SyntaxError) {
101
- const { message } = e;
102
- const msg = message.split(':', 1)[0].toLowerCase(), error = (0, lint_1.generateForSelf)(this, rect, 'unmatched-tag', msg), noSelfClosing = {
103
- desc: 'no self-closing',
104
- range: [error.endIndex - 2, error.endIndex - 1],
105
- text: '',
106
- };
107
- switch (msg) {
108
- case 'unclosed tag': {
109
- const childNodes = this.parentNode?.childNodes;
110
- if (formattingTags.has(this.name)
111
- && childNodes?.slice(0, childNodes.indexOf(this))
112
- .some(({ type, name }) => type === 'html' && name === this.name)) {
113
- error.suggestions = [{ desc: 'close', range: [start + 1, start + 1], text: '/' }];
114
- }
115
- else if (!this.closest('heading-title')) {
116
- error.severity = 'warning';
117
- }
118
- break;
119
- }
120
- case 'unmatched closing tag': {
121
- const ancestor = this.closest('magic-word');
122
- if (ancestor && magicWords.has(ancestor.name)) {
123
- error.severity = 'warning';
124
- }
125
- else {
126
- error.suggestions = [{ desc: 'remove', range: [start, error.endIndex], text: '' }];
127
- }
128
- break;
129
- }
130
- case 'tag that is both closing and self-closing': {
131
- const { html: [normalTags, , voidTags] } = this.getAttribute('config'), open = { desc: 'open', range: [start + 1, start + 2], text: '' };
132
- if (voidTags.includes(this.name)) {
133
- error.fix = open;
99
+ /** 是否是闭合标签 */
100
+ get closing() {
101
+ return this.#closing;
102
+ }
103
+ /**
104
+ * @param name 标签名
105
+ * @param attr 标签属性
106
+ * @param closing 是否闭合
107
+ * @param selfClosing 是否自封闭
108
+ */
109
+ constructor(name, attr, closing, selfClosing, config, accum) {
110
+ super(undefined, config, accum);
111
+ this.insertAt(attr);
112
+ this.setAttribute('name', name.toLowerCase());
113
+ this.#closing = closing;
114
+ this.#selfClosing = selfClosing;
115
+ this.#tag = name;
116
+ }
117
+ /** @private */
118
+ toString(skip) {
119
+ return `<${this.closing ? '/' : ''}${this.#tag}${super.toString(skip)}${this.#selfClosing ? '/' : ''}>`;
120
+ }
121
+ /** @private */
122
+ text() {
123
+ const { closing, } = this, tag = this.#tag + (closing ? '' : super.text());
124
+ return `<${closing ? '/' : ''}${tag}${this.#selfClosing ? '/' : ''}>`;
125
+ }
126
+ /** @private */
127
+ getAttribute(key) {
128
+ return key === 'padding'
129
+ ? this.#tag.length + (this.closing ? 2 : 1)
130
+ : super.getAttribute(key);
131
+ }
132
+ /** @private */
133
+ lint(start = this.getAbsoluteIndex(), re) {
134
+ const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start);
135
+ if (this.name === 'h1' && !this.closing) {
136
+ const e = (0, lint_1.generateForSelf)(this, rect, 'h1', '<h1>');
137
+ e.suggestions = [{ desc: 'h2', range: [start + 2, start + 3], text: '2' }];
138
+ errors.push(e);
139
+ }
140
+ if (this.closest('table-attrs')) {
141
+ const e = (0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'HTML tag in table attributes');
142
+ e.fix = { desc: 'remove', range: [start, e.endIndex], text: '' };
143
+ errors.push(e);
144
+ }
145
+ try {
146
+ this.findMatchingTag();
147
+ }
148
+ catch (e) {
149
+ if (e instanceof SyntaxError) {
150
+ const { message } = e;
151
+ const msg = message.split(':', 1)[0].toLowerCase(), error = (0, lint_1.generateForSelf)(this, rect, 'unmatched-tag', msg), noSelfClosing = {
152
+ desc: 'no self-closing',
153
+ range: [error.endIndex - 2, error.endIndex - 1],
154
+ text: '',
155
+ };
156
+ switch (msg) {
157
+ case 'unclosed tag': {
158
+ const childNodes = this.parentNode?.childNodes;
159
+ if (formattingTags.has(this.name)
160
+ && childNodes?.slice(0, childNodes.indexOf(this))
161
+ .some(({ type, name }) => type === 'html' && name === this.name)) {
162
+ error.suggestions = [{ desc: 'close', range: [start + 1, start + 1], text: '/' }];
163
+ }
164
+ else if (!this.closest('heading-title')) {
165
+ error.severity = 'warning';
166
+ }
167
+ break;
134
168
  }
135
- else if (normalTags.includes(this.name)) {
136
- error.fix = noSelfClosing;
169
+ case 'unmatched closing tag': {
170
+ const ancestor = this.closest('magic-word');
171
+ if (ancestor && magicWords.has(ancestor.name)) {
172
+ error.severity = 'warning';
173
+ }
174
+ else {
175
+ error.suggestions = [{ desc: 'remove', range: [start, error.endIndex], text: '' }];
176
+ }
177
+ break;
137
178
  }
138
- else {
139
- error.suggestions = [open, noSelfClosing];
179
+ case 'tag that is both closing and self-closing': {
180
+ const { html: [normalTags, , voidTags] } = this.getAttribute('config'), open = { desc: 'open', range: [start + 1, start + 2], text: '' };
181
+ if (voidTags.includes(this.name)) {
182
+ error.fix = open;
183
+ }
184
+ else if (normalTags.includes(this.name)) {
185
+ error.fix = noSelfClosing;
186
+ }
187
+ else {
188
+ error.suggestions = [open, noSelfClosing];
189
+ }
190
+ break;
140
191
  }
141
- break;
192
+ case 'invalid self-closing tag':
193
+ error.suggestions = [
194
+ noSelfClosing,
195
+ { desc: 'close', range: [error.endIndex - 2, error.endIndex], text: `></${this.name}>` },
196
+ ];
197
+ // no default
142
198
  }
143
- case 'invalid self-closing tag':
144
- error.suggestions = [
145
- noSelfClosing,
146
- { desc: 'close', range: [error.endIndex - 2, error.endIndex], text: `></${this.name}>` },
147
- ];
148
- // no default
199
+ errors.push(error);
149
200
  }
150
- errors.push(error);
151
201
  }
202
+ if (obsoleteTags.has(this.name)) {
203
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'obsolete-tag', 'obsolete HTML tag', 'warning'));
204
+ }
205
+ if ((this.name === 'b' || this.name === 'strong') && this.closest('heading-title')) {
206
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'bold-header', 'bold in section header', 'warning'));
207
+ }
208
+ return errors;
152
209
  }
153
- if (obsoleteTags.has(this.name)) {
154
- errors.push((0, lint_1.generateForSelf)(this, rect, 'obsolete-tag', 'obsolete HTML tag', 'warning'));
155
- }
156
- if ((this.name === 'b' || this.name === 'strong') && this.closest('heading-title')) {
157
- errors.push((0, lint_1.generateForSelf)(this, rect, 'bold-header', 'bold in section header', 'warning'));
158
- }
159
- return errors;
160
- }
161
- /**
162
- * 搜索匹配的标签
163
- * @throws `SyntaxError` 同时闭合和自封闭的标签
164
- * @throws `SyntaxError` 无效自封闭标签
165
- * @throws `SyntaxError` 未匹配的标签
166
- */
167
- findMatchingTag() {
168
- const { html: [normalTags, flexibleTags, voidTags] } = this.getAttribute('config'), { name: tagName, parentNode, closing } = this, string = (0, string_1.noWrap)(this.toString());
169
- if (closing && (this.#selfClosing || voidTags.includes(tagName))) {
170
- throw new SyntaxError(`Tag that is both closing and self-closing: ${string}`);
171
- }
172
- else if (voidTags.includes(tagName) || this.#selfClosing && flexibleTags.includes(tagName)) { // 自封闭标签
173
- return this;
174
- }
175
- else if (this.#selfClosing && normalTags.includes(tagName)) {
176
- throw new SyntaxError(`Invalid self-closing tag: ${string}`);
177
- }
178
- else if (!parentNode) {
179
- return undefined;
180
- }
181
- const { childNodes } = parentNode, i = childNodes.indexOf(this), siblings = closing ? childNodes.slice(0, i).reverse() : childNodes.slice(i + 1);
182
- let imbalance = closing ? -1 : 1;
183
- for (const token of siblings) {
184
- if (!token.is('html') || token.name !== tagName) {
185
- continue;
210
+ /**
211
+ * 搜索匹配的标签
212
+ * @throws `SyntaxError` 同时闭合和自封闭的标签
213
+ * @throws `SyntaxError` 无效自封闭标签
214
+ * @throws `SyntaxError` 未匹配的标签
215
+ */
216
+ findMatchingTag() {
217
+ const { html: [normalTags, flexibleTags, voidTags] } = this.getAttribute('config'), { name: tagName, parentNode, closing } = this, string = (0, string_1.noWrap)(this.toString());
218
+ if (closing && (this.#selfClosing || voidTags.includes(tagName))) {
219
+ throw new SyntaxError(`Tag that is both closing and self-closing: ${string}`);
220
+ }
221
+ else if (voidTags.includes(tagName) || this.#selfClosing && flexibleTags.includes(tagName)) { // 自封闭标签
222
+ return this;
186
223
  }
187
- else if (token.#closing) {
188
- imbalance--;
224
+ else if (this.#selfClosing && normalTags.includes(tagName)) {
225
+ throw new SyntaxError(`Invalid self-closing tag: ${string}`);
189
226
  }
190
- else {
191
- imbalance++;
227
+ else if (!parentNode) {
228
+ return undefined;
192
229
  }
193
- if (imbalance === 0) {
194
- return token;
230
+ const { childNodes } = parentNode, i = childNodes.indexOf(this), siblings = closing ? childNodes.slice(0, i).reverse() : childNodes.slice(i + 1);
231
+ let imbalance = closing ? -1 : 1;
232
+ for (const token of siblings) {
233
+ if (!token.is('html') || token.name !== tagName) {
234
+ continue;
235
+ }
236
+ else if (token.#closing) {
237
+ imbalance--;
238
+ }
239
+ else {
240
+ imbalance++;
241
+ }
242
+ if (imbalance === 0) {
243
+ return token;
244
+ }
195
245
  }
246
+ throw new SyntaxError(`${closing ? 'Unmatched closing' : 'Unclosed'} tag: ${string}`);
196
247
  }
197
- throw new SyntaxError(`${closing ? 'Unmatched closing' : 'Unclosed'} tag: ${string}`);
198
- }
199
- }
248
+ };
249
+ return HtmlToken = _classThis;
250
+ })();
200
251
  exports.HtmlToken = HtmlToken;
@@ -4,10 +4,6 @@ import { AstText } from '../lib/text';
4
4
  import type { LintError, TokenTypes } from '../base';
5
5
  import type { Title } from '../lib/title';
6
6
  import type { AstNodes } from '../internal';
7
- declare interface CaretPosition {
8
- readonly offsetNode: AstNodes;
9
- readonly offset: number;
10
- }
11
7
  /**
12
8
  * 所有节点的基类
13
9
  * @classdesc `{childNodes: ...(AstText|Token)}`
@@ -25,21 +21,4 @@ export declare class Token extends AstElement {
25
21
  */
26
22
  insertAt(child: string, i?: number): AstText;
27
23
  insertAt<T extends AstNodes>(child: T, i?: number): T;
28
- /**
29
- * 找到给定位置
30
- * @param index 位置
31
- */
32
- caretPositionFromIndex(index?: number): CaretPosition | undefined;
33
- /**
34
- * 找到给定位置所在的最外层节点
35
- * @param index 位置
36
- */
37
- elementFromIndex(index?: number): Token | undefined;
38
- /**
39
- * 找到给定位置所在的最外层节点
40
- * @param x 列数
41
- * @param y 行数
42
- */
43
- elementFromPoint(x: number, y: number): Token | undefined;
44
24
  }
45
- export {};
package/dist/src/index.js CHANGED
@@ -419,60 +419,5 @@ class Token extends element_1.AstElement {
419
419
  }
420
420
  });
421
421
  }
422
- /**
423
- * 找到给定位置
424
- * @param index 位置
425
- */
426
- caretPositionFromIndex(index) {
427
- LSP: { // eslint-disable-line no-unused-labels
428
- if (index === undefined) {
429
- return undefined;
430
- }
431
- const { length } = this.toString();
432
- if (index > length || index < -length) {
433
- return undefined;
434
- }
435
- index += index < 0 ? length : 0;
436
- let self = this, acc = 0, start = 0;
437
- while (self.type !== 'text') {
438
- const { childNodes } = self;
439
- acc += self.getAttribute('padding');
440
- for (let i = 0; acc < index && i < childNodes.length; i++) {
441
- const cur = childNodes[i], l = cur.toString().length;
442
- acc += l;
443
- if (acc >= index) {
444
- self = cur;
445
- acc -= l;
446
- start = acc;
447
- break;
448
- }
449
- acc += self.getGaps(i);
450
- }
451
- if (self.childNodes === childNodes) {
452
- return { offsetNode: self, offset: index - start };
453
- }
454
- }
455
- return { offsetNode: self, offset: index - start };
456
- }
457
- }
458
- /**
459
- * 找到给定位置所在的最外层节点
460
- * @param index 位置
461
- */
462
- elementFromIndex(index) {
463
- LSP: { // eslint-disable-line no-unused-labels
464
- const node = this.caretPositionFromIndex(index)?.offsetNode;
465
- return node?.type === 'text' ? node.parentNode : node;
466
- }
467
- }
468
- /**
469
- * 找到给定位置所在的最外层节点
470
- * @param x 列数
471
- * @param y 行数
472
- */
473
- elementFromPoint(x, y) {
474
- // eslint-disable-next-line no-unused-labels
475
- LSP: return this.elementFromIndex(this.indexFromPos(y, x));
476
- }
477
422
  }
478
423
  exports.Token = Token;
@@ -14,6 +14,8 @@ export declare abstract class LinkBaseToken extends Token {
14
14
  readonly childNodes: readonly [AtomToken, ...Token[]];
15
15
  abstract get firstChild(): AtomToken;
16
16
  abstract get lastChild(): Token;
17
+ /** 完整链接 */
18
+ get link(): string | Title;
17
19
  /**
18
20
  * @param link 链接标题
19
21
  * @param linkText 链接显示文字