happy-dom 9.9.1 → 9.10.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.
Potentially problematic release.
This version of happy-dom might be problematic. Click here for more details.
- package/lib/css/declaration/utilities/CSSStyleDeclarationElementStyle.js +1 -1
- package/lib/css/declaration/utilities/CSSStyleDeclarationElementStyle.js.map +1 -1
- package/lib/nodes/document/Document.d.ts.map +1 -1
- package/lib/nodes/document/Document.js +3 -0
- package/lib/nodes/document/Document.js.map +1 -1
- package/lib/nodes/document-fragment/DocumentFragment.d.ts.map +1 -1
- package/lib/nodes/document-fragment/DocumentFragment.js +3 -0
- package/lib/nodes/document-fragment/DocumentFragment.js.map +1 -1
- package/lib/nodes/element/Element.d.ts.map +1 -1
- package/lib/nodes/element/Element.js +5 -15
- package/lib/nodes/element/Element.js.map +1 -1
- package/lib/nodes/element/ElementUtility.d.ts.map +1 -1
- package/lib/nodes/element/ElementUtility.js +18 -22
- package/lib/nodes/element/ElementUtility.js.map +1 -1
- package/lib/nodes/node/Node.d.ts +0 -8
- package/lib/nodes/node/Node.d.ts.map +1 -1
- package/lib/nodes/node/Node.js +4 -23
- package/lib/nodes/node/Node.js.map +1 -1
- package/lib/nodes/node/NodeUtility.d.ts.map +1 -1
- package/lib/nodes/node/NodeUtility.js +3 -4
- package/lib/nodes/node/NodeUtility.js.map +1 -1
- package/lib/query-selector/ISelectorAttribute.d.ts +6 -0
- package/lib/query-selector/ISelectorAttribute.d.ts.map +1 -0
- package/lib/query-selector/ISelectorAttribute.js +3 -0
- package/lib/query-selector/ISelectorAttribute.js.map +1 -0
- package/lib/query-selector/ISelectorMatch.d.ts +4 -0
- package/lib/query-selector/ISelectorMatch.d.ts.map +1 -0
- package/lib/query-selector/ISelectorMatch.js +3 -0
- package/lib/query-selector/ISelectorMatch.js.map +1 -0
- package/lib/query-selector/QuerySelector.d.ts +21 -31
- package/lib/query-selector/QuerySelector.d.ts.map +1 -1
- package/lib/query-selector/QuerySelector.js +123 -131
- package/lib/query-selector/QuerySelector.js.map +1 -1
- package/lib/query-selector/SelectorCombinatorEnum.d.ts +7 -0
- package/lib/query-selector/SelectorCombinatorEnum.d.ts.map +1 -0
- package/lib/query-selector/SelectorCombinatorEnum.js +10 -0
- package/lib/query-selector/SelectorCombinatorEnum.js.map +1 -0
- package/lib/query-selector/SelectorItem.d.ts +41 -56
- package/lib/query-selector/SelectorItem.d.ts.map +1 -1
- package/lib/query-selector/SelectorItem.js +194 -220
- package/lib/query-selector/SelectorItem.js.map +1 -1
- package/lib/query-selector/SelectorParser.d.ts +21 -0
- package/lib/query-selector/SelectorParser.d.ts.map +1 -0
- package/lib/query-selector/SelectorParser.js +154 -0
- package/lib/query-selector/SelectorParser.js.map +1 -0
- package/package.json +1 -1
- package/src/css/declaration/utilities/CSSStyleDeclarationElementStyle.ts +2 -2
- package/src/nodes/document/Document.ts +6 -0
- package/src/nodes/document-fragment/DocumentFragment.ts +6 -0
- package/src/nodes/element/Element.ts +9 -17
- package/src/nodes/element/ElementUtility.ts +20 -25
- package/src/nodes/node/Node.ts +6 -25
- package/src/nodes/node/NodeUtility.ts +3 -8
- package/src/query-selector/ISelectorAttribute.ts +5 -0
- package/src/query-selector/ISelectorMatch.ts +3 -0
- package/src/query-selector/QuerySelector.ts +187 -170
- package/src/query-selector/SelectorCombinatorEnum.ts +7 -0
- package/src/query-selector/SelectorItem.ts +238 -264
- package/src/query-selector/SelectorParser.ts +148 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const SelectorItem_1 = __importDefault(require("./SelectorItem"));
|
7
|
+
const SelectorCombinatorEnum_1 = __importDefault(require("./SelectorCombinatorEnum"));
|
8
|
+
const DOMException_1 = __importDefault(require("../exception/DOMException"));
|
9
|
+
/**
|
10
|
+
* Selector RegExp.
|
11
|
+
*
|
12
|
+
* Group 1: All (e.g. "*")
|
13
|
+
* Group 2: Tag name (e.g. "div")
|
14
|
+
* Group 3: ID (e.g. "#id")
|
15
|
+
* Group 4: Class (e.g. ".class")
|
16
|
+
* Group 5: Attribute name when no value (e.g. "attr1")
|
17
|
+
* Group 6: Attribute name when there is a value (e.g. "attr1")
|
18
|
+
* Group 7: Attribute operator (e.g. "~")
|
19
|
+
* Group 8: Attribute value (e.g. "value1")
|
20
|
+
* Group 9: Pseudo (e.g. "nth-child")
|
21
|
+
* Group 10: Arguments of pseudo (e.g. "2n + 1")
|
22
|
+
* Group 11: Combinator.
|
23
|
+
*/
|
24
|
+
const SELECTOR_REGEXP = /(\*)|([a-zA-Z0-9-]+)|#([a-zA-Z0-9-_]+)|\.((?:[a-zA-Z0-9-_]|\\.)+)|\[([a-zA-Z0-9-_]+)\]|\[([a-zA-Z0-9-_]+)([~|^$*]{0,1}) *= *["']{0,1}([^"']+)["']{0,1}\]|:([a-zA-Z-:]+)|\(([^)]+)\)|([ ,+>]*)/g;
|
25
|
+
/**
|
26
|
+
* Escaped Character RegExp.
|
27
|
+
*/
|
28
|
+
const CLASS_ESCAPED_CHARACTER_REGEXP = /\\/g;
|
29
|
+
/**
|
30
|
+
* Simple Selector RegExp.
|
31
|
+
*
|
32
|
+
* Group 1: Tag name (e.g. "div")
|
33
|
+
* Group 2: Class (e.g. ".classA.classB")
|
34
|
+
* Group 3: ID (e.g. "#id")
|
35
|
+
*/
|
36
|
+
const SIMPLE_SELECTOR_REGEXP = /(^[a-zA-Z0-9-]+$)|(^\.[a-zA-Z0-9-_.]+$)|(^#[a-zA-Z0-9-_]+$)/;
|
37
|
+
/**
|
38
|
+
* Utility for parsing a selection string.
|
39
|
+
*/
|
40
|
+
class SelectorParser {
|
41
|
+
/**
|
42
|
+
* Parses a selector string and returns an instance of SelectorItem.
|
43
|
+
*
|
44
|
+
* @param selector Selector.
|
45
|
+
* @returns Selector itme.
|
46
|
+
*/
|
47
|
+
static getSelectorItem(selector) {
|
48
|
+
return this.getSelectorGroups(selector)[0][0];
|
49
|
+
}
|
50
|
+
/**
|
51
|
+
* Parses a selector string and returns groups with SelectorItem instances.
|
52
|
+
*
|
53
|
+
* @param selector Selector.
|
54
|
+
* @returns Selector groups.
|
55
|
+
*/
|
56
|
+
static getSelectorGroups(selector) {
|
57
|
+
const simpleMatch = selector.match(SIMPLE_SELECTOR_REGEXP);
|
58
|
+
if (simpleMatch) {
|
59
|
+
if (simpleMatch[1]) {
|
60
|
+
return [[new SelectorItem_1.default({ tagName: selector.toUpperCase() })]];
|
61
|
+
}
|
62
|
+
else if (simpleMatch[2]) {
|
63
|
+
return [[new SelectorItem_1.default({ classNames: selector.replace('.', '').split('.') })]];
|
64
|
+
}
|
65
|
+
else if (simpleMatch[3]) {
|
66
|
+
return [[new SelectorItem_1.default({ id: selector.replace('#', '') })]];
|
67
|
+
}
|
68
|
+
}
|
69
|
+
const regexp = new RegExp(SELECTOR_REGEXP);
|
70
|
+
let currentSelectorItem = new SelectorItem_1.default({
|
71
|
+
combinator: SelectorCombinatorEnum_1.default.descendant
|
72
|
+
});
|
73
|
+
let currentGroup = [currentSelectorItem];
|
74
|
+
const groups = [currentGroup];
|
75
|
+
let isValid = false;
|
76
|
+
let match;
|
77
|
+
while ((match = regexp.exec(selector))) {
|
78
|
+
if (match[0]) {
|
79
|
+
isValid = true;
|
80
|
+
if (match[1]) {
|
81
|
+
currentSelectorItem.all = '*';
|
82
|
+
}
|
83
|
+
else if (match[2]) {
|
84
|
+
currentSelectorItem.tagName = match[2].toUpperCase();
|
85
|
+
}
|
86
|
+
else if (match[3]) {
|
87
|
+
currentSelectorItem.id = match[3];
|
88
|
+
}
|
89
|
+
else if (match[4]) {
|
90
|
+
currentSelectorItem.classNames = currentSelectorItem.classNames || [];
|
91
|
+
currentSelectorItem.classNames.push(match[4].replace(CLASS_ESCAPED_CHARACTER_REGEXP, ''));
|
92
|
+
}
|
93
|
+
else if (match[5]) {
|
94
|
+
currentSelectorItem.attributes = currentSelectorItem.attributes || [];
|
95
|
+
currentSelectorItem.attributes.push({
|
96
|
+
name: match[5].toLowerCase(),
|
97
|
+
operator: null,
|
98
|
+
value: null
|
99
|
+
});
|
100
|
+
}
|
101
|
+
else if (match[6] && match[8]) {
|
102
|
+
currentSelectorItem.attributes = currentSelectorItem.attributes || [];
|
103
|
+
currentSelectorItem.attributes.push({
|
104
|
+
name: match[6].toLowerCase(),
|
105
|
+
operator: match[7] || null,
|
106
|
+
value: match[8]
|
107
|
+
});
|
108
|
+
}
|
109
|
+
else if (match[9]) {
|
110
|
+
currentSelectorItem.pseudoClass = match[9].toLowerCase();
|
111
|
+
}
|
112
|
+
else if (match[10]) {
|
113
|
+
currentSelectorItem.pseudoArguments = match[10];
|
114
|
+
}
|
115
|
+
else if (match[11]) {
|
116
|
+
switch (match[11].trim()) {
|
117
|
+
case ',':
|
118
|
+
currentSelectorItem = new SelectorItem_1.default({
|
119
|
+
combinator: SelectorCombinatorEnum_1.default.descendant
|
120
|
+
});
|
121
|
+
currentGroup = [currentSelectorItem];
|
122
|
+
groups.push(currentGroup);
|
123
|
+
break;
|
124
|
+
case '>':
|
125
|
+
currentSelectorItem = new SelectorItem_1.default({ combinator: SelectorCombinatorEnum_1.default.child });
|
126
|
+
currentGroup.push(currentSelectorItem);
|
127
|
+
break;
|
128
|
+
case '+':
|
129
|
+
currentSelectorItem = new SelectorItem_1.default({
|
130
|
+
combinator: SelectorCombinatorEnum_1.default.adjacentSibling
|
131
|
+
});
|
132
|
+
currentGroup.push(currentSelectorItem);
|
133
|
+
break;
|
134
|
+
case '':
|
135
|
+
currentSelectorItem = new SelectorItem_1.default({
|
136
|
+
combinator: SelectorCombinatorEnum_1.default.descendant
|
137
|
+
});
|
138
|
+
currentGroup.push(currentSelectorItem);
|
139
|
+
break;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}
|
143
|
+
else {
|
144
|
+
break;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
if (!isValid) {
|
148
|
+
throw new DOMException_1.default(`Invalid selector: "${selector}"`);
|
149
|
+
}
|
150
|
+
return groups;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
exports.default = SelectorParser;
|
154
|
+
//# sourceMappingURL=SelectorParser.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SelectorParser.js","sourceRoot":"","sources":["../../src/query-selector/SelectorParser.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -289,8 +289,8 @@ export default class CSSStyleDeclarationElementStyle {
|
|
289
289
|
}
|
290
290
|
} else {
|
291
291
|
for (const element of options.elements) {
|
292
|
-
const matchResult = QuerySelector.match(element.element, selectorText);
|
293
|
-
if (matchResult
|
292
|
+
const matchResult = QuerySelector.match(<IElement>element.element, selectorText);
|
293
|
+
if (matchResult) {
|
294
294
|
element.cssTexts.push({
|
295
295
|
cssText: (<CSSStyleRule>rule)._cssText,
|
296
296
|
priorityWeight: matchResult.priorityWeight
|
@@ -637,6 +637,12 @@ export default class Document extends Node implements IDocument {
|
|
637
637
|
* @override
|
638
638
|
*/
|
639
639
|
public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
|
640
|
+
if (arguments.length < 2) {
|
641
|
+
throw new TypeError(
|
642
|
+
`Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
|
643
|
+
);
|
644
|
+
}
|
645
|
+
|
640
646
|
// We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
|
641
647
|
return ElementUtility.insertBefore(this, newNode, referenceNode);
|
642
648
|
}
|
@@ -171,6 +171,12 @@ export default class DocumentFragment extends Node implements IDocumentFragment
|
|
171
171
|
* @override
|
172
172
|
*/
|
173
173
|
public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
|
174
|
+
if (arguments.length < 2) {
|
175
|
+
throw new TypeError(
|
176
|
+
`Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
|
177
|
+
);
|
178
|
+
}
|
179
|
+
|
174
180
|
// We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
|
175
181
|
return ElementUtility.insertBefore(this, newNode, referenceNode);
|
176
182
|
}
|
@@ -386,6 +386,12 @@ export default class Element extends Node implements IElement {
|
|
386
386
|
* @override
|
387
387
|
*/
|
388
388
|
public override insertBefore(newNode: INode, referenceNode: INode | null): INode {
|
389
|
+
if (arguments.length < 2) {
|
390
|
+
throw new TypeError(
|
391
|
+
`Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
|
392
|
+
);
|
393
|
+
}
|
394
|
+
|
389
395
|
// We do not call super here as this will be handled by ElementUtility to improve performance by avoiding validation and other checks.
|
390
396
|
return ElementUtility.insertBefore(this, newNode, referenceNode);
|
391
397
|
}
|
@@ -717,7 +723,7 @@ export default class Element extends Node implements IElement {
|
|
717
723
|
* @returns "true" if matching.
|
718
724
|
*/
|
719
725
|
public matches(selector: string): boolean {
|
720
|
-
return QuerySelector.match(this, selector)
|
726
|
+
return !!QuerySelector.match(this, selector);
|
721
727
|
}
|
722
728
|
|
723
729
|
/**
|
@@ -727,30 +733,16 @@ export default class Element extends Node implements IElement {
|
|
727
733
|
* @returns Closest matching element.
|
728
734
|
*/
|
729
735
|
public closest(selector: string): IElement {
|
730
|
-
let rootElement: IElement = this.ownerDocument.documentElement;
|
731
|
-
if (!this.isConnected) {
|
732
|
-
rootElement = this;
|
733
|
-
while (rootElement.parentNode) {
|
734
|
-
rootElement = <IElement>rootElement.parentNode;
|
735
|
-
}
|
736
|
-
}
|
737
|
-
const elements = rootElement.querySelectorAll(selector);
|
738
|
-
|
739
736
|
// eslint-disable-next-line
|
740
737
|
let parent: IElement = this;
|
738
|
+
|
741
739
|
while (parent) {
|
742
|
-
if (
|
740
|
+
if (QuerySelector.match(parent, selector)) {
|
743
741
|
return parent;
|
744
742
|
}
|
745
743
|
parent = parent.parentElement;
|
746
744
|
}
|
747
745
|
|
748
|
-
// QuerySelectorAll() will not match the element it is looking in when searched for
|
749
|
-
// Therefore we need to check if it matches the root
|
750
|
-
if (rootElement.matches(selector)) {
|
751
|
-
return rootElement;
|
752
|
-
}
|
753
|
-
|
754
746
|
return null;
|
755
747
|
}
|
756
748
|
|
@@ -123,7 +123,8 @@ export default class ElementUtility {
|
|
123
123
|
referenceNode: INode | null,
|
124
124
|
options?: { disableAncestorValidation?: boolean }
|
125
125
|
): INode {
|
126
|
-
|
126
|
+
// NodeUtility.insertBefore() will call appendChild() for the scenario where "referenceNode" is "null" or "undefined"
|
127
|
+
if (newNode.nodeType === NodeTypeEnum.elementNode && referenceNode) {
|
127
128
|
if (
|
128
129
|
!options?.disableAncestorValidation &&
|
129
130
|
NodeUtility.isInclusiveAncestor(newNode, ancestorNode)
|
@@ -152,36 +153,30 @@ export default class ElementUtility {
|
|
152
153
|
}
|
153
154
|
}
|
154
155
|
|
155
|
-
|
156
|
+
if (referenceNode.nodeType === NodeTypeEnum.elementNode) {
|
157
|
+
const index = ancestorNode.children.indexOf(<IElement>referenceNode);
|
158
|
+
if (index !== -1) {
|
159
|
+
ancestorNode.children.splice(index, 0, <IElement>newNode);
|
160
|
+
}
|
161
|
+
} else {
|
162
|
+
ancestorNode.children.length = 0;
|
156
163
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
if (index !== -1) {
|
161
|
-
ancestorNode.children.splice(index, 0, <IElement>newNode);
|
164
|
+
for (const node of ancestorNode.childNodes) {
|
165
|
+
if (node === referenceNode) {
|
166
|
+
ancestorNode.children.push(<IElement>newNode);
|
162
167
|
}
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
for (const node of ancestorNode.childNodes) {
|
167
|
-
if (node === referenceNode) {
|
168
|
-
ancestorNode.children.push(<IElement>newNode);
|
169
|
-
}
|
170
|
-
if (node.nodeType === NodeTypeEnum.elementNode) {
|
171
|
-
ancestorNode.children.push(<IElement>node);
|
172
|
-
}
|
168
|
+
if (node.nodeType === NodeTypeEnum.elementNode) {
|
169
|
+
ancestorNode.children.push(<IElement>node);
|
173
170
|
}
|
174
171
|
}
|
175
172
|
}
|
176
173
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
);
|
184
|
-
}
|
174
|
+
for (const attribute of NAMED_ITEM_ATTRIBUTES) {
|
175
|
+
if ((<Element>newNode)._attributes[attribute]) {
|
176
|
+
(<HTMLCollection<IHTMLElement>>ancestorNode.children)._appendNamedItem(
|
177
|
+
<IHTMLElement>newNode,
|
178
|
+
(<Element>newNode)._attributes[attribute].value
|
179
|
+
);
|
185
180
|
}
|
186
181
|
}
|
187
182
|
|
package/src/nodes/node/Node.ts
CHANGED
@@ -11,17 +11,6 @@ import IAttr from '../attr/IAttr';
|
|
11
11
|
import NodeList from './NodeList';
|
12
12
|
import INodeList from './INodeList';
|
13
13
|
|
14
|
-
const JSON_CIRCULAR_PROPERTIES = [
|
15
|
-
'ownerDocument',
|
16
|
-
'parentNode',
|
17
|
-
'ownerElement',
|
18
|
-
'defaultView',
|
19
|
-
'_rootNode',
|
20
|
-
'_formNode',
|
21
|
-
'_selectNode',
|
22
|
-
'_textAreaNode'
|
23
|
-
];
|
24
|
-
|
25
14
|
/**
|
26
15
|
* Node.
|
27
16
|
*/
|
@@ -198,7 +187,7 @@ export default class Node extends EventTarget implements INode {
|
|
198
187
|
*/
|
199
188
|
public get parentElement(): IElement {
|
200
189
|
let parent = this.parentNode;
|
201
|
-
while (parent && parent.nodeType !==
|
190
|
+
while (parent && parent.nodeType !== NodeTypeEnum.elementNode) {
|
202
191
|
parent = parent.parentNode;
|
203
192
|
}
|
204
193
|
return <IElement>parent;
|
@@ -322,6 +311,11 @@ export default class Node extends EventTarget implements INode {
|
|
322
311
|
* @returns Inserted node.
|
323
312
|
*/
|
324
313
|
public insertBefore(newNode: INode, referenceNode: INode | null): INode {
|
314
|
+
if (arguments.length < 2) {
|
315
|
+
throw new TypeError(
|
316
|
+
`Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`
|
317
|
+
);
|
318
|
+
}
|
325
319
|
return NodeUtility.insertBefore(this, newNode, referenceNode);
|
326
320
|
}
|
327
321
|
|
@@ -643,17 +637,4 @@ export default class Node extends EventTarget implements INode {
|
|
643
637
|
child = child.nextSibling;
|
644
638
|
}
|
645
639
|
}
|
646
|
-
|
647
|
-
/**
|
648
|
-
* This will be called by JSON.stringify() when serializing this node.
|
649
|
-
*
|
650
|
-
* @returns Object without circular references.
|
651
|
-
*/
|
652
|
-
public toJSON(): { [key: string]: unknown } {
|
653
|
-
const result = {};
|
654
|
-
for (const key of Object.keys(this)) {
|
655
|
-
result[key] = !JSON_CIRCULAR_PROPERTIES.includes(key) ? this[key] : null;
|
656
|
-
}
|
657
|
-
return result;
|
658
|
-
}
|
659
640
|
}
|
@@ -164,18 +164,13 @@ export default class NodeUtility {
|
|
164
164
|
return newNode;
|
165
165
|
}
|
166
166
|
|
167
|
-
|
167
|
+
// If the referenceNode is null or undefined, then the newNode should be appended to the ancestorNode.
|
168
|
+
// According to spec only null is valid, but browsers support undefined as well.
|
169
|
+
if (!referenceNode) {
|
168
170
|
ancestorNode.appendChild(newNode);
|
169
171
|
return newNode;
|
170
172
|
}
|
171
173
|
|
172
|
-
if (!referenceNode) {
|
173
|
-
throw new DOMException(
|
174
|
-
"Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only 1 present.",
|
175
|
-
'TypeError'
|
176
|
-
);
|
177
|
-
}
|
178
|
-
|
179
174
|
if (ancestorNode.childNodes.indexOf(referenceNode) === -1) {
|
180
175
|
throw new DOMException(
|
181
176
|
"Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node."
|