@tkeron/html-parser 1.1.2 → 1.3.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.
Files changed (131) hide show
  1. package/.github/workflows/npm_deploy.yml +14 -4
  2. package/README.md +6 -6
  3. package/bun.lock +6 -8
  4. package/check-versions.ts +147 -0
  5. package/index.ts +4 -8
  6. package/package.json +5 -6
  7. package/src/dom-simulator/append-child.ts +130 -0
  8. package/src/dom-simulator/append.ts +18 -0
  9. package/src/dom-simulator/attributes.ts +23 -0
  10. package/src/dom-simulator/clone-node.ts +51 -0
  11. package/src/dom-simulator/convert-ast-node-to-dom.ts +37 -0
  12. package/src/dom-simulator/create-cdata.ts +18 -0
  13. package/src/dom-simulator/create-comment.ts +23 -0
  14. package/src/dom-simulator/create-doctype.ts +24 -0
  15. package/src/dom-simulator/create-document.ts +81 -0
  16. package/src/dom-simulator/create-element.ts +195 -0
  17. package/src/dom-simulator/create-processing-instruction.ts +19 -0
  18. package/src/dom-simulator/create-temp-parent.ts +9 -0
  19. package/src/dom-simulator/create-text-node.ts +23 -0
  20. package/src/dom-simulator/escape-text-content.ts +6 -0
  21. package/src/dom-simulator/find-special-elements.ts +14 -0
  22. package/src/dom-simulator/get-text-content.ts +18 -0
  23. package/src/dom-simulator/index.ts +36 -0
  24. package/src/dom-simulator/inner-outer-html.ts +182 -0
  25. package/src/dom-simulator/insert-after.ts +20 -0
  26. package/src/dom-simulator/insert-before.ts +108 -0
  27. package/src/dom-simulator/matches.ts +26 -0
  28. package/src/dom-simulator/node-types.ts +26 -0
  29. package/src/dom-simulator/prepend.ts +24 -0
  30. package/src/dom-simulator/remove-child.ts +68 -0
  31. package/src/dom-simulator/remove.ts +7 -0
  32. package/src/dom-simulator/replace-child.ts +152 -0
  33. package/src/dom-simulator/set-text-content.ts +33 -0
  34. package/src/dom-simulator/update-element-content.ts +56 -0
  35. package/src/dom-simulator.ts +12 -1126
  36. package/src/encoding/constants.ts +8 -0
  37. package/src/encoding/detect-encoding.ts +21 -0
  38. package/src/encoding/index.ts +1 -0
  39. package/src/encoding/normalize-encoding.ts +6 -0
  40. package/src/html-entities.ts +2127 -0
  41. package/src/index.ts +5 -5
  42. package/src/parser/adoption-agency-helpers.ts +145 -0
  43. package/src/parser/constants.ts +137 -0
  44. package/src/parser/dom-to-ast.ts +79 -0
  45. package/src/parser/index.ts +9 -0
  46. package/src/parser/parse.ts +772 -0
  47. package/src/parser/types.ts +56 -0
  48. package/src/selectors/find-elements-descendant.ts +47 -0
  49. package/src/selectors/index.ts +2 -0
  50. package/src/selectors/matches-selector.ts +12 -0
  51. package/src/selectors/matches-token.ts +27 -0
  52. package/src/selectors/parse-selector.ts +48 -0
  53. package/src/selectors/query-selector-all.ts +43 -0
  54. package/src/selectors/query-selector.ts +6 -0
  55. package/src/selectors/types.ts +10 -0
  56. package/src/serializer/attributes.ts +74 -0
  57. package/src/serializer/escape.ts +13 -0
  58. package/src/serializer/index.ts +1 -0
  59. package/src/serializer/serialize-tokens.ts +511 -0
  60. package/src/tokenizer/calculate-position.ts +10 -0
  61. package/src/tokenizer/constants.ts +11 -0
  62. package/src/tokenizer/decode-entities.ts +64 -0
  63. package/src/tokenizer/index.ts +2 -0
  64. package/src/tokenizer/parse-attributes.ts +74 -0
  65. package/src/tokenizer/tokenize.ts +165 -0
  66. package/src/tokenizer/types.ts +25 -0
  67. package/tests/adoption-agency-helpers.test.ts +304 -0
  68. package/tests/advanced.test.ts +242 -221
  69. package/tests/cloneNode.test.ts +19 -66
  70. package/tests/custom-elements-head.test.ts +54 -55
  71. package/tests/dom-extended.test.ts +77 -64
  72. package/tests/dom-manipulation.test.ts +51 -24
  73. package/tests/dom.test.ts +15 -13
  74. package/tests/encoding/detect-encoding.test.ts +33 -0
  75. package/tests/google-dom.test.ts +2 -2
  76. package/tests/helpers/tokenizer-adapter.test.ts +29 -43
  77. package/tests/helpers/tokenizer-adapter.ts +36 -33
  78. package/tests/helpers/tree-adapter.test.ts +20 -20
  79. package/tests/helpers/tree-adapter.ts +34 -24
  80. package/tests/html-entities-text.test.ts +6 -2
  81. package/tests/innerhtml-void-elements.test.ts +52 -36
  82. package/tests/outerHTML-replacement.test.ts +37 -65
  83. package/tests/parser/dom-to-ast.test.ts +109 -0
  84. package/tests/parser/parse.test.ts +139 -0
  85. package/tests/parser.test.ts +281 -217
  86. package/tests/selectors/query-selector-all.test.ts +39 -0
  87. package/tests/selectors/query-selector.test.ts +42 -0
  88. package/tests/serializer/attributes.test.ts +132 -0
  89. package/tests/serializer/escape.test.ts +51 -0
  90. package/tests/serializer/serialize-tokens.test.ts +80 -0
  91. package/tests/serializer-core.test.ts +6 -6
  92. package/tests/serializer-injectmeta.test.ts +6 -6
  93. package/tests/serializer-optionaltags.test.ts +9 -6
  94. package/tests/serializer-options.test.ts +6 -6
  95. package/tests/serializer-whitespace.test.ts +6 -6
  96. package/tests/tokenizer/calculate-position.test.ts +34 -0
  97. package/tests/tokenizer/decode-entities.test.ts +31 -0
  98. package/tests/tokenizer/parse-attributes.test.ts +44 -0
  99. package/tests/tokenizer/tokenize.test.ts +757 -0
  100. package/tests/tokenizer-namedEntities.test.ts +10 -7
  101. package/tests/tokenizer-pendingSpecChanges.test.ts +10 -7
  102. package/tests/tokenizer.test.ts +268 -256
  103. package/tests/tree-construction-adoption01.test.ts +25 -16
  104. package/tests/tree-construction-adoption02.test.ts +30 -19
  105. package/tests/tree-construction-domjs-unsafe.test.ts +6 -4
  106. package/tests/tree-construction-entities02.test.ts +18 -16
  107. package/tests/tree-construction-html5test-com.test.ts +16 -10
  108. package/tests/tree-construction-math.test.ts +11 -9
  109. package/tests/tree-construction-namespace-sensitivity.test.ts +11 -9
  110. package/tests/tree-construction-noscript01.test.ts +11 -9
  111. package/tests/tree-construction-ruby.test.ts +6 -4
  112. package/tests/tree-construction-scriptdata01.test.ts +6 -4
  113. package/tests/tree-construction-svg.test.ts +6 -4
  114. package/tests/tree-construction-template.test.ts +6 -4
  115. package/tests/tree-construction-tests10.test.ts +6 -4
  116. package/tests/tree-construction-tests11.test.ts +6 -4
  117. package/tests/tree-construction-tests20.test.ts +7 -4
  118. package/tests/tree-construction-tests21.test.ts +7 -4
  119. package/tests/tree-construction-tests23.test.ts +7 -4
  120. package/tests/tree-construction-tests24.test.ts +7 -4
  121. package/tests/tree-construction-tests5.test.ts +6 -5
  122. package/tests/tree-construction-tests6.test.ts +6 -5
  123. package/tests/tree-construction-tests_innerHTML_1.test.ts +6 -5
  124. package/tests/void-elements.test.ts +85 -40
  125. package/tsconfig.json +1 -1
  126. package/src/css-selector.ts +0 -185
  127. package/src/encoding.ts +0 -39
  128. package/src/parser.ts +0 -682
  129. package/src/serializer.ts +0 -450
  130. package/src/tokenizer.ts +0 -325
  131. package/tests/selectors.test.ts +0 -128
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect } from "vitest";
2
2
  import { parseHTML } from "../index.js";
