happy-dom 7.6.7 → 7.7.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.

Files changed (35) hide show
  1. package/lib/config/ElementTag.d.ts +2 -1
  2. package/lib/config/ElementTag.js +2 -1
  3. package/lib/config/ElementTag.js.map +1 -1
  4. package/lib/dom-token-list/DOMTokenList.js +1 -1
  5. package/lib/dom-token-list/DOMTokenList.js.map +1 -1
  6. package/lib/nodes/element/Element.d.ts +0 -4
  7. package/lib/nodes/element/Element.js +6 -10
  8. package/lib/nodes/element/Element.js.map +1 -1
  9. package/lib/nodes/html-anchor-element/HTMLAnchorElement.d.ts +250 -0
  10. package/lib/nodes/html-anchor-element/HTMLAnchorElement.js +395 -0
  11. package/lib/nodes/html-anchor-element/HTMLAnchorElement.js.map +1 -0
  12. package/lib/nodes/html-anchor-element/HTMLAnchorElementUtility.d.ts +29 -0
  13. package/lib/nodes/html-anchor-element/HTMLAnchorElementUtility.js +45 -0
  14. package/lib/nodes/html-anchor-element/HTMLAnchorElementUtility.js.map +1 -0
  15. package/lib/nodes/html-anchor-element/IHTMLAnchorElement.d.ts +20 -0
  16. package/lib/nodes/html-anchor-element/IHTMLAnchorElement.js +3 -0
  17. package/lib/nodes/html-anchor-element/IHTMLAnchorElement.js.map +1 -0
  18. package/lib/nodes/html-anchor-element/IHTMLHyperlinkElementUtils.d.ts +19 -0
  19. package/lib/nodes/html-anchor-element/IHTMLHyperlinkElementUtils.js +3 -0
  20. package/lib/nodes/html-anchor-element/IHTMLHyperlinkElementUtils.js.map +1 -0
  21. package/lib/nodes/html-link-element/HTMLLinkElement.d.ts +3 -7
  22. package/lib/nodes/html-link-element/HTMLLinkElement.js +13 -13
  23. package/lib/nodes/html-link-element/HTMLLinkElement.js.map +1 -1
  24. package/lib/query-selector/SelectorItem.js +10 -13
  25. package/lib/query-selector/SelectorItem.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/config/ElementTag.ts +2 -1
  28. package/src/dom-token-list/DOMTokenList.ts +1 -1
  29. package/src/nodes/element/Element.ts +6 -11
  30. package/src/nodes/html-anchor-element/HTMLAnchorElement.ts +439 -0
  31. package/src/nodes/html-anchor-element/HTMLAnchorElementUtility.ts +48 -0
  32. package/src/nodes/html-anchor-element/IHTMLAnchorElement.ts +21 -0
  33. package/src/nodes/html-anchor-element/IHTMLHyperlinkElementUtils.ts +19 -0
  34. package/src/nodes/html-link-element/HTMLLinkElement.ts +18 -16
  35. package/src/query-selector/SelectorItem.ts +11 -14
@@ -0,0 +1,19 @@
1
+ /**
2
+ * HTMLHyperlinkElementUtils.
3
+ *
4
+ * Reference:
5
+ * https://html.spec.whatwg.org/multipage/links.html#htmlhyperlinkelementutils.
6
+ */
7
+ export default interface IHTMLHyperlinkElementUtils {
8
+ readonly origin: string;
9
+ href: string;
10
+ protocol: string;
11
+ username: string;
12
+ password: string;
13
+ host: string;
14
+ hostname: string;
15
+ port: string;
16
+ pathname: string;
17
+ search: string;
18
+ hash: string;
19
+ }
@@ -180,17 +180,17 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
180
180
  }
181
181
 
182
182
  /**
183
- * The setAttributeNode() method adds a new Attr node to the specified element.
184
- *
185
183
  * @override
186
- * @param attribute Attribute.
187
- * @returns Replaced attribute.
188
184
  */
189
- public setAttributeNode(attribute: IAttr): IAttr {
185
+ public override setAttributeNode(attribute: IAttr): IAttr {
190
186
  const replacedAttribute = super.setAttributeNode(attribute);
191
187
  const rel = this.getAttributeNS(null, 'rel');
192
188
  const href = this.getAttributeNS(null, 'href');
193
189
 
190
+ if (attribute.name === 'rel' && this._relList) {
191
+ this._relList._updateIndices();
192
+ }
193
+
194
194
  if (
195
195
  (attribute.name === 'rel' || attribute.name === 'href') &&
196
196
  href !== null &&
@@ -233,6 +233,19 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
233
233
  return replacedAttribute;
234
234
  }
235
235
 
236
+ /**
237
+ * @override
238
+ */
239
+ public override removeAttributeNode(attribute: IAttr): IAttr {
240
+ super.removeAttributeNode(attribute);
241
+
242
+ if (attribute.name === 'rel' && this._relList) {
243
+ this._relList._updateIndices();
244
+ }
245
+
246
+ return attribute;
247
+ }
248
+
236
249
  /**
237
250
  * @override
238
251
  */
@@ -280,15 +293,4 @@ export default class HTMLLinkElement extends HTMLElement implements IHTMLLinkEle
280
293
  }
281
294
  }
