@markuplint/ml-core 5.4.0 → 5.6.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/CHANGELOG.md +29 -0
- package/lib/ml-core.js +3 -0
- package/lib/ml-dom/helper/accname.d.ts +35 -0
- package/lib/ml-dom/helper/accname.js +69 -17
- package/lib/ml-dom/helper/debug.js +1 -1
- package/lib/ml-dom/helper/literal-values.d.ts +102 -0
- package/lib/ml-dom/helper/literal-values.js +193 -0
- package/lib/ml-dom/helper/pretended-attrs.d.ts +16 -0
- package/lib/ml-dom/helper/pretended-attrs.js +21 -0
- package/lib/ml-dom/helper/slot-assignment.d.ts +48 -0
- package/lib/ml-dom/helper/slot-assignment.js +292 -0
- package/lib/ml-dom/helper/tree-scope.d.ts +130 -0
- package/lib/ml-dom/helper/tree-scope.js +341 -0
- package/lib/ml-dom/helper/walkers.d.ts +15 -0
- package/lib/ml-dom/helper/walkers.js +34 -0
- package/lib/ml-dom/index.d.ts +4 -0
- package/lib/ml-dom/index.js +2 -0
- package/lib/ml-dom/node/attr.d.ts +77 -10
- package/lib/ml-dom/node/attr.js +209 -20
- package/lib/ml-dom/node/block.d.ts +15 -6
- package/lib/ml-dom/node/block.js +17 -8
- package/lib/ml-dom/node/document-fragment.d.ts +18 -6
- package/lib/ml-dom/node/document-fragment.js +19 -7
- package/lib/ml-dom/node/document.d.ts +36 -7
- package/lib/ml-dom/node/document.js +60 -17
- package/lib/ml-dom/node/dom-token-list.js +28 -3
- package/lib/ml-dom/node/element.d.ts +148 -24
- package/lib/ml-dom/node/element.js +258 -48
- package/lib/ml-dom/node/named-node-map.js +2 -1
- package/lib/ml-dom/node/node-list.js +2 -3
- package/lib/ml-dom/node/node.d.ts +55 -10
- package/lib/ml-dom/node/node.js +98 -13
- package/lib/ml-dom/node/parent-node.d.ts +39 -8
- package/lib/ml-dom/node/parent-node.js +79 -12
- package/lib/ml-dom/node/shadow-root.d.ts +162 -0
- package/lib/ml-dom/node/shadow-root.js +219 -0
- package/lib/ml-dom/node/text.d.ts +12 -3
- package/lib/ml-dom/node/text.js +14 -3
- package/lib/ml-rule/ml-rule.js +4 -1
- package/lib/test/index.js +3 -0
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +1 -0
- package/lib/utils/search-node-at-location.d.ts +39 -0
- package/lib/utils/search-node-at-location.js +53 -0
- package/package.json +12 -15
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { MLDocument } from './document.js';
|
|
2
|
+
import type { MLElement } from './element.js';
|
|
3
|
+
import type { MLASTNode } from '@markuplint/ml-ast';
|
|
4
|
+
import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
|
|
5
|
+
import { MLDocumentFragment } from './document-fragment.js';
|
|
6
|
+
/**
|
|
7
|
+
* A declarative shadow root: the content of a `template` element with a `shadowrootmode` attribute
|
|
8
|
+
* that the HTML parser attaches to the parent of the `template` element as a shadow root. As the
|
|
9
|
+
* parser sets the template contents of such a `template` element to the shadow root, a
|
|
10
|
+
* shadow root is the `content` of its `template` element, and it is a tree of its own.
|
|
11
|
+
*
|
|
12
|
+
* @template T - The rule configuration value type
|
|
13
|
+
* @template O - The rule options type
|
|
14
|
+
* @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhead
|
|
15
|
+
*/
|
|
16
|
+
export declare class MLShadowRoot<T extends RuleConfigValue, O extends PlainData = undefined> extends MLDocumentFragment<T, O> implements ShadowRoot {
|
|
17
|
+
#private;
|
|
18
|
+
/**
|
|
19
|
+
* @param astNode - A copy of the AST node of the `template` element that has a uuid of its own
|
|
20
|
+
* @param document - The owning document
|
|
21
|
+
* @param template - The `template` element whose content it is
|
|
22
|
+
*/
|
|
23
|
+
constructor(astNode: MLASTNode, document: MLDocument<T, O>, template: MLElement<T, O>);
|
|
24
|
+
/**
|
|
25
|
+
* The element that the shadow root is attached to.
|
|
26
|
+
*
|
|
27
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-host
|
|
28
|
+
*/
|
|
29
|
+
get host(): MLElement<T, O>;
|
|
30
|
+
/**
|
|
31
|
+
* The `shadowrootmode` attribute of the `template` element.
|
|
32
|
+
*
|
|
33
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-mode
|
|
34
|
+
*/
|
|
35
|
+
get mode(): 'open' | 'closed';
|
|
36
|
+
/**
|
|
37
|
+
* Whether the `template` element has the `shadowrootdelegatesfocus` attribute.
|
|
38
|
+
*
|
|
39
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-delegatesfocus
|
|
40
|
+
*/
|
|
41
|
+
get delegatesFocus(): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the `template` element has the `shadowrootclonable` attribute.
|
|
44
|
+
*
|
|
45
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-clonable
|
|
46
|
+
*/
|
|
47
|
+
get clonable(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Whether the `template` element has the `shadowrootserializable` attribute.
|
|
50
|
+
*
|
|
51
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-serializable
|
|
52
|
+
*/
|
|
53
|
+
get serializable(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* `manual` when the `shadowrootslotassignment` attribute of the `template` element says so,
|
|
56
|
+
* `named` otherwise.
|
|
57
|
+
*
|
|
58
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-slotassignment
|
|
59
|
+
*/
|
|
60
|
+
get slotAssignment(): 'named' | 'manual';
|
|
61
|
+
/**
|
|
62
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
63
|
+
*
|
|
64
|
+
* @unsupported
|
|
65
|
+
* @implements DOM API: `ShadowRoot`
|
|
66
|
+
*/
|
|
67
|
+
get innerHTML(): string;
|
|
68
|
+
set innerHTML(html: string);
|
|
69
|
+
/**
|
|
70
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
71
|
+
*
|
|
72
|
+
* @unsupported
|
|
73
|
+
* @implements DOM API: `ShadowRoot`
|
|
74
|
+
*/
|
|
75
|
+
get onslotchange(): ((this: ShadowRoot, ev: Event) => any) | null;
|
|
76
|
+
set onslotchange(handler: ((this: ShadowRoot, ev: Event) => any) | null);
|
|
77
|
+
/**
|
|
78
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
79
|
+
*
|
|
80
|
+
* @unsupported
|
|
81
|
+
* @implements DOM API: `ShadowRoot`
|
|
82
|
+
*/
|
|
83
|
+
getHTML(options?: GetHTMLOptions): string;
|
|
84
|
+
/**
|
|
85
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
86
|
+
*
|
|
87
|
+
* @unsupported
|
|
88
|
+
* @implements DOM API: `ShadowRoot`
|
|
89
|
+
*/
|
|
90
|
+
setHTMLUnsafe(html: string): void;
|
|
91
|
+
/**
|
|
92
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
93
|
+
*
|
|
94
|
+
* @unsupported
|
|
95
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
96
|
+
*/
|
|
97
|
+
get activeElement(): Element | null;
|
|
98
|
+
/**
|
|
99
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
100
|
+
*
|
|
101
|
+
* @unsupported
|
|
102
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
103
|
+
*/
|
|
104
|
+
get adoptedStyleSheets(): CSSStyleSheet[];
|
|
105
|
+
set adoptedStyleSheets(sheets: CSSStyleSheet[]);
|
|
106
|
+
/**
|
|
107
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
108
|
+
*
|
|
109
|
+
* @unsupported
|
|
110
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
111
|
+
*/
|
|
112
|
+
get customElementRegistry(): CustomElementRegistry | null;
|
|
113
|
+
/**
|
|
114
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
115
|
+
*
|
|
116
|
+
* @unsupported
|
|
117
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
118
|
+
*/
|
|
119
|
+
get fullscreenElement(): Element | null;
|
|
120
|
+
/**
|
|
121
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
122
|
+
*
|
|
123
|
+
* @unsupported
|
|
124
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
125
|
+
*/
|
|
126
|
+
get pictureInPictureElement(): Element | null;
|
|
127
|
+
/**
|
|
128
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
129
|
+
*
|
|
130
|
+
* @unsupported
|
|
131
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
132
|
+
*/
|
|
133
|
+
get pointerLockElement(): Element | null;
|
|
134
|
+
/**
|
|
135
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
136
|
+
*
|
|
137
|
+
* @unsupported
|
|
138
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
139
|
+
*/
|
|
140
|
+
get styleSheets(): StyleSheetList;
|
|
141
|
+
/**
|
|
142
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
143
|
+
*
|
|
144
|
+
* @unsupported
|
|
145
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
146
|
+
*/
|
|
147
|
+
elementFromPoint(x: number, y: number): Element | null;
|
|
148
|
+
/**
|
|
149
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
150
|
+
*
|
|
151
|
+
* @unsupported
|
|
152
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
153
|
+
*/
|
|
154
|
+
elementsFromPoint(x: number, y: number): Element[];
|
|
155
|
+
/**
|
|
156
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
157
|
+
*
|
|
158
|
+
* @unsupported
|
|
159
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
160
|
+
*/
|
|
161
|
+
getAnimations(): Animation[];
|
|
162
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { getShadowHost } from '../helper/tree-scope.js';
|
|
2
|
+
import { MLDocumentFragment } from './document-fragment.js';
|
|
3
|
+
import { UnexpectedCallError } from '@markuplint/shared';
|
|
4
|
+
/**
|
|
5
|
+
* A declarative shadow root: the content of a `template` element with a `shadowrootmode` attribute
|
|
6
|
+
* that the HTML parser attaches to the parent of the `template` element as a shadow root. As the
|
|
7
|
+
* parser sets the template contents of such a `template` element to the shadow root, a
|
|
8
|
+
* shadow root is the `content` of its `template` element, and it is a tree of its own.
|
|
9
|
+
*
|
|
10
|
+
* @template T - The rule configuration value type
|
|
11
|
+
* @template O - The rule options type
|
|
12
|
+
* @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhead
|
|
13
|
+
*/
|
|
14
|
+
export class MLShadowRoot extends MLDocumentFragment {
|
|
15
|
+
#template;
|
|
16
|
+
/**
|
|
17
|
+
* @param astNode - A copy of the AST node of the `template` element that has a uuid of its own
|
|
18
|
+
* @param document - The owning document
|
|
19
|
+
* @param template - The `template` element whose content it is
|
|
20
|
+
*/
|
|
21
|
+
constructor(astNode,
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
23
|
+
document,
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
25
|
+
template) {
|
|
26
|
+
super(astNode, document);
|
|
27
|
+
this.#template = template;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The element that the shadow root is attached to.
|
|
31
|
+
*
|
|
32
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-host
|
|
33
|
+
*/
|
|
34
|
+
get host() {
|
|
35
|
+
const host = getShadowHost(this.#template);
|
|
36
|
+
if (!host) {
|
|
37
|
+
throw new TypeError('A shadow root is attached to an element');
|
|
38
|
+
}
|
|
39
|
+
return host;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The `shadowrootmode` attribute of the `template` element.
|
|
43
|
+
*
|
|
44
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-mode
|
|
45
|
+
*/
|
|
46
|
+
get mode() {
|
|
47
|
+
return this.#template.declarativeShadowRootMode ?? 'open';
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Whether the `template` element has the `shadowrootdelegatesfocus` attribute.
|
|
51
|
+
*
|
|
52
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-delegatesfocus
|
|
53
|
+
*/
|
|
54
|
+
get delegatesFocus() {
|
|
55
|
+
return this.#template.hasAttribute('shadowrootdelegatesfocus');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether the `template` element has the `shadowrootclonable` attribute.
|
|
59
|
+
*
|
|
60
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-clonable
|
|
61
|
+
*/
|
|
62
|
+
get clonable() {
|
|
63
|
+
return this.#template.hasAttribute('shadowrootclonable');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Whether the `template` element has the `shadowrootserializable` attribute.
|
|
67
|
+
*
|
|
68
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-serializable
|
|
69
|
+
*/
|
|
70
|
+
get serializable() {
|
|
71
|
+
return this.#template.hasAttribute('shadowrootserializable');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* `manual` when the `shadowrootslotassignment` attribute of the `template` element says so,
|
|
75
|
+
* `named` otherwise.
|
|
76
|
+
*
|
|
77
|
+
* @see https://dom.spec.whatwg.org/#dom-shadowroot-slotassignment
|
|
78
|
+
*/
|
|
79
|
+
get slotAssignment() {
|
|
80
|
+
return this.#template.getAttribute('shadowrootslotassignment')?.toLowerCase() === 'manual' ? 'manual' : 'named';
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
84
|
+
*
|
|
85
|
+
* @unsupported
|
|
86
|
+
* @implements DOM API: `ShadowRoot`
|
|
87
|
+
*/
|
|
88
|
+
get innerHTML() {
|
|
89
|
+
throw new UnexpectedCallError('Not supported "innerHTML" property');
|
|
90
|
+
}
|
|
91
|
+
set innerHTML(html) {
|
|
92
|
+
throw new UnexpectedCallError('Not supported "innerHTML" property');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
96
|
+
*
|
|
97
|
+
* @unsupported
|
|
98
|
+
* @implements DOM API: `ShadowRoot`
|
|
99
|
+
*/
|
|
100
|
+
get onslotchange() {
|
|
101
|
+
throw new UnexpectedCallError('Not supported "onslotchange" property');
|
|
102
|
+
}
|
|
103
|
+
set onslotchange(handler) {
|
|
104
|
+
throw new UnexpectedCallError('Not supported "onslotchange" property');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
108
|
+
*
|
|
109
|
+
* @unsupported
|
|
110
|
+
* @implements DOM API: `ShadowRoot`
|
|
111
|
+
*/
|
|
112
|
+
getHTML(
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
114
|
+
options) {
|
|
115
|
+
throw new UnexpectedCallError('Not supported "getHTML" method');
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
119
|
+
*
|
|
120
|
+
* @unsupported
|
|
121
|
+
* @implements DOM API: `ShadowRoot`
|
|
122
|
+
*/
|
|
123
|
+
setHTMLUnsafe(html) {
|
|
124
|
+
throw new UnexpectedCallError('Not supported "setHTMLUnsafe" method');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
128
|
+
*
|
|
129
|
+
* @unsupported
|
|
130
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
131
|
+
*/
|
|
132
|
+
get activeElement() {
|
|
133
|
+
throw new UnexpectedCallError('Not supported "activeElement" property');
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
137
|
+
*
|
|
138
|
+
* @unsupported
|
|
139
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
140
|
+
*/
|
|
141
|
+
get adoptedStyleSheets() {
|
|
142
|
+
throw new UnexpectedCallError('Not supported "adoptedStyleSheets" property');
|
|
143
|
+
}
|
|
144
|
+
set adoptedStyleSheets(sheets) {
|
|
145
|
+
throw new UnexpectedCallError('Not supported "adoptedStyleSheets" property');
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
149
|
+
*
|
|
150
|
+
* @unsupported
|
|
151
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
152
|
+
*/
|
|
153
|
+
get customElementRegistry() {
|
|
154
|
+
throw new UnexpectedCallError('Not supported "customElementRegistry" property');
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
158
|
+
*
|
|
159
|
+
* @unsupported
|
|
160
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
161
|
+
*/
|
|
162
|
+
get fullscreenElement() {
|
|
163
|
+
throw new UnexpectedCallError('Not supported "fullscreenElement" property');
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
167
|
+
*
|
|
168
|
+
* @unsupported
|
|
169
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
170
|
+
*/
|
|
171
|
+
get pictureInPictureElement() {
|
|
172
|
+
throw new UnexpectedCallError('Not supported "pictureInPictureElement" property');
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
176
|
+
*
|
|
177
|
+
* @unsupported
|
|
178
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
179
|
+
*/
|
|
180
|
+
get pointerLockElement() {
|
|
181
|
+
throw new UnexpectedCallError('Not supported "pointerLockElement" property');
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
185
|
+
*
|
|
186
|
+
* @unsupported
|
|
187
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
188
|
+
*/
|
|
189
|
+
get styleSheets() {
|
|
190
|
+
throw new UnexpectedCallError('Not supported "styleSheets" property');
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
194
|
+
*
|
|
195
|
+
* @unsupported
|
|
196
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
197
|
+
*/
|
|
198
|
+
elementFromPoint(x, y) {
|
|
199
|
+
throw new UnexpectedCallError('Not supported "elementFromPoint" method');
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
203
|
+
*
|
|
204
|
+
* @unsupported
|
|
205
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
206
|
+
*/
|
|
207
|
+
elementsFromPoint(x, y) {
|
|
208
|
+
throw new UnexpectedCallError('Not supported "elementsFromPoint" method');
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* **IT THROWS AN ERROR WHEN CALLING THIS.**
|
|
212
|
+
*
|
|
213
|
+
* @unsupported
|
|
214
|
+
* @implements DOM API: `DocumentOrShadowRoot`
|
|
215
|
+
*/
|
|
216
|
+
getAnimations() {
|
|
217
|
+
throw new UnexpectedCallError('Not supported "getAnimations" method');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MLElement } from './element.js';
|
|
1
2
|
import type { TextNodeType } from './types.js';
|
|
2
3
|
import type { MLASTText } from '@markuplint/ml-ast';
|
|
3
4
|
import type { PlainData, RuleConfigValue } from '@markuplint/ml-config';
|
|
@@ -12,12 +13,20 @@ import { MLCharacterData } from './character-data.js';
|
|
|
12
13
|
*/
|
|
13
14
|
export declare class MLText<T extends RuleConfigValue, O extends PlainData = undefined> extends MLCharacterData<T, O, MLASTText> implements Text {
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
+
* The slot of an open declarative shadow root that this text is assigned to, or `null` when no
|
|
17
|
+
* slot takes it, the root is closed (the DOM does not expose it), or the assignment is not known.
|
|
16
18
|
*
|
|
17
|
-
* @unsupported
|
|
18
19
|
* @implements DOM API: `Text`
|
|
20
|
+
* @see https://dom.spec.whatwg.org/#dom-slotable-assignedslot
|
|
21
|
+
*/
|
|
22
|
+
get assignedSlot(): HTMLSlotElement | null;
|
|
23
|
+
/**
|
|
24
|
+
* The slot that places this text in the flat tree. See {@link MLElement.getFlatTreeSlot}.
|
|
25
|
+
*
|
|
26
|
+
* @implements `@markuplint/ml-core` API: `MLText`
|
|
27
|
+
* @see https://dom.spec.whatwg.org/#find-a-slot
|
|
19
28
|
*/
|
|
20
|
-
|
|
29
|
+
getFlatTreeSlot(): MLElement<T, O> | null | undefined;
|
|
21
30
|
/**
|
|
22
31
|
* Returns `true` if this text node originated from an invalid (bogus) AST
|
|
23
32
|
* node, such as an orphaned end tag.
|
package/lib/ml-dom/node/text.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getAssignedSlot, getFlatTreeSlot } from '../helper/slot-assignment.js';
|
|
1
2
|
import { MLCharacterData } from './character-data.js';
|
|
2
3
|
import { UnexpectedCallError } from '@markuplint/shared';
|
|
3
4
|
/**
|
|
@@ -16,13 +17,23 @@ const rawTextElements = new Set(['script', 'style']);
|
|
|
16
17
|
*/
|
|
17
18
|
export class MLText extends MLCharacterData {
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
+
* The slot of an open declarative shadow root that this text is assigned to, or `null` when no
|
|
21
|
+
* slot takes it, the root is closed (the DOM does not expose it), or the assignment is not known.
|
|
20
22
|
*
|
|
21
|
-
* @unsupported
|
|
22
23
|
* @implements DOM API: `Text`
|
|
24
|
+
* @see https://dom.spec.whatwg.org/#dom-slotable-assignedslot
|
|
23
25
|
*/
|
|
24
26
|
get assignedSlot() {
|
|
25
|
-
|
|
27
|
+
return getAssignedSlot(this);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The slot that places this text in the flat tree. See {@link MLElement.getFlatTreeSlot}.
|
|
31
|
+
*
|
|
32
|
+
* @implements `@markuplint/ml-core` API: `MLText`
|
|
33
|
+
* @see https://dom.spec.whatwg.org/#find-a-slot
|
|
34
|
+
*/
|
|
35
|
+
getFlatTreeSlot() {
|
|
36
|
+
return getFlatTreeSlot(this);
|
|
26
37
|
}
|
|
27
38
|
/**
|
|
28
39
|
* Returns `true` if this text node originated from an invalid (bogus) AST
|
package/lib/ml-rule/ml-rule.js
CHANGED
|
@@ -172,7 +172,10 @@ export class MLRule {
|
|
|
172
172
|
const aliasName = this.baseRuleId ? this.name : undefined;
|
|
173
173
|
const violations = context.reports.map(report => {
|
|
174
174
|
let fixData;
|
|
175
|
-
|
|
175
|
+
// An attribute that a pretender made is not in the source: the position of its tokens is that of
|
|
176
|
+
// the element, so a fix that edits the range of the attribute would rewrite the tag
|
|
177
|
+
const isPretendedScope = 'scope' in report && 'isPretended' in report.scope && report.scope.isPretended;
|
|
178
|
+
if (fix && report.fix && !isPretendedScope) {
|
|
176
179
|
const edits = report.fix(sharedFixer);
|
|
177
180
|
const editArray = Array.isArray(edits) ? edits : [edits];
|
|
178
181
|
if (editArray.length > 0) {
|
package/lib/test/index.js
CHANGED
|
@@ -20,6 +20,9 @@ export function createTestDocument(sourceCode, options) {
|
|
|
20
20
|
// The settings of the language are what the parser says, as `MLCore` hands them to the document
|
|
21
21
|
endTag: usedParser.endTag,
|
|
22
22
|
booleanish: usedParser.booleanish,
|
|
23
|
+
attrExpressionLanguage: usedParser.attrExpressionLanguage,
|
|
24
|
+
literalValues: usedParser.literalValues,
|
|
25
|
+
slotElement: usedParser.slotElement,
|
|
23
26
|
tagNameCaseSensitive: usedParser.tagNameCaseSensitive,
|
|
24
27
|
componentNameVariants: usedParser.componentNameVariants,
|
|
25
28
|
isComponentName: usedParser.isComponentName?.bind(usedParser),
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A source range: from its start, included, to its end, excluded (the end is
|
|
3
|
+
* where the next token starts). Without an end, it holds only its start.
|
|
4
|
+
*/
|
|
5
|
+
export interface LocatedToken {
|
|
6
|
+
readonly startLine: number;
|
|
7
|
+
readonly startCol: number;
|
|
8
|
+
readonly endLine?: number;
|
|
9
|
+
readonly endCol?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A node with its source range. The range of an element is its start tag; its
|
|
13
|
+
* end tag, which is not in a document's node list, is `closeTag`.
|
|
14
|
+
*/
|
|
15
|
+
export interface LocatedNode extends LocatedToken {
|
|
16
|
+
readonly closeTag?: LocatedToken | null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Finds the node of `nodeList` at the source location `line`:`col` (both 1-based).
|
|
20
|
+
*
|
|
21
|
+
* The node is the one whose range holds the position, or whose end tag does: a
|
|
22
|
+
* document's node list has no attribute nodes and no end tags, so a position at
|
|
23
|
+
* an attribute, inside its value or in an end tag is the element that has it. Of
|
|
24
|
+
* several such nodes the last in the list is taken: the innermost. A block
|
|
25
|
+
* (`#ml-block`) holds the elements nested in it, and an omitted element
|
|
26
|
+
* (`<tbody>` with an empty source) starts where its first child does.
|
|
27
|
+
*
|
|
28
|
+
* The list is in document order, as the parser sorts its nodes by offset, so the
|
|
29
|
+
* search stops at the first node that starts after the position. It works on the
|
|
30
|
+
* structural `LocatedNode` so that it reads the node list of any version of the
|
|
31
|
+
* engine: the language server searches the document of the markuplint the user
|
|
32
|
+
* installed, and the suppressions search a node list cast to their own type.
|
|
33
|
+
*
|
|
34
|
+
* @param nodeList - The nodes of a document, in document order.
|
|
35
|
+
* @param line - The 1-based line number to search at.
|
|
36
|
+
* @param col - The 1-based column number to search at.
|
|
37
|
+
* @returns The node at the location, or `null` if there is none.
|
|
38
|
+
*/
|
|
39
|
+
export declare function searchNodeAtLocation<N extends LocatedNode>(nodeList: Iterable<N>, line: number, col: number): N | null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the node of `nodeList` at the source location `line`:`col` (both 1-based).
|
|
3
|
+
*
|
|
4
|
+
* The node is the one whose range holds the position, or whose end tag does: a
|
|
5
|
+
* document's node list has no attribute nodes and no end tags, so a position at
|
|
6
|
+
* an attribute, inside its value or in an end tag is the element that has it. Of
|
|
7
|
+
* several such nodes the last in the list is taken: the innermost. A block
|
|
8
|
+
* (`#ml-block`) holds the elements nested in it, and an omitted element
|
|
9
|
+
* (`<tbody>` with an empty source) starts where its first child does.
|
|
10
|
+
*
|
|
11
|
+
* The list is in document order, as the parser sorts its nodes by offset, so the
|
|
12
|
+
* search stops at the first node that starts after the position. It works on the
|
|
13
|
+
* structural `LocatedNode` so that it reads the node list of any version of the
|
|
14
|
+
* engine: the language server searches the document of the markuplint the user
|
|
15
|
+
* installed, and the suppressions search a node list cast to their own type.
|
|
16
|
+
*
|
|
17
|
+
* @param nodeList - The nodes of a document, in document order.
|
|
18
|
+
* @param line - The 1-based line number to search at.
|
|
19
|
+
* @param col - The 1-based column number to search at.
|
|
20
|
+
* @returns The node at the location, or `null` if there is none.
|
|
21
|
+
*/
|
|
22
|
+
export function searchNodeAtLocation(nodeList, line, col) {
|
|
23
|
+
let found = null;
|
|
24
|
+
for (const node of nodeList) {
|
|
25
|
+
if (isBefore(line, col, node)) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (holdsLocation(node, line, col) || (node.closeTag != null && holdsLocation(node.closeTag, line, col))) {
|
|
29
|
+
found = node;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return found;
|
|
33
|
+
}
|
|
34
|
+
/** Whether `line`:`col` comes before the start of `token`. */
|
|
35
|
+
function isBefore(line, col, token) {
|
|
36
|
+
return line < token.startLine || (line === token.startLine && col < token.startCol);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Whether `line`:`col` is the start of `token` or in its range. The start is
|
|
40
|
+
* compared first: the end of an `MLNode` is computed from its source on every read.
|
|
41
|
+
*/
|
|
42
|
+
function holdsLocation(token, line, col) {
|
|
43
|
+
if (isBefore(line, col, token)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (line === token.startLine && col === token.startCol) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
if (token.endLine === undefined || token.endCol === undefined) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return line < token.endLine || (line === token.endLine && col < token.endCol);
|
|
53
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.6.0",
|
|
4
4
|
"description": "The core module of markuplint",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -22,9 +22,6 @@
|
|
|
22
22
|
"publishConfig": {
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
|
-
"typedoc": {
|
|
26
|
-
"entryPoint": "./src/index.ts"
|
|
27
|
-
},
|
|
28
25
|
"scripts": {
|
|
29
26
|
"build": "tsc --project tsconfig.build.json",
|
|
30
27
|
"dev": "tsc --watch --project tsconfig.build.json",
|
|
@@ -34,20 +31,20 @@
|
|
|
34
31
|
"./lib/configs.js": "./lib/configs.browser.js"
|
|
35
32
|
},
|
|
36
33
|
"dependencies": {
|
|
37
|
-
"@markuplint/config-presets": "5.
|
|
38
|
-
"@markuplint/html-parser": "5.
|
|
39
|
-
"@markuplint/html-spec": "5.
|
|
40
|
-
"@markuplint/i18n": "5.
|
|
41
|
-
"@markuplint/ml-ast": "5.
|
|
42
|
-
"@markuplint/ml-config": "5.
|
|
43
|
-
"@markuplint/ml-spec": "5.
|
|
44
|
-
"@markuplint/parser-utils": "5.
|
|
45
|
-
"@markuplint/selector": "5.
|
|
46
|
-
"@markuplint/shared": "5.
|
|
34
|
+
"@markuplint/config-presets": "5.6.0",
|
|
35
|
+
"@markuplint/html-parser": "5.6.0",
|
|
36
|
+
"@markuplint/html-spec": "5.6.0",
|
|
37
|
+
"@markuplint/i18n": "5.6.0",
|
|
38
|
+
"@markuplint/ml-ast": "5.6.0",
|
|
39
|
+
"@markuplint/ml-config": "5.6.0",
|
|
40
|
+
"@markuplint/ml-spec": "5.6.0",
|
|
41
|
+
"@markuplint/parser-utils": "5.6.0",
|
|
42
|
+
"@markuplint/selector": "5.6.0",
|
|
43
|
+
"@markuplint/shared": "5.6.0",
|
|
47
44
|
"@types/debug": "^4.1.13",
|
|
48
45
|
"debug": "^4.4.3",
|
|
49
46
|
"is-plain-object": "^5.1.0",
|
|
50
47
|
"type-fest": "^5.10.0"
|
|
51
48
|
},
|
|
52
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "eade3d7202682e567f3c1b6985478f1d4b5c5481"
|
|
53
50
|
}
|