3
- import { NodeType } from "../src/dom-simulator.js";
3
+ import { NodeType } from "../src/dom-simulator/index.js";
4
4
 
5
5
  describe("cloneNode functionality", () => {
6
6
  describe("cloneNode(true) - deep cloning", () => {
@@ -11,17 +11,13 @@ describe("cloneNode functionality", () => {
11
11
 
12
12
  const cloned = original.cloneNode(true);
13
13
 
14
-
15
14
  expect(cloned).toBeTruthy();
16
15
  expect(cloned.nodeName).toBe("DIV");
17
16
 
18
-
19
17
  expect(cloned.getAttribute("id")).toBe("original");
20
18
 
21
-
22
19
  expect(cloned.textContent).toBe("Hello World");
23
20
 
24
-
25
21
  expect(cloned.childNodes.length).toBeGreaterThan(0);
26
22
  });
27
23
 
@@ -38,20 +34,16 @@ describe("cloneNode functionality", () => {
38
34
 
39
35
  const cloned = parent.cloneNode(true);
40
36
 
41
-
42
37
  expect(cloned.nodeName).toBe("DIV");
43
38
  expect(cloned.getAttribute("id")).toBe("parent");
44
39
 
45
-
46
40
  expect(cloned.childNodes.length).toBeGreaterThan(0);
47
-
48
-
41
+
49
42
  const childDiv = cloned.querySelector(".child");
50
43
  expect(childDiv).toBeTruthy();
51
44
  expect(childDiv?.nodeName).toBe("DIV");
52
45
  expect(childDiv?.getAttribute("class")).toBe("child");
53
46
 
54
-
55
47
  const span = cloned.querySelector("span");
56
48
  expect(span).toBeTruthy();
57
49
  expect(span?.textContent).toBe("Nested Text");
@@ -70,7 +62,6 @@ describe("cloneNode functionality", () => {
70
62
 
71
63
  const cloned = list.cloneNode(true);
72
64
 
73
-
74
65
  const items = cloned.querySelectorAll("li");
75
66
  expect(items.length).toBe(3);
76
67
  expect(items[0]?.textContent).toBe("Item 1");
@@ -89,18 +80,15 @@ describe("cloneNode functionality", () => {
89
80
  const doc = parseHTML(html);
90
81
  const container = doc.querySelector("#container")!;
91
82
 
92
-
93
83
  const originalInnerHTML = container.innerHTML;
94
84
  expect(originalInnerHTML).toBeTruthy();
95
85
  expect(originalInnerHTML.length).toBeGreaterThan(0);
96
86
 
97
87
  const cloned = container.cloneNode(true);
98
88
 
99
-
100
89
  expect(cloned.innerHTML).toBeTruthy();
101
90
  expect(cloned.innerHTML.length).toBeGreaterThan(0);
102
91
 
103
-
104
92
  expect(cloned.innerHTML).toContain("<h1>Title</h1>");
105
93
  expect(cloned.innerHTML).toContain("<p>Paragraph 1</p>");
106
94
  expect(cloned.innerHTML).toContain("<p>Paragraph 2</p>");
@@ -111,19 +99,15 @@ describe("cloneNode functionality", () => {
111
99
  const doc = parseHTML(html);
112
100
  const mixed = doc.querySelector("#mixed")!;
113
101
 
114
-
115
102
  const originalChildCount = mixed.childNodes.length;
116
103
  expect(originalChildCount).toBeGreaterThan(0);
117
104
 
118
105
  const cloned = mixed.cloneNode(true);
119
106
 
120
-
121
107
  expect(cloned.childNodes.length).toBe(originalChildCount);
122
108
 
123
-
124
109
  expect(cloned.textContent).toBe("Text beforebold textText after");
125
110
 
126
-
127
111
  const strong = cloned.querySelector("strong");
128
112
  expect(strong).toBeTruthy();
129
113
  expect(strong?.textContent).toBe("bold text");
@@ -136,7 +120,6 @@ describe("cloneNode functionality", () => {
136
120
 
137
121
  const cloned = element.cloneNode(true);
138
122
 
139
-
140
123
  expect(cloned.getAttribute("id")).toBe("attrs");
141
124
  expect(cloned.getAttribute("class")).toBe("test");
142
125
  expect(cloned.getAttribute("data-value")).toBe("123");
@@ -161,26 +144,22 @@ describe("cloneNode functionality", () => {
161
144
 
162
145
  const cloned = article.cloneNode(true);
163
146
 
164
-
165
147
  expect(cloned.nodeName).toBe("ARTICLE");
166
148
  expect(cloned.getAttribute("id")).toBe("article");
167
149
 
168
-
169
150
  expect(cloned.querySelector("h2")?.textContent).toBe("Article Title");
170
-
151
+
171
152
  const paragraphs = cloned.querySelectorAll("p");
172
153
  expect(paragraphs.length).toBe(2);
173
154
  expect(paragraphs[0]?.textContent).toBe("First paragraph");
174
155
  expect(paragraphs[1]?.textContent).toBe("Last paragraph");
175
156
 
176
-
177
157
  const highlight = cloned.querySelector(".highlight");
178
158
  expect(highlight).toBeTruthy();
179
159
  expect(highlight?.querySelector("span")?.textContent).toBe("Highlighted");
180
160
 
181
-
182
161
  const hasComment = Array.from(cloned.childNodes).some(
183
- (node: any) => node.nodeType === NodeType.COMMENT_NODE
162
+ (node: any) => node.nodeType === NodeType.COMMENT_NODE,
184
163
  );
185
164
  expect(hasComment).toBe(true);
186
165
  });
@@ -203,10 +182,9 @@ describe("cloneNode functionality", () => {
203
182
 
204
183
  const cloned = section.cloneNode(true);
205
184
 
206
-
207
185
  expect(cloned.outerHTML).toBeTruthy();
208
186
  expect(cloned.outerHTML).toContain("section");
209
- expect(cloned.outerHTML).toContain("class=\"main\"");
187
+ expect(cloned.outerHTML).toContain('class="main"');
210
188
  expect(cloned.outerHTML).toContain("<h1>Title</h1>");
211
189
  expect(cloned.outerHTML).toContain("<p>Text</p>");
212
190
  });
@@ -220,7 +198,6 @@ describe("cloneNode functionality", () => {
220
198
 
221
199
  const cloned = parent.cloneNode(false);
222
200
 
223
-
224
201
  expect(cloned.nodeName).toBe("DIV");
225
202
  expect(cloned.getAttribute("id")).toBe("parent");
226
203
  expect(cloned.childNodes.length).toBe(0);
@@ -234,12 +211,10 @@ describe("cloneNode functionality", () => {
234
211
 
235
212
  const cloned = element.cloneNode(false);
236
213
 
237
-
238
214
  expect(cloned.getAttribute("id")).toBe("test");
239
215
  expect(cloned.getAttribute("class")).toBe("container");
240
216
  expect(cloned.getAttribute("data-value")).toBe("123");
241
217
 
242
-
243
218
  expect(cloned.childNodes.length).toBe(0);
244
219
  expect(cloned.innerHTML).toBe("");
245
220
  });
@@ -253,7 +228,6 @@ describe("cloneNode functionality", () => {
253
228
 
254
229
  const cloned = original.cloneNode(true);
255
230
 
256
-
257
231
  cloned.setAttribute("id", "cloned");
258
232
  cloned.setAttribute("data-modified", "true");
259
233
 
@@ -270,13 +244,11 @@ describe("cloneNode functionality", () => {
270
244
 
271
245
  const cloned = parent.cloneNode(true);
272
246
  const clonedChild = cloned.querySelector("#child");
273
-
247
+
274
248
  expect(clonedChild).toBeTruthy();
275
-
276
-
249
+
277
250
  clonedChild?.setAttribute("data-cloned", "yes");
278
251
 
279
-
280
252
  const originalChild = parent.querySelector("#child");
281
253
  expect(originalChild?.hasAttribute("data-cloned")).toBe(false);
282
254
  });
@@ -324,7 +296,6 @@ describe("cloneNode functionality", () => {
324
296
 
325
297
  const cloned = level1.cloneNode(true);
326
298
 
327
-
328
299
  expect(cloned.querySelector("#level2")).toBeTruthy();
329
300
  expect(cloned.querySelector("#level3")).toBeTruthy();
330
301
  expect(cloned.querySelector("#level4")).toBeTruthy();
@@ -340,22 +311,18 @@ describe("cloneNode functionality", () => {
340
311
  const doc = parseHTML(html);
341
312
  const container = doc.querySelector("#container")!;
342
313
 
343
-
344
314
  const originalInnerHTML = container.innerHTML;
345
315
  expect(originalInnerHTML).toBeTruthy();
346
316
 
347
317
  const cloned = container.cloneNode(true);
348
318
 
349
-
350
319
  const clonedInnerHTML = cloned.innerHTML;
351
320
  expect(clonedInnerHTML).toBeTruthy();
352
321
  expect(clonedInnerHTML.length).toBeGreaterThan(0);
353
322
 
354
-
355
323
  expect(clonedInnerHTML).toContain("<p>Paragraph 1</p>");
356
324
  expect(clonedInnerHTML).toContain("<p>Paragraph 2</p>");
357
325
 
358
-
359
326
  expect(typeof cloned.innerHTML).toBe("string");
360
327
  });
361
328
 
@@ -369,10 +336,8 @@ describe("cloneNode functionality", () => {
369
336
 
370
337
  const cloned = parent.cloneNode(true);
371
338
 
372
-
373
339
  expect(cloned.childNodes.length).toBe(originalChildCount);
374
-
375
-
340
+
376
341
  for (let i = 0; i < cloned.childNodes.length; i++) {
377
342
  expect(cloned.childNodes[i]).toBeTruthy();
378
343
  expect(cloned.childNodes[i].nodeType).toBeDefined();
@@ -386,12 +351,10 @@ describe("cloneNode functionality", () => {
386
351
 
387
352
  const cloned = container.cloneNode(true);
388
353
 
389
-
390
354
  expect(cloned.children).toBeTruthy();
391
355
  expect(Array.isArray(cloned.children)).toBe(true);
392
356
  expect(cloned.children.length).toBe(3);
393
357
 
394
-
395
358
  for (const child of cloned.children) {
396
359
  expect(child.nodeType).toBe(NodeType.ELEMENT_NODE);
397
360
  }
@@ -404,18 +367,15 @@ describe("cloneNode functionality", () => {
404
367
 
405
368
  const cloned = list.cloneNode(true);
406
369
 
407
-
408
370
  expect(cloned.firstChild).toBeTruthy();
409
371
  expect(cloned.lastChild).toBeTruthy();
410
-
411
-
412
-
372
+
413
373
  expect(cloned.firstElementChild).toBeTruthy();
414
374
  expect(cloned.lastElementChild).toBeTruthy();
415
-
375
+
416
376
  const firstLi = cloned.firstElementChild;
417
377
  const lastLi = cloned.lastElementChild;
418
-
378
+
419
379
  expect(firstLi?.textContent).toContain("First");
420
380
  expect(lastLi?.textContent).toContain("Last");
421
381
  });
@@ -427,12 +387,10 @@ describe("cloneNode functionality", () => {
427
387
  const doc = parseHTML(html);
428
388
  const dynamic = doc.querySelector("#dynamic")!;
429
389
 
430
-
431
390
  dynamic.innerHTML = "<p>Dynamic content</p><span>More content</span>";
432
391
 
433
392
  const cloned = dynamic.cloneNode(true);
434
393
 
435
-
436
394
  expect(cloned.querySelector("p")).toBeTruthy();
437
395
  expect(cloned.querySelector("p")?.textContent).toBe("Dynamic content");
438
396
  expect(cloned.querySelector("span")).toBeTruthy();
@@ -446,17 +404,13 @@ describe("cloneNode functionality", () => {
446
404
 
447
405
  const cloned = original.cloneNode(true);
448
406
 
449
-
450
407
  expect(cloned.querySelector("p")?.textContent).toBe("Original");
451
408
 
452
-
453
409
  cloned.innerHTML = "<span>Modified</span>";
454
410
 
455
-
456
411
  expect(original.querySelector("p")?.textContent).toBe("Original");
457
412
  expect(original.querySelector("span")).toBeNull();
458
413
 
459
-
460
414
  expect(cloned.querySelector("span")?.textContent).toBe("Modified");
461
415
  expect(cloned.querySelector("p")).toBeNull();
462
416
  });
@@ -488,21 +442,21 @@ describe("cloneNode functionality", () => {
488
442
 
489
443
  const cloned = card.cloneNode(true);
490
444
 
491
-
492
445
  expect(cloned.getAttribute("data-id")).toBe("123");
493
446
  expect(cloned.querySelector(".card-header")).toBeTruthy();
494
447
  expect(cloned.querySelector(".card-body")).toBeTruthy();
495
448
  expect(cloned.querySelector(".card-footer")).toBeTruthy();
496
449
 
497
-
498
- expect(cloned.querySelector(".card-title")?.textContent).toBe("Card Title");
450
+ expect(cloned.querySelector(".card-title")?.textContent).toBe(
451
+ "Card Title",
452
+ );
499
453
  expect(cloned.querySelector("strong")?.textContent).toBe("bold");
500
-
454
+
501
455
  const items = cloned.querySelectorAll("li");
502
456
  expect(items.length).toBe(2);
503
-
457
+
504
458
  const buttons = cloned.querySelectorAll("button");
505
- expect(buttons.length).toBe(3);
459
+ expect(buttons.length).toBe(3);
506
460
  });
507
461
 
508
462
  it("should clone a form with various input types", () => {
@@ -522,7 +476,6 @@ describe("cloneNode functionality", () => {
522
476
 
523
477
  const cloned = form.cloneNode(true);
524
478
 
525
-
526
479
  const textInput = cloned.querySelector('[name="username"]');
527
480
  expect(textInput).toBeTruthy();
528
481
  expect(textInput?.getAttribute("value")).toBe("john");
@@ -569,7 +522,7 @@ describe("cloneNode functionality", () => {
569
522
 
570
523
  expect(cloned.querySelector("thead")).toBeTruthy();
571
524
  expect(cloned.querySelector("tbody")).toBeTruthy();
572
-
525
+
573
526
  const headers = cloned.querySelectorAll("th");
574
527
  expect(headers.length).toBe(2);
575
528
  expect(headers[0]?.textContent).toBe("Name");
@@ -577,7 +530,7 @@ describe("cloneNode functionality", () => {
577
530
 
578
531
  const rows = cloned.querySelectorAll("tbody tr");
579
532
  expect(rows.length).toBe(2);
580
-
533
+
581
534
  const firstRowCells = rows[0]?.querySelectorAll("td");
582
535
  expect(firstRowCells?.length).toBe(2);
583
536
  expect(firstRowCells?.[0]?.textContent).toBe("John");
@@ -1,105 +1,104 @@
1
- import { describe, it, expect } from 'bun:test';
2
- import { parseHTML } from '../index';
1
+ import { describe, it, expect } from "bun:test";
2
+ import { parseHTML } from "../index";
3
3
 
4
- describe('Custom Elements in <head>', () => {
5
-
6
- it('should keep <meta-tags> custom element in head', () => {
4
+ describe("Custom Elements in <head>", () => {
5
+ it("should keep <meta-tags> custom element in head", () => {
7
6
  const doc = parseHTML(
8
- '<!DOCTYPE html><html><head><meta-tags></meta-tags></head><body></body></html>'
7
+ "<!DOCTYPE html><html><head><meta-tags></meta-tags></head><body></body></html>",
9
8
  );
10
-
11
- const metaTags = doc.head?.querySelector('meta-tags');
9
+
10
+ const metaTags = doc.head?.querySelector("meta-tags");
12
11
  expect(metaTags).toBeTruthy();
13
- expect(metaTags?.parentElement?.tagName).toBe('HEAD');
12
+ expect(metaTags?.parentElement?.tagName).toBe("HEAD");
14
13
  });
15
14
 
16
- it('should keep <social-meta> custom element in head', () => {
15
+ it("should keep <social-meta> custom element in head", () => {
17
16
  const doc = parseHTML(
18
- '<!DOCTYPE html><html><head><social-meta></social-meta></head><body></body></html>'
17
+ "<!DOCTYPE html><html><head><social-meta></social-meta></head><body></body></html>",
19
18
  );
20
-
21
- const socialMeta = doc.head?.querySelector('social-meta');
19
+
20
+ const socialMeta = doc.head?.querySelector("social-meta");
22
21
  expect(socialMeta).toBeTruthy();
23
- expect(socialMeta?.parentElement?.tagName).toBe('HEAD');
22
+ expect(socialMeta?.parentElement?.tagName).toBe("HEAD");
24
23
  });
25
24
 
26
- it('should keep any <custom-element> with hyphen in head', () => {
25
+ it("should keep any <custom-element> with hyphen in head", () => {
27
26
  const doc = parseHTML(
28
- '<!DOCTYPE html><html><head><my-component></my-component></head><body></body></html>'
27
+ "<!DOCTYPE html><html><head><my-component></my-component></head><body></body></html>",
29
28
  );
30
-
31
- const myComponent = doc.head?.querySelector('my-component');
29
+
30
+ const myComponent = doc.head?.querySelector("my-component");
32
31
  expect(myComponent).toBeTruthy();
33
- expect(myComponent?.parentElement?.tagName).toBe('HEAD');
32
+ expect(myComponent?.parentElement?.tagName).toBe("HEAD");
34
33
  });
35
34
 
36
- it('should still eject non-custom elements like <div> to body', () => {
35
+ it("should still eject non-custom elements like <div> to body", () => {
37
36
  const doc = parseHTML(
38
- '<!DOCTYPE html><html><head><div>test</div></head><body></body></html>'
37
+ "<!DOCTYPE html><html><head><div>test</div></head><body></body></html>",
39
38
  );
40
-
41
- const divInHead = doc.head?.querySelector('div');
42
- const divInBody = doc.body?.querySelector('div');
39
+
40
+ const divInHead = doc.head?.querySelector("div");
41
+ const divInBody = doc.body?.querySelector("div");
43
42
  expect(divInHead).toBeFalsy();
44
43
  expect(divInBody).toBeTruthy();
45
44
  });
46
45
 
47
- it('should handle nested custom elements in head', () => {
46
+ it("should handle nested custom elements in head", () => {
48
47
  const doc = parseHTML(
49
- '<!DOCTYPE html><html><head><my-wrapper><inner-comp></inner-comp></my-wrapper></head><body></body></html>'
48
+ "<!DOCTYPE html><html><head><my-wrapper><inner-comp></inner-comp></my-wrapper></head><body></body></html>",
50
49
  );
51
-
52
- const myWrapper = doc.head?.querySelector('my-wrapper');
50
+
51
+ const myWrapper = doc.head?.querySelector("my-wrapper");
53
52
  expect(myWrapper).toBeTruthy();
54
- expect(myWrapper?.parentElement?.tagName).toBe('HEAD');
55
-
56
- const innerComp = myWrapper?.querySelector('inner-comp');
53
+ expect(myWrapper?.parentElement?.tagName).toBe("HEAD");
54
+
55
+ const innerComp = myWrapper?.querySelector("inner-comp");
57
56
  expect(innerComp).toBeTruthy();
58
57
  });
59
58
 
60
- it('should keep custom elements with attributes in head', () => {
59
+ it("should keep custom elements with attributes in head", () => {
61
60
  const doc = parseHTML(
62
- '<!DOCTYPE html><html><head><seo-meta property="og:title" content="Test"></seo-meta></head><body></body></html>'
61
+ '<!DOCTYPE html><html><head><seo-meta property="og:title" content="Test"></seo-meta></head><body></body></html>',
63
62
  );
64
-
65
- const seoMeta = doc.head?.querySelector('seo-meta');
63
+
64
+ const seoMeta = doc.head?.querySelector("seo-meta");
66
65
  expect(seoMeta).toBeTruthy();
67
- expect(seoMeta?.getAttribute('property')).toBe('og:title');
68
- expect(seoMeta?.getAttribute('content')).toBe('Test');
69
- expect(seoMeta?.parentElement?.tagName).toBe('HEAD');
66
+ expect(seoMeta?.getAttribute("property")).toBe("og:title");
67
+ expect(seoMeta?.getAttribute("content")).toBe("Test");
68
+ expect(seoMeta?.parentElement?.tagName).toBe("HEAD");
70
69
  });
71
70
 
72
- it('should keep self-closing custom elements in head', () => {
71
+ it("should keep self-closing custom elements in head", () => {
73
72
  const doc = parseHTML(
74
- '<!DOCTYPE html><html><head><custom-void /></head><body></body></html>'
73
+ "<!DOCTYPE html><html><head><custom-void /></head><body></body></html>",
75
74
  );
76
-
77
- const customVoid = doc.head?.querySelector('custom-void');
75
+
76
+ const customVoid = doc.head?.querySelector("custom-void");
78
77
  expect(customVoid).toBeTruthy();
79
- expect(customVoid?.parentElement?.tagName).toBe('HEAD');
78
+ expect(customVoid?.parentElement?.tagName).toBe("HEAD");
80
79
  });
81
80
 
82
- it('should handle custom elements mixed with standard head elements', () => {
81
+ it("should handle custom elements mixed with standard head elements", () => {
83
82
  const doc = parseHTML(
84
- '<!DOCTYPE html><html><head><title>Test</title><meta-tags></meta-tags><link rel="stylesheet" href="style.css"></head><body></body></html>'
83
+ '<!DOCTYPE html><html><head><title>Test</title><meta-tags></meta-tags><link rel="stylesheet" href="style.css"></head><body></body></html>',
85
84
  );
86
-
87
- const title = doc.head?.querySelector('title');
88
- const metaTags = doc.head?.querySelector('meta-tags');
89
- const link = doc.head?.querySelector('link');
90
-
85
+
86
+ const title = doc.head?.querySelector("title");
87
+ const metaTags = doc.head?.querySelector("meta-tags");
88
+ const link = doc.head?.querySelector("link");
89
+
91
90
  expect(title).toBeTruthy();
92
91
  expect(metaTags).toBeTruthy();
93
92
  expect(link).toBeTruthy();
94
93
  });
95
94
 
96
- it('should handle custom element containing text in head', () => {
95
+ it("should handle custom element containing text in head", () => {
97
96
  const doc = parseHTML(
98
- '<!DOCTYPE html><html><head><inline-script>console.log("test")</inline-script></head><body></body></html>'
97
+ '<!DOCTYPE html><html><head><inline-script>console.log("test")</inline-script></head><body></body></html>',
99
98
  );
100
-
101
- const inlineScript = doc.head?.querySelector('inline-script');
99
+
100
+ const inlineScript = doc.head?.querySelector("inline-script");
102
101
  expect(inlineScript).toBeTruthy();
103
- expect(inlineScript?.parentElement?.tagName).toBe('HEAD');
102
+ expect(inlineScript?.parentElement?.tagName).toBe("HEAD");
104
103
  });
105
104
  });