@praxisjs/head 0.2.6 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @praxisjs/head
2
2
 
3
+ ## 0.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 98f3a18: Updating the head only adds and removes the tags that actually changed instead of recreating every managed tag on each update.
8
+ - Updated dependencies [a97a37c]
9
+ - Updated dependencies [c7a5950]
10
+ - @praxisjs/core@2.2.0
11
+ - @praxisjs/decorators@1.7.0
12
+
13
+ ## 0.3.0
14
+
15
+ ### Minor Changes
16
+
17
+ - ef46e56: Add a `@praxisjs/head/internal` entry point exporting `resetHeadState()`, so `@praxisjs/ssg`'s prerender runner can clear `<head>` tag state between routes rendered in the same Node process.
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies [1ec5b2f]
22
+ - @praxisjs/core@2.1.0
23
+ - @praxisjs/decorators@1.6.1
24
+
3
25
  ## 0.2.6
4
26
 
5
27
  ### Patch Changes
@@ -37,10 +37,10 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
37
37
  import { signal } from "@praxisjs/core/internal";
38
38
  import { StatefulComponent } from "@praxisjs/core";
39
39
  import { Head } from "../index";
40
- import { pushHead, removeHead, _resetHead, headVersion } from "../head-stack";
40
+ import { pushHead, removeHead, resetHeadState, headVersion } from "../head-stack";
41
41
  beforeEach(() => {
42
42
  document.head.innerHTML = "";
43
- _resetHead();
43
+ resetHeadState();
44
44
  document.title = "initial";
45
45
  });
46
46
  // ─── head-stack unit tests ────────────────────────────────────────────────────
@@ -114,16 +114,15 @@ describe("pushHead / removeHead", () => {
114
114
  });
115
115
  it("removeHead with a non-existent id is a no-op (idx < 0 branch)", () => {
116
116
  const id = Symbol("never-pushed");
117
- // _apply() still runs but the stack stays empty
118
117
  expect(() => removeHead(id)).not.toThrow();
119
118
  expect(document.querySelectorAll("[data-praxis-head]").length).toBe(0);
120
119
  });
121
120
  it("_apply restores title to '' when _initialTitle is undefined and stack is empty", () => {
122
- // _resetHead leaves _initialTitle = undefined; calling removeHead on a missing id
121
+ // resetHeadState leaves _initialTitle = undefined; calling removeHead on a missing id
123
122
  // triggers _apply with an empty stack and undefined _initialTitle → title = "" fallback.
124
123
  const id = Symbol("missing");
125
124
  document.title = "should-be-cleared";
126
- removeHead(id); // idx < 0 → no splice; _apply runs → empty stack, _initialTitle = undefined
125
+ removeHead(id);
127
126
  expect(document.title).toBe("");
128
127
  });
