@markuplint/ml-core 4.0.0-dev.20 → 4.0.0-dev.23

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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017-2023 Yusuke Hirao
3
+ Copyright (c) 2017-2024 Yusuke Hirao
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/lib/index.d.ts CHANGED
@@ -3,7 +3,6 @@ export { ariaSpecs, contentModelCategoryToTagNames, getAttrSpecs, getComputedRol
3
3
  export { Ruleset } from './ruleset/index.js';
4
4
  export { enableDebug } from './debug.js';
5
5
  export { getIndent } from './ml-dom/helper/get-indent.js';
6
- export * from './configs.js';
7
6
  export * from './convert-ruleset.js';
8
7
  export * from './ml-core.js';
9
8
  export * from './ml-dom/index.js';
package/lib/index.js CHANGED
@@ -2,7 +2,6 @@ export { ariaSpecs, contentModelCategoryToTagNames, getAttrSpecs, getComputedRol
2
2
  export { Ruleset } from './ruleset/index.js';
3
3
  export { enableDebug } from './debug.js';
4
4
  export { getIndent } from './ml-dom/helper/get-indent.js';
5
- export * from './configs.js';
6
5
  export * from './convert-ruleset.js';
7
6
  export * from './ml-core.js';
8
7
  export * from './ml-dom/index.js';
package/lib/ml-core.d.ts CHANGED
@@ -10,7 +10,7 @@ export type MLCoreParams = {
10
10
  export declare class MLCore {
11
11
  #private;
12
12
  constructor({ parser, sourceCode, ruleset, rules, locale, schemas, parserOptions, pretenders, filename, debug, configErrors, }: MLCoreParams);
13
- get document(): ParserError | Document<RuleConfigValue, PlainData>;
13
+ get document(): Document<RuleConfigValue, PlainData> | ParserError;
14
14
  setCode(sourceCode: string): void;
15
15
  update({ parser, ruleset, rules, locale, schemas, parserOptions, configErrors }: Partial<MLFabric>): void;
16
16
  verify(fix?: boolean): Promise<Violation[]>;
@@ -1,5 +1,5 @@
1
1
  import type { MLDocument } from '../node/document.js';
2
2
  import type { MappedNode } from '../node/types.js';
3
- import type { MLASTAbstractNode } from '@markuplint/ml-ast';
3
+ import type { MLASTNode } from '@markuplint/ml-ast';
4
4
  import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
5
- export declare function createNode<N extends MLASTAbstractNode, T extends RuleConfigValue, O extends PlainData = undefined>(astNode: N, document: MLDocument<T, O>): MappedNode<N, T, O>;
5
+ export declare function createNode<N extends MLASTNode, T extends RuleConfigValue, O extends PlainData = undefined>(astNode: N, document: MLDocument<T, O>): MappedNode<N, T, O>;
@@ -6,22 +6,47 @@ import { MLText } from '../node/text.js';
6
6
  export function createNode(astNode,
7
7
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
8
8
  document) {
9
- const _astNode = astNode;
10
- switch (_astNode.type) {
9
+ switch (astNode.type) {
11
10
  case 'doctype': {
12
- return new MLDocumentType(_astNode, document);
11
+ return new MLDocumentType(astNode, document);
13
12
  }
14
13
  case 'starttag': {
15
- return new MLElement(_astNode, document);
14
+ return new MLElement(astNode, document);
16
15
  }
17
16
  case 'psblock': {
18
- return new MLBlock(_astNode, document);
17
+ return new MLBlock(astNode, document);
19
18
  }
20
19
  case 'comment': {
21
- return new MLComment(_astNode, document);
20
+ return new MLComment(astNode, document);
22
21
  }
23
22
  case 'text': {
24
- return new MLText(_astNode, document);
23
+ return new MLText(astNode, document);
24
+ }
25
+ case 'invalid': {
26
+ switch (astNode.kind) {
27
+ case 'starttag': {
28
+ return new MLElement({
29
+ ...astNode,
30
+ type: 'starttag',
31
+ nodeName: 'x-invalid',
32
+ namespace: 'http://www.w3.org/1999/xhtml',
33
+ elementType: 'web-component',
34
+ attributes: [],
35
+ childNodes: [],
36
+ pairNode: null,
37
+ tagOpenChar: '',
38
+ tagCloseChar: '',
39
+ isGhost: false,
40
+ }, document);
41
+ }
42
+ default: {
43
+ return new MLText({
44
+ ...astNode,
45
+ type: 'text',
46
+ nodeName: '#text',
47
+ }, document);
48
+ }
49
+ }
25
50
  }
26
51
  }
27
52
  throw new TypeError(`Invalid AST node types "${astNode.type}"`);
@@ -91,8 +91,26 @@ export declare class MLAttr<T extends RuleConfigValue, O extends PlainData = und
91
91
  * @see https://dom.spec.whatwg.org/#dom-attr-value
92
92
  */
93
93
  get value(): string;
94
+ /**
95
+ * Fixes the attribute value.
96
+ * If the attribute is not a spread attribute, it calls the `fix` method of the `valueNode`.
97
+ *
98
+ * @implements `@markuplint/ml-core` API: `MLAttr`
99
+ *
100
+ * @param raw - The raw attribute value.
101
+ */
102
+ fix(raw: string): void;
94
103
  /**
95
104
  * @implements `@markuplint/ml-core` API: `MLAttr`
96
105
  */
97
106
  toNormalizeString(): string;
107
+ /**
108
+ * Returns a string representation of the attribute.
109
+ *
110
+ * @implements DOM API: `Attr`
111
+ *
112
+ * @param includesSpacesBeforeName - Whether to include spaces before the attribute name.
113
+ * @returns The string representation of the attribute.
114
+ */
115
+ toString(fixed?: boolean): string;
98
116
  }
@@ -16,9 +16,7 @@ import { MLDomTokenList } from './dom-token-list.js';
16
16
  import { MLNode } from './node.js';
17
17
  import { UnexpectedCallError } from './unexpected-call-error.js';
18
18
  export class MLAttr extends MLNode {
19
- constructor(
20
- // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
21
- astToken,
19
+ constructor(astToken,
22
20
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
23
21
  ownElement) {
24
22
  super(astToken, ownElement.ownerMLDocument);
@@ -41,32 +39,35 @@ export class MLAttr extends MLNode {
41
39
  * @implements `@markuplint/ml-core` API: `MLAttr`
42
40
  */
43
41
  this.valueType = 'string';
44
- if (this._astToken.type === 'html-attr') {
45
- this.spacesBeforeName = new MLToken(this._astToken.spacesBeforeName);
46
- this.nameNode = new MLToken(this._astToken.name);
47
- this.spacesBeforeEqual = new MLToken(this._astToken.spacesBeforeEqual);
48
- this.equal = new MLToken(this._astToken.equal);
49
- this.spacesAfterEqual = new MLToken(this._astToken.spacesAfterEqual);
50
- this.startQuote = new MLToken(this._astToken.startQuote);
51
- this.valueNode = new MLToken(this._astToken.value);
52
- this.endQuote = new MLToken(this._astToken.endQuote);
53
- this.isDynamicValue = this._astToken.isDynamicValue;
54
- this.isDirective = this._astToken.isDirective;
55
- this.candidate = this._astToken.candidate;
56
- __classPrivateFieldSet(this, _MLAttr_potentialName, this._astToken.potentialName ?? this.nameNode?.raw ?? '', "f");
57
- __classPrivateFieldSet(this, _MLAttr_potentialValue, this._astToken.potentialValue ?? this.valueNode?.raw ?? '', "f");
58
- }
59
- else {
60
- this.valueType = this._astToken.valueType;
61
- this.isDuplicatable = this._astToken.isDuplicatable;
62
- __classPrivateFieldSet(this, _MLAttr_potentialName, this._astToken.potentialName, "f");
63
- __classPrivateFieldSet(this, _MLAttr_potentialValue, this._astToken.potentialValue, "f");
42
+ this.ownerElement = ownElement;
43
+ if (this._astToken.type === 'spread') {
44
+ __classPrivateFieldSet(this, _MLAttr_namespaceURI, ownElement.namespaceURI, "f");
45
+ this.valueType = 'code';
46
+ __classPrivateFieldSet(this, _MLAttr_localName, '#spread', "f");
47
+ __classPrivateFieldSet(this, _MLAttr_potentialName, '#spread', "f");
48
+ __classPrivateFieldSet(this, _MLAttr_potentialValue, this._astToken.raw, "f");
49
+ this.isDirective = true;
50
+ this.isDynamicValue = true;
51
+ this.isDuplicatable = true;
52
+ return;
64
53
  }
54
+ this.spacesBeforeName = new MLToken(this._astToken.spacesBeforeName);
55
+ this.nameNode = new MLToken(this._astToken.name);
56
+ this.spacesBeforeEqual = new MLToken(this._astToken.spacesBeforeEqual);
57
+ this.equal = new MLToken(this._astToken.equal);
58
+ this.spacesAfterEqual = new MLToken(this._astToken.spacesAfterEqual);
59
+ this.startQuote = new MLToken(this._astToken.startQuote);
60
+ this.valueNode = new MLToken(this._astToken.value);
61
+ this.endQuote = new MLToken(this._astToken.endQuote);
62
+ this.isDynamicValue = this._astToken.isDynamicValue;
63
+ this.isDirective = this._astToken.isDirective;
64
+ this.candidate = this._astToken.candidate;
65
+ __classPrivateFieldSet(this, _MLAttr_potentialName, this._astToken.potentialName ?? this.nameNode?.raw ?? '', "f");
66
+ __classPrivateFieldSet(this, _MLAttr_potentialValue, this._astToken.potentialValue ?? this.valueNode?.raw ?? '', "f");
67
+ this.isDuplicatable = this._astToken.isDuplicatable;
65
68
  const ns = resolveNamespace(__classPrivateFieldGet(this, _MLAttr_potentialName, "f"), ownElement.namespaceURI);
66
69
  __classPrivateFieldSet(this, _MLAttr_localName, ns.localName, "f");
67
70
  __classPrivateFieldSet(this, _MLAttr_namespaceURI, ns.namespaceURI, "f");
68
- this.ownerElement = ownElement;
69
- this.isDuplicatable = this._astToken.isDuplicatable;
70
71
  }
71
72
  /**
72
73
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -149,18 +150,55 @@ export class MLAttr extends MLNode {
149
150
  get value() {
150
151
  return __classPrivateFieldGet(this, _MLAttr_potentialValue, "f");
151
152
  }
153
+ /**
154
+ * Fixes the attribute value.
155
+ * If the attribute is not a spread attribute, it calls the `fix` method of the `valueNode`.
156
+ *
157
+ * @implements `@markuplint/ml-core` API: `MLAttr`
158
+ *
159
+ * @param raw - The raw attribute value.
160
+ */
161
+ fix(raw) {
162
+ if (this.localName === '#spread') {
163
+ return;
164
+ }
165
+ // `valueNode` is not null when it is no spread.
166
+ this.valueNode?.fix(raw);
167
+ }
152
168
  /**
153
169
  * @implements `@markuplint/ml-core` API: `MLAttr`
154
170
  */
155
171
  toNormalizeString() {
156
172
  if (this.nameNode && this.equal && this.startQuote && this.valueNode && this.endQuote) {
157
- return (this.nameNode.originRaw +
158
- this.equal.originRaw +
159
- this.startQuote.originRaw +
160
- this.valueNode.originRaw +
161
- this.endQuote.originRaw);
173
+ return this.nameNode.raw + this.equal.raw + this.startQuote.raw + this.valueNode.raw + this.endQuote.raw;
162
174
  }
163
175
  return this.raw;
164
176
  }
177
+ /**
178
+ * Returns a string representation of the attribute.
179
+ *
180
+ * @implements DOM API: `Attr`
181
+ *
182
+ * @param includesSpacesBeforeName - Whether to include spaces before the attribute name.
183
+ * @returns The string representation of the attribute.
184
+ */
185
+ toString(fixed = false) {
186
+ if (!fixed) {
187
+ return this.raw;
188
+ }
189
+ if (this.localName === '#spread') {
190
+ return this.raw;
191
+ }
192
+ const tokens = [this.nameNode?.toString(true) ?? ''];
193
+ if (this.equal && this.equal.toString(true) !== '') {
194
+ tokens.push(this.spacesBeforeEqual?.toString(true) ?? '', this.equal?.toString(true) ?? '', this.spacesAfterEqual?.toString(true) ?? '', this.startQuote?.toString(true) ?? '', this.valueNode?.toString(true) ?? '', this.endQuote?.toString(true) ?? '');
195
+ }
196
+ else if (this.valueNode && this.valueNode.toString(true) !== '') {
197
+ tokens.push(
198
+ //
199
+ '=', this.startQuote?.toString(true) || '"', this.valueNode.toString(true), this.endQuote?.toString(true) || '"');
200
+ }
201
+ return tokens.join('');
202
+ }
165
203
  }
166
204
  _MLAttr_localName = new WeakMap(), _MLAttr_namespaceURI = new WeakMap(), _MLAttr_potentialName = new WeakMap(), _MLAttr_potentialValue = new WeakMap();
@@ -1,9 +1,7 @@
1
1
  import { after, before, remove, replaceWith } from '../manipulations/child-node-methods.js';
2
2
  import { MLNode } from './node.js';
3
3
  export class MLBlock extends MLNode {
4
- constructor(
5
- // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
6
- astNode,
4
+ constructor(astNode,
7
5
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
8
6
  document) {
9
7
  super(astNode, document);
@@ -1,8 +1,8 @@
1
1
  import type { MLElement } from './element.js';
2
- import type { MLASTAbstractNode } from '@markuplint/ml-ast';
2
+ import type { MLASTNode } from '@markuplint/ml-ast';
3
3
  import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
4
4
  import { MLNode } from './node.js';
5
- export declare abstract class MLCharacterData<T extends RuleConfigValue, O extends PlainData = undefined, A extends MLASTAbstractNode = MLASTAbstractNode> extends MLNode<T, O, A> implements CharacterData {
5
+ export declare abstract class MLCharacterData<T extends RuleConfigValue, O extends PlainData = undefined, A extends MLASTNode = MLASTNode> extends MLNode<T, O, A> implements CharacterData {
6
6
  /**
7
7
  * @implements DOM API: `CharacterData`
8
8
  * @see https://dom.spec.whatwg.org/#dom-characterdata-data
@@ -1,9 +1,9 @@
1
1
  import type { MLBlock } from './block.js';
2
2
  import type { MLCharacterData } from './character-data.js';
3
- import type { MLDocumentType } from './document-type.js';
3
+ import type { MLComment } from './comment.js';
4
4
  import type { MLElement } from './element.js';
5
5
  import type { MLNode } from './node.js';
6
6
  import type { MLText } from './text.js';
7
7
  import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
8
- export type MLChildNode<T extends RuleConfigValue, O extends PlainData = undefined> = MLDocumentType<T, O> | MLCharacterData<T, O> | MLText<T, O> | MLElement<T, O> | MLBlock<T, O>;
8
+ export type MLChildNode<T extends RuleConfigValue, O extends PlainData = undefined> = MLCharacterData<T, O> | MLComment<T, O> | MLText<T, O> | MLElement<T, O> | MLBlock<T, O>;
9
9
  export declare function isChildNode<T extends RuleConfigValue, O extends PlainData = undefined>(node: MLNode<T, O>): node is MLChildNode<T, O>;
@@ -1,8 +1,8 @@
1
1
  import type { DocumentFragmentNodeType } from './types.js';
2
- import type { MLASTAbstractNode } from '@markuplint/ml-ast';
2
+ import type { MLASTNode } from '@markuplint/ml-ast';
3
3
  import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
4
4
  import { MLParentNode } from './parent-node.js';
5
- export declare class MLDocumentFragment<T extends RuleConfigValue, O extends PlainData = undefined> extends MLParentNode<T, O, MLASTAbstractNode> implements DocumentFragment {
5
+ export declare class MLDocumentFragment<T extends RuleConfigValue, O extends PlainData = undefined> extends MLParentNode<T, O, MLASTNode> implements DocumentFragment {
6
6
  /**
7
7
  * Returns a string appropriate for the type of node as `DocumentFragment`
8
8
  *
@@ -1,9 +1,7 @@
1
1
  import { after, before, remove, replaceWith } from '../manipulations/child-node-methods.js';
2
2
  import { MLNode } from './node.js';
3
3
  export class MLDocumentType extends MLNode {
4
- constructor(
5
- // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
6
- astNode,
4
+ constructor(astNode,
7
5
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
8
6
  document) {
9
7
  super(astNode, document);
@@ -1479,7 +1479,7 @@ export declare class MLDocument<T extends RuleConfigValue, O extends PlainData =
1479
1479
  /**
1480
1480
  * @implements `@markuplint/ml-core` API: `MLDocument`
1481
1481
  */
1482
- getTokenList(): readonly MLToken<import("@markuplint/ml-ast").MLToken>[];
1482
+ getTokenList(): readonly MLToken<import("@markuplint/ml-ast").MLASTToken>[];
1483
1483
  /**
1484
1484
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
1485
1485
  *
@@ -1566,7 +1566,7 @@ export declare class MLDocument<T extends RuleConfigValue, O extends PlainData =
1566
1566
  /**
1567
1567
  * @implements `@markuplint/ml-core` API: `MLDocument`
1568
1568
  */
1569
- searchNodeByLocation(line: number, col: number): MLNode<T, O, import("@markuplint/ml-ast").MLASTAbstractNode> | null;
1569
+ searchNodeByLocation(line: number, col: number): MLNode<T, O, import("@markuplint/ml-ast").MLASTNode> | null;
1570
1570
  /**
1571
1571
  * @implements `@markuplint/ml-core` API: `MLDocument`
1572
1572
  */
@@ -1574,7 +1574,7 @@ export declare class MLDocument<T extends RuleConfigValue, O extends PlainData =
1574
1574
  /**
1575
1575
  * @implements `@markuplint/ml-core` API: `MLDocument`
1576
1576
  */
1577
- toString(): string;
1577
+ toString(fixed?: boolean): string;
1578
1578
  /**
1579
1579
  * @implements `@markuplint/ml-core` API: `MLDocument`
1580
1580
  */
@@ -31,9 +31,7 @@ export class MLDocument extends MLParentNode {
31
31
  * @param ast node list of markuplint AST
32
32
  * @param ruleset ruleset object
33
33
  */
34
- constructor(
35
- // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
36
- ast, ruleset, schemas, options) {
34
+ constructor(ast, ruleset, schemas, options) {
37
35
  // @ts-ignore
38
36
  super(ast, null);
39
37
  /**
@@ -2090,12 +2088,18 @@ export class MLDocument extends MLParentNode {
2090
2088
  /**
2091
2089
  * @implements `@markuplint/ml-core` API: `MLDocument`
2092
2090
  */
2093
- toString() {
2094
- const html = [];
2091
+ toString(fixed = false) {
2092
+ if (!fixed) {
2093
+ return this.raw;
2094
+ }
2095
+ let raw = this.raw;
2096
+ let offset = 0;
2095
2097
  for (const node of this.getTokenList()) {
2096
- html.push(node.toString());
2098
+ const nodeRaw = node.toString(true);
2099
+ raw = raw.slice(0, node.startOffset + offset) + nodeRaw + raw.slice(node.endOffset + offset);
2100
+ offset += nodeRaw.length - (node.endOffset - node.startOffset);
2097
2101
  }
2098
- return html.join('');
2102
+ return raw;
2099
2103
  }
2100
2104
  walkOn(type, walker, skipWhenRuleIsDisabled = true) {
2101
2105
  return sequentialWalker(this.nodeList, node => {
@@ -2141,9 +2145,6 @@ export class MLDocument extends MLParentNode {
2141
2145
  if (docLog.enabled) {
2142
2146
  docLog('Pretending: %O', pretenders);
2143
2147
  }
2144
- if (!pretenders) {
2145
- return;
2146
- }
2147
2148
  for (const node of this.nodeList) {
2148
2149
  if (node.is(node.ELEMENT_NODE)) {
2149
2150
  node.pretending(pretenders);
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
12
  var _MLDomTokenList_origin, _MLDomTokenList_ownerAttrs, _MLDomTokenList_set;
13
- import { getCol, getLine } from '@markuplint/parser-utils';
13
+ import { getCol, getLine } from '@markuplint/parser-utils/location';
14
14
  import { UnexpectedCallError } from './unexpected-call-error.js';
15
15
  export class MLDomTokenList extends Array {
16
16
  constructor(tokens,
@@ -0,0 +1,20 @@
1
+ import type { MLDocument } from './document.js';
2
+ import type { MLElement } from './element.js';
3
+ import type { MLASTElementCloseTag } from '@markuplint/ml-ast';
4
+ import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
5
+ import { MLNode } from './node.js';
6
+ export declare class MLElementCloseTag<T extends RuleConfigValue, O extends PlainData = undefined> extends MLNode<T, O, MLASTElementCloseTag> {
7
+ readonly pair: MLElement<T, O>;
8
+ constructor(astNode: MLASTElementCloseTag, document: MLDocument<T, O>, pair: MLElement<T, O>);
9
+ /**
10
+ * Returns a string appropriate for the type of node as `MLBlock`
11
+ *
12
+ * @implements `@markuplint/ml-core` API: `MLBlock`
13
+ */
14
+ get nodeName(): string;
15
+ /**
16
+ * @implements `@markuplint/ml-core` API: `MLElement`
17
+ */
18
+ get rawName(): string;
19
+ toString(fixed?: boolean): string;
20
+ }
@@ -0,0 +1,39 @@
1
+ import { MLNode } from './node.js';
2
+ export class MLElementCloseTag extends MLNode {
3
+ constructor(astNode,
4
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
5
+ document,
6
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
7
+ pair) {
8
+ super(astNode, document);
9
+ this.pair = pair;
10
+ }
11
+ /**
12
+ * Returns a string appropriate for the type of node as `MLBlock`
13
+ *
14
+ * @implements `@markuplint/ml-core` API: `MLBlock`
15
+ */
16
+ get nodeName() {
17
+ return this.pair.nodeName;
18
+ }
19
+ /**
20
+ * @implements `@markuplint/ml-core` API: `MLElement`
21
+ */
22
+ get rawName() {
23
+ return this._astToken.nodeName;
24
+ }
25
+ toString(fixed = false) {
26
+ if (!fixed) {
27
+ return this.raw;
28
+ }
29
+ if (this.pair.isOmitted) {
30
+ return this.raw;
31
+ }
32
+ return [
33
+ this.pair.tagOpenChar,
34
+ this.pair.tagOpenChar === '' ? '' : '/',
35
+ this.pair.fixedNodeName === this.pair.rawName ? this.rawName : this.pair.fixedNodeName,
36
+ this.pair.tagCloseChar,
37
+ ].join('');
38
+ }
39
+ }
@@ -8,13 +8,19 @@ import type { ARIAVersion } from '@markuplint/ml-spec';
8
8
  import { MLToken } from '../token/token.js';
9
9
  import { MLAttr } from './attr.js';
10
10
  import { MLDomTokenList } from './dom-token-list.js';
11
+ import { MLElementCloseTag } from './element-close-tag.js';
11
12
  import { MLParentNode } from './parent-node.js';
12
13
  export declare class MLElement<T extends RuleConfigValue, O extends PlainData = undefined> extends MLParentNode<T, O, MLASTElement> implements Element, HTMLOrSVGElement, HTMLElement {
13
14
  #private;
14
- readonly closeTag: MLToken | null;
15
+ readonly closeTag: MLElementCloseTag<T, O> | null;
16
+ /**
17
+ * Element type
18
+ *
19
+ * - `html`: From native HTML Standard
20
+ * - `web-component`: As the Web Component according to HTML Standard
21
+ * - `authored`: Authored element (JSX Element etc.) through the view framework or the template engine.
22
+ */
15
23
  readonly elementType: ElementType;
16
- readonly endSpace: MLToken | null;
17
- readonly hasSpreadAttr: boolean;
18
24
  readonly isForeignElement: boolean;
19
25
  readonly isOmitted: boolean;
20
26
  readonly namespaceURI: NamespaceURI;
@@ -24,6 +30,8 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
24
30
  readonly ontouchstart?: ((this: GlobalEventHandlers, ev: TouchEvent) => any) | null | undefined;
25
31
  pretenderContext: PretenderContext<MLElement<T, O>, T, O> | null;
26
32
  readonly selfClosingSolidus: MLToken | null;
33
+ readonly tagCloseChar: string;
34
+ readonly tagOpenChar: string;
27
35
  constructor(astNode: MLASTElement, document: MLDocument<T, O>);
28
36
  /**
29
37
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -469,6 +477,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
469
477
  * @implements `@markuplint/ml-core` API: `MLElement`
470
478
  */
471
479
  get fixedNodeName(): string;
480
+ get hasSpreadAttr(): boolean;
472
481
  /**
473
482
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
474
483
  *
@@ -1398,7 +1407,6 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1398
1407
  * @see https://dom.spec.whatwg.org/#ref-for-dom-nondocumenttypechildnode-previouselementsibling%E2%91%A1
1399
1408
  */
1400
1409
  get previousElementSibling(): MLElement<T, O> | null;
1401
- get raw(): string;
1402
1410
  /**
1403
1411
  * @implements `@markuplint/ml-core` API: `MLElement`
1404
1412
  */
@@ -1781,7 +1789,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1781
1789
  /**
1782
1790
  * Pretenders Initialization
1783
1791
  */
1784
- pretending(pretenders: readonly Pretender[]): void;
1792
+ pretending(pretenders?: readonly Pretender[]): void;
1785
1793
  /**
1786
1794
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
1787
1795
  *
@@ -1925,7 +1933,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1925
1933
  /**
1926
1934
  * @implements `@markuplint/ml-core` API: `MLElement`
1927
1935
  */
1928
- toString(): string;
1936
+ toString(fixed?: boolean): string;
1929
1937
  /**
1930
1938
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
1931
1939
  *
@@ -10,24 +10,22 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _MLElement_attributes, _MLElement_fixedNodeName, _MLElement_getChildElementsAndTextNodeWithoutWhitespacesCache, _MLElement_localName, _MLElement_normalizedAttrs, _MLElement_normalizedString, _MLElement_tagOpenChar;
13
+ var _MLElement_attributes, _MLElement_fixedNodeName, _MLElement_getChildElementsAndTextNodeWithoutWhitespacesCache, _MLElement_localName, _MLElement_normalizedAttrs, _MLElement_normalizedString;
14
14
  import { resolveNamespace } from '@markuplint/ml-spec';
15
15
  import { createSelector } from '@markuplint/selector';
16
- import { stringSplice } from '../../utils/string-splice.js';
17
16
  import { getAccname } from '../helper/accname.js';
18
17
  import { after, before, nextElementSibling, previousElementSibling, remove, replaceWith, } from '../manipulations/child-node-methods.js';
19
18
  import { MLToken } from '../token/token.js';
20
19
  import { MLAttr } from './attr.js';
21
20
  import { MLDomTokenList } from './dom-token-list.js';
21
+ import { MLElementCloseTag } from './element-close-tag.js';
22
22
  import { toNamedNodeMap } from './named-node-map.js';
23
23
  import { toHTMLCollection } from './node-list.js';
24
24
  import { MLParentNode } from './parent-node.js';
25
25
  import { UnexpectedCallError } from './unexpected-call-error.js';
26
26
  const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
27
27
  export class MLElement extends MLParentNode {
28
- constructor(
29
- // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
30
- astNode,
28
+ constructor(astNode,
31
29
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
32
30
  document) {
33
31
  super(astNode, document);
@@ -38,12 +36,9 @@ export class MLElement extends MLParentNode {
38
36
  _MLElement_normalizedAttrs.set(this, new Map());
39
37
  _MLElement_normalizedString.set(this, null);
40
38
  this.pretenderContext = null;
41
- _MLElement_tagOpenChar.set(this, void 0);
42
39
  __classPrivateFieldSet(this, _MLElement_attributes, astNode.attributes.map(attr => new MLAttr(attr, this)), "f");
43
- this.hasSpreadAttr = astNode.hasSpreadAttr;
44
40
  this.selfClosingSolidus = astNode.selfClosingSolidus ? new MLToken(astNode.selfClosingSolidus) : null;
45
- this.endSpace = astNode.endSpace ? new MLToken(astNode.endSpace) : null;
46
- this.closeTag = astNode.pearNode ? new MLToken(astNode.pearNode) : null;
41
+ this.closeTag = astNode.pairNode ? new MLElementCloseTag(astNode.pairNode, document, this) : null;
47
42
  const ns = resolveNamespace(astNode.nodeName, astNode.namespace);
48
43
  this.namespaceURI = ns.namespaceURI;
49
44
  this.elementType = astNode.elementType;
@@ -51,7 +46,8 @@ export class MLElement extends MLParentNode {
51
46
  this.isForeignElement = this.namespaceURI !== HTML_NAMESPACE;
52
47
  __classPrivateFieldSet(this, _MLElement_fixedNodeName, astNode.nodeName, "f");
53
48
  this.isOmitted = astNode.isGhost;
54
- __classPrivateFieldSet(this, _MLElement_tagOpenChar, astNode.tagOpenChar, "f");
49
+ this.tagOpenChar = astNode.tagOpenChar;
50
+ this.tagCloseChar = astNode.tagCloseChar;
55
51
  }
56
52
  /**
57
53
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -634,6 +630,9 @@ export class MLElement extends MLParentNode {
634
630
  get fixedNodeName() {
635
631
  return __classPrivateFieldGet(this, _MLElement_fixedNodeName, "f");
636
632
  }
633
+ get hasSpreadAttr() {
634
+ return __classPrivateFieldGet(this, _MLElement_attributes, "f").some(attr => attr.localName === '#spread');
635
+ }
637
636
  /**
638
637
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
639
638
  *
@@ -1809,26 +1808,6 @@ export class MLElement extends MLParentNode {
1809
1808
  get previousElementSibling() {
1810
1809
  return previousElementSibling(this);
1811
1810
  }
1812
- get raw() {
1813
- if (this.pretenderContext?.type === 'pretender') {
1814
- return this.originRaw;
1815
- }
1816
- let fixed = this.originRaw;
1817
- let gap = 0;
1818
- if (this.nodeName !== this.fixedNodeName) {
1819
- fixed = stringSplice(fixed, __classPrivateFieldGet(this, _MLElement_tagOpenChar, "f").length, this.nodeName.length, this.fixedNodeName);
1820
- gap = gap + this.fixedNodeName.length - this.nodeName.length;
1821
- }
1822
- for (const attr of this.attributes) {
1823
- const startOffset = (attr.spacesBeforeName?.startOffset ?? attr.startOffset) - this.startOffset;
1824
- const fixedAttr = attr.toString();
1825
- if (attr.originRaw !== fixedAttr) {
1826
- fixed = stringSplice(fixed, startOffset + gap, attr.originRaw.length, fixedAttr);
1827
- gap = gap + fixedAttr.length - attr.originRaw.length;
1828
- }
1829
- }
1830
- return fixed;
1831
- }
1832
1811
  /**
1833
1812
  * @implements `@markuplint/ml-core` API: `MLElement`
1834
1813
  */
@@ -2293,7 +2272,7 @@ export class MLElement extends MLParentNode {
2293
2272
  return {
2294
2273
  offset: this.startOffset,
2295
2274
  line: this.startLine,
2296
- col: this.startCol + __classPrivateFieldGet(this, _MLElement_tagOpenChar, "f").length,
2275
+ col: this.startCol + this.tagOpenChar.length,
2297
2276
  };
2298
2277
  }
2299
2278
  /**
@@ -2454,24 +2433,32 @@ export class MLElement extends MLParentNode {
2454
2433
  */
2455
2434
  pretending(pretenders) {
2456
2435
  const pretenderConfig = pretenders?.find(option => this.matches(option.selector));
2457
- if (!pretenderConfig) {
2436
+ const asAttrValue = this.getAttribute('as');
2437
+ const pretenderElement = pretenderConfig?.as ??
2438
+ (this.elementType === 'html' || !asAttrValue
2439
+ ? null
2440
+ : {
2441
+ element: asAttrValue,
2442
+ inheritAttrs: true,
2443
+ });
2444
+ if (pretenderElement == null) {
2458
2445
  return;
2459
2446
  }
2460
2447
  let nodeName;
2461
2448
  let namespace = 'html';
2462
2449
  const attributes = [];
2463
2450
  let aria;
2464
- if (typeof pretenderConfig.as === 'string') {
2465
- nodeName = pretenderConfig.as;
2451
+ if (typeof pretenderElement === 'string') {
2452
+ nodeName = pretenderElement;
2466
2453
  }
2467
2454
  else {
2468
- nodeName = pretenderConfig.as.element;
2469
- namespace = pretenderConfig.as.namespace ?? namespace;
2470
- if (pretenderConfig.as.inheritAttrs) {
2455
+ nodeName = pretenderElement.element;
2456
+ namespace = pretenderElement.namespace ?? namespace;
2457
+ if (pretenderElement.inheritAttrs) {
2471
2458
  attributes.push(...this._astToken.attributes);
2472
2459
  }
2473
- if (pretenderConfig.as.attrs) {
2474
- attributes.push(...pretenderConfig.as.attrs.map(({ name, value }, i) => {
2460
+ if (pretenderElement.attrs) {
2461
+ attributes.push(...pretenderElement.attrs.map(({ name, value }, i) => {
2475
2462
  const _value = value == null
2476
2463
  ? ''
2477
2464
  : typeof value === 'string'
@@ -2480,7 +2467,7 @@ export class MLElement extends MLParentNode {
2480
2467
  return {
2481
2468
  ...this._astToken,
2482
2469
  uuid: `${this.uuid}_attr_${i}`,
2483
- type: 'html-attr',
2470
+ type: 'attr',
2484
2471
  nodeName: name,
2485
2472
  spacesBeforeName: {
2486
2473
  ...this._astToken,
@@ -2523,7 +2510,7 @@ export class MLElement extends MLParentNode {
2523
2510
  };
2524
2511
  }));
2525
2512
  }
2526
- aria = pretenderConfig.as.aria;
2513
+ aria = pretenderElement.aria;
2527
2514
  }
2528
2515
  const as = new MLElement({
2529
2516
  ...this._astToken,
@@ -2744,7 +2731,7 @@ export class MLElement extends MLParentNode {
2744
2731
  if (node.is(node.ELEMENT_NODE)) {
2745
2732
  return node.toNormalizeString();
2746
2733
  }
2747
- return node.originRaw;
2734
+ return node.raw;
2748
2735
  });
2749
2736
  const endTag = `</${this.nodeName}>`;
2750
2737
  const normalizedString = `${startTag}${childNodes.join('')}${endTag}`;
@@ -2754,8 +2741,37 @@ export class MLElement extends MLParentNode {
2754
2741
  /**
2755
2742
  * @implements `@markuplint/ml-core` API: `MLElement`
2756
2743
  */
2757
- toString() {
2758
- return this.raw;
2744
+ toString(fixed = false) {
2745
+ if (!fixed) {
2746
+ return this.raw;
2747
+ }
2748
+ if (this.pretenderContext?.type === 'pretender') {
2749
+ return this.raw;
2750
+ }
2751
+ if (this.nodeName.startsWith('#')) {
2752
+ return this.raw;
2753
+ }
2754
+ if (this.isOmitted) {
2755
+ return this.raw;
2756
+ }
2757
+ let raw = this.raw;
2758
+ let offset = 0;
2759
+ const nodes = [
2760
+ {
2761
+ toString: () => this.tagOpenChar + this.fixedNodeName,
2762
+ startOffset: this.startOffset,
2763
+ endOffset: this.startOffset + this.tagOpenChar.length + this.nodeName.length,
2764
+ },
2765
+ ...this.attributes,
2766
+ ];
2767
+ for (const node of nodes) {
2768
+ const before = raw.slice(0, node.startOffset + offset - this.startOffset);
2769
+ const rawCode = node.toString(true);
2770
+ const after = raw.slice(node.endOffset + offset - this.startOffset);
2771
+ raw = before + rawCode + after;
2772
+ offset += rawCode.length - (node.endOffset - node.startOffset);
2773
+ }
2774
+ return raw;
2759
2775
  }
2760
2776
  /**
2761
2777
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -2788,4 +2804,4 @@ export class MLElement extends MLParentNode {
2788
2804
  throw new UnexpectedCallError('Not supported "webkitMatchesSelector" method');
2789
2805
  }
2790
2806
  }
2791
- _MLElement_attributes = new WeakMap(), _MLElement_fixedNodeName = new WeakMap(), _MLElement_getChildElementsAndTextNodeWithoutWhitespacesCache = new WeakMap(), _MLElement_localName = new WeakMap(), _MLElement_normalizedAttrs = new WeakMap(), _MLElement_normalizedString = new WeakMap(), _MLElement_tagOpenChar = new WeakMap();
2807
+ _MLElement_attributes = new WeakMap(), _MLElement_fixedNodeName = new WeakMap(), _MLElement_getChildElementsAndTextNodeWithoutWhitespacesCache = new WeakMap(), _MLElement_localName = new WeakMap(), _MLElement_normalizedAttrs = new WeakMap(), _MLElement_normalizedString = new WeakMap();
@@ -1,11 +1,11 @@
1
1
  import type { MLNode } from './node.js';
2
2
  import type { MappedNode } from './types.js';
3
- import type { MLASTAbstractNode } from '@markuplint/ml-ast';
3
+ import type { MLASTNode } from '@markuplint/ml-ast';
4
4
  import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
5
5
  declare class NodeStore {
6
6
  #private;
7
- getNode<N extends MLASTAbstractNode, T extends RuleConfigValue, O extends PlainData = undefined>(astNode: N): MappedNode<N, T, O>;
8
- setNode<A extends MLASTAbstractNode, T extends RuleConfigValue, O extends PlainData = undefined>(astNode: A, node: MLNode<T, O, A>): void;
7
+ getNode<N extends MLASTNode, T extends RuleConfigValue, O extends PlainData = undefined>(astNode: N): MappedNode<N, T, O>;
8
+ setNode<A extends MLASTNode, T extends RuleConfigValue, O extends PlainData = undefined>(astNode: A, node: MLNode<T, O, A>): void;
9
9
  }
10
10
  /**
11
11
  * `NodeStore` Singleton
@@ -5,10 +5,10 @@ import type { MLDocument } from './document.js';
5
5
  import type { MLElement } from './element.js';
6
6
  import type { MarkuplintPreprocessorBlockType, NodeType, NodeTypeOf } from './types.js';
7
7
  import type { RuleInfo } from '../../index.js';
8
- import type { MLASTAbstractNode } from '@markuplint/ml-ast';
8
+ import type { MLASTNode } from '@markuplint/ml-ast';
9
9
  import type { AnyRule, PlainData, RuleConfigValue } from '@markuplint/ml-config';
10
10
  import { MLToken } from '../token/token.js';
11
- export declare abstract class MLNode<T extends RuleConfigValue, O extends PlainData = undefined, A extends MLASTAbstractNode = MLASTAbstractNode> extends MLToken<A> implements Node {
11
+ export declare abstract class MLNode<T extends RuleConfigValue, O extends PlainData = undefined, A extends MLASTNode = MLASTNode> extends MLToken<A> implements Node {
12
12
  #private;
13
13
  /**
14
14
  * @implements DOM API: `Node`
@@ -175,11 +175,17 @@ export class MLNode extends MLToken {
175
175
  if (this.is(this.DOCUMENT_FRAGMENT_NODE) ||
176
176
  this.is(this.ELEMENT_NODE) ||
177
177
  this.is(this.MARKUPLINT_PREPROCESSOR_BLOCK)) {
178
+ const astChildren =
178
179
  // @ts-ignore
179
- const astChildren = this._astToken.childNodes ?? [];
180
+ this._astToken?.childNodes?.filter(node => {
181
+ if (node.type === 'endtag' || node.type === 'invalid') {
182
+ return null;
183
+ }
184
+ return node;
185
+ }) ?? [];
180
186
  const childNodes = astChildren
181
187
  .map(node => nodeStore.getNode(node))
182
- .filter((node) => isChildNode(node));
188
+ .filter(node => isChildNode(node));
183
189
  // Cache
184
190
  __classPrivateFieldSet(this, _MLNode_childNodes, toNodeList(childNodes), "f");
185
191
  return __classPrivateFieldGet(this, _MLNode_childNodes, "f");
@@ -223,10 +229,9 @@ export class MLNode extends MLToken {
223
229
  * @implements `@markuplint/ml-core` API: `MLNode`
224
230
  */
225
231
  get nextNode() {
226
- if (!this._astToken.nextNode) {
227
- return null;
228
- }
229
- return nodeStore.getNode(this._astToken.nextNode);
232
+ const siblings = [...(this.syntacticalParentNode?.childNodes ?? __classPrivateFieldGet(this, _MLNode_ownerDocument, "f").nodeList)];
233
+ const index = siblings.findIndex(node => node.uuid === this.uuid);
234
+ return siblings[index + 1] ?? null;
230
235
  }
231
236
  /**
232
237
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -368,10 +373,9 @@ export class MLNode extends MLToken {
368
373
  * @implements `@markuplint/ml-core` API: `MLNode`
369
374
  */
370
375
  get prevNode() {
371
- if (!this._astToken.prevNode) {
372
- return null;
373
- }
374
- return nodeStore.getNode(this._astToken.prevNode);
376
+ const siblings = [...(this.syntacticalParentNode?.childNodes ?? __classPrivateFieldGet(this, _MLNode_ownerDocument, "f").nodeList)];
377
+ const index = siblings.findIndex(node => node.uuid === this.uuid);
378
+ return siblings[index - 1] ?? null;
375
379
  }
376
380
  /**
377
381
  * @implements `@markuplint/ml-core` API: `MLNode`
@@ -466,6 +470,9 @@ export class MLNode extends MLToken {
466
470
  * @implements `@markuplint/ml-core` API: `MLNode`
467
471
  */
468
472
  get syntacticalParentNode() {
473
+ if (this._astToken.type === 'attr' || this._astToken.type === 'spread') {
474
+ return null;
475
+ }
469
476
  if (!this._astToken.parentNode) {
470
477
  return this.ownerMLDocument;
471
478
  }
@@ -1,12 +1,12 @@
1
1
  import type { MLElement } from './element.js';
2
- import type { MLASTAbstractNode } from '@markuplint/ml-ast';
2
+ import type { MLASTNode } from '@markuplint/ml-ast';
3
3
  import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
4
4
  import { MLNode } from './node.js';
5
5
  /**
6
6
  *
7
7
  * @see https://dom.spec.whatwg.org/#interface-parentnode
8
8
  */
9
- export declare abstract class MLParentNode<T extends RuleConfigValue, O extends PlainData = undefined, A extends MLASTAbstractNode = MLASTAbstractNode> extends MLNode<T, O, A> implements ParentNode {
9
+ export declare abstract class MLParentNode<T extends RuleConfigValue, O extends PlainData = undefined, A extends MLASTNode = MLASTNode> extends MLNode<T, O, A> implements ParentNode {
10
10
  #private;
11
11
  /**
12
12
  * @implements DOM API: `Element`, `Document`, `DocumentFragment`
@@ -5,12 +5,11 @@ import type { MLDocumentFragment } from './document-fragment.js';
5
5
  import type { MLDocumentType } from './document-type.js';
6
6
  import type { MLDocument } from './document.js';
7
7
  import type { MLElement } from './element.js';
8
- import type { MLNode } from './node.js';
9
8
  import type { MLText } from './text.js';
10
9
  import type { MLToken } from '../token/token.js';
11
- import type { MLASTAbstractNode, MLASTAttr, MLASTComment, MLASTDoctype, MLASTElement, MLASTParentNode, MLASTPreprocessorSpecificBlock, MLASTText, MLToken as MLASTToken } from '@markuplint/ml-ast/';
10
+ import type { MLASTAttr, MLASTComment, MLASTDoctype, MLASTElement, MLASTInvalid, MLASTParentNode, MLASTPreprocessorSpecificBlock, MLASTText, MLASTToken as MLASTToken } from '@markuplint/ml-ast/';
12
11
  import type { PlainData, PretenderARIA, RuleConfigValue } from '@markuplint/ml-config';
13
- export type MappedNode<N, T extends RuleConfigValue, O extends PlainData = undefined> = N extends MLASTElement ? MLElement<T, O> : N extends MLASTParentNode ? MLElement<T, O> : N extends MLASTComment ? MLComment<T, O> : N extends MLASTText ? MLText<T, O> : N extends MLASTDoctype ? MLDocumentType<T, O> : N extends MLASTPreprocessorSpecificBlock ? MLBlock<T, O> : N extends MLASTAbstractNode ? MLNode<T, O, MLASTAbstractNode> : N extends MLASTAttr ? MLAttr<T, O> : N extends MLASTToken ? MLToken : never;
12
+ export type MappedNode<N, T extends RuleConfigValue, O extends PlainData = undefined> = N extends MLASTElement ? MLElement<T, O> : N extends MLASTParentNode ? MLElement<T, O> : N extends MLASTComment ? MLComment<T, O> : N extends MLASTText ? MLText<T, O> : N extends MLASTDoctype ? MLDocumentType<T, O> : N extends MLASTPreprocessorSpecificBlock ? MLBlock<T, O> : N extends MLASTAttr ? MLAttr<T, O> : N extends MLASTInvalid ? MLText<T, O> : N extends MLASTToken ? MLToken : never;
14
13
  export type NodeTypeOf<NT extends NodeType, T extends RuleConfigValue, O extends PlainData = undefined> = NT extends ElementNodeType ? MLElement<T, O> : NT extends CommentNodeType ? MLComment<T, O> : NT extends TextNodeType ? MLText<T, O> : NT extends DocumentNodeType ? MLDocument<T, O> : NT extends DocumentTypeNodeType ? MLDocumentType<T, O> : NT extends DocumentFragmentNodeType ? MLDocumentFragment<T, O> : NT extends MarkuplintPreprocessorBlockType ? MLBlock<T, O> : NT extends AttributeNodeType ? MLAttr<T, O> : never;
15
14
  export type ElementNodeType = 1;
16
15
  export type AttributeNodeType = 2;
@@ -1,4 +1,4 @@
1
- import type { MLToken as MLASTToken } from '@markuplint/ml-ast';
1
+ import type { MLASTToken } from '@markuplint/ml-ast';
2
2
  export declare class MLToken<A extends MLASTToken = MLASTToken> {
3
3
  #private;
4
4
  readonly uuid: string;
@@ -19,7 +19,7 @@ export declare class MLToken<A extends MLASTToken = MLASTToken> {
19
19
  /**
20
20
  * @implements `@markuplint/ml-core` API: `MLDOMToken`
21
21
  */
22
- get originRaw(): string;
22
+ get fixed(): string;
23
23
  /**
24
24
  * @implements `@markuplint/ml-core` API: `MLDOMToken`
25
25
  */
@@ -43,5 +43,5 @@ export declare class MLToken<A extends MLASTToken = MLASTToken> {
43
43
  /**
44
44
  * @implements `@markuplint/ml-core` API: `MLDOMToken`
45
45
  */
46
- toString(): string;
46
+ toString(fixed?: boolean): string;
47
47
  }
@@ -52,14 +52,14 @@ export class MLToken {
52
52
  /**
53
53
  * @implements `@markuplint/ml-core` API: `MLDOMToken`
54
54
  */
55
- get originRaw() {
56
- return __classPrivateFieldGet(this, _MLToken_raw, "f");
55
+ get fixed() {
56
+ return __classPrivateFieldGet(this, _MLToken_fixed, "f");
57
57
  }
58
58
  /**
59
59
  * @implements `@markuplint/ml-core` API: `MLDOMToken`
60
60
  */
61
61
  get raw() {
62
- return __classPrivateFieldGet(this, _MLToken_fixed, "f");
62
+ return __classPrivateFieldGet(this, _MLToken_raw, "f");
63
63
  }
64
64
  /**
65
65
  * @implements `@markuplint/ml-core` API: `MLDOMToken`
@@ -88,8 +88,8 @@ export class MLToken {
88
88
  /**
89
89
  * @implements `@markuplint/ml-core` API: `MLDOMToken`
90
90
  */
91
- toString() {
92
- return this.raw;
91
+ toString(fixed = false) {
92
+ return fixed ? __classPrivateFieldGet(this, _MLToken_fixed, "f") : __classPrivateFieldGet(this, _MLToken_raw, "f");
93
93
  }
94
94
  }
95
95
  _MLToken_endCol = new WeakMap(), _MLToken_endLine = new WeakMap(), _MLToken_endOffset = new WeakMap(), _MLToken_fixed = new WeakMap(), _MLToken_raw = new WeakMap(), _MLToken_startCol = new WeakMap(), _MLToken_startLine = new WeakMap(), _MLToken_startOffset = new WeakMap();
@@ -3,6 +3,9 @@ import type { Attr, Element } from '../ml-dom/index.js';
3
3
  import type { Translator } from '@markuplint/i18n';
4
4
  import type { PlainData, Report, RuleConfigValue, Severity } from '@markuplint/ml-config';
5
5
  export type RuleSeed<T extends RuleConfigValue = boolean, O extends PlainData = undefined> = {
6
+ readonly meta?: {
7
+ readonly category?: 'validation' | 'style' | 'naming-convention' | 'a11y' | 'maintainability';
8
+ };
6
9
  readonly defaultSeverity?: Severity;
7
10
  readonly defaultValue?: T;
8
11
  readonly defaultOptions?: O;
@@ -1,15 +1,17 @@
1
- import type { MLMarkupLanguageParser } from '@markuplint/ml-ast';
1
+ import type { MLParser } from '@markuplint/ml-ast';
2
2
  import type { Config, PlainData, RuleConfigValue } from '@markuplint/ml-config';
3
3
  import type { ExtendedSpec, MLMLSpec } from '@markuplint/ml-spec';
4
4
  import { Document } from '../ml-dom/index.js';
5
5
  export type CreateTestOptions = {
6
6
  readonly config?: Config;
7
- readonly parser?: Readonly<MLMarkupLanguageParser>;
7
+ readonly parser?: {
8
+ readonly parser: Readonly<MLParser>;
9
+ } | Readonly<MLParser>;
8
10
  readonly specs?: MLMLSpec;
9
11
  };
10
12
  export declare function createTestDocument<T extends RuleConfigValue = any, O extends PlainData = any>(sourceCode: string, options?: CreateTestOptions): Document<T, O>;
11
- export declare function createTestNodeList(sourceCode: string, options?: CreateTestOptions): readonly import("../ml-dom/node/node.js").MLNode<any, any, import("@markuplint/ml-ast").MLASTAbstractNode>[];
12
- export declare function createTestTokenList(sourceCode: string, options?: CreateTestOptions): readonly import("../ml-dom/token/token.js").MLToken<import("@markuplint/ml-ast").MLToken>[];
13
+ export declare function createTestNodeList(sourceCode: string, options?: CreateTestOptions): readonly import("../ml-dom/node/node.js").MLNode<any, any, import("@markuplint/ml-ast").MLASTNode>[];
14
+ export declare function createTestTokenList(sourceCode: string, options?: CreateTestOptions): readonly import("../ml-dom/token/token.js").MLToken<import("@markuplint/ml-ast").MLASTToken>[];
13
15
  export declare function createTestElement(sourceCode: string, options?: CreateTestOptions): import("../ml-dom/index.js").Element<any, any>;
14
16
  /**
15
17
  * for test suite
package/lib/test/index.js CHANGED
@@ -1,9 +1,13 @@
1
- import { parse } from '@markuplint/html-parser';
1
+ import { parser } from '@markuplint/html-parser';
2
2
  import spec from '@markuplint/html-spec';
3
3
  import { convertRuleset } from '../convert-ruleset.js';
4
4
  import { Document } from '../ml-dom/index.js';
5
5
  export function createTestDocument(sourceCode, options) {
6
- const ast = options?.parser ? options.parser.parse(sourceCode) : parse(sourceCode);
6
+ const ast = options?.parser
7
+ ? 'parser' in options.parser
8
+ ? options.parser.parser.parse(sourceCode, options.config?.parserOptions)
9
+ : options.parser.parse(sourceCode, options.config?.parserOptions)
10
+ : parser.parse(sourceCode, options?.config?.parserOptions);
7
11
  const ruleset = convertRuleset(options?.config);
8
12
  const document = new Document(ast, ruleset, [options?.specs ?? {}, {}]);
9
13
  return document;
package/lib/types.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import type { AnyMLRule } from './ml-rule/index.js';
2
2
  import type { Ruleset } from './ruleset/index.js';
3
3
  import type { LocaleSet } from '@markuplint/i18n';
4
- import type { MLMarkupLanguageParser, ParserOptions } from '@markuplint/ml-ast';
4
+ import type { MLParser, ParserOptions } from '@markuplint/ml-ast';
5
5
  import type { Pretender } from '@markuplint/ml-config';
6
6
  import type { ExtendedSpec, MLMLSpec } from '@markuplint/ml-spec';
7
7
  export type MLSchema = readonly [MLMLSpec, ...ExtendedSpec[]];
8
8
  export type MLFabric = {
9
- readonly parser: Readonly<MLMarkupLanguageParser>;
9
+ readonly parser: Readonly<MLParser>;
10
10
  readonly ruleset: Partial<Readonly<Ruleset>>;
11
11
  readonly rules: readonly Readonly<AnyMLRule>[];
12
12
  readonly locale: LocaleSet;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/ml-core",
3
- "version": "4.0.0-dev.20+6b35da16",
3
+ "version": "4.0.0-dev.23+d6f2aa9bc",
4
4
  "description": "The core module of markuplint",
5
5
  "repository": "git@github.com:markuplint/markuplint.git",
6
6
  "author": "Yusuke Hirao <yusukehirao@me.com>",
@@ -28,19 +28,19 @@
28
28
  "./lib/configs.js": "./lib/configs.browser.js"
29
29
  },
30
30
  "dependencies": {
31
- "@markuplint/config-presets": "4.0.0-dev.20+6b35da16",
32
- "@markuplint/html-parser": "4.0.0-dev.20+6b35da16",
33
- "@markuplint/html-spec": "4.0.0-dev.20+6b35da16",
34
- "@markuplint/i18n": "4.0.0-dev.20+6b35da16",
35
- "@markuplint/ml-ast": "4.0.0-dev.20+6b35da16",
36
- "@markuplint/ml-config": "4.0.0-dev.20+6b35da16",
37
- "@markuplint/ml-spec": "4.0.0-dev.20+6b35da16",
38
- "@markuplint/parser-utils": "4.0.0-dev.20+6b35da16",
39
- "@markuplint/selector": "4.0.0-dev.20+6b35da16",
31
+ "@markuplint/config-presets": "4.0.0-dev.23+d6f2aa9bc",
32
+ "@markuplint/html-parser": "4.0.0-dev.23+d6f2aa9bc",
33
+ "@markuplint/html-spec": "4.0.0-dev.23+d6f2aa9bc",
34
+ "@markuplint/i18n": "4.0.0-dev.23+d6f2aa9bc",
35
+ "@markuplint/ml-ast": "4.0.0-dev.23+d6f2aa9bc",
36
+ "@markuplint/ml-config": "4.0.0-dev.23+d6f2aa9bc",
37
+ "@markuplint/ml-spec": "4.0.0-dev.23+d6f2aa9bc",
38
+ "@markuplint/parser-utils": "4.0.0-dev.23+d6f2aa9bc",
39
+ "@markuplint/selector": "4.0.0-dev.23+d6f2aa9bc",
40
40
  "@types/debug": "^4.1.12",
41
41
  "debug": "^4.3.4",
42
42
  "is-plain-object": "^5.0.0",
43
- "type-fest": "^4.8.3"
43
+ "type-fest": "^4.9.0"
44
44
  },
45
- "gitHead": "6b35da161d94f784953d0adecc2d28502052d92a"
45
+ "gitHead": "d6f2aa9bc287768466f23b5340e4e0eecfa30d59"
46
46
  }
package/lib/configs.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import type { Config } from '@markuplint/ml-config';
2
- export declare function getPreset(name: string): Promise<Config>;
package/lib/configs.js DELETED
@@ -1,37 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { log } from './debug.js';
4
- export async function getPreset(name) {
5
- const json = await forceImportJsonInModule(`@markuplint/config-presets/preset.${name}.json`);
6
- if (json instanceof Error) {
7
- throw new ReferenceError(`Preset markuplint:${name} is not found`);
8
- }
9
- return json;
10
- }
11
- async function forceImportJsonInModule(modPath) {
12
- const error = await import(modPath).catch(error => error);
13
- if (error instanceof Error) {
14
- log('Error in forceImportJsonInModule: %O', error);
15
- if (!('code' in error)) {
16
- throw error;
17
- }
18
- if (error.code !== 'ERR_IMPORT_ASSERTION_TYPE_MISSING') {
19
- throw error;
20
- }
21
- const searchPath = /module\s"([^"]+)"\sneeds/i.exec(error.message);
22
- const absPath = searchPath?.[1] ?? null;
23
- log('Extract path: %s', absPath);
24
- if (!absPath) {
25
- throw error;
26
- }
27
- const normalizePath = absPath
28
- .replace(/^file:\/\//, '')
29
- .replaceAll('/', path.sep)
30
- // Windows
31
- .replace(/^[/\\][a-z]:/i, '');
32
- log('Find JSON file path: %s', normalizePath);
33
- const fileContent = await readFile(normalizePath, { encoding: 'utf8' });
34
- return JSON.parse(fileContent);
35
- }
36
- return error.default ?? error;
37
- }