happy-dom 9.9.2 → 9.10.1
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/element/Element.d.ts.map +1 -1
- package/lib/nodes/element/Element.js +2 -15
- package/lib/nodes/element/Element.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 +1 -23
- package/lib/nodes/node/Node.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/element/Element.ts +3 -17
- package/src/nodes/node/Node.ts +1 -25
- 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,148 @@
|
|
1
|
+
import SelectorItem from './SelectorItem';
|
2
|
+
import SelectorCombinatorEnum from './SelectorCombinatorEnum';
|
3
|
+
import DOMException from '../exception/DOMException';
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Selector RegExp.
|
7
|
+
*
|
8
|
+
* Group 1: All (e.g. "*")
|
9
|
+
* Group 2: Tag name (e.g. "div")
|
10
|
+
* Group 3: ID (e.g. "#id")
|
11
|
+
* Group 4: Class (e.g. ".class")
|
12
|
+
* Group 5: Attribute name when no value (e.g. "attr1")
|
13
|
+
* Group 6: Attribute name when there is a value (e.g. "attr1")
|
14
|
+
* Group 7: Attribute operator (e.g. "~")
|
15
|
+
* Group 8: Attribute value (e.g. "value1")
|
16
|
+
* Group 9: Pseudo (e.g. "nth-child")
|
17
|
+
* Group 10: Arguments of pseudo (e.g. "2n + 1")
|
18
|
+
* Group 11: Combinator.
|
19
|
+
*/
|
20
|
+
const SELECTOR_REGEXP =
|
21
|
+
/(\*)|([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;
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Escaped Character RegExp.
|
25
|
+
*/
|
26
|
+
const CLASS_ESCAPED_CHARACTER_REGEXP = /\\/g;
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Simple Selector RegExp.
|
30
|
+
*
|
31
|
+
* Group 1: Tag name (e.g. "div")
|
32
|
+
* Group 2: Class (e.g. ".classA.classB")
|
33
|
+
* Group 3: ID (e.g. "#id")
|
34
|
+
*/
|
35
|
+
const SIMPLE_SELECTOR_REGEXP = /(^[a-zA-Z0-9-]+$)|(^\.[a-zA-Z0-9-_.]+$)|(^#[a-zA-Z0-9-_]+$)/;
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Utility for parsing a selection string.
|
39
|
+
*/
|
40
|
+
export default 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
|
+
public static getSelectorItem(selector: string): SelectorItem {
|
48
|
+
return this.getSelectorGroups(selector)[0][0];
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Parses a selector string and returns groups with SelectorItem instances.
|
53
|
+
*
|
54
|
+
* @param selector Selector.
|
55
|
+
* @returns Selector groups.
|
56
|
+
*/
|
57
|
+
public static getSelectorGroups(selector: string): Array<Array<SelectorItem>> {
|
58
|
+
const simpleMatch = selector.match(SIMPLE_SELECTOR_REGEXP);
|
59
|
+
|
60
|
+
if (simpleMatch) {
|
61
|
+
if (simpleMatch[1]) {
|
62
|
+
return [[new SelectorItem({ tagName: selector.toUpperCase() })]];
|
63
|
+
} else if (simpleMatch[2]) {
|
64
|
+
return [[new SelectorItem({ classNames: selector.replace('.', '').split('.') })]];
|
65
|
+
} else if (simpleMatch[3]) {
|
66
|
+
return [[new SelectorItem({ id: selector.replace('#', '') })]];
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
const regexp = new RegExp(SELECTOR_REGEXP);
|
71
|
+
let currentSelectorItem: SelectorItem = new SelectorItem({
|
72
|
+
combinator: SelectorCombinatorEnum.descendant
|
73
|
+
});
|
74
|
+
let currentGroup: SelectorItem[] = [currentSelectorItem];
|
75
|
+
const groups: Array<Array<SelectorItem>> = [currentGroup];
|
76
|
+
let isValid = false;
|
77
|
+
let match;
|
78
|
+
|
79
|
+
while ((match = regexp.exec(selector))) {
|
80
|
+
if (match[0]) {
|
81
|
+
isValid = true;
|
82
|
+
|
83
|
+
if (match[1]) {
|
84
|
+
currentSelectorItem.all = '*';
|
85
|
+
} else if (match[2]) {
|
86
|
+
currentSelectorItem.tagName = match[2].toUpperCase();
|
87
|
+
} else if (match[3]) {
|
88
|
+
currentSelectorItem.id = match[3].replace(CLASS_ESCAPED_CHARACTER_REGEXP, '');
|
89
|
+
} else if (match[4]) {
|
90
|
+
currentSelectorItem.classNames = currentSelectorItem.classNames || [];
|
91
|
+
currentSelectorItem.classNames.push(match[4].replace(CLASS_ESCAPED_CHARACTER_REGEXP, ''));
|
92
|
+
} else if (match[5]) {
|
93
|
+
currentSelectorItem.attributes = currentSelectorItem.attributes || [];
|
94
|
+
currentSelectorItem.attributes.push({
|
95
|
+
name: match[5].toLowerCase(),
|
96
|
+
operator: null,
|
97
|
+
value: null
|
98
|
+
});
|
99
|
+
} else if (match[6] && match[8]) {
|
100
|
+
currentSelectorItem.attributes = currentSelectorItem.attributes || [];
|
101
|
+
currentSelectorItem.attributes.push({
|
102
|
+
name: match[6].toLowerCase(),
|
103
|
+
operator: match[7] || null,
|
104
|
+
value: match[8]
|
105
|
+
});
|
106
|
+
} else if (match[9]) {
|
107
|
+
currentSelectorItem.pseudoClass = match[9].toLowerCase();
|
108
|
+
} else if (match[10]) {
|
109
|
+
currentSelectorItem.pseudoArguments = match[10];
|
110
|
+
} else if (match[11]) {
|
111
|
+
switch (match[11].trim()) {
|
112
|
+
case ',':
|
113
|
+
currentSelectorItem = new SelectorItem({
|
114
|
+
combinator: SelectorCombinatorEnum.descendant
|
115
|
+
});
|
116
|
+
currentGroup = [currentSelectorItem];
|
117
|
+
groups.push(currentGroup);
|
118
|
+
break;
|
119
|
+
case '>':
|
120
|
+
currentSelectorItem = new SelectorItem({ combinator: SelectorCombinatorEnum.child });
|
121
|
+
currentGroup.push(currentSelectorItem);
|
122
|
+
break;
|
123
|
+
case '+':
|
124
|
+
currentSelectorItem = new SelectorItem({
|
125
|
+
combinator: SelectorCombinatorEnum.adjacentSibling
|
126
|
+
});
|
127
|
+
currentGroup.push(currentSelectorItem);
|
128
|
+
break;
|
129
|
+
case '':
|
130
|
+
currentSelectorItem = new SelectorItem({
|
131
|
+
combinator: SelectorCombinatorEnum.descendant
|
132
|
+
});
|
133
|
+
currentGroup.push(currentSelectorItem);
|
134
|
+
break;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
} else {
|
138
|
+
break;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
if (!isValid) {
|
143
|
+
throw new DOMException(`Invalid selector: "${selector}"`);
|
144
|
+
}
|
145
|
+
|
146
|
+
return groups;
|
147
|
+
}
|
148
|
+
}
|