@pyreon/head 0.21.0 → 0.22.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.
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"4825d939-1","name":"context.ts"},{"uid":"4825d939-3","name":"provider.ts"},{"uid":"4825d939-5","name":"dom.ts"},{"uid":"4825d939-7","name":"use-head.ts"},{"uid":"4825d939-9","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"4825d939-1":{"renderedLength":1373,"gzipLength":509,"brotliLength":0,"metaUid":"4825d939-0"},"4825d939-3":{"renderedLength":2121,"gzipLength":1074,"brotliLength":0,"metaUid":"4825d939-2"},"4825d939-5":{"renderedLength":3447,"gzipLength":1292,"brotliLength":0,"metaUid":"4825d939-4"},"4825d939-7":{"renderedLength":2634,"gzipLength":1093,"brotliLength":0,"metaUid":"4825d939-6"},"4825d939-9":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"4825d939-8"}},"nodeMetas":{"4825d939-0":{"id":"/src/context.ts","moduleParts":{"index.js":"4825d939-1"},"imported":[{"uid":"4825d939-10"}],"importedBy":[{"uid":"4825d939-8"},{"uid":"4825d939-2"},{"uid":"4825d939-6"}]},"4825d939-2":{"id":"/src/provider.ts","moduleParts":{"index.js":"4825d939-3"},"imported":[{"uid":"4825d939-10"},{"uid":"4825d939-0"}],"importedBy":[{"uid":"4825d939-8"}]},"4825d939-4":{"id":"/src/dom.ts","moduleParts":{"index.js":"4825d939-5"},"imported":[],"importedBy":[{"uid":"4825d939-6"}]},"4825d939-6":{"id":"/src/use-head.ts","moduleParts":{"index.js":"4825d939-7"},"imported":[{"uid":"4825d939-10"},{"uid":"4825d939-11"},{"uid":"4825d939-0"},{"uid":"4825d939-4"}],"importedBy":[{"uid":"4825d939-8"}]},"4825d939-8":{"id":"/src/index.ts","moduleParts":{"index.js":"4825d939-9"},"imported":[{"uid":"4825d939-0"},{"uid":"4825d939-2"},{"uid":"4825d939-6"}],"importedBy":[],"isEntry":true},"4825d939-10":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"4825d939-0"},{"uid":"4825d939-2"},{"uid":"4825d939-6"}]},"4825d939-11":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"4825d939-6"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"19674450-1","name":"provider.ts"},{"uid":"19674450-3","name":"dom.ts"},{"uid":"19674450-5","name":"use-head.ts"},{"uid":"19674450-7","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"19674450-1":{"renderedLength":2127,"gzipLength":1080,"brotliLength":0,"metaUid":"19674450-0"},"19674450-3":{"renderedLength":3447,"gzipLength":1292,"brotliLength":0,"metaUid":"19674450-2"},"19674450-5":{"renderedLength":2636,"gzipLength":1095,"brotliLength":0,"metaUid":"19674450-4"},"19674450-7":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"19674450-6"}},"nodeMetas":{"19674450-0":{"id":"/src/provider.ts","moduleParts":{"index.js":"19674450-1"},"imported":[{"uid":"19674450-9"},{"uid":"19674450-8"}],"importedBy":[{"uid":"19674450-6"}]},"19674450-2":{"id":"/src/dom.ts","moduleParts":{"index.js":"19674450-3"},"imported":[],"importedBy":[{"uid":"19674450-4"}]},"19674450-4":{"id":"/src/use-head.ts","moduleParts":{"index.js":"19674450-5"},"imported":[{"uid":"19674450-9"},{"uid":"19674450-10"},{"uid":"19674450-8"},{"uid":"19674450-2"}],"importedBy":[{"uid":"19674450-6"}]},"19674450-6":{"id":"/src/index.ts","moduleParts":{"index.js":"19674450-7"},"imported":[{"uid":"19674450-8"},{"uid":"19674450-0"},{"uid":"19674450-4"}],"importedBy":[],"isEntry":true},"19674450-8":{"id":"@pyreon/head/context","moduleParts":{},"imported":[],"importedBy":[{"uid":"19674450-6"},{"uid":"19674450-0"},{"uid":"19674450-4"}]},"19674450-9":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"19674450-0"},{"uid":"19674450-4"}]},"19674450-10":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"19674450-4"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"provider.js","children":[{"name":"src","children":[{"uid":"11781eb7-1","name":"context.ts"},{"uid":"11781eb7-3","name":"provider.ts"}]}]}],"isRoot":true},"nodeParts":{"11781eb7-1":{"renderedLength":1373,"gzipLength":509,"brotliLength":0,"metaUid":"11781eb7-0"},"11781eb7-3":{"renderedLength":2121,"gzipLength":1074,"brotliLength":0,"metaUid":"11781eb7-2"}},"nodeMetas":{"11781eb7-0":{"id":"/src/context.ts","moduleParts":{"provider.js":"11781eb7-1"},"imported":[{"uid":"11781eb7-4"}],"importedBy":[{"uid":"11781eb7-2"}]},"11781eb7-2":{"id":"/src/provider.ts","moduleParts":{"provider.js":"11781eb7-3"},"imported":[{"uid":"11781eb7-4"},{"uid":"11781eb7-0"}],"importedBy":[],"isEntry":true},"11781eb7-4":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"11781eb7-2"},{"uid":"11781eb7-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"provider.js","children":[{"name":"src/provider.ts","uid":"5e1e2d37-1"}]}],"isRoot":true},"nodeParts":{"5e1e2d37-1":{"renderedLength":2121,"gzipLength":1074,"brotliLength":0,"metaUid":"5e1e2d37-0"}},"nodeMetas":{"5e1e2d37-0":{"id":"/src/provider.ts","moduleParts":{"provider.js":"5e1e2d37-1"},"imported":[{"uid":"5e1e2d37-2"},{"uid":"5e1e2d37-3"}],"importedBy":[],"isEntry":true},"5e1e2d37-2":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"5e1e2d37-0"}]},"5e1e2d37-3":{"id":"@pyreon/head/context","moduleParts":{},"imported":[],"importedBy":[{"uid":"5e1e2d37-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"ssr.js","children":[{"name":"src","children":[{"uid":"b6fd5bb7-1","name":"context.ts"},{"uid":"b6fd5bb7-3","name":"ssr.ts"}]}]}],"isRoot":true},"nodeParts":{"b6fd5bb7-1":{"renderedLength":1373,"gzipLength":509,"brotliLength":0,"metaUid":"b6fd5bb7-0"},"b6fd5bb7-3":{"renderedLength":1370,"gzipLength":701,"brotliLength":0,"metaUid":"b6fd5bb7-2"}},"nodeMetas":{"b6fd5bb7-0":{"id":"/src/context.ts","moduleParts":{"ssr.js":"b6fd5bb7-1"},"imported":[{"uid":"b6fd5bb7-4"}],"importedBy":[{"uid":"b6fd5bb7-2"}]},"b6fd5bb7-2":{"id":"/src/ssr.ts","moduleParts":{"ssr.js":"b6fd5bb7-3"},"imported":[{"uid":"b6fd5bb7-4"},{"uid":"b6fd5bb7-5"},{"uid":"b6fd5bb7-0"}],"importedBy":[],"isEntry":true},"b6fd5bb7-4":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"b6fd5bb7-2"},{"uid":"b6fd5bb7-0"}]},"b6fd5bb7-5":{"id":"@pyreon/runtime-server","moduleParts":{},"imported":[],"importedBy":[{"uid":"b6fd5bb7-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"ssr.js","children":[{"name":"src/ssr.ts","uid":"6c67066c-1"}]}],"isRoot":true},"nodeParts":{"6c67066c-1":{"renderedLength":1370,"gzipLength":701,"brotliLength":0,"metaUid":"6c67066c-0"}},"nodeMetas":{"6c67066c-0":{"id":"/src/ssr.ts","moduleParts":{"ssr.js":"6c67066c-1"},"imported":[{"uid":"6c67066c-2"},{"uid":"6c67066c-3"},{"uid":"6c67066c-4"}],"importedBy":[],"isEntry":true},"6c67066c-2":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"6c67066c-0"}]},"6c67066c-3":{"id":"@pyreon/runtime-server","moduleParts":{},"imported":[],"importedBy":[{"uid":"6c67066c-0"}]},"6c67066c-4":{"id":"@pyreon/head/context","moduleParts":{},"imported":[],"importedBy":[{"uid":"6c67066c-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
5386
5386
  </script>
5387
5387
  <script>
5388
5388
  /*<!--*/
5389
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"use-head.js","children":[{"name":"src","children":[{"uid":"a2d4ff75-1","name":"context.ts"},{"uid":"a2d4ff75-3","name":"dom.ts"},{"uid":"a2d4ff75-5","name":"use-head.ts"}]}]}],"isRoot":true},"nodeParts":{"a2d4ff75-1":{"renderedLength":79,"gzipLength":85,"brotliLength":0,"metaUid":"a2d4ff75-0"},"a2d4ff75-3":{"renderedLength":3447,"gzipLength":1292,"brotliLength":0,"metaUid":"a2d4ff75-2"},"a2d4ff75-5":{"renderedLength":2634,"gzipLength":1093,"brotliLength":0,"metaUid":"a2d4ff75-4"}},"nodeMetas":{"a2d4ff75-0":{"id":"/src/context.ts","moduleParts":{"use-head.js":"a2d4ff75-1"},"imported":[{"uid":"a2d4ff75-6"}],"importedBy":[{"uid":"a2d4ff75-4"}]},"a2d4ff75-2":{"id":"/src/dom.ts","moduleParts":{"use-head.js":"a2d4ff75-3"},"imported":[],"importedBy":[{"uid":"a2d4ff75-4"}]},"a2d4ff75-4":{"id":"/src/use-head.ts","moduleParts":{"use-head.js":"a2d4ff75-5"},"imported":[{"uid":"a2d4ff75-6"},{"uid":"a2d4ff75-7"},{"uid":"a2d4ff75-0"},{"uid":"a2d4ff75-2"}],"importedBy":[],"isEntry":true},"a2d4ff75-6":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"a2d4ff75-4"},{"uid":"a2d4ff75-0"}]},"a2d4ff75-7":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"a2d4ff75-4"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5389
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"use-head.js","children":[{"name":"src","children":[{"uid":"e064605f-1","name":"dom.ts"},{"uid":"e064605f-3","name":"use-head.ts"}]}]}],"isRoot":true},"nodeParts":{"e064605f-1":{"renderedLength":3447,"gzipLength":1292,"brotliLength":0,"metaUid":"e064605f-0"},"e064605f-3":{"renderedLength":2634,"gzipLength":1093,"brotliLength":0,"metaUid":"e064605f-2"}},"nodeMetas":{"e064605f-0":{"id":"/src/dom.ts","moduleParts":{"use-head.js":"e064605f-1"},"imported":[],"importedBy":[{"uid":"e064605f-2"}]},"e064605f-2":{"id":"/src/use-head.ts","moduleParts":{"use-head.js":"e064605f-3"},"imported":[{"uid":"e064605f-4"},{"uid":"e064605f-5"},{"uid":"e064605f-6"},{"uid":"e064605f-0"}],"importedBy":[],"isEntry":true},"e064605f-4":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"e064605f-2"}]},"e064605f-5":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"e064605f-2"}]},"e064605f-6":{"id":"@pyreon/head/context","moduleParts":{},"imported":[],"importedBy":[{"uid":"e064605f-2"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
5390
5390
 
5391
5391
  const run = () => {
5392
5392
  const width = window.innerWidth;
package/lib/context.js ADDED
@@ -0,0 +1,62 @@
1
+ import { createContext } from "@pyreon/core";
2
+
3
+ //#region src/context.ts
4
+ function createHeadContext() {
5
+ const map = /* @__PURE__ */ new Map();
6
+ let dirty = true;
7
+ let cachedTags = [];
8
+ let cachedTitleTemplate;
9
+ let cachedHtmlAttrs = {};
10
+ let cachedBodyAttrs = {};
11
+ function rebuild() {
12
+ if (!dirty) return;
13
+ dirty = false;
14
+ const keyed = /* @__PURE__ */ new Map();
15
+ const unkeyed = [];
16
+ let titleTemplate;
17
+ const htmlAttrs = {};
18
+ const bodyAttrs = {};
19
+ for (const entry of map.values()) {
20
+ for (const tag of entry.tags) if (tag.key) keyed.set(tag.key, tag);
21
+ else unkeyed.push(tag);
22
+ if (entry.titleTemplate !== void 0) titleTemplate = entry.titleTemplate;
23
+ if (entry.htmlAttrs) Object.assign(htmlAttrs, entry.htmlAttrs);
24
+ if (entry.bodyAttrs) Object.assign(bodyAttrs, entry.bodyAttrs);
25
+ }
26
+ cachedTags = [...keyed.values(), ...unkeyed];
27
+ cachedTitleTemplate = titleTemplate;
28
+ cachedHtmlAttrs = htmlAttrs;
29
+ cachedBodyAttrs = bodyAttrs;
30
+ }
31
+ return {
32
+ add(id, entry) {
33
+ map.set(id, entry);
34
+ dirty = true;
35
+ },
36
+ remove(id) {
37
+ map.delete(id);
38
+ dirty = true;
39
+ },
40
+ resolve() {
41
+ rebuild();
42
+ return cachedTags;
43
+ },
44
+ resolveTitleTemplate() {
45
+ rebuild();
46
+ return cachedTitleTemplate;
47
+ },
48
+ resolveHtmlAttrs() {
49
+ rebuild();
50
+ return cachedHtmlAttrs;
51
+ },
52
+ resolveBodyAttrs() {
53
+ rebuild();
54
+ return cachedBodyAttrs;
55
+ }
56
+ };
57
+ }
58
+ const HeadContext = createContext(null);
59
+
60
+ //#endregion
61
+ export { HeadContext, createHeadContext };
62
+ //# sourceMappingURL=context.js.map
package/lib/index.js CHANGED
@@ -1,64 +1,7 @@
1
- import { createContext, nativeCompat, onMount, onUnmount, provide, useContext } from "@pyreon/core";
1
+ import { HeadContext, HeadContext as HeadContext$1, createHeadContext, createHeadContext as createHeadContext$1 } from "@pyreon/head/context";
2
+ import { nativeCompat, onMount, onUnmount, provide, useContext } from "@pyreon/core";
2
3
  import { effect } from "@pyreon/reactivity";
3
4
 
4
- //#region src/context.ts
5
- function createHeadContext() {
6
- const map = /* @__PURE__ */ new Map();
7
- let dirty = true;
8
- let cachedTags = [];
9
- let cachedTitleTemplate;
10
- let cachedHtmlAttrs = {};
11
- let cachedBodyAttrs = {};
12
- function rebuild() {
13
- if (!dirty) return;
14
- dirty = false;
15
- const keyed = /* @__PURE__ */ new Map();
16
- const unkeyed = [];
17
- let titleTemplate;
18
- const htmlAttrs = {};
19
- const bodyAttrs = {};
20
- for (const entry of map.values()) {
21
- for (const tag of entry.tags) if (tag.key) keyed.set(tag.key, tag);
22
- else unkeyed.push(tag);
23
- if (entry.titleTemplate !== void 0) titleTemplate = entry.titleTemplate;
24
- if (entry.htmlAttrs) Object.assign(htmlAttrs, entry.htmlAttrs);
25
- if (entry.bodyAttrs) Object.assign(bodyAttrs, entry.bodyAttrs);
26
- }
27
- cachedTags = [...keyed.values(), ...unkeyed];
28
- cachedTitleTemplate = titleTemplate;
29
- cachedHtmlAttrs = htmlAttrs;
30
- cachedBodyAttrs = bodyAttrs;
31
- }
32
- return {
33
- add(id, entry) {
34
- map.set(id, entry);
35
- dirty = true;
36
- },
37
- remove(id) {
38
- map.delete(id);
39
- dirty = true;
40
- },
41
- resolve() {
42
- rebuild();
43
- return cachedTags;
44
- },
45
- resolveTitleTemplate() {
46
- rebuild();
47
- return cachedTitleTemplate;
48
- },
49
- resolveHtmlAttrs() {
50
- rebuild();
51
- return cachedHtmlAttrs;
52
- },
53
- resolveBodyAttrs() {
54
- rebuild();
55
- return cachedBodyAttrs;
56
- }
57
- };
58
- }
59
- const HeadContext = createContext(null);
60
-
61
- //#endregion
62
5
  //#region src/provider.ts
63
6
  /**
64
7
  * Provides a HeadContextValue to all descendant components.
@@ -99,7 +42,7 @@ const HeadContext = createContext(null);
99
42
  * const { html, head } = await renderWithHead(h(HeadProvider, null, h(App, null)))
100
43
  */
101
44
  const HeadProvider = (props) => {
102
- provide(HeadContext, props.context ?? useContext(HeadContext) ?? createHeadContext());
45
+ provide(HeadContext$1, props.context ?? useContext(HeadContext$1) ?? createHeadContext$1());
103
46
  const ch = props.children;
104
47
  return typeof ch === "function" ? ch() : ch;
105
48
  };
@@ -293,7 +236,7 @@ function buildEntry(o) {
293
236
  * Requires a <HeadProvider> (CSR) or renderWithHead() (SSR) ancestor.
294
237
  */
295
238
  function useHead(input) {
296
- const ctx = useContext(HeadContext);
239
+ const ctx = useContext(HeadContext$1);
297
240
  if (!ctx) return;
298
241
  const id = Symbol();
299
242
  if (typeof input === "function") if (typeof document !== "undefined") effect(() => {
package/lib/provider.js CHANGED
@@ -1,63 +1,6 @@
1
- import { createContext, nativeCompat, provide, useContext } from "@pyreon/core";
1
+ import { nativeCompat, provide, useContext } from "@pyreon/core";
2
+ import { HeadContext, createHeadContext } from "@pyreon/head/context";
2
3
 
3
- //#region src/context.ts
4
- function createHeadContext() {
5
- const map = /* @__PURE__ */ new Map();
6
- let dirty = true;
7
- let cachedTags = [];
8
- let cachedTitleTemplate;
9
- let cachedHtmlAttrs = {};
10
- let cachedBodyAttrs = {};
11
- function rebuild() {
12
- if (!dirty) return;
13
- dirty = false;
14
- const keyed = /* @__PURE__ */ new Map();
15
- const unkeyed = [];
16
- let titleTemplate;
17
- const htmlAttrs = {};
18
- const bodyAttrs = {};
19
- for (const entry of map.values()) {
20
- for (const tag of entry.tags) if (tag.key) keyed.set(tag.key, tag);
21
- else unkeyed.push(tag);
22
- if (entry.titleTemplate !== void 0) titleTemplate = entry.titleTemplate;
23
- if (entry.htmlAttrs) Object.assign(htmlAttrs, entry.htmlAttrs);
24
- if (entry.bodyAttrs) Object.assign(bodyAttrs, entry.bodyAttrs);
25
- }
26
- cachedTags = [...keyed.values(), ...unkeyed];
27
- cachedTitleTemplate = titleTemplate;
28
- cachedHtmlAttrs = htmlAttrs;
29
- cachedBodyAttrs = bodyAttrs;
30
- }
31
- return {
32
- add(id, entry) {
33
- map.set(id, entry);
34
- dirty = true;
35
- },
36
- remove(id) {
37
- map.delete(id);
38
- dirty = true;
39
- },
40
- resolve() {
41
- rebuild();
42
- return cachedTags;
43
- },
44
- resolveTitleTemplate() {
45
- rebuild();
46
- return cachedTitleTemplate;
47
- },
48
- resolveHtmlAttrs() {
49
- rebuild();
50
- return cachedHtmlAttrs;
51
- },
52
- resolveBodyAttrs() {
53
- rebuild();
54
- return cachedBodyAttrs;
55
- }
56
- };
57
- }
58
- const HeadContext = createContext(null);
59
-
60
- //#endregion
61
4
  //#region src/provider.ts
62
5
  /**
63
6
  * Provides a HeadContextValue to all descendant components.
package/lib/ssr.js CHANGED
@@ -1,64 +1,7 @@
1
- import { createContext, h, pushContext } from "@pyreon/core";
1
+ import { h, pushContext } from "@pyreon/core";
2
2
  import { renderToString } from "@pyreon/runtime-server";
3
+ import { HeadContext, createHeadContext } from "@pyreon/head/context";
3
4
 
4
- //#region src/context.ts
5
- function createHeadContext() {
6
- const map = /* @__PURE__ */ new Map();
7
- let dirty = true;
8
- let cachedTags = [];
9
- let cachedTitleTemplate;
10
- let cachedHtmlAttrs = {};
11
- let cachedBodyAttrs = {};
12
- function rebuild() {
13
- if (!dirty) return;
14
- dirty = false;
15
- const keyed = /* @__PURE__ */ new Map();
16
- const unkeyed = [];
17
- let titleTemplate;
18
- const htmlAttrs = {};
19
- const bodyAttrs = {};
20
- for (const entry of map.values()) {
21
- for (const tag of entry.tags) if (tag.key) keyed.set(tag.key, tag);
22
- else unkeyed.push(tag);
23
- if (entry.titleTemplate !== void 0) titleTemplate = entry.titleTemplate;
24
- if (entry.htmlAttrs) Object.assign(htmlAttrs, entry.htmlAttrs);
25
- if (entry.bodyAttrs) Object.assign(bodyAttrs, entry.bodyAttrs);
26
- }
27
- cachedTags = [...keyed.values(), ...unkeyed];
28
- cachedTitleTemplate = titleTemplate;
29
- cachedHtmlAttrs = htmlAttrs;
30
- cachedBodyAttrs = bodyAttrs;
31
- }
32
- return {
33
- add(id, entry) {
34
- map.set(id, entry);
35
- dirty = true;
36
- },
37
- remove(id) {
38
- map.delete(id);
39
- dirty = true;
40
- },
41
- resolve() {
42
- rebuild();
43
- return cachedTags;
44
- },
45
- resolveTitleTemplate() {
46
- rebuild();
47
- return cachedTitleTemplate;
48
- },
49
- resolveHtmlAttrs() {
50
- rebuild();
51
- return cachedHtmlAttrs;
52
- },
53
- resolveBodyAttrs() {
54
- rebuild();
55
- return cachedBodyAttrs;
56
- }
57
- };
58
- }
59
- const HeadContext = createContext(null);
60
-
61
- //#endregion
62
5
  //#region src/ssr.ts
63
6
  const VOID_TAGS = new Set([
64
7
  "meta",
@@ -0,0 +1,205 @@
1
+ //#region src/context.d.ts
2
+ interface HeadTag {
3
+ /** HTML tag name */
4
+ tag: 'title' | 'meta' | 'link' | 'script' | 'style' | 'base' | 'noscript';
5
+ /**
6
+ * Deduplication key. Tags with the same key replace each other;
7
+ * innermost component (last added) wins.
8
+ * Example: all components setting the page title use key "title".
9
+ */
10
+ key?: string;
11
+ /** HTML attributes for the tag */
12
+ props?: Record<string, string>;
13
+ /** Text content — for <title>, <script>, <style>, <noscript> */
14
+ children?: string;
15
+ }
16
+ /** Standard `<meta>` tag attributes. Catches typos like `{ naem: "description" }`. */
17
+ interface MetaTag {
18
+ /** Standard meta name (e.g. "description", "viewport", "robots") */
19
+ name?: string;
20
+ /** Open Graph / social property (e.g. "og:title", "twitter:card") */
21
+ property?: string;
22
+ /** HTTP equivalent header (e.g. "refresh", "content-type") */
23
+ 'http-equiv'?: string;
24
+ /** Value associated with name, property, or http-equiv */
25
+ content?: string;
26
+ /** Document character encoding (e.g. "utf-8") */
27
+ charset?: string;
28
+ /** Schema.org itemprop */
29
+ itemprop?: string;
30
+ /** Media condition for applicability (e.g. "(prefers-color-scheme: dark)") */
31
+ media?: string;
32
+ }
33
+ /** Standard `<link>` tag attributes. */
34
+ interface LinkTag {
35
+ /** Relationship to the current document (e.g. "stylesheet", "icon", "canonical") */
36
+ rel?: string;
37
+ /** URL of the linked resource */
38
+ href?: string;
39
+ /** Resource type hint for preloading (e.g. "style", "script", "font") */
40
+ as?: string;
41
+ /** MIME type (e.g. "text/css", "image/png") */
42
+ type?: string;
43
+ /** Media query for conditional loading */
44
+ media?: string;
45
+ /** CORS mode */
46
+ crossorigin?: string;
47
+ /** Subresource integrity hash */
48
+ integrity?: string;
49
+ /** Icon sizes (e.g. "32x32", "any") */
50
+ sizes?: string;
51
+ /** Language of the linked resource */
52
+ hreflang?: string;
53
+ /** Title for the link (used for alternate stylesheets) */
54
+ title?: string;
55
+ /** Fetch priority hint */
56
+ fetchpriority?: 'high' | 'low' | 'auto';
57
+ /** Referrer policy */
58
+ referrerpolicy?: string;
59
+ /** Image source set for preloading responsive images */
60
+ imagesrcset?: string;
61
+ /** Image sizes for preloading responsive images */
62
+ imagesizes?: string;
63
+ /** Disable the resource (for stylesheets) */
64
+ disabled?: string;
65
+ /** Color for mask-icon */
66
+ color?: string;
67
+ }
68
+ /** Standard `<script>` tag attributes. */
69
+ interface ScriptTag {
70
+ /** External script URL */
71
+ src?: string;
72
+ /** Script MIME type or module type (e.g. "module", "importmap") */
73
+ type?: string;
74
+ /** Load asynchronously */
75
+ async?: string;
76
+ /** Defer execution until document is parsed */
77
+ defer?: string;
78
+ /** CORS mode */
79
+ crossorigin?: string;
80
+ /** Subresource integrity hash */
81
+ integrity?: string;
82
+ /** Exclude from module-supporting browsers */
83
+ nomodule?: string;
84
+ /** Referrer policy */
85
+ referrerpolicy?: string;
86
+ /** Fetch priority hint */
87
+ fetchpriority?: string;
88
+ /** Inline script content */
89
+ children?: string;
90
+ }
91
+ /** Standard `<style>` tag attributes. */
92
+ interface StyleTag {
93
+ /** Inline CSS content (required) */
94
+ children: string;
95
+ /** Media query for conditional styles */
96
+ media?: string;
97
+ /** Nonce for CSP */
98
+ nonce?: string;
99
+ /** Title for alternate stylesheets */
100
+ title?: string;
101
+ /** Render-blocking behavior */
102
+ blocking?: string;
103
+ }
104
+ /**
105
+ * How eagerly the browser should act on a speculation rule.
106
+ * Per the W3C Speculation Rules spec.
107
+ */
108
+ type SpeculationEagerness = 'immediate' | 'eager' | 'moderate' | 'conservative';
109
+ /**
110
+ * A single speculation rule (one entry in a `prefetch` / `prerender` list).
111
+ *
112
+ * - `source: 'list'` + `urls` — prefetch/prerender these explicit URLs.
113
+ * - `source: 'document'` + `where` — let the browser pick links from the
114
+ * current document that match the predicate (e.g. a CSS selector via
115
+ * `{ selector_matches: '.router-link' }`).
116
+ */
117
+ interface SpeculationRule {
118
+ /** `'list'` (explicit `urls`) or `'document'` (predicate-driven). */
119
+ source?: 'list' | 'document';
120
+ /** Same-origin URLs to prefetch/prerender (for `source: 'list'`). */
121
+ urls?: string[];
122
+ /** Document predicate (for `source: 'document'`) — e.g. `{ selector_matches: 'a.next' }`. */
123
+ where?: Record<string, unknown>;
124
+ /** When the browser should fetch — defaults to the browser's per-source default. */
125
+ eagerness?: SpeculationEagerness;
126
+ /** Capability requirements, e.g. `['anonymous-client-ip-when-cross-origin']`. */
127
+ requires?: string[];
128
+ /** Referrer policy for the speculative request. */
129
+ referrer_policy?: string;
130
+ }
131
+ /**
132
+ * Declarative Speculation Rules — emitted as a single
133
+ * `<script type="speculationrules">` tag. Supported browsers prefetch or
134
+ * fully prerender the next document(s) so navigation is instant. Inert in
135
+ * non-supporting browsers (no polyfill needed). Opt-in: only emitted when
136
+ * `useHead({ speculationRules })` is called.
137
+ *
138
+ * @see https://developer.mozilla.org/docs/Web/API/Speculation_Rules_API
139
+ */
140
+ interface SpeculationRules {
141
+ /** Lightweight: fetch the response, no rendering. */
142
+ prefetch?: SpeculationRule[];
143
+ /** Heavy: fully render the next document in the background. */
144
+ prerender?: SpeculationRule[];
145
+ }
146
+ /** Standard `<base>` tag attributes. */
147
+ interface BaseTag {
148
+ /** Base URL for relative URLs in the document */
149
+ href?: string;
150
+ /** Default target for links and forms */
151
+ target?: '_blank' | '_self' | '_parent' | '_top';
152
+ }
153
+ interface UseHeadInput {
154
+ title?: string;
155
+ /**
156
+ * Title template — use `%s` as a placeholder for the page title.
157
+ * Applied to the resolved title after deduplication.
158
+ * @example useHead({ titleTemplate: "%s | My App" })
159
+ */
160
+ titleTemplate?: string | ((title: string) => string);
161
+ meta?: MetaTag[];
162
+ link?: LinkTag[];
163
+ script?: ScriptTag[];
164
+ style?: StyleTag[];
165
+ noscript?: {
166
+ children: string;
167
+ }[];
168
+ /** Convenience: emits a <script type="application/ld+json"> tag with JSON.stringify'd content */
169
+ jsonLd?: Record<string, unknown> | Record<string, unknown>[];
170
+ /**
171
+ * Convenience: emits a `<script type="speculationrules">` tag with the
172
+ * JSON.stringify'd rules. Supported browsers prefetch/prerender the next
173
+ * document(s) for near-instant navigation; inert elsewhere. Opt-in.
174
+ * @example useHead({ speculationRules: { prerender: [{ source: 'list', urls: ['/about'], eagerness: 'moderate' }] } })
175
+ */
176
+ speculationRules?: SpeculationRules;
177
+ base?: BaseTag;
178
+ /** Attributes to set on the <html> element (e.g. { lang: "en", dir: "ltr" }) */
179
+ htmlAttrs?: Record<string, string>;
180
+ /** Attributes to set on the <body> element (e.g. { class: "dark" }) */
181
+ bodyAttrs?: Record<string, string>;
182
+ }
183
+ interface HeadEntry {
184
+ tags: HeadTag[];
185
+ titleTemplate?: string | ((title: string) => string) | undefined;
186
+ htmlAttrs?: Record<string, string> | undefined;
187
+ bodyAttrs?: Record<string, string> | undefined;
188
+ }
189
+ interface HeadContextValue {
190
+ add(id: symbol, entry: HeadEntry): void;
191
+ remove(id: symbol): void;
192
+ /** Returns deduplicated tags — last-added entry wins per key */
193
+ resolve(): HeadTag[];
194
+ /** Returns the merged titleTemplate (last-added wins) */
195
+ resolveTitleTemplate(): (string | ((title: string) => string)) | undefined;
196
+ /** Returns merged htmlAttrs (later entries override earlier) */
197
+ resolveHtmlAttrs(): Record<string, string>;
198
+ /** Returns merged bodyAttrs (later entries override earlier) */
199
+ resolveBodyAttrs(): Record<string, string>;
200
+ }
201
+ declare function createHeadContext(): HeadContextValue;
202
+ declare const HeadContext: import("@pyreon/core").Context<HeadContextValue | null>;
203
+ //#endregion
204
+ export { BaseTag, HeadContext, HeadContextValue, HeadEntry, HeadTag, LinkTag, MetaTag, ScriptTag, SpeculationEagerness, SpeculationRule, SpeculationRules, StyleTag, UseHeadInput, createHeadContext };
205
+ //# sourceMappingURL=context2.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { HeadContext, createHeadContext } from "@pyreon/head/context";
1
2
  import { ComponentFn, Props, VNodeChild } from "@pyreon/core";
2
3
 
3
4
  //#region src/context.d.ts
@@ -200,8 +201,6 @@ interface HeadContextValue {
200
201
  /** Returns merged bodyAttrs (later entries override earlier) */
201
202
  resolveBodyAttrs(): Record<string, string>;
202
203
  }
203
- declare function createHeadContext(): HeadContextValue;
204
- declare const HeadContext: import("@pyreon/core").Context<HeadContextValue | null>;
205
204
  //#endregion
206
205
  //#region src/provider.d.ts
207
206
  interface HeadProviderProps extends Props {
package/lib/use-head.js CHANGED
@@ -1,10 +1,7 @@
1
- import { createContext, onMount, onUnmount, useContext } from "@pyreon/core";
1
+ import { onMount, onUnmount, useContext } from "@pyreon/core";
2
2
  import { effect } from "@pyreon/reactivity";
3
+ import { HeadContext } from "@pyreon/head/context";
3
4
 
4
- //#region src/context.ts
5
- const HeadContext = createContext(null);
6
-
7
- //#endregion
8
5
  //#region src/dom.ts
9
6
  const ATTR = "data-pyreon-head";
10
7
  /** Tracks managed elements by key — avoids querySelectorAll on every sync */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/head",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Head tag management for Pyreon — works in SSR and CSR",
5
5
  "homepage": "https://github.com/pyreon/pyreon/tree/main/packages/head#readme",
6
6
  "bugs": {
@@ -30,6 +30,11 @@
30
30
  "import": "./lib/index.js",
31
31
  "types": "./lib/types/index.d.ts"
32
32
  },
33
+ "./context": {
34
+ "bun": "./src/context.ts",
35
+ "import": "./lib/context.js",
36
+ "types": "./lib/types/context.d.ts"
37
+ },
33
38
  "./provider": {
34
39
  "bun": "./src/provider.ts",
35
40
  "import": "./lib/provider.js",
@@ -59,16 +64,16 @@
59
64
  "prepublishOnly": "bun run build"
60
65
  },
61
66
  "dependencies": {
62
- "@pyreon/core": "^0.21.0",
63
- "@pyreon/reactivity": "^0.21.0",
64
- "@pyreon/runtime-server": "^0.21.0"
67
+ "@pyreon/core": "^0.22.0",
68
+ "@pyreon/reactivity": "^0.22.0",
69
+ "@pyreon/runtime-server": "^0.22.0"
65
70
  },
66
71
  "devDependencies": {
67
72
  "@happy-dom/global-registrator": "^20.8.9",
68
73
  "@pyreon/manifest": "0.13.1",
69
- "@pyreon/runtime-dom": "^0.21.0",
70
- "@pyreon/runtime-server": "^0.21.0",
71
- "@pyreon/test-utils": "^0.13.8",
74
+ "@pyreon/runtime-dom": "^0.22.0",
75
+ "@pyreon/runtime-server": "^0.22.0",
76
+ "@pyreon/test-utils": "^0.13.9",
72
77
  "@vitest/browser-playwright": "^4.1.4"
73
78
  },
74
79
  "peerDependenciesMeta": {
package/src/index.ts CHANGED
@@ -12,7 +12,12 @@ export type {
12
12
  StyleTag,
13
13
  UseHeadInput,
14
14
  } from './context'
15
- export { createHeadContext, HeadContext } from './context'
15
+ // Runtime VALUE re-export via self-package path so the build externalizes
16
+ // the symbol — main entry + every sub-entry resolves to the same
17
+ // `lib/context.js` at runtime. The type re-exports above stay as `./context`
18
+ // (types erase, externalization doesn't apply). See `ssr.ts` for the full
19
+ // rationale + `tests/context-identity.test.ts` for the post-build contract.
20
+ export { createHeadContext, HeadContext } from '@pyreon/head/context'
16
21
  export type { HeadProviderProps } from './provider'
17
22
  export { HeadProvider } from './provider'
18
23
  export { useHead } from './use-head'
package/src/provider.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import type { ComponentFn, Props, VNodeChild } from '@pyreon/core'
2
2
  import { nativeCompat, provide, useContext } from '@pyreon/core'
3
3
  import type { HeadContextValue } from './context'
4
- import { createHeadContext, HeadContext } from './context'
4
+ // Runtime VALUE import via self-package path so the build externalizes
5
+ // the symbol — every sub-entry resolves to the same `lib/context.js` at
6
+ // runtime. See `ssr.ts` for the full rationale + `tests/context-identity.test.ts`.
7
+ import { createHeadContext, HeadContext } from '@pyreon/head/context'
5
8
 
6
9
  export interface HeadProviderProps extends Props {
7
10
  context?: HeadContextValue | undefined