happy-dom 2.42.0 → 2.45.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/CSSStyleDeclaration.js +1 -1
- package/lib/css/CSSStyleDeclaration.js.map +1 -1
- package/lib/{nodes/element → dom-token-list}/DOMTokenList.d.ts +32 -29
- package/lib/dom-token-list/DOMTokenList.js +209 -0
- package/lib/dom-token-list/DOMTokenList.js.map +1 -0
- package/lib/{nodes/element → dom-token-list}/IDOMTokenList.d.ts +6 -4
- package/lib/{nodes/element → dom-token-list}/IDOMTokenList.js +0 -0
- package/lib/dom-token-list/IDOMTokenList.js.map +1 -0
- package/lib/navigator/MimeType.d.ts +25 -0
- package/lib/navigator/MimeType.js +32 -0
- package/lib/navigator/MimeType.js.map +1 -0
- package/lib/navigator/MimeTypeArray.d.ts +31 -0
- package/lib/navigator/MimeTypeArray.js +45 -0
- package/lib/navigator/MimeTypeArray.js.map +1 -0
- package/lib/navigator/Navigator.d.ts +41 -0
- package/lib/navigator/Navigator.js +78 -0
- package/lib/navigator/Navigator.js.map +1 -0
- package/lib/navigator/Plugin.d.ts +40 -0
- package/lib/navigator/Plugin.js +55 -0
- package/lib/navigator/Plugin.js.map +1 -0
- package/lib/navigator/PluginArray.d.ts +38 -0
- package/lib/navigator/PluginArray.js +54 -0
- package/lib/navigator/PluginArray.js.map +1 -0
- package/lib/nodes/document/Document.d.ts +2 -1
- package/lib/nodes/document/Document.js.map +1 -1
- package/lib/nodes/document/IDocument.d.ts +13 -2
- package/lib/nodes/element/Element.d.ts +12 -2
- package/lib/nodes/element/Element.js +27 -2
- package/lib/nodes/element/Element.js.map +1 -1
- package/lib/nodes/element/IElement.d.ts +2 -2
- package/lib/nodes/html-label-element/HTMLLabelElement.d.ts +0 -1
- package/lib/nodes/html-label-element/HTMLLabelElement.js +2 -6
- package/lib/nodes/html-label-element/HTMLLabelElement.js.map +1 -1
- package/lib/nodes/html-link-element/HTMLLinkElement.d.ts +12 -0
- package/lib/nodes/html-link-element/HTMLLinkElement.js +26 -0
- package/lib/nodes/html-link-element/HTMLLinkElement.js.map +1 -1
- package/lib/nodes/html-link-element/IHTMLLinkElement.d.ts +2 -0
- package/lib/query-selector/SelectorItem.d.ts +18 -2
- package/lib/query-selector/SelectorItem.js +54 -25
- package/lib/query-selector/SelectorItem.js.map +1 -1
- package/lib/window/IWindow.d.ts +13 -4
- package/lib/window/Window.d.ts +11 -3
- package/lib/window/Window.js +11 -1
- package/lib/window/Window.js.map +1 -1
- package/package.json +2 -2
- package/src/css/CSSStyleDeclaration.ts +1 -1
- package/src/dom-token-list/DOMTokenList.ts +219 -0
- package/src/{nodes/element → dom-token-list}/IDOMTokenList.ts +6 -4
- package/src/navigator/MimeType.ts +35 -0
- package/src/navigator/MimeTypeArray.ts +48 -0
- package/src/navigator/Navigator.ts +93 -0
- package/src/navigator/Plugin.ts +61 -0
- package/src/navigator/PluginArray.ts +58 -0
- package/src/nodes/document/Document.ts +3 -2
- package/src/nodes/document/IDocument.ts +13 -2
- package/src/nodes/element/Element.ts +29 -3
- package/src/nodes/element/IElement.ts +2 -2
- package/src/nodes/html-label-element/HTMLLabelElement.ts +1 -5
- package/src/nodes/html-link-element/HTMLLinkElement.ts +26 -0
- package/src/nodes/html-link-element/IHTMLLinkElement.ts +2 -0
- package/src/query-selector/SelectorItem.ts +62 -26
- package/src/window/IWindow.ts +13 -2
- package/src/window/Window.ts +11 -1
- package/lib/nodes/element/DOMTokenList.js +0 -205
- package/lib/nodes/element/DOMTokenList.js.map +0 -1
- package/lib/nodes/element/IDOMTokenList.js.map +0 -1
- package/src/nodes/element/DOMTokenList.ts +0 -201
@@ -0,0 +1,48 @@
|
|
1
|
+
import MimeType from './MimeType';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* MimeTypeArray.
|
5
|
+
*
|
6
|
+
* Reference:
|
7
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/MimeTypeArray.
|
8
|
+
*/
|
9
|
+
export default class MimeTypeArray {
|
10
|
+
[n: number]: MimeType;
|
11
|
+
public readonly length: number;
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Constructor.
|
15
|
+
*
|
16
|
+
* @param mimeTypes
|
17
|
+
*/
|
18
|
+
constructor(mimeTypes: MimeType[]) {
|
19
|
+
for (let i = 0, max = mimeTypes.length; i < max; i++) {
|
20
|
+
this[i] = mimeTypes[i];
|
21
|
+
this[mimeTypes[i].type] = mimeTypes[i];
|
22
|
+
}
|
23
|
+
this.length = mimeTypes.length;
|
24
|
+
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* @param index
|
28
|
+
*/
|
29
|
+
public item(index: number): MimeType {
|
30
|
+
return this[index] || null;
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* @param name
|
35
|
+
*/
|
36
|
+
public namedItem(name: string): MimeType {
|
37
|
+
return this[name] || null;
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Returns the object as a string.
|
42
|
+
*
|
43
|
+
* @returns String.
|
44
|
+
*/
|
45
|
+
public toString(): string {
|
46
|
+
return '[object MimeTypeArray]';
|
47
|
+
}
|
48
|
+
}
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import MimeTypeArray from './MimeTypeArray';
|
2
|
+
import PluginArray from './PluginArray';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Browser Navigator API.
|
6
|
+
*
|
7
|
+
* Mocked information is taken from FireFox.
|
8
|
+
*
|
9
|
+
* Reference:
|
10
|
+
* https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator.
|
11
|
+
*/
|
12
|
+
export default class Navigator {
|
13
|
+
// False if setting a cookie will be ignored and true otherwise.
|
14
|
+
public readonly cookieEnabled: boolean = true;
|
15
|
+
|
16
|
+
// TODO: Not implemented.
|
17
|
+
public readonly credentials: string = null;
|
18
|
+
|
19
|
+
// TODO: Not implemented.
|
20
|
+
public readonly geolocation: string = null;
|
21
|
+
|
22
|
+
// String representing the preferred language of the user, usually the language of the browser UI.
|
23
|
+
public readonly language: string = 'en-US';
|
24
|
+
|
25
|
+
// Array of string representing the user's preferred languages.
|
26
|
+
public readonly languages: string[] = ['en-US', 'en'];
|
27
|
+
|
28
|
+
// TODO: Not implemented.
|
29
|
+
public readonly locks: string = null;
|
30
|
+
|
31
|
+
// Maximum number of simultaneous touch contact points are supported by the current device.
|
32
|
+
public readonly maxTouchPoints: number = 0;
|
33
|
+
|
34
|
+
// Number of logical processors available to run threads on the user's computer.
|
35
|
+
public readonly hardwareConcurrency: number = 8;
|
36
|
+
|
37
|
+
// Browser app code name.
|
38
|
+
public readonly appCodeName: string = 'Mozilla';
|
39
|
+
|
40
|
+
// Browser app name.
|
41
|
+
public readonly appName: string = 'Netscape';
|
42
|
+
|
43
|
+
// Browser app version.
|
44
|
+
public readonly appVersion: string = '5.0 (Windows)';
|
45
|
+
|
46
|
+
// Browser platform.
|
47
|
+
public readonly platform: string = 'Win32';
|
48
|
+
|
49
|
+
// Browser product.
|
50
|
+
public readonly product: string = 'Gecko';
|
51
|
+
|
52
|
+
// Browser product sub.
|
53
|
+
public readonly productSub: string = '20100101';
|
54
|
+
|
55
|
+
// Browser vendor.
|
56
|
+
public readonly vendor: string = '';
|
57
|
+
|
58
|
+
// Browser vendor sub.
|
59
|
+
public readonly vendorSub: string = '';
|
60
|
+
|
61
|
+
// Browser user agent.
|
62
|
+
// "appCodeName/appVersion number (Platform; Security; OS-or-CPU; Localization; rv: revision-version-number) product/productSub Application-Name Application-Name-version".
|
63
|
+
public readonly userAgent: string =
|
64
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0';
|
65
|
+
|
66
|
+
// Boolean value indicating whether the browser is working online.
|
67
|
+
public readonly onLine: boolean = true;
|
68
|
+
|
69
|
+
// TODO: Not implemented.
|
70
|
+
public readonly permissions: string = null;
|
71
|
+
|
72
|
+
// Boolean Indicates whether the user agent is controlled by automation.
|
73
|
+
public readonly webdriver: boolean = true;
|
74
|
+
|
75
|
+
// The user's Do Not Track setting, which indicates whether the user is requesting web sites and advertisers to not track them.
|
76
|
+
// The value of the property reflects that of the DNT HTTP header, i.e. Values of "1", "0", or "unspecified".
|
77
|
+
public readonly doNotTrack: string = 'unspecified';
|
78
|
+
|
79
|
+
// Browser mime-types.
|
80
|
+
public readonly mimeTypes: MimeTypeArray = new MimeTypeArray([]);
|
81
|
+
|
82
|
+
// Browser plugins.
|
83
|
+
public readonly plugins: PluginArray = new PluginArray([]);
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Returns the object as a string.
|
87
|
+
*
|
88
|
+
* @returns String.
|
89
|
+
*/
|
90
|
+
public toString(): string {
|
91
|
+
return '[object Navigator]';
|
92
|
+
}
|
93
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import MimeType from './MimeType';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Plugin.
|
5
|
+
*/
|
6
|
+
export default class Plugin {
|
7
|
+
[n: number]: MimeType;
|
8
|
+
public readonly length: number = 0;
|
9
|
+
public readonly description: string;
|
10
|
+
public readonly filename: string;
|
11
|
+
public readonly name: string;
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Constructor.
|
15
|
+
*
|
16
|
+
* @param mimeTypes Mime types.
|
17
|
+
* @param description Description.
|
18
|
+
* @param filename Filename.
|
19
|
+
* @param name Name.
|
20
|
+
*/
|
21
|
+
constructor(mimeTypes: MimeType[], description: string, filename: string, name: string) {
|
22
|
+
this.description = description;
|
23
|
+
this.filename = filename;
|
24
|
+
this.name = name;
|
25
|
+
|
26
|
+
for (let i = 0, max = mimeTypes.length; i < max; i++) {
|
27
|
+
this[i] = mimeTypes[i];
|
28
|
+
this[mimeTypes[i].type] = mimeTypes[i];
|
29
|
+
}
|
30
|
+
this.length = mimeTypes.length;
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Item.
|
35
|
+
*
|
36
|
+
* @param index Number.
|
37
|
+
* @returns IMimeType.
|
38
|
+
*/
|
39
|
+
public item(index: number): MimeType {
|
40
|
+
return this[index] || null;
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* NamedItem.
|
45
|
+
*
|
46
|
+
* @param name String.
|
47
|
+
* @returns IMimeType.
|
48
|
+
*/
|
49
|
+
public namedItem(name: string): MimeType {
|
50
|
+
return this[name] || null;
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Returns the object as a string.
|
55
|
+
*
|
56
|
+
* @returns String.
|
57
|
+
*/
|
58
|
+
public toString(): string {
|
59
|
+
return '[object Plugin]';
|
60
|
+
}
|
61
|
+
}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import Plugin from './Plugin';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* PluginArray.
|
5
|
+
*/
|
6
|
+
export default class PluginArray {
|
7
|
+
[n: number]: Plugin;
|
8
|
+
public readonly length: number;
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Constructor.
|
12
|
+
*
|
13
|
+
* @param plugins Plugins.
|
14
|
+
*/
|
15
|
+
constructor(plugins: Plugin[]) {
|
16
|
+
for (let i = 0, max = plugins.length; i < max; i++) {
|
17
|
+
this[i] = plugins[i];
|
18
|
+
this[plugins[i].name] = plugins[i];
|
19
|
+
}
|
20
|
+
this.length = plugins.length;
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* Returns an item.
|
25
|
+
*
|
26
|
+
* @param index Index.
|
27
|
+
* @returns Plugin.
|
28
|
+
*/
|
29
|
+
public item(index: number): Plugin {
|
30
|
+
return this[index] || null;
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Returns an item.
|
35
|
+
*
|
36
|
+
* @param name Name.
|
37
|
+
* @returns Plugin.
|
38
|
+
*/
|
39
|
+
public namedItem(name: string): Plugin {
|
40
|
+
return this[name] || null;
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Refreshes the list.
|
45
|
+
*/
|
46
|
+
public refresh(): void {
|
47
|
+
// Do nothing
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Returns the object as a string.
|
52
|
+
*
|
53
|
+
* @returns String.
|
54
|
+
*/
|
55
|
+
public toString(): string {
|
56
|
+
return '[object PluginArray]';
|
57
|
+
}
|
58
|
+
}
|
@@ -21,6 +21,7 @@ import CSSStyleSheet from '../../css/CSSStyleSheet';
|
|
21
21
|
import DOMException from '../../exception/DOMException';
|
22
22
|
import CookieUtility from '../../cookie/CookieUtility';
|
23
23
|
import IElement from '../element/IElement';
|
24
|
+
import IHTMLScriptElement from '../html-script-element/IHTMLScriptElement';
|
24
25
|
import IHTMLElement from '../html-element/IHTMLElement';
|
25
26
|
import IDocumentType from '../document-type/IDocumentType';
|
26
27
|
import INode from '../node/INode';
|
@@ -245,8 +246,8 @@ export default class Document extends Node implements IDocument {
|
|
245
246
|
*
|
246
247
|
* @returns Scripts.
|
247
248
|
*/
|
248
|
-
public get scripts(): IHTMLCollection<
|
249
|
-
return this.getElementsByTagName('script');
|
249
|
+
public get scripts(): IHTMLCollection<IHTMLScriptElement> {
|
250
|
+
return <IHTMLCollection<IHTMLScriptElement>>this.getElementsByTagName('script');
|
250
251
|
}
|
251
252
|
|
252
253
|
/**
|
@@ -12,6 +12,11 @@ import INode from '../node/INode';
|
|
12
12
|
import ICharacterData from '../character-data/ICharacterData';
|
13
13
|
import IDocumentFragment from '../document-fragment/IDocumentFragment';
|
14
14
|
import Selection from '../../selection/Selection';
|
15
|
+
import IHTMLCollection from '../element/IHTMLCollection';
|
16
|
+
import IHTMLScriptElement from '../html-script-element/IHTMLScriptElement';
|
17
|
+
import CSSStyleSheet from '../../css/CSSStyleSheet';
|
18
|
+
import Location from '../../location/Location';
|
19
|
+
import DocumentReadyStateEnum from './DocumentReadyStateEnum';
|
15
20
|
|
16
21
|
/**
|
17
22
|
* Document.
|
@@ -24,7 +29,13 @@ export default interface IDocument extends IParentNode {
|
|
24
29
|
readonly doctype: IDocumentType;
|
25
30
|
readonly body: IHTMLElement;
|
26
31
|
readonly head: IHTMLElement;
|
32
|
+
readonly scripts: IHTMLCollection<IHTMLScriptElement>;
|
27
33
|
readonly activeElement: IHTMLElement;
|
34
|
+
readonly styleSheets: CSSStyleSheet[];
|
35
|
+
readonly scrollingElement: IHTMLElement;
|
36
|
+
readonly location: Location;
|
37
|
+
readonly readyState: DocumentReadyStateEnum;
|
38
|
+
cookie: string;
|
28
39
|
|
29
40
|
/**
|
30
41
|
* Replaces the document HTML with new HTML.
|
@@ -69,7 +80,7 @@ export default interface IDocument extends IParentNode {
|
|
69
80
|
* @param data Text data.
|
70
81
|
* @returns Text node.
|
71
82
|
*/
|
72
|
-
createTextNode(data
|
83
|
+
createTextNode(data?: string): ICharacterData;
|
73
84
|
|
74
85
|
/**
|
75
86
|
* Creates a comment node.
|
@@ -77,7 +88,7 @@ export default interface IDocument extends IParentNode {
|
|
77
88
|
* @param data Text data.
|
78
89
|
* @returns Text node.
|
79
90
|
*/
|
80
|
-
createComment(data
|
91
|
+
createComment(data?: string): ICharacterData;
|
81
92
|
|
82
93
|
/**
|
83
94
|
* Creates a document fragment.
|
@@ -3,7 +3,8 @@ import ShadowRoot from '../shadow-root/ShadowRoot';
|
|
3
3
|
import Attr from '../../attribute/Attr';
|
4
4
|
import DOMRect from './DOMRect';
|
5
5
|
import Range from './Range';
|
6
|
-
import DOMTokenList from '
|
6
|
+
import DOMTokenList from '../../dom-token-list/DOMTokenList';
|
7
|
+
import IDOMTokenList from '../../dom-token-list/IDOMTokenList';
|
7
8
|
import QuerySelector from '../../query-selector/QuerySelector';
|
8
9
|
import SelectorItem from '../../query-selector/SelectorItem';
|
9
10
|
import MutationRecord from '../../mutation-observer/MutationRecord';
|
@@ -37,13 +38,25 @@ export default class Element extends Node implements IElement {
|
|
37
38
|
public nodeType = Node.ELEMENT_NODE;
|
38
39
|
public shadowRoot: IShadowRoot = null;
|
39
40
|
public _attributes: { [k: string]: Attr } = {};
|
40
|
-
public readonly classList = new DOMTokenList(this);
|
41
41
|
public scrollTop = 0;
|
42
42
|
public scrollLeft = 0;
|
43
43
|
public children: IHTMLCollection<IElement> = HTMLCollectionFactory.create();
|
44
|
-
|
45
44
|
public readonly namespaceURI: string = null;
|
46
45
|
|
46
|
+
private _classList: DOMTokenList = null;
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Returns class list.
|
50
|
+
*
|
51
|
+
* @returns Class list.
|
52
|
+
*/
|
53
|
+
public get classList(): IDOMTokenList {
|
54
|
+
if (!this._classList) {
|
55
|
+
this._classList = new DOMTokenList(this, 'class');
|
56
|
+
}
|
57
|
+
return <IDOMTokenList>this._classList;
|
58
|
+
}
|
59
|
+
|
47
60
|
/**
|
48
61
|
* Returns ID.
|
49
62
|
*
|
@@ -770,6 +783,8 @@ export default class Element extends Node implements IElement {
|
|
770
783
|
|
771
784
|
this._attributes[name] = attribute;
|
772
785
|
|
786
|
+
this._updateDomListIndices();
|
787
|
+
|
773
788
|
if (
|
774
789
|
this.attributeChangedCallback &&
|
775
790
|
(<typeof Element>this.constructor)._observedAttributes &&
|
@@ -843,6 +858,8 @@ export default class Element extends Node implements IElement {
|
|
843
858
|
public removeAttributeNode(attribute: Attr): void {
|
844
859
|
delete this._attributes[attribute.name];
|
845
860
|
|
861
|
+
this._updateDomListIndices();
|
862
|
+
|
846
863
|
if (
|
847
864
|
this.attributeChangedCallback &&
|
848
865
|
(<typeof Element>this.constructor)._observedAttributes &&
|
@@ -934,4 +951,13 @@ export default class Element extends Node implements IElement {
|
|
934
951
|
}
|
935
952
|
return name.toLowerCase();
|
936
953
|
}
|
954
|
+
|
955
|
+
/**
|
956
|
+
* Updates DOM list indices.
|
957
|
+
*/
|
958
|
+
protected _updateDomListIndices(): void {
|
959
|
+
if (this._classList) {
|
960
|
+
this._classList._updateIndices();
|
961
|
+
}
|
962
|
+
}
|
937
963
|
}
|
@@ -2,7 +2,7 @@ import IShadowRoot from '../shadow-root/IShadowRoot';
|
|
2
2
|
import Attr from '../../attribute/Attr';
|
3
3
|
import DOMRect from './DOMRect';
|
4
4
|
import Range from './Range';
|
5
|
-
import
|
5
|
+
import IDOMTokenList from '../../dom-token-list/IDOMTokenList';
|
6
6
|
import INode from './../node/INode';
|
7
7
|
import IChildNode from '../child-node/IChildNode';
|
8
8
|
import IParentNode from '../parent-node/IParentNode';
|
@@ -16,7 +16,7 @@ export type TInsertAdjacentPositions = 'beforebegin' | 'afterbegin' | 'beforeend
|
|
16
16
|
export default interface IElement extends IChildNode, INonDocumentTypeChildNode, IParentNode {
|
17
17
|
readonly tagName: string;
|
18
18
|
readonly shadowRoot: IShadowRoot;
|
19
|
-
readonly classList:
|
19
|
+
readonly classList: IDOMTokenList;
|
20
20
|
readonly namespaceURI: string;
|
21
21
|
scrollTop: number;
|
22
22
|
scrollLeft: number;
|
@@ -10,8 +10,6 @@ import IHTMLLabelElement from './IHTMLLabelElement';
|
|
10
10
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement.
|
11
11
|
*/
|
12
12
|
export default class HTMLLabelElement extends HTMLElement implements IHTMLLabelElement {
|
13
|
-
public _htmlFor: string = null;
|
14
|
-
|
15
13
|
/**
|
16
14
|
* Returns a string containing the ID of the labeled control. This reflects the "for" attribute.
|
17
15
|
*
|
@@ -73,8 +71,6 @@ export default class HTMLLabelElement extends HTMLElement implements IHTMLLabelE
|
|
73
71
|
* @returns Cloned node.
|
74
72
|
*/
|
75
73
|
public cloneNode(deep = false): IHTMLLabelElement {
|
76
|
-
|
77
|
-
clone._htmlFor = this._htmlFor;
|
78
|
-
return clone;
|
74
|
+
return <HTMLLabelElement>super.cloneNode(deep);
|
79
75
|
}
|
80
76
|
}
|
@@ -7,6 +7,8 @@ import IHTMLLinkElement from './IHTMLLinkElement';
|
|
7
7
|
import Event from '../../event/Event';
|
8
8
|
import ErrorEvent from '../../event/events/ErrorEvent';
|
9
9
|
import INode from '../../nodes/node/INode';
|
10
|
+
import DOMTokenList from '../../dom-token-list/DOMTokenList';
|
11
|
+
import IDOMTokenList from '../../dom-token-list/IDOMTokenList';
|
10
12
|
|
11
13
|
/**
|
12
14
|
* HTML Link Element.
|
@@ -19,6 +21,19 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
|
|
19
21
|
public onload: (event: Event) => void = null;
|
20
22
|
public readonly sheet: CSSStyleSheet = null;
|
21
23
|
public _evaluateCSS = true;
|
24
|
+
private _relList: DOMTokenList = null;
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Returns rel list.
|
28
|
+
*
|
29
|
+
* @returns Rel list.
|
30
|
+
*/
|
31
|
+
public get relList(): IDOMTokenList {
|
32
|
+
if (!this._relList) {
|
33
|
+
this._relList = new DOMTokenList(this, 'rel');
|
34
|
+
}
|
35
|
+
return <IDOMTokenList>this._relList;
|
36
|
+
}
|
22
37
|
|
23
38
|
/**
|
24
39
|
* Returns as.
|
@@ -259,4 +274,15 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
|
|
259
274
|
}
|
260
275
|
}
|
261
276
|
}
|
277
|
+
|
278
|
+
/**
|
279
|
+
* Updates DOM list indices.
|
280
|
+
*/
|
281
|
+
protected _updateDomListIndices(): void {
|
282
|
+
super._updateDomListIndices();
|
283
|
+
|
284
|
+
if (this._relList) {
|
285
|
+
this._relList._updateIndices();
|
286
|
+
}
|
287
|
+
}
|
262
288
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import CSSStyleSheet from '../../css/CSSStyleSheet';
|
2
|
+
import IDOMTokenList from '../../dom-token-list/IDOMTokenList';
|
2
3
|
import IHTMLElement from '../html-element/IHTMLElement';
|
3
4
|
|
4
5
|
/**
|
@@ -9,6 +10,7 @@ import IHTMLElement from '../html-element/IHTMLElement';
|
|
9
10
|
*/
|
10
11
|
export default interface IHTMLLinkElement extends IHTMLElement {
|
11
12
|
readonly sheet: CSSStyleSheet;
|
13
|
+
readonly relList: IDOMTokenList;
|
12
14
|
as: string;
|
13
15
|
crossOrigin: string;
|
14
16
|
href: string;
|
@@ -27,10 +27,11 @@ export default class SelectorItem {
|
|
27
27
|
* @param selector Selector.
|
28
28
|
*/
|
29
29
|
constructor(selector: string) {
|
30
|
+
const isNotPseudo = selector.includes(':not(');
|
31
|
+
|
30
32
|
this.isAll = selector === '*';
|
31
33
|
this.isID = !this.isAll ? selector.startsWith('#') : false;
|
32
|
-
this.isAttribute =
|
33
|
-
!this.isAll && !this.isID && selector.includes('[') && !selector.includes(':not(');
|
34
|
+
this.isAttribute = !this.isAll && !this.isID && selector.includes('[') && !isNotPseudo;
|
34
35
|
this.isPseudo = !this.isAll && !this.isID && selector.includes(':');
|
35
36
|
this.isClass = !this.isAll && !this.isID && new RegExp(CLASS_REGEXP, 'g').test(selector);
|
36
37
|
this.tagName = !this.isAll && !this.isID ? selector.match(TAG_NAME_REGEXP) : null;
|
@@ -48,7 +49,6 @@ export default class SelectorItem {
|
|
48
49
|
*/
|
49
50
|
public match(element: Element): boolean {
|
50
51
|
const selector = this.selector;
|
51
|
-
let match;
|
52
52
|
|
53
53
|
// Is all (*)
|
54
54
|
if (this.isAll) {
|
@@ -68,29 +68,13 @@ export default class SelectorItem {
|
|
68
68
|
}
|
69
69
|
|
70
70
|
// Class match
|
71
|
-
if (this.isClass) {
|
72
|
-
|
73
|
-
|
74
|
-
while ((match = regexp.exec(selector))) {
|
75
|
-
if (!element.classList.contains(match[1])) {
|
76
|
-
return false;
|
77
|
-
}
|
78
|
-
}
|
71
|
+
if (this.isClass && !this.matchesClass(element, selector)) {
|
72
|
+
return false;
|
79
73
|
}
|
80
74
|
|
81
75
|
// Pseudo match
|
82
|
-
if (this.isPseudo) {
|
83
|
-
|
84
|
-
|
85
|
-
while ((match = regexp.exec(selector))) {
|
86
|
-
if (match[1] && !this.matchesNthChild(element, match[1], match[2])) {
|
87
|
-
return false;
|
88
|
-
} else if (match[3] && this.matchesAttribute(element, match[3])) {
|
89
|
-
return false;
|
90
|
-
} else if (match[4] && !this.matchesPsuedo(element, match[4])) {
|
91
|
-
return false;
|
92
|
-
}
|
93
|
-
}
|
76
|
+
if (this.isPseudo && !this.matchesPsuedo(element, selector)) {
|
77
|
+
return false;
|
94
78
|
}
|
95
79
|
|
96
80
|
// Attribute match
|
@@ -101,6 +85,35 @@ export default class SelectorItem {
|
|
101
85
|
return true;
|
102
86
|
}
|
103
87
|
|
88
|
+
/**
|
89
|
+
* Matches a psuedo selector.
|
90
|
+
*
|
91
|
+
* @param element Element.
|
92
|
+
* @param selector Selector.
|
93
|
+
* @returns True if it is a match.
|
94
|
+
*/
|
95
|
+
private matchesPsuedo(element: Element, selector: string): boolean {
|
96
|
+
const regexp = new RegExp(PSUEDO_REGEXP, 'g');
|
97
|
+
let match: RegExpMatchArray;
|
98
|
+
|
99
|
+
while ((match = regexp.exec(selector))) {
|
100
|
+
const isNotClass = match[3] && match[3].trim()[0] === '.';
|
101
|
+
if (match[1] && !this.matchesNthChild(element, match[1], match[2])) {
|
102
|
+
return false;
|
103
|
+
} else if (
|
104
|
+
match[3] &&
|
105
|
+
((isNotClass && this.matchesClass(element, match[3])) ||
|
106
|
+
(!isNotClass && this.matchesAttribute(element, match[3])))
|
107
|
+
) {
|
108
|
+
return false;
|
109
|
+
} else if (match[4] && !this.matchesPsuedoExpression(element, match[4])) {
|
110
|
+
return false;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
return true;
|
115
|
+
}
|
116
|
+
|
104
117
|
/**
|
105
118
|
* Matches a nth-child selector.
|
106
119
|
*
|
@@ -158,13 +171,13 @@ export default class SelectorItem {
|
|
158
171
|
}
|
159
172
|
|
160
173
|
/**
|
161
|
-
* Matches a psuedo selector.
|
174
|
+
* Matches a psuedo selector expression.
|
162
175
|
*
|
163
176
|
* @param element Element.
|
164
177
|
* @param psuedo Psuedo name.
|
165
178
|
* @returns True if it is a match.
|
166
179
|
*/
|
167
|
-
private
|
180
|
+
private matchesPsuedoExpression(element: Element, psuedo: string): boolean {
|
168
181
|
const parent = <Element>element.parentNode;
|
169
182
|
|
170
183
|
if (!parent) {
|
@@ -220,7 +233,7 @@ export default class SelectorItem {
|
|
220
233
|
*/
|
221
234
|
private matchesAttribute(element: Element, selector: string): boolean {
|
222
235
|
const regexp = new RegExp(ATTRIBUTE_REGEXP, 'g');
|
223
|
-
let match;
|
236
|
+
let match: RegExpMatchArray;
|
224
237
|
|
225
238
|
while ((match = regexp.exec(selector))) {
|
226
239
|
const isPsuedo = match.index > 0 && selector[match.index] === '(';
|
@@ -236,6 +249,29 @@ export default class SelectorItem {
|
|
236
249
|
return true;
|
237
250
|
}
|
238
251
|
|
252
|
+
/**
|
253
|
+
* Matches class.
|
254
|
+
*
|
255
|
+
* @param element Element.
|
256
|
+
* @param selector Selector.
|
257
|
+
* @returns True if it is a match.
|
258
|
+
*/
|
259
|
+
private matchesClass(element: Element, selector: string): boolean {
|
260
|
+
const regexp = new RegExp(CLASS_REGEXP, 'g');
|
261
|
+
const classList = element.className.split(' ');
|
262
|
+
let previousIndex = 0;
|
263
|
+
let match: RegExpMatchArray;
|
264
|
+
|
265
|
+
while ((match = regexp.exec(selector)) && match.index === previousIndex) {
|
266
|
+
if (!classList.includes(match[1])) {
|
267
|
+
return false;
|
268
|
+
}
|
269
|
+
previousIndex = match.index + match[0].length - 1;
|
270
|
+
}
|
271
|
+
|
272
|
+
return true;
|
273
|
+
}
|
274
|
+
|
239
275
|
/**
|
240
276
|
* Matches attribute name only.
|
241
277
|
*
|
package/src/window/IWindow.ts
CHANGED
@@ -69,11 +69,17 @@ import URLSearchParams from '../url-search-params/URLSearchParams';
|
|
69
69
|
import HTMLCollection from '../nodes/element/HTMLCollection';
|
70
70
|
import NodeList from '../nodes/node/NodeList';
|
71
71
|
import Selection from '../selection/Selection';
|
72
|
+
import IEventTarget from '../event/IEventTarget';
|
73
|
+
import Navigator from '../navigator/Navigator';
|
74
|
+
import MimeType from '../navigator/MimeType';
|
75
|
+
import MimeTypeArray from '../navigator/MimeTypeArray';
|
76
|
+
import Plugin from '../navigator/Plugin';
|
77
|
+
import PluginArray from '../navigator/PluginArray';
|
72
78
|
|
73
79
|
/**
|
74
80
|
* Window.
|
75
81
|
*/
|
76
|
-
export default interface IWindow {
|
82
|
+
export default interface IWindow extends IEventTarget {
|
77
83
|
// Public Properties
|
78
84
|
readonly happyDOM: {
|
79
85
|
whenAsyncComplete: () => Promise<void>;
|
@@ -150,6 +156,11 @@ export default interface IWindow {
|
|
150
156
|
readonly CSSUnitValue: typeof CSSUnitValue;
|
151
157
|
readonly CSS: CSS;
|
152
158
|
readonly Selection: typeof Selection;
|
159
|
+
readonly Navigator: typeof Navigator;
|
160
|
+
readonly MimeType: typeof MimeType;
|
161
|
+
readonly MimeTypeArray: typeof MimeTypeArray;
|
162
|
+
readonly Plugin: typeof Plugin;
|
163
|
+
readonly PluginArray: typeof PluginArray;
|
153
164
|
|
154
165
|
// Events
|
155
166
|
onload: (event: Event) => void;
|
@@ -160,7 +171,7 @@ export default interface IWindow {
|
|
160
171
|
readonly customElements: CustomElementRegistry;
|
161
172
|
readonly location: Location;
|
162
173
|
readonly history: History;
|
163
|
-
readonly navigator:
|
174
|
+
readonly navigator: Navigator;
|
164
175
|
readonly console: Console;
|
165
176
|
readonly self: IWindow;
|
166
177
|
readonly top: IWindow;
|