129
128
  it("adds preload link with href and as", () => {
@@ -191,7 +190,6 @@ describe("pushHead / removeHead", () => {
191
190
  it("meta tag with neither name nor property is silently skipped", () => {
192
191
  const id = Symbol();
193
192
  pushHead(id, { meta: [{ content: "orphan-content" }] });
194
- // Neither _metaName nor _metaProp should be called
195
193
  const all = document.querySelectorAll("[data-praxis-head]");
196
194
  const hasOrphan = Array.from(all).some((el) => el.getAttribute("content") === "orphan-content");
197
195
  expect(hasOrphan).toBe(false);
@@ -222,18 +220,18 @@ describe("SSR guards — no DOM operations when document is undefined", () => {
222
220
  const id = Symbol();
223
221
  expect(() => removeHead(id)).not.toThrow();
224
222
  });
225
- it("_resetHead skips DOM cleanup when document is undefined", () => {
223
+ it("resetHeadState skips DOM cleanup when document is undefined", () => {
226
224
  vi.stubGlobal("document", undefined);
227
- expect(() => _resetHead()).not.toThrow();
225
+ expect(() => resetHeadState()).not.toThrow();
228
226
  });
229
227
  });
230
- describe("_resetHead — DOM cleanup", () => {
228
+ describe("resetHeadState — DOM cleanup", () => {
231
229
  it("removes managed elements from document.head when called with elements present", () => {
232
230
  const id = Symbol();
233
231
  pushHead(id, { title: "Before Reset", description: "desc" });
234
232
  expect(document.querySelectorAll("[data-praxis-head]").length).toBeGreaterThan(0);
235
- // Call _resetHead WITHOUT clearing head.innerHTML first — exercises the forEach
236
- _resetHead();
233
+ // Call resetHeadState WITHOUT clearing head.innerHTML first — exercises the forEach
234
+ resetHeadState();
237
235
  expect(document.querySelectorAll("[data-praxis-head]").length).toBe(0);
238
236
  });
239
237
  });
@@ -480,4 +478,67 @@ describe("@Head decorator — reactive config", () => {
480
478
  inst.onUnmount?.();
481
479
  });
482
480
  });
481
+ describe("head tag diffing", () => {
482
+ const tags = () => [...document.head.querySelectorAll("[data-praxis-head]")];
483
+ const byName = (name) => document.head.querySelector(`meta[name="${name}"]`);
484
+ it("keeps tags that did not change and only replaces the ones that did", () => {
485
+ const id = Symbol();
486
+ pushHead(id, { description: "same", meta: [{ name: "robots", content: "index" }] });
487
+ const description = byName("description");
488
+ const robots = byName("robots");
489
+ pushHead(id, { description: "same", meta: [{ name: "robots", content: "noindex" }] });
490
+ expect(byName("description")).toBe(description);
491
+ expect(byName("robots")).not.toBe(robots);
492
+ expect(byName("robots")?.getAttribute("content")).toBe("noindex");
493
+ expect(tags()).toHaveLength(2);
494
+ });
495
+ it("removes tags that are no longer in the config", () => {
496
+ const id = Symbol();
497
+ pushHead(id, { description: "d", canonical: "https://example.com/" });
498
+ pushHead(id, { description: "d" });
499
+ expect(document.head.querySelector('link[rel="canonical"]')).toBeNull();
500
+ expect(byName("description")).not.toBeNull();
501
+ });
502
+ it("keeps identical repeated tags as separate elements", () => {
503
+ const id = Symbol();
504
+ pushHead(id, { meta: [{ name: "x", content: "1" }, { name: "x", content: "1" }] });
505
+ expect(document.head.querySelectorAll('meta[name="x"]')).toHaveLength(2);
506
+ pushHead(id, { meta: [{ name: "x", content: "1" }, { name: "x", content: "1" }] });
507
+ expect(document.head.querySelectorAll('meta[name="x"]')).toHaveLength(2);
508
+ });
509
+ it("recreates a managed tag that was removed from the document", () => {
510
+ const id = Symbol();
511
+ pushHead(id, { description: "d" });
512
+ byName("description")?.remove();
513
+ pushHead(id, { description: "d" });
514
+ expect(byName("description")?.getAttribute("content")).toBe("d");
515
+ expect(tags()).toHaveLength(1);
516
+ });
517
+ it("sweeps managed-looking tags a prerender left behind", () => {
518
+ const stale = document.createElement("meta");
519
+ stale.setAttribute("name", "old");
520
+ stale.setAttribute("data-praxis-head", "");
521
+ document.head.appendChild(stale);
522
+ pushHead(Symbol(), { description: "d" });
523
+ expect(byName("old")).toBeNull();
524
+ expect(byName("description")).not.toBeNull();
525
+ });
526
+ it("restores the title and removes every tag once the last entry is gone", () => {
527
+ const id = Symbol();
528
+ pushHead(id, { title: "Page", description: "d" });
529
+ removeHead(id);
530
+ expect(document.title).toBe("initial");
531
+ expect(tags()).toHaveLength(0);
532
+ });
533
+ it("a nested entry's tags replace the outer ones and the outer ones come back on removal", () => {
534
+ const outer = Symbol();
535
+ const inner = Symbol();
536
+ pushHead(outer, { description: "outer" });
537
+ pushHead(inner, { description: "inner" });
538
+ expect(byName("description")?.getAttribute("content")).toBe("inner");
539
+ removeHead(inner);
540
+ expect(byName("description")?.getAttribute("content")).toBe("outer");
541
+ expect(tags()).toHaveLength(1);
542
+ });
543
+ });
483
544
  //# sourceMappingURL=head.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"head.test.js","sourceRoot":"","sources":["../../src/__tests__/head.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"head.test.js","sourceRoot":"","sources":["../../src/__tests__/head.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=internal.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/internal.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,32 @@
1
+ // @vitest-environment jsdom
2
+ import { describe, it, expect } from "vitest";
3
+ import { pushHead, removeHead } from "../head-stack";
4
+ import { resetHeadState } from "../internal";
5
+ describe("@praxisjs/head/internal", () => {
6
+ it("exports resetHeadState, which removes managed head elements", () => {
7
+ document.head.innerHTML = "";
8
+ pushHead(Symbol("page"), { title: "pushed", description: "desc" });
9
+ expect(document.head.querySelectorAll("[data-praxis-head]").length).toBeGreaterThan(0);
10
+ resetHeadState();
11
+ expect(document.head.querySelectorAll("[data-praxis-head]")).toHaveLength(0);
12
+ });
13
+ it("forgets the remembered initial title, so the next page's baseline is captured fresh", () => {
14
+ // Without resetHeadState between "pages", the initial title is only ever
15
+ // captured once (pushHead's `_initialTitle ??=`) — exactly the leak an
16
+ // @praxisjs/ssg prerender run (many render() calls, one Node process)
17
+ // needs this export to avoid between routes.
18
+ document.head.innerHTML = "";
19
+ document.title = "page A";
20
+ const idA = Symbol("a");
21
+ pushHead(idA, { title: "A" });
22
+ removeHead(idA);
23
+ expect(document.title).toBe("page A");
24
+ resetHeadState();
25
+ document.title = "page B";
26
+ const idB = Symbol("b");
27
+ pushHead(idB, { title: "B" });
28
+ removeHead(idB);
29
+ expect(document.title).toBe("page B");
30
+ });
31
+ });
32
+ //# sourceMappingURL=internal.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.test.js","sourceRoot":"","sources":["../../src/__tests__/internal.test.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAC7B,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;QACnE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAEvF,cAAc,EAAE,CAAC;QAEjB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,yEAAyE;QACzE,uEAAuE;QACvE,sEAAsE;QACtE,6CAA6C;QAC7C,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAC7B,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC;QAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9B,UAAU,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAEtC,cAAc,EAAE,CAAC;QAEjB,QAAQ,CAAC,KAAK,GAAG,QAAQ,CAAC;QAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9B,UAAU,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -39,6 +39,11 @@ export interface HeadConfig {
39
39
  export declare const headVersion: import("@praxisjs/shared").Signal<number>;
40
40
  export declare function pushHead(id: symbol, config: HeadConfig): void;
41
41
  export declare function removeHead(id: symbol): void;
42
- /** Resets all head state. For use in tests only. */
43
- export declare function _resetHead(): void;
42
+ /**
43
+ * Resets all head state — the tag stack and the remembered initial `<title>`.
44
+ * Used between pages in an `@praxisjs/ssg` prerender run (same Node process,
45
+ * many `render()` calls) so one route's `<head>` never leaks into the next;
46
+ * also used by this package's own tests.
47
+ */
48
+ export declare function resetHeadState(): void;
44
49
  //# sourceMappingURL=head-stack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"head-stack.d.ts","sourceRoot":"","sources":["../src/head-stack.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,GAAG,iBAAiB,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,EAAE,CAAC,EAAE;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAYD,qFAAqF;AACrF,eAAO,MAAM,WAAW,2CAAY,CAAC;AAErC,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAU7D;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAK3C;AAuGD,oDAAoD;AACpD,wBAAgB,UAAU,IAAI,IAAI,CAMjC"}
1
+ {"version":3,"file":"head-stack.d.ts","sourceRoot":"","sources":["../src/head-stack.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,WAAW,GAAG,iBAAiB,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,EAAE,CAAC,EAAE;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAaD,qFAAqF;AACrF,eAAO,MAAM,WAAW,2CAAY,CAAC;AAErC,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAU7D;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAK3C;AAsHD;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAOrC"}
@@ -1,6 +1,7 @@
1
1
  import { signal } from "@praxisjs/core/internal";
2
2
  const ATTR = "data-praxis-head";
3
3
  const _stack = [];
4
+ let _managed = new Map();
4
5
  let _initialTitle;
5
6
  /** Increments on every head update. Read reactively to subscribe to head changes. */
6
7
  export const headVersion = signal(0);
@@ -25,34 +26,42 @@ export function removeHead(id) {
25
26
  _stack.splice(idx, 1);
26
27
  _apply();
27
28
  }
28
- function _apply() {
29
- headVersion.update((n) => n + 1);
30
- document.querySelectorAll(`[${ATTR}]`).forEach((el) => { el.remove(); });
31
- const top = _stack.at(-1);
32
- if (top === undefined) {
33
- document.title = _initialTitle ?? "";
34
- return;
35
- }
36
- const { config } = top;
37
- if (config.title != null)
38
- document.title = config.title;
29
+ function _collect(config) {
30
+ const specs = [];
31
+ const name = (key, content) => {
32
+ specs.push({ tag: "meta", attrs: [["name", key], ["content", content]] });
33
+ };
34
+ const property = (key, content) => {
35
+ specs.push({ tag: "meta", attrs: [["property", key], ["content", content]] });
36
+ };
39
37
  if (config.description != null)
40
- _metaName("description", config.description);
41
- if (config.canonical != null)
42
- _canonical(config.canonical);
43
- for (const link of config.preload ?? [])
44
- _linkPreload(link);
45
- for (const link of config.prefetch ?? [])
46
- _linkPrefetch(link);
38
+ name("description", config.description);
39
+ if (config.canonical != null) {
40
+ specs.push({ tag: "link", attrs: [["rel", "canonical"], ["href", config.canonical]] });
41
+ }
42
+ for (const link of config.preload ?? []) {
43
+ const attrs = [["rel", "preload"], ["href", link.href], ["as", link.as]];
44
+ if (link.type != null)
45
+ attrs.push(["type", link.type]);
46
+ if (link.crossOrigin != null)
47
+ attrs.push(["crossorigin", link.crossOrigin]);
48
+ specs.push({ tag: "link", attrs });
49
+ }
50
+ for (const link of config.prefetch ?? []) {
51
+ const attrs = [["rel", "prefetch"], ["href", link.href]];
52
+ if (link.as != null)
53
+ attrs.push(["as", link.as]);
54
+ specs.push({ tag: "link", attrs });
55
+ }
47
56
  for (const tag of config.meta ?? []) {
48
57
  if (tag.property != null)
49
- _metaProp(tag.property, tag.content);
58
+ property(tag.property, tag.content);
50
59
  else if (tag.name != null)
51
- _metaName(tag.name, tag.content);
60
+ name(tag.name, tag.content);
52
61
  }
53
62
  if (config.og != null) {
54
63
  const og = config.og;
55
- _applyMap("property", {
64
+ _collectMap(property, {
56
65
  "og:title": og.title,
57
66
  "og:description": og.description,
58
67
  "og:image": og.image,
@@ -63,71 +72,75 @@ function _apply() {
63
72
  }
64
73
  if (config.twitter != null) {
65
74
  const tw = config.twitter;
66
- _applyMap("name", {
75
+ _collectMap(name, {
67
76
  "twitter:card": tw.card,
68
77
  "twitter:title": tw.title,
69
78
  "twitter:description": tw.description,
70
79
  "twitter:image": tw.image,
71
80
  });
72
81
  }
82
+ return specs;
73
83
  }
74
- function _applyMap(attr, map) {
84
+ function _collectMap(add, map) {
75
85
  for (const [key, value] of Object.entries(map)) {
76
- if (value != null) {
77
- if (attr === "name") {
78
- _metaName(key, value);
79
- }
80
- else {
81
- _metaProp(key, value);
82
- }
83
- }
86
+ if (value != null)
87
+ add(key, value);
84
88
  }
85
89
  }
86
- function _metaName(name, content) {
87
- const el = document.createElement("meta");
88
- el.name = name;
89
- el.content = content;
90
- el.setAttribute(ATTR, "");
91
- document.head.appendChild(el);
92
- }
93
- function _metaProp(property, content) {
94
- const el = document.createElement("meta");
95
- el.setAttribute("property", property);
96
- el.content = content;
90
+ function _create(spec) {
91
+ const el = document.createElement(spec.tag);
92
+ for (const [attr, value] of spec.attrs)
93
+ el.setAttribute(attr, value);
97
94
  el.setAttribute(ATTR, "");
98
- document.head.appendChild(el);
95
+ return el;
99
96
  }
100
- function _canonical(href) {
101
- const el = document.createElement("link");
102
- el.rel = "canonical";
103
- el.href = href;
104
- el.setAttribute(ATTR, "");
105
- document.head.appendChild(el);
106
- }
107
- function _linkPreload(link) {
108
- const el = document.createElement("link");
109
- el.rel = "preload";
110
- el.href = link.href;
111
- el.setAttribute("as", link.as);
112
- if (link.type != null)
113
- el.type = link.type;
114
- if (link.crossOrigin != null)
115
- el.crossOrigin = link.crossOrigin;
116
- el.setAttribute(ATTR, "");
117
- document.head.appendChild(el);
97
+ // Tags the new config shares with the previous one stay in the document untouched instead of being
98
+ // removed and recreated on every update; only the difference is added or removed.
99
+ function _syncTags(specs) {
100
+ const next = new Map();
101
+ const occurrences = new Map();
102
+ for (const spec of specs) {
103
+ const base = JSON.stringify([spec.tag, spec.attrs]);
104
+ const n = (occurrences.get(base) ?? 0) + 1;
105
+ occurrences.set(base, n);
106
+ const key = `${base}#${String(n)}`;
107
+ let el = _managed.get(key);
108
+ if (!el?.isConnected) {
109
+ el = _create(spec);
110
+ document.head.appendChild(el);
111
+ }
112
+ next.set(key, el);
113
+ }
114
+ // Also sweeps tags a prerender left in the document, which aren't in `_managed`.
115
+ const keep = new Set(next.values());
116
+ document.head.querySelectorAll(`[${ATTR}]`).forEach((el) => {
117
+ if (!keep.has(el))
118
+ el.remove();
119
+ });
120
+ _managed = next;
118
121
  }
119
- function _linkPrefetch(link) {
120
- const el = document.createElement("link");
121
- el.rel = "prefetch";
122
- el.href = link.href;
123
- if (link.as != null)
124
- el.setAttribute("as", link.as);
125
- el.setAttribute(ATTR, "");
126
- document.head.appendChild(el);
122
+ function _apply() {
123
+ headVersion.update((n) => n + 1);
124
+ const top = _stack.at(-1);
125
+ if (top === undefined) {
126
+ _syncTags([]);
127
+ document.title = _initialTitle ?? "";
128
+ return;
129
+ }
130
+ const { config } = top;
131
+ if (config.title != null)
132
+ document.title = config.title;
133
+ _syncTags(_collect(config));
127
134
  }
128
- /** Resets all head state. For use in tests only. */
129
- export function _resetHead() {
135
+ /**
136
+ * Resets all head state — the tag stack and the remembered initial `<title>`.
137
+ * Used between pages in an `@praxisjs/ssg` prerender run (same Node process,
138
+ * many `render()` calls) so one route's `<head>` never leaks into the next;
139
+ * also used by this package's own tests.
140
+ */
141
+ export function resetHeadState() {
130
142
  _stack.length = 0;
143
+ _managed = new Map();
131
144
  _initialTitle = undefined;
132
145
  if (typeof document !== "undefined") {
133
146
  document.querySelectorAll(`[${ATTR}]`).forEach((el) => { el.remove(); });
@@ -1 +1 @@
1
- {"version":3,"file":"head-stack.js","sourceRoot":"","sources":["../src/head-stack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"head-stack.js","sourceRoot":"","sources":["../src/head-stack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { resetHeadState } from "./head-stack";
2
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { resetHeadState } from "./head-stack";
2
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisjs/head",
3
- "version": "0.2.6",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -8,14 +8,18 @@
8
8
  ".": {
9
9
  "import": "./dist/index.js",
10
10
  "types": "./dist/index.d.ts"
11
+ },
12
+ "./internal": {
13
+ "import": "./dist/internal.js",
14
+ "types": "./dist/internal.d.ts"
11
15
  }
12
16
  },
13
17
  "devDependencies": {
14
18
  "typescript": "^6.0.3"
15
19
  },
16
20
  "dependencies": {
17
- "@praxisjs/core": "2.0.0",
18
- "@praxisjs/decorators": "1.6.0",
21
+ "@praxisjs/decorators": "1.7.0",
22
+ "@praxisjs/core": "2.2.0",
19
23
  "@praxisjs/shared": "0.3.1"
20
24
  },
21
25
  "scripts": {
@@ -4,11 +4,11 @@ import { signal } from "@praxisjs/core/internal";
4
4
  import { StatefulComponent } from "@praxisjs/core";
5
5
 
6
6
  import { Head } from "../index";
7
- import { pushHead, removeHead, _resetHead, headVersion } from "../head-stack";
7
+ import { pushHead, removeHead, resetHeadState, headVersion } from "../head-stack";
8
8
 
9
9
  beforeEach(() => {
10
10
  document.head.innerHTML = "";
11
- _resetHead();
11
+ resetHeadState();
12
12
  document.title = "initial";
13
13
  });
14
14
 
@@ -94,17 +94,16 @@ describe("pushHead / removeHead", () => {
94
94
 
95
95
  it("removeHead with a non-existent id is a no-op (idx < 0 branch)", () => {
96
96
  const id = Symbol("never-pushed");
97
- // _apply() still runs but the stack stays empty
98
97
  expect(() => removeHead(id)).not.toThrow();
99
98
  expect(document.querySelectorAll("[data-praxis-head]").length).toBe(0);
100
99
  });
101
100
 
102
101
  it("_apply restores title to '' when _initialTitle is undefined and stack is empty", () => {
103
- // _resetHead leaves _initialTitle = undefined; calling removeHead on a missing id
102
+ // resetHeadState leaves _initialTitle = undefined; calling removeHead on a missing id
104
103
  // triggers _apply with an empty stack and undefined _initialTitle → title = "" fallback.
105
104
  const id = Symbol("missing");
106
105
  document.title = "should-be-cleared";
107
- removeHead(id); // idx < 0 → no splice; _apply runs → empty stack, _initialTitle = undefined
106
+ removeHead(id);
108
107
  expect(document.title).toBe("");
109
108
  });
110
109
 
@@ -180,7 +179,6 @@ describe("pushHead / removeHead", () => {
180
179
  it("meta tag with neither name nor property is silently skipped", () => {
181
180
  const id = Symbol();
182
181
  pushHead(id, { meta: [{ content: "orphan-content" }] });
183
- // Neither _metaName nor _metaProp should be called
184
182
  const all = document.querySelectorAll("[data-praxis-head]");
185
183
  const hasOrphan = Array.from(all).some((el) =>
186
184
  el.getAttribute("content") === "orphan-content",
@@ -219,20 +217,20 @@ describe("SSR guards — no DOM operations when document is undefined", () => {
219
217
  expect(() => removeHead(id)).not.toThrow();
220
218
  });
221
219
 
222
- it("_resetHead skips DOM cleanup when document is undefined", () => {
220
+ it("resetHeadState skips DOM cleanup when document is undefined", () => {
223
221
  vi.stubGlobal("document", undefined);
224
- expect(() => _resetHead()).not.toThrow();
222
+ expect(() => resetHeadState()).not.toThrow();
225
223
  });
226
224
  });
227
225
 
228
- describe("_resetHead — DOM cleanup", () => {
226
+ describe("resetHeadState — DOM cleanup", () => {
229
227
  it("removes managed elements from document.head when called with elements present", () => {
230
228
  const id = Symbol();
231
229
  pushHead(id, { title: "Before Reset", description: "desc" });
232
230
  expect(document.querySelectorAll("[data-praxis-head]").length).toBeGreaterThan(0);
233
231
 
234
- // Call _resetHead WITHOUT clearing head.innerHTML first — exercises the forEach
235
- _resetHead();
232
+ // Call resetHeadState WITHOUT clearing head.innerHTML first — exercises the forEach
233
+ resetHeadState();
236
234
  expect(document.querySelectorAll("[data-praxis-head]").length).toBe(0);
237
235
  });
238
236
  });
@@ -381,3 +379,76 @@ describe("@Head decorator — reactive config", () => {
381
379
  inst.onUnmount?.();
382
380
  });
383
381
  });
382
+
383
+ describe("head tag diffing", () => {
384
+ const tags = () => [...document.head.querySelectorAll("[data-praxis-head]")];
385
+ const byName = (name: string) => document.head.querySelector(`meta[name="${name}"]`);
386
+
387
+ it("keeps tags that did not change and only replaces the ones that did", () => {
388
+ const id = Symbol();
389
+ pushHead(id, { description: "same", meta: [{ name: "robots", content: "index" }] });
390
+ const description = byName("description");
391
+ const robots = byName("robots");
392
+
393
+ pushHead(id, { description: "same", meta: [{ name: "robots", content: "noindex" }] });
394
+
395
+ expect(byName("description")).toBe(description);
396
+ expect(byName("robots")).not.toBe(robots);
397
+ expect(byName("robots")?.getAttribute("content")).toBe("noindex");
398
+ expect(tags()).toHaveLength(2);
399
+ });
400
+
401
+ it("removes tags that are no longer in the config", () => {
402
+ const id = Symbol();
403
+ pushHead(id, { description: "d", canonical: "https://example.com/" });
404
+ pushHead(id, { description: "d" });
405
+ expect(document.head.querySelector('link[rel="canonical"]')).toBeNull();
406
+ expect(byName("description")).not.toBeNull();
407
+ });
408
+
409
+ it("keeps identical repeated tags as separate elements", () => {
410
+ const id = Symbol();
411
+ pushHead(id, { meta: [{ name: "x", content: "1" }, { name: "x", content: "1" }] });
412
+ expect(document.head.querySelectorAll('meta[name="x"]')).toHaveLength(2);
413
+ pushHead(id, { meta: [{ name: "x", content: "1" }, { name: "x", content: "1" }] });
414
+ expect(document.head.querySelectorAll('meta[name="x"]')).toHaveLength(2);
415
+ });
416
+
417
+ it("recreates a managed tag that was removed from the document", () => {
418
+ const id = Symbol();
419
+ pushHead(id, { description: "d" });
420
+ byName("description")?.remove();
421
+ pushHead(id, { description: "d" });
422
+ expect(byName("description")?.getAttribute("content")).toBe("d");
423
+ expect(tags()).toHaveLength(1);
424
+ });
425
+
426
+ it("sweeps managed-looking tags a prerender left behind", () => {
427
+ const stale = document.createElement("meta");
428
+ stale.setAttribute("name", "old");
429
+ stale.setAttribute("data-praxis-head", "");
430
+ document.head.appendChild(stale);
431
+ pushHead(Symbol(), { description: "d" });
432
+ expect(byName("old")).toBeNull();
433
+ expect(byName("description")).not.toBeNull();
434
+ });
435
+
436
+ it("restores the title and removes every tag once the last entry is gone", () => {
437
+ const id = Symbol();
438
+ pushHead(id, { title: "Page", description: "d" });
439
+ removeHead(id);
440
+ expect(document.title).toBe("initial");
441
+ expect(tags()).toHaveLength(0);
442
+ });
443
+
444
+ it("a nested entry's tags replace the outer ones and the outer ones come back on removal", () => {
445
+ const outer = Symbol();
446
+ const inner = Symbol();
447
+ pushHead(outer, { description: "outer" });
448
+ pushHead(inner, { description: "inner" });
449
+ expect(byName("description")?.getAttribute("content")).toBe("inner");
450
+ removeHead(inner);
451
+ expect(byName("description")?.getAttribute("content")).toBe("outer");
452
+ expect(tags()).toHaveLength(1);
453
+ });
454
+ });
@@ -0,0 +1,38 @@
1
+ // @vitest-environment jsdom
2
+ import { describe, it, expect } from "vitest";
3
+
4
+ import { pushHead, removeHead } from "../head-stack";
5
+ import { resetHeadState } from "../internal";
6
+
7
+ describe("@praxisjs/head/internal", () => {
8
+ it("exports resetHeadState, which removes managed head elements", () => {
9
+ document.head.innerHTML = "";
10
+ pushHead(Symbol("page"), { title: "pushed", description: "desc" });
11
+ expect(document.head.querySelectorAll("[data-praxis-head]").length).toBeGreaterThan(0);
12
+
13
+ resetHeadState();
14
+
15
+ expect(document.head.querySelectorAll("[data-praxis-head]")).toHaveLength(0);
16
+ });
17
+
18
+ it("forgets the remembered initial title, so the next page's baseline is captured fresh", () => {
19
+ // Without resetHeadState between "pages", the initial title is only ever
20
+ // captured once (pushHead's `_initialTitle ??=`) — exactly the leak an
21
+ // @praxisjs/ssg prerender run (many render() calls, one Node process)
22
+ // needs this export to avoid between routes.
23
+ document.head.innerHTML = "";
24
+ document.title = "page A";
25
+ const idA = Symbol("a");
26
+ pushHead(idA, { title: "A" });
27
+ removeHead(idA);
28
+ expect(document.title).toBe("page A");
29
+
30
+ resetHeadState();
31
+
32
+ document.title = "page B";
33
+ const idB = Symbol("b");
34
+ pushHead(idB, { title: "B" });
35
+ removeHead(idB);
36
+ expect(document.title).toBe("page B");
37
+ });
38
+ });
package/src/head-stack.ts CHANGED
@@ -49,6 +49,7 @@ interface HeadEntry {
49
49
  }
50
50
 
51
51
  const _stack: HeadEntry[] = [];
52
+ let _managed = new Map<string, HTMLElement>();
52
53
  let _initialTitle: string | undefined;
53
54
 
54
55
  /** Increments on every head update. Read reactively to subscribe to head changes. */
@@ -73,32 +74,43 @@ export function removeHead(id: symbol): void {
73
74
  _apply();
74
75
  }
75
76
 
76
- function _apply(): void {
77
- headVersion.update((n) => n + 1);
78
- document.querySelectorAll(`[${ATTR}]`).forEach((el) => { el.remove(); });
79
-
80
- const top = _stack.at(-1);
81
- if (top === undefined) {
82
- document.title = _initialTitle ?? "";
83
- return;
84
- }
85
-
86
- const { config } = top;
77
+ interface TagSpec {
78
+ tag: "meta" | "link";
79
+ attrs: Array<[string, string]>;
80
+ }
87
81
 
88
- if (config.title != null) document.title = config.title;
89
- if (config.description != null) _metaName("description", config.description);
90
- if (config.canonical != null) _canonical(config.canonical);
91
- for (const link of config.preload ?? []) _linkPreload(link);
92
- for (const link of config.prefetch ?? []) _linkPrefetch(link);
82
+ function _collect(config: HeadConfig): TagSpec[] {
83
+ const specs: TagSpec[] = [];
84
+ const name = (key: string, content: string): void => {
85
+ specs.push({ tag: "meta", attrs: [["name", key], ["content", content]] });
86
+ };
87
+ const property = (key: string, content: string): void => {
88
+ specs.push({ tag: "meta", attrs: [["property", key], ["content", content]] });
89
+ };
93
90
 
91
+ if (config.description != null) name("description", config.description);
92
+ if (config.canonical != null) {
93
+ specs.push({ tag: "link", attrs: [["rel", "canonical"], ["href", config.canonical]] });
94
+ }
95
+ for (const link of config.preload ?? []) {
96
+ const attrs: Array<[string, string]> = [["rel", "preload"], ["href", link.href], ["as", link.as]];
97
+ if (link.type != null) attrs.push(["type", link.type]);
98
+ if (link.crossOrigin != null) attrs.push(["crossorigin", link.crossOrigin]);
99
+ specs.push({ tag: "link", attrs });
100
+ }
101
+ for (const link of config.prefetch ?? []) {
102
+ const attrs: Array<[string, string]> = [["rel", "prefetch"], ["href", link.href]];
103
+ if (link.as != null) attrs.push(["as", link.as]);
104
+ specs.push({ tag: "link", attrs });
105
+ }
94
106
  for (const tag of config.meta ?? []) {
95
- if (tag.property != null) _metaProp(tag.property, tag.content);
96
- else if (tag.name != null) _metaName(tag.name, tag.content);
107
+ if (tag.property != null) property(tag.property, tag.content);
108
+ else if (tag.name != null) name(tag.name, tag.content);
97
109
  }
98
110
 
99
111
  if (config.og != null) {
100
112
  const og = config.og;
101
- _applyMap("property", {
113
+ _collectMap(property, {
102
114
  "og:title": og.title,
103
115
  "og:description": og.description,
104
116
  "og:image": og.image,
@@ -107,76 +119,86 @@ function _apply(): void {
107
119
  "og:site_name": og.siteName,
108
120
  });
109
121
  }
110
-
111
122
  if (config.twitter != null) {
112
123
  const tw = config.twitter;
113
- _applyMap("name", {
124
+ _collectMap(name, {
114
125
  "twitter:card": tw.card,
115
126
  "twitter:title": tw.title,
116
127
  "twitter:description": tw.description,
117
128
  "twitter:image": tw.image,
118
129
  });
119
130
  }
131
+ return specs;
120
132
  }
121
133
 
122
- function _applyMap(
123
- attr: "name" | "property",
134
+ function _collectMap(
135
+ add: (key: string, content: string) => void,
124
136
  map: Record<string, string | undefined>,
125
137
  ): void {
126
138
  for (const [key, value] of Object.entries(map)) {
127
- if (value != null) {
128
- if (attr === "name") { _metaName(key, value); } else { _metaProp(key, value); }
129
- }
139
+ if (value != null) add(key, value);
130
140
  }
131
141
  }
132
142
 
133
- function _metaName(name: string, content: string): void {
134
- const el = document.createElement("meta");
135
- el.name = name;
136
- el.content = content;
143
+ function _create(spec: TagSpec): HTMLElement {
144
+ const el = document.createElement(spec.tag);
145
+ for (const [attr, value] of spec.attrs) el.setAttribute(attr, value);
137
146
  el.setAttribute(ATTR, "");
138
- document.head.appendChild(el);
147
+ return el;
139
148
  }
140
149
 
141
- function _metaProp(property: string, content: string): void {
142
- const el = document.createElement("meta");
143
- el.setAttribute("property", property);
144
- el.content = content;
145
- el.setAttribute(ATTR, "");
146
- document.head.appendChild(el);
147
- }
150
+ // Tags the new config shares with the previous one stay in the document untouched instead of being
151
+ // removed and recreated on every update; only the difference is added or removed.
152
+ function _syncTags(specs: TagSpec[]): void {
153
+ const next = new Map<string, HTMLElement>();
154
+ const occurrences = new Map<string, number>();
155
+
156
+ for (const spec of specs) {
157
+ const base = JSON.stringify([spec.tag, spec.attrs]);
158
+ const n = (occurrences.get(base) ?? 0) + 1;
159
+ occurrences.set(base, n);
160
+ const key = `${base}#${String(n)}`;
161
+
162
+ let el = _managed.get(key);
163
+ if (!el?.isConnected) {
164
+ el = _create(spec);
165
+ document.head.appendChild(el);
166
+ }
167
+ next.set(key, el);
168
+ }
148
169
 
149
- function _canonical(href: string): void {
150
- const el = document.createElement("link");
151
- el.rel = "canonical";
152
- el.href = href;
153
- el.setAttribute(ATTR, "");
154
- document.head.appendChild(el);
170
+ // Also sweeps tags a prerender left in the document, which aren't in `_managed`.
171
+ const keep = new Set(next.values());
172
+ document.head.querySelectorAll(`[${ATTR}]`).forEach((el) => {
173
+ if (!keep.has(el as HTMLElement)) el.remove();
174
+ });
175
+ _managed = next;
155
176
  }
156
177
 
157
- function _linkPreload(link: LinkPreload): void {
158
- const el = document.createElement("link");
159
- el.rel = "preload";
160
- el.href = link.href;
161
- el.setAttribute("as", link.as);
162
- if (link.type != null) el.type = link.type;
163
- if (link.crossOrigin != null) el.crossOrigin = link.crossOrigin;
164
- el.setAttribute(ATTR, "");
165
- document.head.appendChild(el);
166
- }
178
+ function _apply(): void {
179
+ headVersion.update((n) => n + 1);
167
180
 
168
- function _linkPrefetch(link: LinkPrefetch): void {
169
- const el = document.createElement("link");
170
- el.rel = "prefetch";
171
- el.href = link.href;
172
- if (link.as != null) el.setAttribute("as", link.as);
173
- el.setAttribute(ATTR, "");
174
- document.head.appendChild(el);
181
+ const top = _stack.at(-1);
182
+ if (top === undefined) {
183
+ _syncTags([]);
184
+ document.title = _initialTitle ?? "";
185
+ return;
186
+ }
187
+
188
+ const { config } = top;
189
+ if (config.title != null) document.title = config.title;
190
+ _syncTags(_collect(config));
175
191
  }
176
192
 
177
- /** Resets all head state. For use in tests only. */
178
- export function _resetHead(): void {
193
+ /**
194
+ * Resets all head state — the tag stack and the remembered initial `<title>`.
195
+ * Used between pages in an `@praxisjs/ssg` prerender run (same Node process,
196
+ * many `render()` calls) so one route's `<head>` never leaks into the next;
197
+ * also used by this package's own tests.
198
+ */
199
+ export function resetHeadState(): void {
179
200
  _stack.length = 0;
201
+ _managed = new Map();
180
202
  _initialTitle = undefined;
181
203
  if (typeof document !== "undefined") {
182
204
  document.querySelectorAll(`[${ATTR}]`).forEach((el) => { el.remove(); });
@@ -0,0 +1 @@
1
+ export { resetHeadState } from "./head-stack";