happy-dom 9.10.9 → 9.12.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/config/PlainTextElements.d.ts +4 -1
- package/lib/config/PlainTextElements.d.ts.map +1 -1
- package/lib/config/PlainTextElements.js +4 -1
- package/lib/config/PlainTextElements.js.map +1 -1
- package/lib/config/UnnestableElements.d.ts +18 -1
- package/lib/config/UnnestableElements.d.ts.map +1 -1
- package/lib/config/UnnestableElements.js +18 -18
- package/lib/config/UnnestableElements.js.map +1 -1
- package/lib/config/VoidElements.d.ts +16 -1
- package/lib/config/VoidElements.d.ts.map +1 -1
- package/lib/config/VoidElements.js +16 -17
- package/lib/config/VoidElements.js.map +1 -1
- package/lib/dom-parser/DOMParser.js +2 -2
- package/lib/dom-parser/DOMParser.js.map +1 -1
- package/lib/nodes/document/Document.d.ts.map +1 -1
- package/lib/nodes/document/Document.js +19 -18
- package/lib/nodes/document/Document.js.map +1 -1
- package/lib/nodes/element/Element.d.ts.map +1 -1
- package/lib/nodes/element/Element.js +1 -3
- package/lib/nodes/element/Element.js.map +1 -1
- package/lib/nodes/html-template-element/HTMLTemplateElement.d.ts.map +1 -1
- package/lib/nodes/html-template-element/HTMLTemplateElement.js +2 -4
- package/lib/nodes/html-template-element/HTMLTemplateElement.js.map +1 -1
- package/lib/nodes/parent-node/ParentNodeUtility.d.ts +3 -3
- package/lib/nodes/parent-node/ParentNodeUtility.d.ts.map +1 -1
- package/lib/nodes/parent-node/ParentNodeUtility.js +1 -4
- package/lib/nodes/parent-node/ParentNodeUtility.js.map +1 -1
- package/lib/nodes/shadow-root/ShadowRoot.d.ts.map +1 -1
- package/lib/nodes/shadow-root/ShadowRoot.js +1 -3
- package/lib/nodes/shadow-root/ShadowRoot.js.map +1 -1
- package/lib/query-selector/ISelectorPseudo.d.ts +3 -0
- package/lib/query-selector/ISelectorPseudo.d.ts.map +1 -1
- package/lib/query-selector/SelectorItem.d.ts +0 -9
- package/lib/query-selector/SelectorItem.d.ts.map +1 -1
- package/lib/query-selector/SelectorItem.js +21 -44
- package/lib/query-selector/SelectorItem.js.map +1 -1
- package/lib/query-selector/SelectorParser.d.ts +18 -0
- package/lib/query-selector/SelectorParser.d.ts.map +1 -1
- package/lib/query-selector/SelectorParser.js +100 -8
- package/lib/query-selector/SelectorParser.js.map +1 -1
- package/lib/range/Range.js.map +1 -1
- package/lib/xml-parser/XMLParser.d.ts +14 -38
- package/lib/xml-parser/XMLParser.d.ts.map +1 -1
- package/lib/xml-parser/XMLParser.js +222 -200
- package/lib/xml-parser/XMLParser.js.map +1 -1
- package/lib/xml-serializer/XMLSerializer.d.ts.map +1 -1
- package/lib/xml-serializer/XMLSerializer.js +11 -7
- package/lib/xml-serializer/XMLSerializer.js.map +1 -1
- package/package.json +1 -1
- package/src/config/PlainTextElements.ts +4 -1
- package/src/config/UnnestableElements.ts +18 -18
- package/src/config/VoidElements.ts +16 -17
- package/src/dom-parser/DOMParser.ts +2 -2
- package/src/nodes/document/Document.ts +19 -18
- package/src/nodes/element/Element.ts +1 -3
- package/src/nodes/html-template-element/HTMLTemplateElement.ts +2 -4
- package/src/nodes/parent-node/ParentNodeUtility.ts +13 -11
- package/src/nodes/shadow-root/ShadowRoot.ts +1 -3
- package/src/query-selector/ISelectorPseudo.ts +4 -0
- package/src/query-selector/SelectorItem.ts +21 -56
- package/src/query-selector/SelectorParser.ts +118 -8
- package/src/range/Range.ts +1 -1
- package/src/xml-parser/XMLParser.ts +280 -226
- package/src/xml-serializer/XMLSerializer.ts +12 -7
- package/lib/config/ChildLessElements.d.ts +0 -3
- package/lib/config/ChildLessElements.d.ts.map +0 -1
- package/lib/config/ChildLessElements.js +0 -4
- package/lib/config/ChildLessElements.js.map +0 -1
- package/src/config/ChildLessElements.ts +0 -1
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const Node_1 = __importDefault(require("../nodes/node/Node"));
|
7
7
|
const VoidElements_1 = __importDefault(require("../config/VoidElements"));
|
8
8
|
const he_1 = require("he");
|
9
|
+
const NodeTypeEnum_1 = __importDefault(require("../nodes/node/NodeTypeEnum"));
|
9
10
|
/**
|
10
11
|
* Utility for converting an element to string.
|
11
12
|
*/
|
@@ -20,13 +21,13 @@ class XMLSerializer {
|
|
20
21
|
*/
|
21
22
|
serializeToString(root, options) {
|
22
23
|
switch (root.nodeType) {
|
23
|
-
case
|
24
|
+
case NodeTypeEnum_1.default.elementNode:
|
24
25
|
const element = root;
|
25
26
|
const tagName = element.tagName.toLowerCase();
|
26
|
-
if (VoidElements_1.default.
|
27
|
+
if (VoidElements_1.default[element.tagName]) {
|
27
28
|
return `<${tagName}${this._getAttributes(element)}>`;
|
28
29
|
}
|
29
|
-
const childNodes =
|
30
|
+
const childNodes = tagName === 'template'
|
30
31
|
? root.content.childNodes
|
31
32
|
: root.childNodes;
|
32
33
|
let innerHTML = '';
|
@@ -48,11 +49,14 @@ class XMLSerializer {
|
|
48
49
|
html += this.serializeToString(node, options);
|
49
50
|
}
|
50
51
|
return html;
|
51
|
-
case
|
52
|
+
case NodeTypeEnum_1.default.commentNode:
|
52
53
|
return `<!--${root.textContent}-->`;
|
53
|
-
case
|
54
|
-
|
55
|
-
|
54
|
+
case NodeTypeEnum_1.default.processingInstructionNode:
|
55
|
+
// TODO: Add support for processing instructions.
|
56
|
+
return `<!--?${root.target} ${root.textContent}?-->`;
|
57
|
+
case NodeTypeEnum_1.default.textNode:
|
58
|
+
return root.textContent;
|
59
|
+
case NodeTypeEnum_1.default.documentTypeNode:
|
56
60
|
const doctype = root;
|
57
61
|
const identifier = doctype.publicId ? ' PUBLIC' : doctype.systemId ? ' SYSTEM' : '';
|
58
62
|
const publicId = doctype.publicId ? ` "${doctype.publicId}"` : '';
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"XMLSerializer.js","sourceRoot":"","sources":["../../src/xml-serializer/XMLSerializer.ts"],"names":[],"mappings":";;;;;AACA,8DAAsC;AACtC,0EAAkD;AAElD,2BAA4B;
|
1
|
+
{"version":3,"file":"XMLSerializer.js","sourceRoot":"","sources":["../../src/xml-serializer/XMLSerializer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
export default
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
1
|
+
export default {
|
2
|
+
A: true,
|
3
|
+
BUTTON: true,
|
4
|
+
DD: true,
|
5
|
+
DT: true,
|
6
|
+
FORM: true,
|
7
|
+
H1: true,
|
8
|
+
H2: true,
|
9
|
+
H3: true,
|
10
|
+
H4: true,
|
11
|
+
H5: true,
|
12
|
+
H6: true,
|
13
|
+
LI: true,
|
14
|
+
OPTION: true,
|
15
|
+
P: true,
|
16
|
+
SELECT: true,
|
17
|
+
TABLE: true
|
18
|
+
};
|
@@ -1,17 +1,16 @@
|
|
1
|
-
export default
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
];
|
1
|
+
export default {
|
2
|
+
AREA: true,
|
3
|
+
BASE: true,
|
4
|
+
BR: true,
|
5
|
+
COL: true,
|
6
|
+
EMBED: true,
|
7
|
+
HR: true,
|
8
|
+
IMG: true,
|
9
|
+
INPUT: true,
|
10
|
+
LINK: true,
|
11
|
+
META: true,
|
12
|
+
PARAM: true,
|
13
|
+
SOURCE: true,
|
14
|
+
TRACK: true,
|
15
|
+
WBR: true
|
16
|
+
};
|
@@ -44,7 +44,7 @@ export default class DOMParser {
|
|
44
44
|
newDocument.childNodes.length = 0;
|
45
45
|
newDocument.children.length = 0;
|
46
46
|
|
47
|
-
const root = XMLParser.parse(newDocument, string, true);
|
47
|
+
const root = XMLParser.parse(newDocument, string, { evaluateScripts: true });
|
48
48
|
let documentElement = null;
|
49
49
|
let documentTypeNode = null;
|
50
50
|
|
@@ -65,7 +65,7 @@ export default class DOMParser {
|
|
65
65
|
newDocument.appendChild(documentTypeNode);
|
66
66
|
}
|
67
67
|
newDocument.appendChild(documentElement);
|
68
|
-
const body = newDocument.
|
68
|
+
const body = newDocument.body;
|
69
69
|
if (body) {
|
70
70
|
for (const child of root.childNodes.slice()) {
|
71
71
|
body.appendChild(child);
|
@@ -236,9 +236,9 @@ export default class Document extends Node implements IDocument {
|
|
236
236
|
* @returns Title.
|
237
237
|
*/
|
238
238
|
public get title(): string {
|
239
|
-
const
|
240
|
-
if (
|
241
|
-
return
|
239
|
+
const element = ParentNodeUtility.getElementByTagName(this, 'title');
|
240
|
+
if (element) {
|
241
|
+
return element.textContent;
|
242
242
|
}
|
243
243
|
return '';
|
244
244
|
}
|
@@ -248,13 +248,13 @@ export default class Document extends Node implements IDocument {
|
|
248
248
|
*
|
249
249
|
*/
|
250
250
|
public set title(title: string) {
|
251
|
-
const
|
252
|
-
if (
|
253
|
-
|
251
|
+
const element = ParentNodeUtility.getElementByTagName(this, 'title');
|
252
|
+
if (element) {
|
253
|
+
element.textContent = title;
|
254
254
|
} else {
|
255
|
-
const
|
256
|
-
|
257
|
-
this.head.appendChild(
|
255
|
+
const newElement = this.createElement('title');
|
256
|
+
newElement.textContent = title;
|
257
|
+
this.head.appendChild(newElement);
|
258
258
|
}
|
259
259
|
}
|
260
260
|
|
@@ -430,9 +430,9 @@ export default class Document extends Node implements IDocument {
|
|
430
430
|
* @returns Base URI.
|
431
431
|
*/
|
432
432
|
public get baseURI(): string {
|
433
|
-
const
|
434
|
-
if (
|
435
|
-
return
|
433
|
+
const element = <IHTMLBaseElement | null>ParentNodeUtility.getElementByTagName(this, 'base');
|
434
|
+
if (element) {
|
435
|
+
return element.href;
|
436
436
|
}
|
437
437
|
return this.defaultView.location.href;
|
438
438
|
}
|
@@ -653,7 +653,7 @@ export default class Document extends Node implements IDocument {
|
|
653
653
|
* @param html HTML.
|
654
654
|
*/
|
655
655
|
public write(html: string): void {
|
656
|
-
const root = XMLParser.parse(this, html, true);
|
656
|
+
const root = XMLParser.parse(this, html, { evaluateScripts: true });
|
657
657
|
|
658
658
|
if (this._isFirstWrite || this._isFirstWriteAfterOpen) {
|
659
659
|
if (this._isFirstWrite) {
|
@@ -688,8 +688,8 @@ export default class Document extends Node implements IDocument {
|
|
688
688
|
|
689
689
|
this.appendChild(documentElement);
|
690
690
|
} else {
|
691
|
-
const rootBody =
|
692
|
-
const body =
|
691
|
+
const rootBody = ParentNodeUtility.getElementByTagName(root, 'body');
|
692
|
+
const body = ParentNodeUtility.getElementByTagName(this, 'body');
|
693
693
|
if (rootBody && body) {
|
694
694
|
for (const child of rootBody.childNodes.slice()) {
|
695
695
|
body.appendChild(child);
|
@@ -697,7 +697,7 @@ export default class Document extends Node implements IDocument {
|
|
697
697
|
}
|
698
698
|
}
|
699
699
|
|
700
|
-
const body =
|
700
|
+
const body = ParentNodeUtility.getElementByTagName(this, 'body');
|
701
701
|
if (body) {
|
702
702
|
for (const child of root.childNodes.slice()) {
|
703
703
|
if (child['tagName'] !== 'HTML' && child.nodeType !== Node.DOCUMENT_TYPE_NODE) {
|
@@ -720,9 +720,10 @@ export default class Document extends Node implements IDocument {
|
|
720
720
|
this.appendChild(documentElement);
|
721
721
|
}
|
722
722
|
} else {
|
723
|
-
const bodyNode =
|
723
|
+
const bodyNode = ParentNodeUtility.getElementByTagName(root, 'body');
|
724
|
+
const body = ParentNodeUtility.getElementByTagName(this, 'body');
|
724
725
|
for (const child of (bodyNode || root).childNodes.slice()) {
|
725
|
-
|
726
|
+
body.appendChild(child);
|
726
727
|
}
|
727
728
|
}
|
728
729
|
}
|
@@ -244,9 +244,7 @@ export default class Element extends Node implements IElement {
|
|
244
244
|
this.removeChild(child);
|
245
245
|
}
|
246
246
|
|
247
|
-
|
248
|
-
this.appendChild(node);
|
249
|
-
}
|
247
|
+
XMLParser.parse(this.ownerDocument, html, { rootNode: this });
|
250
248
|
}
|
251
249
|
|
252
250
|
/**
|
@@ -2,8 +2,8 @@ import HTMLElement from '../html-element/HTMLElement';
|
|
2
2
|
import IDocumentFragment from '../document-fragment/IDocumentFragment';
|
3
3
|
import INode from '../node/INode';
|
4
4
|
import IHTMLTemplateElement from './IHTMLTemplateElement';
|
5
|
-
import XMLParser from '../../xml-parser/XMLParser';
|
6
5
|
import XMLSerializer from '../../xml-serializer/XMLSerializer';
|
6
|
+
import XMLParser from '../../xml-parser/XMLParser';
|
7
7
|
|
8
8
|
/**
|
9
9
|
* HTML Template Element.
|
@@ -29,9 +29,7 @@ export default class HTMLTemplateElement extends HTMLElement implements IHTMLTem
|
|
29
29
|
this.content.removeChild(child);
|
30
30
|
}
|
31
31
|
|
32
|
-
|
33
|
-
this.content.appendChild(node);
|
34
|
-
}
|
32
|
+
XMLParser.parse(this.ownerDocument, html, { rootNode: this.content });
|
35
33
|
}
|
36
34
|
|
37
35
|
/**
|
@@ -16,16 +16,13 @@ export default class ParentNodeUtility {
|
|
16
16
|
* @param parentNode Parent node.
|
17
17
|
* @param nodes List of Node or DOMString.
|
18
18
|
*/
|
19
|
-
public static append(
|
19
|
+
public static append(
|
20
|
+
parentNode: IElement | IDocument | IDocumentFragment,
|
21
|
+
...nodes: (INode | string)[]
|
22
|
+
): void {
|
20
23
|
for (const node of nodes) {
|
21
24
|
if (typeof node === 'string') {
|
22
|
-
|
23
|
-
<IDocument>parentNode.ownerDocument,
|
24
|
-
node
|
25
|
-
).childNodes.slice();
|
26
|
-
for (const newChildNode of newChildNodes) {
|
27
|
-
parentNode.appendChild(newChildNode);
|
28
|
-
}
|
25
|
+
XMLParser.parse(<IDocument>parentNode.ownerDocument, node, { rootNode: parentNode });
|
29
26
|
} else {
|
30
27
|
parentNode.appendChild(node);
|
31
28
|
}
|
@@ -38,9 +35,11 @@ export default class ParentNodeUtility {
|
|
38
35
|
* @param parentNode Parent node.
|
39
36
|
* @param nodes List of Node or DOMString.
|
40
37
|
*/
|
41
|
-
public static prepend(
|
38
|
+
public static prepend(
|
39
|
+
parentNode: IElement | IDocument | IDocumentFragment,
|
40
|
+
...nodes: (string | INode)[]
|
41
|
+
): void {
|
42
42
|
const firstChild = parentNode.firstChild;
|
43
|
-
|
44
43
|
for (const node of nodes) {
|
45
44
|
if (typeof node === 'string') {
|
46
45
|
const newChildNodes = XMLParser.parse(
|
@@ -62,7 +61,10 @@ export default class ParentNodeUtility {
|
|
62
61
|
* @param parentNode Parent node.
|
63
62
|
* @param nodes List of Node or DOMString.
|
64
63
|
*/
|
65
|
-
public static replaceChildren(
|
64
|
+
public static replaceChildren(
|
65
|
+
parentNode: IElement | IDocument | IDocumentFragment,
|
66
|
+
...nodes: (string | INode)[]
|
67
|
+
): void {
|
66
68
|
for (const node of parentNode.childNodes.slice()) {
|
67
69
|
parentNode.removeChild(node);
|
68
70
|
}
|
@@ -42,9 +42,7 @@ export default class ShadowRoot extends DocumentFragment implements IShadowRoot
|
|
42
42
|
this.removeChild(child);
|
43
43
|
}
|
44
44
|
|
45
|
-
|
46
|
-
this.appendChild(node);
|
47
|
-
}
|
45
|
+
XMLParser.parse(this.ownerDocument, html, { rootNode: this });
|
48
46
|
}
|
49
47
|
|
50
48
|
/**
|
@@ -4,7 +4,6 @@ import Element from '../nodes/element/Element';
|
|
4
4
|
import IHTMLInputElement from '../nodes/html-input-element/IHTMLInputElement';
|
5
5
|
import SelectorCombinatorEnum from './SelectorCombinatorEnum';
|
6
6
|
import ISelectorAttribute from './ISelectorAttribute';
|
7
|
-
import SelectorParser from './SelectorParser';
|
8
7
|
import ISelectorMatch from './ISelectorMatch';
|
9
8
|
import ISelectorPseudo from './ISelectorPseudo';
|
10
9
|
|
@@ -181,74 +180,40 @@ export default class SelectorItem {
|
|
181
180
|
case 'root':
|
182
181
|
return element.tagName === 'HTML';
|
183
182
|
case 'not':
|
184
|
-
return !
|
183
|
+
return !psuedo.selectorItem.match(element);
|
185
184
|
case 'nth-child':
|
186
|
-
|
185
|
+
const nthChildIndex = psuedo.selectorItem
|
186
|
+
? parent.children.filter((child) => psuedo.selectorItem.match(child)).indexOf(element)
|
187
|
+
: parent.children.indexOf(element);
|
188
|
+
return nthChildIndex !== -1 && psuedo.nthFunction(nthChildIndex + 1);
|
187
189
|
case 'nth-of-type':
|
188
190
|
if (!element.parentNode) {
|
189
191
|
return false;
|
190
192
|
}
|
191
|
-
|
192
|
-
element
|
193
|
-
|
194
|
-
|
195
|
-
);
|
193
|
+
const nthOfTypeIndex = parent.children
|
194
|
+
.filter((child) => child.tagName === element.tagName)
|
195
|
+
.indexOf(element);
|
196
|
+
return nthOfTypeIndex !== -1 && psuedo.nthFunction(nthOfTypeIndex + 1);
|
196
197
|
case 'nth-last-child':
|
197
|
-
|
198
|
+
const nthLastChildIndex = psuedo.selectorItem
|
199
|
+
? parent.children
|
200
|
+
.filter((child) => psuedo.selectorItem.match(child))
|
201
|
+
.reverse()
|
202
|
+
.indexOf(element)
|
203
|
+
: parent.children.reverse().indexOf(element);
|
204
|
+
return nthLastChildIndex !== -1 && psuedo.nthFunction(nthLastChildIndex + 1);
|
198
205
|
case 'nth-last-of-type':
|
199
|
-
|
200
|
-
element
|
201
|
-
|
202
|
-
|
203
|
-
);
|
206
|
+
const nthLastOfTypeIndex = parent.children
|
207
|
+
.filter((child) => child.tagName === element.tagName)
|
208
|
+
.reverse()
|
209
|
+
.indexOf(element);
|
210
|
+
return nthLastOfTypeIndex !== -1 && psuedo.nthFunction(nthLastOfTypeIndex + 1);
|
204
211
|
}
|
205
212
|
}
|
206
213
|
|
207
214
|
return true;
|
208
215
|
}
|
209
216
|
|
210
|
-
/**
|
211
|
-
* Matches a nth-child selector.
|
212
|
-
*
|
213
|
-
* @param element Element.
|
214
|
-
* @param parentChildren Parent children.
|
215
|
-
* @param placement Placement.
|
216
|
-
* @returns True if it is a match.
|
217
|
-
*/
|
218
|
-
private matchNthChild(element: IElement, parentChildren: IElement[], placement: string): boolean {
|
219
|
-
if (placement === 'odd') {
|
220
|
-
const index = parentChildren.indexOf(element);
|
221
|
-
return index !== -1 && (index + 1) % 2 !== 0;
|
222
|
-
} else if (placement === 'even') {
|
223
|
-
const index = parentChildren.indexOf(element);
|
224
|
-
return index !== -1 && (index + 1) % 2 === 0;
|
225
|
-
} else if (placement.includes('n')) {
|
226
|
-
const [a, b] = placement.replace(/ /g, '').split('n');
|
227
|
-
const childIndex = parentChildren.indexOf(element);
|
228
|
-
const aNumber = a !== '' ? Number(a) : 1;
|
229
|
-
const bNumber = b !== undefined ? Number(b) : 0;
|
230
|
-
if (isNaN(aNumber) || isNaN(bNumber)) {
|
231
|
-
throw new DOMException(`The selector "${this.getSelectorString()}" is not valid.`);
|
232
|
-
}
|
233
|
-
|
234
|
-
for (let i = 0, max = parentChildren.length; i <= max; i += aNumber) {
|
235
|
-
if (childIndex === i + bNumber - 1) {
|
236
|
-
return true;
|
237
|
-
}
|
238
|
-
}
|
239
|
-
|
240
|
-
return false;
|
241
|
-
}
|
242
|
-
|
243
|
-
const number = Number(placement);
|
244
|
-
|
245
|
-
if (isNaN(number)) {
|
246
|
-
throw new DOMException(`The selector "${this.getSelectorString()}" is not valid.`);
|
247
|
-
}
|
248
|
-
|
249
|
-
return parentChildren[number - 1] === element;
|
250
|
-
}
|
251
|
-
|
252
217
|
/**
|
253
218
|
* Matches attribute.
|
254
219
|
*
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import SelectorItem from './SelectorItem';
|
2
2
|
import SelectorCombinatorEnum from './SelectorCombinatorEnum';
|
3
3
|
import DOMException from '../exception/DOMException';
|
4
|
+
import ISelectorPseudo from './ISelectorPseudo';
|
4
5
|
|
5
6
|
/**
|
6
7
|
* Selector RegExp.
|
@@ -29,6 +30,20 @@ const SELECTOR_REGEXP =
|
|
29
30
|
*/
|
30
31
|
const CLASS_ESCAPED_CHARACTER_REGEXP = /\\/g;
|
31
32
|
|
33
|
+
/**
|
34
|
+
* Nth Function.
|
35
|
+
*/
|
36
|
+
const NTH_FUNCTION = {
|
37
|
+
odd: (n: number) => (n + 1) % 2 === 0,
|
38
|
+
even: (n: number) => (n + 1) % 2 !== 0,
|
39
|
+
alwaysFalse: () => false
|
40
|
+
};
|
41
|
+
|
42
|
+
/**
|
43
|
+
* Space RegExp.
|
44
|
+
*/
|
45
|
+
const SPACE_REGEXP = / /g;
|
46
|
+
|
32
47
|
/**
|
33
48
|
* Simple Selector RegExp.
|
34
49
|
*
|
@@ -120,16 +135,10 @@ export default class SelectorParser {
|
|
120
135
|
});
|
121
136
|
} else if (match[12] && match[13]) {
|
122
137
|
currentSelectorItem.pseudos = currentSelectorItem.pseudos || [];
|
123
|
-
currentSelectorItem.pseudos.push(
|
124
|
-
name: match[12].toLowerCase(),
|
125
|
-
arguments: match[13]
|
126
|
-
});
|
138
|
+
currentSelectorItem.pseudos.push(this.getPseudo(match[12], match[13]));
|
127
139
|
} else if (match[14]) {
|
128
140
|
currentSelectorItem.pseudos = currentSelectorItem.pseudos || [];
|
129
|
-
currentSelectorItem.pseudos.push(
|
130
|
-
name: match[14].toLowerCase(),
|
131
|
-
arguments: null
|
132
|
-
});
|
141
|
+
currentSelectorItem.pseudos.push(this.getPseudo(match[14]));
|
133
142
|
} else if (match[15]) {
|
134
143
|
switch (match[15].trim()) {
|
135
144
|
case ',':
|
@@ -168,4 +177,105 @@ export default class SelectorParser {
|
|
168
177
|
|
169
178
|
return groups;
|
170
179
|
}
|
180
|
+
|
181
|
+
/**
|
182
|
+
* Returns pseudo.
|
183
|
+
*
|
184
|
+
* @param name Pseudo name.
|
185
|
+
* @param args Pseudo arguments.
|
186
|
+
* @returns Pseudo.
|
187
|
+
*/
|
188
|
+
private static getPseudo(name: string, args?: string): ISelectorPseudo {
|
189
|
+
const lowerName = name.toLowerCase();
|
190
|
+
|
191
|
+
if (!args) {
|
192
|
+
return { name: lowerName, arguments: null, selectorItem: null, nthFunction: null };
|
193
|
+
}
|
194
|
+
|
195
|
+
switch (lowerName) {
|
196
|
+
case 'nth-last-child':
|
197
|
+
case 'nth-child':
|
198
|
+
const nthOfIndex = args.indexOf(' of ');
|
199
|
+
const nthFunction = nthOfIndex !== -1 ? args.substring(0, nthOfIndex) : args;
|
200
|
+
const selectorItem =
|
201
|
+
nthOfIndex !== -1 ? this.getSelectorItem(args.substring(nthOfIndex + 4).trim()) : null;
|
202
|
+
return {
|
203
|
+
name: lowerName,
|
204
|
+
arguments: args,
|
205
|
+
selectorItem,
|
206
|
+
nthFunction: this.getPseudoNthFunction(nthFunction)
|
207
|
+
};
|
208
|
+
case 'nth-of-type':
|
209
|
+
case 'nth-last-of-type':
|
210
|
+
return {
|
211
|
+
name: lowerName,
|
212
|
+
arguments: args,
|
213
|
+
selectorItem: null,
|
214
|
+
nthFunction: this.getPseudoNthFunction(args)
|
215
|
+
};
|
216
|
+
case 'not':
|
217
|
+
return {
|
218
|
+
name: lowerName,
|
219
|
+
arguments: args,
|
220
|
+
selectorItem: this.getSelectorItem(args),
|
221
|
+
nthFunction: null
|
222
|
+
};
|
223
|
+
default:
|
224
|
+
return { name: lowerName, arguments: args, selectorItem: null, nthFunction: null };
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
/**
|
229
|
+
* Returns pseudo nth function.
|
230
|
+
*
|
231
|
+
* Based on:
|
232
|
+
* https://github.com/dperini/nwsapi/blob/master/src/nwsapi.js
|
233
|
+
*
|
234
|
+
* @param args Pseudo arguments.
|
235
|
+
* @returns Pseudo nth function.
|
236
|
+
*/
|
237
|
+
private static getPseudoNthFunction(args?: string): ((n: number) => boolean) | null {
|
238
|
+
if (args === 'odd') {
|
239
|
+
return NTH_FUNCTION.odd;
|
240
|
+
} else if (args === 'even') {
|
241
|
+
return NTH_FUNCTION.even;
|
242
|
+
}
|
243
|
+
|
244
|
+
const parts = args.replace(SPACE_REGEXP, '').split('n');
|
245
|
+
let partA = parseInt(parts[0], 10) || 0;
|
246
|
+
|
247
|
+
if (parts[0] == '-') {
|
248
|
+
partA = -1;
|
249
|
+
}
|
250
|
+
|
251
|
+
if (parts.length === 1) {
|
252
|
+
return (n) => n == partA;
|
253
|
+
}
|
254
|
+
|
255
|
+
let partB = parseInt(parts[1], 10) || 0;
|
256
|
+
|
257
|
+
if (parts[0] == '+') {
|
258
|
+
partB = 1;
|
259
|
+
}
|
260
|
+
|
261
|
+
if (partA >= 1 || partA <= -1) {
|
262
|
+
const innerExpression =
|
263
|
+
(partB ? '(n' + (partB > 0 ? '-' : '+') + Math.abs(partB) + ')' : 'n') +
|
264
|
+
'%' +
|
265
|
+
partA +
|
266
|
+
'==0';
|
267
|
+
if (partA >= 1) {
|
268
|
+
return eval(
|
269
|
+
'(n) => n>' + (partB - 1) + (Math.abs(partA) != 1 ? '&&' + innerExpression : '')
|
270
|
+
);
|
271
|
+
}
|
272
|
+
return eval('(n) => n<' + (partB + 1) + (Math.abs(partA) != 1 ? '&&' + innerExpression : ''));
|
273
|
+
}
|
274
|
+
|
275
|
+
if (parts[0]) {
|
276
|
+
return (n) => n === partB;
|
277
|
+
}
|
278
|
+
|
279
|
+
return (n) => n > partB - 1;
|
280
|
+
}
|
171
281
|
}
|
package/src/range/Range.ts
CHANGED
@@ -406,7 +406,7 @@ export default class Range {
|
|
406
406
|
*/
|
407
407
|
public createContextualFragment(tagString: string): IDocumentFragment {
|
408
408
|
// TODO: We only have support for HTML in the parser currently, so it is not necessary to check which context it is
|
409
|
-
return XMLParser.parse(this._ownerDocument, tagString);
|
409
|
+
return <IDocumentFragment>XMLParser.parse(this._ownerDocument, tagString);
|
410
410
|
}
|
411
411
|
|
412
412
|
/**
|