happy-dom 2.40.1 → 2.41.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.d.ts +12 -12
- package/lib/css/CSSStyleDeclaration.js +13 -4
- package/lib/css/CSSStyleDeclaration.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/nodes/document/Document.d.ts +7 -0
- package/lib/nodes/document/Document.js +9 -0
- package/lib/nodes/document/Document.js.map +1 -1
- package/lib/nodes/document/IDocument.d.ts +7 -0
- package/lib/nodes/html-element/HTMLElement.d.ts +5 -5
- package/lib/nodes/html-element/HTMLElement.js +21 -7
- package/lib/nodes/html-element/HTMLElement.js.map +1 -1
- package/lib/selection/Selection.d.ts +95 -0
- package/lib/selection/Selection.js +127 -0
- package/lib/selection/Selection.js.map +1 -0
- package/lib/window/IWindow.d.ts +2 -0
- package/lib/window/Window.d.ts +2 -0
- package/lib/window/Window.js +2 -0
- package/lib/window/Window.js.map +1 -1
- package/lib/xml-parser/XMLParser.js +7 -5
- package/lib/xml-parser/XMLParser.js.map +1 -1
- package/package.json +2 -2
- package/src/css/CSSStyleDeclaration.ts +41 -36
- package/src/index.ts +3 -1
- package/src/nodes/document/Document.ts +10 -0
- package/src/nodes/document/IDocument.ts +8 -0
- package/src/nodes/html-element/HTMLElement.ts +21 -7
- package/src/selection/Selection.ts +140 -0
- package/src/window/IWindow.ts +2 -0
- package/src/window/Window.ts +2 -0
- package/src/xml-parser/XMLParser.ts +7 -5
@@ -10,7 +10,36 @@ export default class CSSStyleDeclaration {
|
|
10
10
|
private _attributes: { [k: string]: Attr } = null;
|
11
11
|
private _computedStyleElement: { isConnected: boolean } = null;
|
12
12
|
|
13
|
-
|
13
|
+
/**
|
14
|
+
* Constructor.
|
15
|
+
*
|
16
|
+
* @param [attributes] Attributes.
|
17
|
+
* @param [computedStyleElement] Computed style element.
|
18
|
+
* @param computedStyleElement.isConnected
|
19
|
+
*/
|
20
|
+
constructor(
|
21
|
+
attributes: { [k: string]: Attr } = {},
|
22
|
+
computedStyleElement: { isConnected: boolean } = null
|
23
|
+
) {
|
24
|
+
const style = attributes['style'];
|
25
|
+
let index = 0;
|
26
|
+
|
27
|
+
this._attributes = attributes;
|
28
|
+
this._computedStyleElement = computedStyleElement;
|
29
|
+
|
30
|
+
if (style && style.value) {
|
31
|
+
const parts = style.value.split(';');
|
32
|
+
for (const part of parts) {
|
33
|
+
if (part) {
|
34
|
+
const [name] = part.trim().split(':');
|
35
|
+
this[index] = name;
|
36
|
+
index++;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
(<number>this.length) = index;
|
42
|
+
}
|
14
43
|
|
15
44
|
/**
|
16
45
|
*
|
@@ -4809,8 +4838,6 @@ export default class CSSStyleDeclaration {
|
|
4809
4838
|
this.setProperty('zoom', zoom);
|
4810
4839
|
}
|
4811
4840
|
|
4812
|
-
/* eslint-enable require-jsdoc */
|
4813
|
-
|
4814
4841
|
/**
|
4815
4842
|
* Returns the style decleration as a CSS text.
|
4816
4843
|
*
|
@@ -4844,7 +4871,11 @@ export default class CSSStyleDeclaration {
|
|
4844
4871
|
for (const part of parts) {
|
4845
4872
|
if (part) {
|
4846
4873
|
const [name, value] = part.trim().split(':');
|
4847
|
-
|
4874
|
+
if (value) {
|
4875
|
+
newStyle.push(`${name}: ${value.trim()};`);
|
4876
|
+
} else {
|
4877
|
+
newStyle.push(name);
|
4878
|
+
}
|
4848
4879
|
this[index] = name;
|
4849
4880
|
index++;
|
4850
4881
|
}
|
@@ -4860,37 +4891,6 @@ export default class CSSStyleDeclaration {
|
|
4860
4891
|
}
|
4861
4892
|
}
|
4862
4893
|
|
4863
|
-
/**
|
4864
|
-
* Constructor.
|
4865
|
-
*
|
4866
|
-
* @param [attributes] Attributes.
|
4867
|
-
* @param [computedStyleElement] Computed style element.
|
4868
|
-
* @param computedStyleElement.isConnected
|
4869
|
-
*/
|
4870
|
-
constructor(
|
4871
|
-
attributes: { [k: string]: Attr } = {},
|
4872
|
-
computedStyleElement: { isConnected: boolean } = null
|
4873
|
-
) {
|
4874
|
-
const style = attributes['style'];
|
4875
|
-
let index = 0;
|
4876
|
-
|
4877
|
-
this._attributes = attributes;
|
4878
|
-
this._computedStyleElement = computedStyleElement;
|
4879
|
-
|
4880
|
-
if (style && style.value) {
|
4881
|
-
const parts = style.value.split(';');
|
4882
|
-
for (const part of parts) {
|
4883
|
-
if (part) {
|
4884
|
-
const [name] = part.trim().split(':');
|
4885
|
-
this[index] = name;
|
4886
|
-
index++;
|
4887
|
-
}
|
4888
|
-
}
|
4889
|
-
}
|
4890
|
-
|
4891
|
-
(<number>this.length) = index;
|
4892
|
-
}
|
4893
|
-
|
4894
4894
|
/**
|
4895
4895
|
* Returns item.
|
4896
4896
|
*
|
@@ -4932,8 +4932,10 @@ export default class CSSStyleDeclaration {
|
|
4932
4932
|
if (name === propertyName) {
|
4933
4933
|
newStyle.push(`${name}: ${value};`);
|
4934
4934
|
isExisting = true;
|
4935
|
-
} else {
|
4935
|
+
} else if (existingValue) {
|
4936
4936
|
newStyle.push(`${name}: ${existingValue.trim()};`);
|
4937
|
+
} else {
|
4938
|
+
newStyle.push(`${name};`);
|
4937
4939
|
}
|
4938
4940
|
|
4939
4941
|
this[index] = name;
|
@@ -5011,6 +5013,9 @@ export default class CSSStyleDeclaration {
|
|
5011
5013
|
if (part) {
|
5012
5014
|
const [name, value] = part.trim().split(':');
|
5013
5015
|
if (name === propertyName) {
|
5016
|
+
if (!value) {
|
5017
|
+
return '';
|
5018
|
+
}
|
5014
5019
|
return value.trim();
|
5015
5020
|
}
|
5016
5021
|
}
|
package/src/index.ts
CHANGED
@@ -106,6 +106,7 @@ import ChildLessElements from './config/ChildLessElements';
|
|
106
106
|
import CSSStyleSheet from './css/CSSStyleSheet';
|
107
107
|
import Storage from './storage/Storage';
|
108
108
|
import URLSearchParams from './url-search-params/URLSearchParams';
|
109
|
+
import Selection from './selection/Selection';
|
109
110
|
|
110
111
|
export {
|
111
112
|
AsyncWindow,
|
@@ -215,5 +216,6 @@ export {
|
|
215
216
|
ChildLessElements,
|
216
217
|
CSSStyleSheet,
|
217
218
|
Storage,
|
218
|
-
URLSearchParams
|
219
|
+
URLSearchParams,
|
220
|
+
Selection
|
219
221
|
};
|
@@ -35,6 +35,7 @@ import IHTMLStyleElement from '../html-style-element/IHTMLStyleElement';
|
|
35
35
|
import DocumentReadyStateEnum from './DocumentReadyStateEnum';
|
36
36
|
import DocumentReadyStateManager from './DocumentReadyStateManager';
|
37
37
|
import Location from '../../location/Location';
|
38
|
+
import Selection from '../../selection/Selection';
|
38
39
|
|
39
40
|
/**
|
40
41
|
* Document.
|
@@ -699,6 +700,15 @@ export default class Document extends Node implements IDocument {
|
|
699
700
|
return adopted;
|
700
701
|
}
|
701
702
|
|
703
|
+
/**
|
704
|
+
* Returns selection.
|
705
|
+
*
|
706
|
+
* @returns Selection.
|
707
|
+
*/
|
708
|
+
public getSelection(): Selection {
|
709
|
+
return new Selection();
|
710
|
+
}
|
711
|
+
|
702
712
|
/**
|
703
713
|
* @override
|
704
714
|
*/
|
@@ -11,6 +11,7 @@ import IParentNode from '../parent-node/IParentNode';
|
|
11
11
|
import INode from '../node/INode';
|
12
12
|
import ICharacterData from '../character-data/ICharacterData';
|
13
13
|
import IDocumentFragment from '../document-fragment/IDocumentFragment';
|
14
|
+
import Selection from '../../selection/Selection';
|
14
15
|
|
15
16
|
/**
|
16
17
|
* Document.
|
@@ -152,4 +153,11 @@ export default interface IDocument extends IParentNode {
|
|
152
153
|
* @returns Adopted node.
|
153
154
|
*/
|
154
155
|
adoptNode(node: INode): INode;
|
156
|
+
|
157
|
+
/**
|
158
|
+
* Returns selection.
|
159
|
+
*
|
160
|
+
* @returns Selection.
|
161
|
+
*/
|
162
|
+
getSelection(): Selection;
|
155
163
|
}
|
@@ -4,6 +4,7 @@ import CSSStyleDeclaration from '../../css/CSSStyleDeclaration';
|
|
4
4
|
import Attr from '../../attribute/Attr';
|
5
5
|
import FocusEvent from '../../event/events/FocusEvent';
|
6
6
|
import PointerEvent from '../../event/events/PointerEvent';
|
7
|
+
import Node from '../node/Node';
|
7
8
|
|
8
9
|
/**
|
9
10
|
* HTML Element.
|
@@ -49,21 +50,34 @@ export default class HTMLElement extends Element implements IHTMLElement {
|
|
49
50
|
}
|
50
51
|
|
51
52
|
/**
|
52
|
-
* Returns inner text.
|
53
|
+
* Returns inner text, which is the rendered appearance of text.
|
53
54
|
*
|
54
|
-
* @returns
|
55
|
+
* @returns Inner text.
|
55
56
|
*/
|
56
57
|
public get innerText(): string {
|
57
|
-
|
58
|
+
let result = '';
|
59
|
+
for (const childNode of this.childNodes) {
|
60
|
+
if (childNode instanceof HTMLElement) {
|
61
|
+
if (childNode.tagName !== 'SCRIPT' && childNode.tagName !== 'STYLE') {
|
62
|
+
result += childNode.innerText;
|
63
|
+
}
|
64
|
+
} else if (
|
65
|
+
childNode.nodeType === Node.ELEMENT_NODE ||
|
66
|
+
childNode.nodeType === Node.TEXT_NODE
|
67
|
+
) {
|
68
|
+
result += childNode.textContent;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
return result;
|
58
72
|
}
|
59
73
|
|
60
74
|
/**
|
61
|
-
* Sets inner text.
|
75
|
+
* Sets the inner text, which is the rendered appearance of text.
|
62
76
|
*
|
63
|
-
* @param text
|
77
|
+
* @param innerText Inner text.
|
64
78
|
*/
|
65
|
-
public set innerText(
|
66
|
-
this.textContent =
|
79
|
+
public set innerText(innerText: string) {
|
80
|
+
this.textContent = innerText;
|
67
81
|
}
|
68
82
|
|
69
83
|
/**
|
@@ -0,0 +1,140 @@
|
|
1
|
+
import INode from '../nodes/node/INode';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Selection.
|
5
|
+
*
|
6
|
+
* Reference:
|
7
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Selection.
|
8
|
+
*/
|
9
|
+
export default class Selection {
|
10
|
+
public readonly anchorNode: INode = null;
|
11
|
+
public readonly anchorOffset: number = 0;
|
12
|
+
public readonly baseNode: INode = null;
|
13
|
+
public readonly baseOffset: number = 0;
|
14
|
+
public readonly extentNode: INode = null;
|
15
|
+
public readonly extentOffset: number = 0;
|
16
|
+
public readonly focusNode: INode = null;
|
17
|
+
public readonly focusOffset: number = 0;
|
18
|
+
public readonly isCollapsed: boolean = true;
|
19
|
+
public readonly rangeCount: number = 0;
|
20
|
+
public readonly type: string = 'None';
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Adds a range.
|
24
|
+
*
|
25
|
+
* @param _range Range.
|
26
|
+
*/
|
27
|
+
public addRange(_range: object): void {
|
28
|
+
// Do nothing.
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Collapses the current selection to a single point.
|
33
|
+
*
|
34
|
+
* @param _node Node.
|
35
|
+
* @param _offset Offset.
|
36
|
+
*/
|
37
|
+
public collapse(_node: INode, _offset?: number): void {
|
38
|
+
// Do nothing.
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Collapses the selection to the end.
|
43
|
+
*/
|
44
|
+
public collapseToEnd(): void {
|
45
|
+
// Do nothing.
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Collapses the selection to the start.
|
50
|
+
*/
|
51
|
+
public collapseToStart(): void {
|
52
|
+
// Do nothing.
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Indicates whether a specified node is part of the selection.
|
57
|
+
*
|
58
|
+
* @param _node Node.
|
59
|
+
* @param _partialContainer Partial container.
|
60
|
+
* @returns Always returns "true" for now.
|
61
|
+
*/
|
62
|
+
public containsNode(_node: INode, _partialContainer?: INode): boolean {
|
63
|
+
return true;
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Deletes the selected text from the document's DOM.
|
68
|
+
*/
|
69
|
+
public deleteFromDocument(): void {
|
70
|
+
// Do nothing.
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Moves the focus of the selection to a specified point.
|
75
|
+
*
|
76
|
+
* @param _node Node.
|
77
|
+
* @param _offset Offset.
|
78
|
+
*/
|
79
|
+
public extend(_node: INode, _offset?: number): void {
|
80
|
+
// Do nothing.
|
81
|
+
}
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Moves the focus of the selection to a specified point.
|
85
|
+
*
|
86
|
+
* @param _index Index.
|
87
|
+
*/
|
88
|
+
public getRangeAt(_index: number): object {
|
89
|
+
throw new Error('Not a valid index.');
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Removes a range from a selection.
|
94
|
+
*
|
95
|
+
* @param _range Range.
|
96
|
+
*/
|
97
|
+
public removeRange(_range: object): void {
|
98
|
+
// Do nothing.
|
99
|
+
}
|
100
|
+
|
101
|
+
/**
|
102
|
+
* Removes all ranges.
|
103
|
+
*/
|
104
|
+
public removeAllRanges(): void {
|
105
|
+
// Do nothing.
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Selects all children.
|
110
|
+
*
|
111
|
+
* @param _parentNode Parent node.
|
112
|
+
*/
|
113
|
+
public selectAllChildren(_parentNode: INode): void {
|
114
|
+
// Do nothing.
|
115
|
+
}
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Sets the selection to be a range including all or parts of two specified DOM nodes, and any content located between them.
|
119
|
+
*
|
120
|
+
* @param _anchorNode Anchor node.
|
121
|
+
* @param _anchorOffset Anchor offset.
|
122
|
+
* @param _focusNode Focus node.
|
123
|
+
* @param _focusOffset Focus offset.
|
124
|
+
*/
|
125
|
+
public setBaseAndExtent(
|
126
|
+
_anchorNode: INode,
|
127
|
+
_anchorOffset: number,
|
128
|
+
_focusNode: INode,
|
129
|
+
_focusOffset: number
|
130
|
+
): void {
|
131
|
+
// Do nothing.
|
132
|
+
}
|
133
|
+
|
134
|
+
/**
|
135
|
+
* Returns string currently being represented by the selection object.
|
136
|
+
*/
|
137
|
+
public toString(): string {
|
138
|
+
return '';
|
139
|
+
}
|
140
|
+
}
|
package/src/window/IWindow.ts
CHANGED
@@ -68,6 +68,7 @@ import Window from './Window';
|
|
68
68
|
import URLSearchParams from '../url-search-params/URLSearchParams';
|
69
69
|
import HTMLCollection from '../nodes/element/HTMLCollection';
|
70
70
|
import NodeList from '../nodes/node/NodeList';
|
71
|
+
import Selection from '../selection/Selection';
|
71
72
|
|
72
73
|
/**
|
73
74
|
* Window.
|
@@ -148,6 +149,7 @@ export default interface IWindow {
|
|
148
149
|
readonly NodeList: typeof NodeList;
|
149
150
|
readonly CSSUnitValue: typeof CSSUnitValue;
|
150
151
|
readonly CSS: CSS;
|
152
|
+
readonly Selection: typeof Selection;
|
151
153
|
|
152
154
|
// Events
|
153
155
|
onload: (event: Event) => void;
|
package/src/window/Window.ts
CHANGED
@@ -73,6 +73,7 @@ import URLSearchParams from '../url-search-params/URLSearchParams';
|
|
73
73
|
import HTMLCollection from '../nodes/element/HTMLCollection';
|
74
74
|
import NodeList from '../nodes/node/NodeList';
|
75
75
|
import MediaQueryList from '../match-media/MediaQueryList';
|
76
|
+
import Selection from '../selection/Selection';
|
76
77
|
import * as PerfHooks from 'perf_hooks';
|
77
78
|
|
78
79
|
const FETCH_RESPONSE_TYPE_METHODS = ['blob', 'json', 'text'];
|
@@ -160,6 +161,7 @@ export default class Window extends EventTarget implements IWindow, NodeJS.Globa
|
|
160
161
|
public readonly NodeList = NodeList;
|
161
162
|
public readonly MediaQueryList = MediaQueryList;
|
162
163
|
public readonly CSSUnitValue = CSSUnitValue;
|
164
|
+
public readonly Selection = Selection;
|
163
165
|
|
164
166
|
// Events
|
165
167
|
public onload: (event: Event) => void = null;
|
@@ -37,7 +37,6 @@ export default class XMLParser {
|
|
37
37
|
let parentUnnestableTagName = null;
|
38
38
|
let lastTextIndex = 0;
|
39
39
|
let match: RegExpExecArray;
|
40
|
-
let childLessIndex = 0;
|
41
40
|
|
42
41
|
while ((match = markupRegexp.exec(data))) {
|
43
42
|
const tagName = match[2].toLowerCase();
|
@@ -88,15 +87,18 @@ export default class XMLParser {
|
|
88
87
|
} else {
|
89
88
|
parent.appendChild(newElement);
|
90
89
|
}
|
91
|
-
lastTextIndex =
|
90
|
+
lastTextIndex = markupRegexp.lastIndex;
|
92
91
|
|
93
92
|
// Tags which contain non-parsed content
|
94
93
|
// For example: <script> JavaScript should not be parsed
|
95
94
|
if (ChildLessElements.includes(tagName)) {
|
96
|
-
|
97
|
-
|
95
|
+
let childLessMatch = null;
|
96
|
+
while ((childLessMatch = markupRegexp.exec(data))) {
|
97
|
+
if (childLessMatch[2] === match[2] && childLessMatch[1]) {
|
98
|
+
markupRegexp.lastIndex -= childLessMatch[0].length;
|
99
|
+
break;
|
100
|
+
}
|
98
101
|
}
|
99
|
-
markupRegexp.lastIndex = childLessIndex;
|
100
102
|
}
|
101
103
|
} else {
|
102
104
|
stack.pop();
|