282
295
  }
283
-
284
- /**
285
- * Updates DOM list indices.
286
- */
287
- protected _updateDomListIndices(): void {
288
- super._updateDomListIndices();
289
-
290
- if (this._relList) {
291
- this._relList._updateIndices();
292
- }
293
- }
294
296
  }
@@ -5,10 +5,13 @@ import Element from '../nodes/element/Element';
5
5
  const ATTRIBUTE_REGEXP =
6
6
  /\[([a-zA-Z0-9-_]+)\]|\[([a-zA-Z0-9-_]+)([~|^$*]{0,1})[ ]*=[ ]*["']{0,1}([^"']+)["']{0,1}\]/g;
7
7
  const ATTRIBUTE_NAME_REGEXP = /[^a-zA-Z0-9-_$]/;
8
- const PSUEDO_REGEXP = /:([a-zA-Z-]+)\(([0-9n+-]+|odd|even)\)|:not\(([^)]+)\)|:([a-zA-Z-]+)/g;
9
- const CLASS_REGEXP = /\.([a-zA-Z0-9-_$]+)/g;
8
+ const PSUEDO_REGEXP =
9
+ /(?<!\\):([a-zA-Z-]+)\(([0-9n+-]+|odd|even)\)|(?<!\\):not\(([^)]+)\)|(?<!\\):([a-zA-Z-]+)/g;
10
+ const CLASS_REGEXP = /\.(([a-zA-Z0-9-_$]|\\.)+)/g;
10
11
  const TAG_NAME_REGEXP = /^[a-zA-Z0-9-]+/;
11
- const ID_REGEXP = /#[A-Za-z][-A-Za-z0-9_]*/g;
12
+ const ID_REGEXP = /(?<!\\)#[A-Za-z][-A-Za-z0-9_]*/g;
13
+ const CSS_ESCAPE_REGEXP = /(?<!\\):/g;
14
+ const CSS_ESCAPE_CHAR_REGEXP = /\\/g;
12
15
 
13
16
  /**
14
17
  * Selector item.
@@ -31,9 +34,10 @@ export default class SelectorItem {
31
34
  */
32
35
  constructor(selector: string) {
33
36
  const baseSelector = selector.replace(new RegExp(PSUEDO_REGEXP, 'g'), '');
37
+ const idMatch = !this.isAll && selector.includes('#') ? baseSelector.match(ID_REGEXP) : null;
34
38
 
35
39
  this.isAll = baseSelector === '*';
36
- this.isID = !this.isAll ? selector.indexOf('#') !== -1 : false;
40
+ this.isID = !!idMatch;
37
41
  this.isAttribute = !this.isAll && baseSelector.includes('[');
38
42
  // If baseSelector !== selector then some psuedo selector was replaced above
39
43
  this.isPseudo = !this.isAll && baseSelector !== selector;
@@ -42,14 +46,7 @@ export default class SelectorItem {
42
46
  this.tagName = this.tagName ? this.tagName[0].toUpperCase() : null;
43
47
  this.isTagName = this.tagName !== null;
44
48
  this.selector = selector;
45
- this.id = null;
46
-
47
- if (!this.isAll && this.isID) {
48
- const idMatches = baseSelector.match(ID_REGEXP);
49
- if (idMatches) {
50
- this.id = idMatches[0].replace('#', '');
51
- }
52
- }
49
+ this.id = idMatch ? idMatch[0].replace('#', '') : null;
53
50
  }
54
51
 
55
52
  /**
@@ -296,13 +293,13 @@ export default class SelectorItem {
296
293
  ): { priorityWeight: number; matches: boolean } {
297
294
  const regexp = new RegExp(CLASS_REGEXP, 'g');
298
295
  const classList = element.className.split(' ');
299
- const classSelector = selector.split(':')[0];
296
+ const classSelector = selector.split(CSS_ESCAPE_REGEXP)[0];
300
297
  let priorityWeight = 0;
301
298
  let match: RegExpMatchArray;
302
299
 
303
300
  while ((match = regexp.exec(classSelector))) {
304
301
  priorityWeight += 10;
305
- if (!classList.includes(match[1])) {
302
+ if (!classList.includes(match[1].replace(CSS_ESCAPE_CHAR_REGEXP, ''))) {
306
303
  return { priorityWeight: 0, matches: false };
307
304
  }
308
305
  }