@markuplint/ml-core 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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(): Document<RuleConfigValue, PlainData> | ParserError;
13
+ get document(): ParserError | Document<RuleConfigValue, PlainData>;
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[]>;
@@ -48,14 +48,12 @@ node) {
48
48
  export function previousElementSibling(
49
49
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
50
50
  node) {
51
- let prevNode = node.prevNode;
51
+ let prevNode = node.previousSibling;
52
52
  while (prevNode) {
53
- if (((node.parentNode === null && prevNode.parentNode === null) ||
54
- node.parentNode?.uuid === prevNode.parentNode?.uuid) &&
55
- prevNode.is(prevNode.ELEMENT_NODE)) {
53
+ if (prevNode.is(prevNode.ELEMENT_NODE)) {
56
54
  return prevNode;
57
55
  }
58
- prevNode = prevNode.prevNode;
56
+ prevNode = prevNode.previousSibling;
59
57
  }
60
58
  return null;
61
59
  }
@@ -66,14 +64,12 @@ node) {
66
64
  export function nextElementSibling(
67
65
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
68
66
  node) {
69
- let nextNode = node.nextNode;
67
+ let nextNode = node.nextSibling;
70
68
  while (nextNode) {
71
- if (((node.parentNode === null && nextNode.parentNode === null) ||
72
- node.parentNode?.uuid === nextNode.parentNode?.uuid) &&
73
- nextNode.is(nextNode.ELEMENT_NODE)) {
69
+ if (nextNode.is(nextNode.ELEMENT_NODE)) {
74
70
  return nextNode;
75
71
  }
76
- nextNode = nextNode.nextNode;
72
+ nextNode = nextNode.nextSibling;
77
73
  }
78
74
  return null;
79
75
  }
@@ -1,9 +1,18 @@
1
1
  import type { MLBlock } from './block.js';
2
2
  import type { MLCharacterData } from './character-data.js';
3
- import type { MLComment } from './comment.js';
3
+ import type { MLDocumentType } from './document-type.js';
4
4
  import type { MLElement } from './element.js';
5
5
  import type { MLNode } from './node.js';
6
- import type { MLText } from './text.js';
7
6
  import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
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>;
7
+ /**
8
+ * > Element includes NonDocumentTypeChildNode;
9
+ * > CharacterData includes NonDocumentTypeChildNode;
10
+ *
11
+ * > DocumentType includes ChildNode;
12
+ * > Element includes ChildNode;
13
+ * > CharacterData includes ChildNode;
14
+ *
15
+ * @see https://dom.spec.whatwg.org/#idl-index
16
+ */
17
+ export type MLChildNode<T extends RuleConfigValue, O extends PlainData = undefined> = MLDocumentType<T, O> | MLCharacterData<T, O> | MLElement<T, O> | MLBlock<T, O>;
9
18
  export declare function isChildNode<T extends RuleConfigValue, O extends PlainData = undefined>(node: MLNode<T, O>): node is MLChildNode<T, O>;
@@ -2,6 +2,8 @@ export function isChildNode(
2
2
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
3
3
  node) {
4
4
  return (node.is(node.DOCUMENT_TYPE_NODE) ||
5
+ node.is(node.CDATA_SECTION_NODE) ||
6
+ node.is(node.COMMENT_NODE) ||
5
7
  node.is(node.TEXT_NODE) ||
6
8
  node.is(node.ELEMENT_NODE) ||
7
9
  node.is(node.MARKUPLINT_PREPROCESSOR_BLOCK));
@@ -2097,6 +2097,9 @@ export class MLDocument extends MLParentNode {
2097
2097
  let offset = 0;
2098
2098
  for (const node of this.getTokenList()) {
2099
2099
  const nodeRaw = node.toString(true);
2100
+ if (nodeRaw === node.raw) {
2101
+ continue;
2102
+ }
2100
2103
  raw = raw.slice(0, node.startOffset + offset) + nodeRaw + raw.slice(node.endOffset + offset);
2101
2104
  offset += nodeRaw.length - (node.endOffset - node.startOffset);
2102
2105
  }
@@ -26,6 +26,9 @@ export class MLElementCloseTag extends MLNode {
26
26
  if (!fixed) {
27
27
  return this.raw;
28
28
  }
29
+ if (this.nodeName.startsWith('#')) {
30
+ return this.raw;
31
+ }
29
32
  if (this.pair.isOmitted) {
30
33
  return this.raw;
31
34
  }
@@ -1785,7 +1785,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1785
1785
  * @implements DOM API: `Element`
1786
1786
  * @see https://dom.spec.whatwg.org/#ref-for-dom-element-matches%E2%91%A0
1787
1787
  */
1788
- matches(selector: string): boolean;
1788
+ matches(selector: string, scope?: MLParentNode<T, O>): boolean;
1789
1789
  /**
1790
1790
  * Pretenders Initialization
1791
1791
  */
@@ -2423,10 +2423,12 @@ export class MLElement extends MLParentNode {
2423
2423
  * @implements DOM API: `Element`
2424
2424
  * @see https://dom.spec.whatwg.org/#ref-for-dom-element-matches%E2%91%A0
2425
2425
  */
2426
- matches(selector) {
2426
+ matches(selector,
2427
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
2428
+ scope) {
2427
2429
  return (createSelector(selector, this.ownerMLDocument.specs).match(
2428
2430
  // Prioritize the pretender
2429
- this.pretenderContext?.type === 'pretender' ? this.pretenderContext.as : this) !== false);
2431
+ this.pretenderContext?.type === 'pretender' ? this.pretenderContext.as : this, scope) !== false);
2430
2432
  }
2431
2433
  /**
2432
2434
  * Pretenders Initialization
@@ -2756,12 +2758,19 @@ export class MLElement extends MLParentNode {
2756
2758
  }
2757
2759
  let raw = this.raw;
2758
2760
  let offset = 0;
2761
+ const overlayedCommentNodes = this.ownerMLDocument.nodeList.filter(node => {
2762
+ if (node.is(node.COMMENT_NODE)) {
2763
+ return this.startOffset < node.startOffset && node.endOffset < this.endOffset;
2764
+ }
2765
+ return false;
2766
+ });
2759
2767
  const nodes = [
2760
2768
  {
2761
2769
  toString: () => this.tagOpenChar + this.fixedNodeName,
2762
2770
  startOffset: this.startOffset,
2763
2771
  endOffset: this.startOffset + this.tagOpenChar.length + this.nodeName.length,
2764
2772
  },
2773
+ ...overlayedCommentNodes,
2765
2774
  ...this.attributes,
2766
2775
  ];
2767
2776
  for (const node of nodes) {
@@ -158,13 +158,12 @@ export declare abstract class MLNode<T extends RuleConfigValue, O extends PlainD
158
158
  */
159
159
  get nextNode(): MLNode<T, O> | null;
160
160
  /**
161
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
161
+ * The next sibling of an object is its first following sibling or null if it has no following sibling.
162
162
  *
163
- * @unsupported
164
163
  * @implements DOM API: `Node`
165
- * @see https://dom.spec.whatwg.org/#ref-for-dom-node-nextsibling%E2%91%A0
164
+ * @see https://dom.spec.whatwg.org/#concept-tree-next-sibling
166
165
  */
167
- get nextSibling(): ChildNode | null;
166
+ get nextSibling(): MLChildNode<T, O> | null;
168
167
  /**
169
168
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
170
169
  *
@@ -263,13 +262,12 @@ export declare abstract class MLNode<T extends RuleConfigValue, O extends PlainD
263
262
  */
264
263
  get prevToken(): MLNode<T, O> | null;
265
264
  /**
266
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
265
+ * The previous sibling of an object is its first preceding sibling or null if it has no preceding sibling.
267
266
  *
268
- * @unsupported
269
267
  * @implements DOM API: `Node`
270
- * @see https://dom.spec.whatwg.org/#ref-for-dom-node-previoussibling%E2%91%A0
268
+ * @see https://dom.spec.whatwg.org/#concept-tree-previous-sibling
271
269
  */
272
- get previousSibling(): ChildNode | null;
270
+ get previousSibling(): MLChildNode<T, O> | null;
273
271
  /**
274
272
  * @implements `@markuplint/ml-core` API: `MLNode`
275
273
  */
@@ -356,13 +354,12 @@ export declare abstract class MLNode<T extends RuleConfigValue, O extends PlainD
356
354
  */
357
355
  compareDocumentPosition(other: Node): number;
358
356
  /**
359
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
357
+ * Returns true if other is an inclusive descendant of node; otherwise false.
360
358
  *
361
- * @unsupported
362
359
  * @implements DOM API: `Node`
363
360
  * @see https://dom.spec.whatwg.org/#ref-for-dom-node-contains%E2%91%A0
364
361
  */
365
- contains(other: Node | null): boolean;
362
+ contains(other: MLNode<T, O> | null): boolean;
366
363
  /**
367
364
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
368
365
  *
@@ -371,6 +368,14 @@ export declare abstract class MLNode<T extends RuleConfigValue, O extends PlainD
371
368
  * @see https://dom.spec.whatwg.org/#ref-for-dom-eventtarget-dispatchevent%E2%91%A2
372
369
  */
373
370
  dispatchEvent(event: Event): boolean;
371
+ /**
372
+ * Finds subsequent nodes that match the given selector.
373
+ *
374
+ * @implements `@markuplint/ml-core` API: `MLNode`
375
+ * @param selector - Optional selector to filter the nodes.
376
+ * @returns An array of matched child nodes.
377
+ */
378
+ findSubsequentNodes(selector?: string): MLChildNode<T, O>[];
374
379
  /**
375
380
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
376
381
  *
@@ -234,14 +234,22 @@ export class MLNode extends MLToken {
234
234
  return siblings[index + 1] ?? null;
235
235
  }
236
236
  /**
237
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
237
+ * The next sibling of an object is its first following sibling or null if it has no following sibling.
238
238
  *
239
- * @unsupported
240
239
  * @implements DOM API: `Node`
241
- * @see https://dom.spec.whatwg.org/#ref-for-dom-node-nextsibling%E2%91%A0
240
+ * @see https://dom.spec.whatwg.org/#concept-tree-next-sibling
242
241
  */
243
242
  get nextSibling() {
244
- throw new UnexpectedCallError('Not supported "nextSibling" property');
243
+ let nextNode = this.nextNode;
244
+ while (nextNode) {
245
+ if (isChildNode(nextNode) &&
246
+ ((this.parentNode === null && nextNode.parentNode === null) ||
247
+ this.parentNode?.uuid === nextNode.parentNode?.uuid)) {
248
+ return nextNode;
249
+ }
250
+ nextNode = nextNode.nextNode;
251
+ }
252
+ return null;
245
253
  }
246
254
  /**
247
255
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -406,14 +414,22 @@ export class MLNode extends MLToken {
406
414
  return __classPrivateFieldGet(this, _MLNode_prevToken, "f") ?? null;
407
415
  }
408
416
  /**
409
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
417
+ * The previous sibling of an object is its first preceding sibling or null if it has no preceding sibling.
410
418
  *
411
- * @unsupported
412
419
  * @implements DOM API: `Node`
413
- * @see https://dom.spec.whatwg.org/#ref-for-dom-node-previoussibling%E2%91%A0
420
+ * @see https://dom.spec.whatwg.org/#concept-tree-previous-sibling
414
421
  */
415
422
  get previousSibling() {
416
- throw new UnexpectedCallError('Not supported "previousSibling" property');
423
+ let prevNode = this.prevNode;
424
+ while (prevNode) {
425
+ if (isChildNode(prevNode) &&
426
+ ((this.parentNode === null && prevNode.parentNode === null) ||
427
+ this.parentNode?.uuid === prevNode.parentNode?.uuid)) {
428
+ return prevNode;
429
+ }
430
+ prevNode = prevNode.prevNode;
431
+ }
432
+ return null;
417
433
  }
418
434
  /**
419
435
  * @implements `@markuplint/ml-core` API: `MLNode`
@@ -535,16 +551,20 @@ export class MLNode extends MLToken {
535
551
  throw new UnexpectedCallError('Not supported "compareDocumentPosition" method');
536
552
  }
537
553
  /**
538
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
554
+ * Returns true if other is an inclusive descendant of node; otherwise false.
539
555
  *
540
- * @unsupported
541
556
  * @implements DOM API: `Node`
542
557
  * @see https://dom.spec.whatwg.org/#ref-for-dom-node-contains%E2%91%A0
543
558
  */
544
559
  contains(
545
560
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
546
561
  other) {
547
- throw new UnexpectedCallError('Not supported "contains" method');
562
+ for (const childNode of this.childNodes) {
563
+ if (other?.uuid === childNode.uuid || childNode.contains(other)) {
564
+ return true;
565
+ }
566
+ }
567
+ return false;
548
568
  }
549
569
  /**
550
570
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -558,6 +578,34 @@ export class MLNode extends MLToken {
558
578
  event) {
559
579
  throw new UnexpectedCallError('Not supported "dispatchEvent" method');
560
580
  }
581
+ /**
582
+ * Finds subsequent nodes that match the given selector.
583
+ *
584
+ * @implements `@markuplint/ml-core` API: `MLNode`
585
+ * @param selector - Optional selector to filter the nodes.
586
+ * @returns An array of matched child nodes.
587
+ */
588
+ findSubsequentNodes(selector) {
589
+ const matched = [];
590
+ for (const node of this.ownerMLDocument.nodeList) {
591
+ if (node.endOffset <= this.endOffset) {
592
+ continue;
593
+ }
594
+ if (this.contains(node)) {
595
+ continue;
596
+ }
597
+ if (selector) {
598
+ if (node.is(node.ELEMENT_NODE) && node.matches(selector)) {
599
+ matched.push(node);
600
+ }
601
+ continue;
602
+ }
603
+ if (isChildNode(node)) {
604
+ matched.push(node);
605
+ }
606
+ }
607
+ return matched;
608
+ }
561
609
  /**
562
610
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
563
611
  *
@@ -106,7 +106,7 @@ export class MLParentNode extends MLNode {
106
106
  return selected;
107
107
  }
108
108
  const elements = toNodeList(this._descendantsToArray(node => {
109
- if (node.is(node.ELEMENT_NODE) && node.matches(selectors)) {
109
+ if (node.is(node.ELEMENT_NODE) && node.matches(selectors, this)) {
110
110
  return node;
111
111
  }
112
112
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markuplint/ml-core",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
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.1",
32
- "@markuplint/html-parser": "4.0.0",
33
- "@markuplint/html-spec": "4.0.1",
34
- "@markuplint/i18n": "4.0.0",
35
- "@markuplint/ml-ast": "4.0.0",
36
- "@markuplint/ml-config": "4.0.0",
37
- "@markuplint/ml-spec": "4.0.0",
38
- "@markuplint/parser-utils": "4.0.0",
39
- "@markuplint/selector": "4.0.0",
31
+ "@markuplint/config-presets": "4.1.0",
32
+ "@markuplint/html-parser": "4.1.0",
33
+ "@markuplint/html-spec": "4.1.0",
34
+ "@markuplint/i18n": "4.1.0",
35
+ "@markuplint/ml-ast": "4.0.1",
36
+ "@markuplint/ml-config": "4.1.0",
37
+ "@markuplint/ml-spec": "4.0.1",
38
+ "@markuplint/parser-utils": "4.1.0",
39
+ "@markuplint/selector": "4.1.0",
40
40
  "@types/debug": "^4.1.12",
41
41
  "debug": "^4.3.4",
42
42
  "is-plain-object": "^5.0.0",
43
43
  "type-fest": "^4.10.2"
44
44
  },
45
- "gitHead": "b21d44dd0ac6b0e8be0201b92062e4b115fbc880"
45
+ "gitHead": "b9817c30c2df71faa866e3b3fe286afa499deede"
46
46
  }