unhead 0.0.1 → 0.0.4
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/dist/client.d.ts +17 -4
- package/dist/client.mjs +44 -50
- package/dist/index.d.ts +8 -7
- package/dist/index.mjs +45 -30
- package/dist/server.d.ts +1 -1
- package/dist/server.mjs +2 -2
- package/dist/{types-e30878c0.d.ts → types-b4318c02.d.ts} +54 -14
- package/package.json +2 -3
package/dist/client.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
-
import { a as HeadClient } from './types-
|
|
1
|
+
import { a as HeadClient } from './types-b4318c02.js';
|
|
2
2
|
import 'hookable';
|
|
3
3
|
import '@unhead/schema';
|
|
4
4
|
|
|
5
5
|
interface RenderDomHeadOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Document to use for rendering. Allows stubbing for testing.
|
|
8
|
+
*/
|
|
6
9
|
document?: Document;
|
|
7
10
|
}
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Render the head tags to the DOM.
|
|
13
|
+
*/
|
|
14
|
+
declare function renderDOMHead<T extends HeadClient<any>>(head: T, options?: RenderDomHeadOptions): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Global instance of the dom update promise. Used for debounding head updates.
|
|
17
|
+
*/
|
|
18
|
+
declare let domUpdatePromise: Promise<void> | null;
|
|
19
|
+
/**
|
|
20
|
+
* Queue a debounced update of the DOM head.
|
|
21
|
+
*/
|
|
22
|
+
declare function debouncedRenderDOMHead<T extends HeadClient<any>>(delayedFn: (fn: () => void) => void, head: T, options?: RenderDomHeadOptions): Promise<void>;
|
|
10
23
|
|
|
11
|
-
export { RenderDomHeadOptions,
|
|
24
|
+
export { RenderDomHeadOptions, debouncedRenderDOMHead, domUpdatePromise, renderDOMHead };
|
package/dist/client.mjs
CHANGED
|
@@ -1,53 +1,56 @@
|
|
|
1
|
-
import { createElement } from 'zhead';
|
|
1
|
+
import { createElement, TagsWithInnerContent } from 'zhead';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const sideEffects = {};
|
|
3
|
+
function setAttributesWithSideEffects(head, $el, entry, tag) {
|
|
5
4
|
const attrs = tag.props || {};
|
|
6
|
-
|
|
5
|
+
const sdeKey = `${tag._p}:attr`;
|
|
6
|
+
Object.entries(entry._sde).filter(([key]) => key.startsWith(sdeKey)).forEach(([key, fn]) => {
|
|
7
|
+
delete entry._sde[key] && fn();
|
|
8
|
+
});
|
|
9
|
+
Object.entries(attrs).forEach(([k, value]) => {
|
|
10
|
+
value = String(value);
|
|
11
|
+
const attrSdeKey = `${sdeKey}:${k}`;
|
|
12
|
+
head._removeQueuedSideEffect(attrSdeKey);
|
|
7
13
|
if (k === "class") {
|
|
8
|
-
for (const c of
|
|
14
|
+
for (const c of value.split(" ")) {
|
|
9
15
|
if (!$el.classList.contains(c)) {
|
|
10
16
|
$el.classList.add(c);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
17
|
+
head._removeQueuedSideEffect(`${attrSdeKey}:${c}`);
|
|
18
|
+
entry._sde[`${attrSdeKey}:${c}`] = () => $el.classList.remove(c);
|
|
14
19
|
}
|
|
15
20
|
}
|
|
16
|
-
|
|
21
|
+
return;
|
|
17
22
|
}
|
|
18
|
-
$el.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
$el.removeAttribute(k);
|
|
22
|
-
};
|
|
23
|
+
if ($el.getAttribute(k) !== value) {
|
|
24
|
+
$el.setAttribute(k, value);
|
|
25
|
+
if (!k.startsWith("data-h-"))
|
|
26
|
+
entry._sde[attrSdeKey] = () => $el.removeAttribute(k);
|
|
23
27
|
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
const renderDOMHead = async (head, options = {}) => {
|
|
31
|
+
async function renderDOMHead(head, options = {}) {
|
|
30
32
|
const dom = options.document || window.document;
|
|
31
33
|
const tags = await head.resolveTags();
|
|
32
34
|
await head.hooks.callHook("dom:beforeRender", { head, tags, document: dom });
|
|
33
|
-
head._flushDomSideEffects();
|
|
34
|
-
const sideEffectMap = {};
|
|
35
35
|
for (const tag of tags) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
36
|
+
const entry = head.headEntries().find((e) => e._i === Number(tag._e));
|
|
37
|
+
const sdeKey = `${tag._s || tag._p}:el`;
|
|
38
|
+
const $newEl = createElement(tag, dom);
|
|
39
|
+
const $el = tag._s ? dom.querySelector(`[${tag._s}]`) : null;
|
|
40
|
+
const renderCtx = { tag, document: dom, head };
|
|
39
41
|
await head.hooks.callHook("dom:renderTag", renderCtx);
|
|
40
42
|
if ($el) {
|
|
43
|
+
head._removeQueuedSideEffect(sdeKey);
|
|
44
|
+
if ($newEl.isEqualNode($el))
|
|
45
|
+
continue;
|
|
41
46
|
if (Object.keys(tag.props).length === 0) {
|
|
42
47
|
$el.remove();
|
|
43
48
|
continue;
|
|
44
49
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
$el.innerHTML = tag.children || "";
|
|
50
|
-
sideEffectMap[tag._e][`${tag._p}:el:remove`] = () => $el?.remove();
|
|
50
|
+
setAttributesWithSideEffects(head, $el, entry, tag);
|
|
51
|
+
if (TagsWithInnerContent.includes(tag.tag))
|
|
52
|
+
$el.innerHTML = tag.children || "";
|
|
53
|
+
entry._sde[sdeKey] = () => $el?.remove();
|
|
51
54
|
continue;
|
|
52
55
|
}
|
|
53
56
|
if (tag.tag === "title" && tag.children) {
|
|
@@ -55,41 +58,32 @@ const renderDOMHead = async (head, options = {}) => {
|
|
|
55
58
|
continue;
|
|
56
59
|
}
|
|
57
60
|
if (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs") {
|
|
58
|
-
|
|
59
|
-
...sideEffectMap[tag._e],
|
|
60
|
-
...setAttributes(dom[tag.tag === "htmlAttrs" ? "documentElement" : "body"], tag)
|
|
61
|
-
};
|
|
61
|
+
setAttributesWithSideEffects(head, dom[tag.tag === "htmlAttrs" ? "documentElement" : "body"], entry, tag);
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
|
-
$el = createElement(tag, dom);
|
|
65
64
|
switch (tag.tagPosition) {
|
|
66
65
|
case "bodyClose":
|
|
67
|
-
dom.body.appendChild($
|
|
66
|
+
dom.body.appendChild($newEl);
|
|
68
67
|
break;
|
|
69
68
|
case "bodyOpen":
|
|
70
|
-
dom.body.insertBefore($
|
|
69
|
+
dom.body.insertBefore($newEl, dom.body.firstChild);
|
|
71
70
|
break;
|
|
72
71
|
case "head":
|
|
73
72
|
default:
|
|
74
|
-
dom.head.appendChild($
|
|
73
|
+
dom.head.appendChild($newEl);
|
|
75
74
|
break;
|
|
76
75
|
}
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
for (const k in sideEffectMap) {
|
|
80
|
-
const entry = head.headEntries().find((e) => e._i === Number(k));
|
|
81
|
-
entry._sde = {
|
|
82
|
-
...entry._sde,
|
|
83
|
-
...sideEffectMap[k]
|
|
84
|
-
};
|
|
76
|
+
entry._sde[sdeKey] = () => $newEl?.remove();
|
|
85
77
|
}
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
head._flushQueuedSideEffects();
|
|
79
|
+
}
|
|
80
|
+
let domUpdatePromise = null;
|
|
81
|
+
async function debouncedRenderDOMHead(delayedFn, head, options = {}) {
|
|
88
82
|
function doDomUpdate() {
|
|
89
83
|
domUpdatePromise = null;
|
|
90
84
|
return renderDOMHead(head, options);
|
|
91
85
|
}
|
|
92
86
|
return domUpdatePromise = domUpdatePromise || new Promise((resolve) => delayedFn(() => resolve(doDomUpdate())));
|
|
93
|
-
}
|
|
87
|
+
}
|
|
94
88
|
|
|
95
|
-
export {
|
|
89
|
+
export { debouncedRenderDOMHead, domUpdatePromise, renderDOMHead };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as _unhead_schema from '@unhead/schema';
|
|
2
2
|
import { Head, Meta, Link, Script, Style, Base, HtmlAttributes, BodyAttributes, Noscript } from '@unhead/schema';
|
|
3
|
-
import { H as HeadPlugin, C as CreateHeadOptions, a as HeadClient, b as HeadEntryOptions } from './types-
|
|
4
|
-
export { A as ActiveHeadEntry, C as CreateHeadOptions, D as DomRenderTagContext, a as HeadClient, c as HeadEntry, b as HeadEntryOptions,
|
|
3
|
+
import { H as HeadPlugin, C as CreateHeadOptions, a as HeadClient, b as HeadEntryOptions } from './types-b4318c02.js';
|
|
4
|
+
export { A as ActiveHeadEntry, C as CreateHeadOptions, D as DomRenderTagContext, E as EntryResolveCtx, a as HeadClient, c as HeadEntry, b as HeadEntryOptions, f as HeadHooks, H as HeadPlugin, e as HookResult, R as RuntimeMode, S as SideEffectsRecord, d as defineHeadPlugin } from './types-b4318c02.js';
|
|
5
5
|
import 'hookable';
|
|
6
6
|
|
|
7
|
-
declare const
|
|
7
|
+
declare const DedupesTagsPlugin: HeadPlugin<_unhead_schema.Head<_unhead_schema.SchemaAugmentations>>;
|
|
8
8
|
|
|
9
|
-
declare const
|
|
9
|
+
declare const SortTagsPlugin: HeadPlugin<_unhead_schema.Head<_unhead_schema.SchemaAugmentations>>;
|
|
10
10
|
|
|
11
|
-
declare const
|
|
11
|
+
declare const TitleTemplatePlugin: HeadPlugin<_unhead_schema.Head<_unhead_schema.SchemaAugmentations>>;
|
|
12
12
|
|
|
13
|
-
declare const
|
|
13
|
+
declare const HydratesStatePlugin: HeadPlugin<_unhead_schema.Head<_unhead_schema.SchemaAugmentations>>;
|
|
14
14
|
|
|
15
15
|
declare function createHead<T extends {} = Head>(options?: CreateHeadOptions<T>): HeadClient<T>;
|
|
16
16
|
|
|
@@ -32,6 +32,7 @@ declare const getActiveHead: <T>() => HeadClient<T>;
|
|
|
32
32
|
|
|
33
33
|
declare type Arrayable<T> = T | Array<T>;
|
|
34
34
|
declare function asArray<T>(value: Arrayable<T>): T[];
|
|
35
|
+
declare const TagConfigKeys: string[];
|
|
35
36
|
declare function hashCode(s: string): string;
|
|
36
37
|
|
|
37
|
-
export { Arrayable,
|
|
38
|
+
export { Arrayable, DedupesTagsPlugin, HydratesStatePlugin, SortTagsPlugin, TagConfigKeys, TitleTemplatePlugin, activeHead, asArray, createHead, getActiveHead, hashCode, setActiveHead, useBase, useBodyAttrs, useHead, useHtmlAttrs, useLink, useMeta, useNoscript, useScript, useStyle, useTitle, useTitleTemplate };
|
package/dist/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ function defineHeadPlugin(plugin) {
|
|
|
9
9
|
return plugin;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const DedupesTagsPlugin = defineHeadPlugin({
|
|
13
13
|
hooks: {
|
|
14
14
|
"tag:normalise": function({ tag }) {
|
|
15
15
|
["hid", "vmid", "key"].forEach((key) => {
|
|
@@ -28,7 +28,10 @@ const dedupePlugin = defineHeadPlugin({
|
|
|
28
28
|
let dedupeKey = tag._d || tag._p || i;
|
|
29
29
|
const dupedTag = deduping[dedupeKey];
|
|
30
30
|
if (dupedTag) {
|
|
31
|
-
|
|
31
|
+
let strategy = tag?.tagDuplicateStrategy;
|
|
32
|
+
if (!strategy && (tag.tag === "htmlAttrs" || tag.tag === "bodyAttrs"))
|
|
33
|
+
strategy = "merge";
|
|
34
|
+
if (strategy === "merge") {
|
|
32
35
|
const oldProps = dupedTag.props;
|
|
33
36
|
["class", "style"].forEach((key) => {
|
|
34
37
|
if (tag.props[key] && oldProps[key])
|
|
@@ -57,7 +60,7 @@ const dedupePlugin = defineHeadPlugin({
|
|
|
57
60
|
}
|
|
58
61
|
});
|
|
59
62
|
|
|
60
|
-
const
|
|
63
|
+
const SortTagsPlugin = defineHeadPlugin({
|
|
61
64
|
hooks: {
|
|
62
65
|
"tags:resolve": (ctx) => {
|
|
63
66
|
const tagIndexForKey = (key) => ctx.tags.find((tag) => tag._d === key)?._p;
|
|
@@ -83,7 +86,7 @@ const sortPlugin = defineHeadPlugin({
|
|
|
83
86
|
}
|
|
84
87
|
});
|
|
85
88
|
|
|
86
|
-
const
|
|
89
|
+
const TitleTemplatePlugin = defineHeadPlugin({
|
|
87
90
|
hooks: {
|
|
88
91
|
"tags:resolve": (ctx) => {
|
|
89
92
|
ctx.tags = resolveTitleTemplateFromTags(ctx.tags);
|
|
@@ -94,6 +97,7 @@ const titleTemplatePlugin = defineHeadPlugin({
|
|
|
94
97
|
function asArray(value) {
|
|
95
98
|
return Array.isArray(value) ? value : [value];
|
|
96
99
|
}
|
|
100
|
+
const TagConfigKeys = ["tagPosition", "tagPriority", "tagDuplicateStrategy"];
|
|
97
101
|
function hashCode(s) {
|
|
98
102
|
let h = 9;
|
|
99
103
|
for (let i = 0; i < s.length; )
|
|
@@ -101,15 +105,16 @@ function hashCode(s) {
|
|
|
101
105
|
return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 7).toLowerCase();
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
const
|
|
108
|
+
const HydratesStatePlugin = defineHeadPlugin({
|
|
105
109
|
hooks: {
|
|
106
110
|
"tag:normalise": (ctx) => {
|
|
107
111
|
const { tag, entry } = ctx;
|
|
108
112
|
if (!HasElementTags.includes(tag.tag))
|
|
109
113
|
return;
|
|
110
|
-
if (typeof tag._d === "undefined" && entry.
|
|
114
|
+
if (typeof tag._d === "undefined" && entry._m === "server")
|
|
111
115
|
return;
|
|
112
|
-
|
|
116
|
+
const hasChildren = tag.children && tag.children.length > 0;
|
|
117
|
+
tag._s = `data-h-${hashCode(tag._d || tag.tag + (hasChildren ? tag.children : JSON.stringify(tag.props)))}`;
|
|
113
118
|
tag.props[tag._s] = "";
|
|
114
119
|
}
|
|
115
120
|
}
|
|
@@ -118,14 +123,20 @@ const hydratesStatePlugin = defineHeadPlugin({
|
|
|
118
123
|
function normaliseTag(tagName, input, entry) {
|
|
119
124
|
const tag = normaliseTag$1(tagName, input, { childrenKeys: ["innerHTML", "textContent"] });
|
|
120
125
|
tag._e = entry._i;
|
|
121
|
-
Object.keys(tag.props).filter((k) =>
|
|
126
|
+
Object.keys(tag.props).filter((k) => TagConfigKeys.includes(k)).forEach((k) => {
|
|
122
127
|
tag[k] = tag.props[k];
|
|
123
128
|
delete tag.props[k];
|
|
124
129
|
});
|
|
130
|
+
if (typeof tag.props.class === "object" && !Array.isArray(tag.props.class)) {
|
|
131
|
+
tag.props.class = Object.keys(tag.props.class).filter((k) => tag.props.class[k]);
|
|
132
|
+
}
|
|
133
|
+
if (Array.isArray(tag.props.class))
|
|
134
|
+
tag.props.class = tag.props.class.join(" ");
|
|
125
135
|
if (tag.props.content && Array.isArray(tag.props.content)) {
|
|
126
|
-
return tag.props.content.map((v) => {
|
|
136
|
+
return tag.props.content.map((v, i) => {
|
|
127
137
|
const newTag = { ...tag, props: { ...tag.props } };
|
|
128
138
|
newTag.props.content = v;
|
|
139
|
+
newTag.key = `${tag.props.name || tag.props.property}:${i}`;
|
|
129
140
|
return newTag;
|
|
130
141
|
});
|
|
131
142
|
}
|
|
@@ -148,15 +159,17 @@ function createHead(options = {}) {
|
|
|
148
159
|
if (options.hooks)
|
|
149
160
|
hooks.addHooks(options.hooks);
|
|
150
161
|
const plugins = [
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
DedupesTagsPlugin,
|
|
163
|
+
SortTagsPlugin,
|
|
164
|
+
TitleTemplatePlugin
|
|
154
165
|
];
|
|
155
166
|
plugins.push(...options.plugins || []);
|
|
156
167
|
plugins.forEach((plugin) => hooks.addHooks(plugin.hooks || {}));
|
|
157
168
|
const head = {
|
|
158
|
-
|
|
159
|
-
|
|
169
|
+
_removeQueuedSideEffect(key) {
|
|
170
|
+
delete _sde[key];
|
|
171
|
+
},
|
|
172
|
+
_flushQueuedSideEffects() {
|
|
160
173
|
Object.values(_sde).forEach((fn) => fn());
|
|
161
174
|
_sde = {};
|
|
162
175
|
},
|
|
@@ -179,33 +192,35 @@ function createHead(options = {}) {
|
|
|
179
192
|
entries = entries.filter((e) => {
|
|
180
193
|
if (e._i !== _i)
|
|
181
194
|
return true;
|
|
182
|
-
_sde = {
|
|
183
|
-
|
|
184
|
-
...e._sde || {}
|
|
185
|
-
};
|
|
195
|
+
_sde = { ..._sde, ...e._sde || {} };
|
|
196
|
+
e._sde = {};
|
|
186
197
|
return false;
|
|
187
198
|
});
|
|
188
199
|
},
|
|
189
200
|
patch(input2) {
|
|
190
201
|
entries = entries.map((e) => {
|
|
191
|
-
|
|
202
|
+
if (e._i === _i) {
|
|
203
|
+
_sde = { ..._sde, ...e._sde || {} };
|
|
204
|
+
e._sde = {};
|
|
205
|
+
e.input = e._i === _i ? input2 : e.input;
|
|
206
|
+
}
|
|
192
207
|
return e;
|
|
193
208
|
});
|
|
194
209
|
}
|
|
195
210
|
};
|
|
196
211
|
},
|
|
197
212
|
async resolveTags() {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
for (const
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
213
|
+
const resolveCtx = { tags: [], entries: [...entries] };
|
|
214
|
+
await hooks.callHook("entries:resolve", resolveCtx);
|
|
215
|
+
for (const entry of resolveCtx.entries) {
|
|
216
|
+
for (const tag of normaliseEntryTags(entry)) {
|
|
217
|
+
const tagCtx = { tag, entry };
|
|
218
|
+
await hooks.callHook("tag:normalise", tagCtx);
|
|
219
|
+
resolveCtx.tags.push(tagCtx.tag);
|
|
220
|
+
}
|
|
204
221
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
await hooks.callHook("tags:resolve", ctx);
|
|
208
|
-
return ctx.tags;
|
|
222
|
+
await hooks.callHook("tags:resolve", resolveCtx);
|
|
223
|
+
return resolveCtx.tags;
|
|
209
224
|
}
|
|
210
225
|
};
|
|
211
226
|
setActiveHead(head);
|
|
@@ -247,4 +262,4 @@ const useNoscript = (noscript) => {
|
|
|
247
262
|
useHead({ noscript: [noscript] });
|
|
248
263
|
};
|
|
249
264
|
|
|
250
|
-
export {
|
|
265
|
+
export { DedupesTagsPlugin, HydratesStatePlugin, SortTagsPlugin, TagConfigKeys, TitleTemplatePlugin, activeHead, asArray, createHead, defineHeadPlugin, getActiveHead, hashCode, setActiveHead, useBase, useBodyAttrs, useHead, useHtmlAttrs, useLink, useMeta, useNoscript, useScript, useStyle, useTitle, useTitleTemplate };
|
package/dist/server.d.ts
CHANGED
package/dist/server.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ssrRenderTags } from 'zhead';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
async function renderSSRHead(ctx) {
|
|
4
4
|
const tags = await ctx.resolveTags();
|
|
5
5
|
const beforeRenderCtx = { tags };
|
|
6
6
|
await ctx.hooks.callHook("ssr:beforeRender", beforeRenderCtx);
|
|
@@ -8,6 +8,6 @@ const renderSSRHead = async (ctx) => {
|
|
|
8
8
|
const renderCXx = { tags, html };
|
|
9
9
|
await ctx.hooks.callHook("ssr:render", renderCXx);
|
|
10
10
|
return renderCXx.html;
|
|
11
|
-
}
|
|
11
|
+
}
|
|
12
12
|
|
|
13
13
|
export { renderSSRHead };
|
|
@@ -11,17 +11,43 @@ interface SSRHeadPayload {
|
|
|
11
11
|
htmlAttrs: string;
|
|
12
12
|
bodyAttrs: string;
|
|
13
13
|
}
|
|
14
|
-
declare
|
|
14
|
+
declare function renderSSRHead<T extends HeadClient<any>>(ctx: T): Promise<SSRHeadPayload>;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* An active head entry provides an API to manipulate it.
|
|
18
|
+
*/
|
|
16
19
|
interface ActiveHeadEntry<T> {
|
|
20
|
+
/**
|
|
21
|
+
* Updates the entry with new input.
|
|
22
|
+
*
|
|
23
|
+
* Will first clear any side effects for previous input.
|
|
24
|
+
*/
|
|
17
25
|
patch: (resolvedInput: T) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Dispose the entry, removing it from the active head.
|
|
28
|
+
*
|
|
29
|
+
* Will queue side effects for removal.
|
|
30
|
+
*/
|
|
18
31
|
dispose: () => void;
|
|
19
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Side effects are mapped with a key and their cleanup function.
|
|
35
|
+
*
|
|
36
|
+
* For example `meta:data-h-4h46h465`: () => { document.querySelector('meta[data-h-4h46h465]').remove() }
|
|
37
|
+
*/
|
|
20
38
|
declare type SideEffectsRecord = Record<string, () => void>;
|
|
21
39
|
declare type RuntimeMode = 'server' | 'client' | 'all';
|
|
22
40
|
interface HeadEntry<T> {
|
|
23
|
-
|
|
41
|
+
/**
|
|
42
|
+
* User provided input for the entry.
|
|
43
|
+
*/
|
|
24
44
|
input: T;
|
|
45
|
+
/**
|
|
46
|
+
* The mode that the entry should be used in.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
_m?: RuntimeMode;
|
|
25
51
|
/**
|
|
26
52
|
* Head entry index
|
|
27
53
|
*
|
|
@@ -33,34 +59,33 @@ interface HeadEntry<T> {
|
|
|
33
59
|
*
|
|
34
60
|
* @internal
|
|
35
61
|
*/
|
|
36
|
-
_sde
|
|
62
|
+
_sde: SideEffectsRecord;
|
|
37
63
|
}
|
|
38
64
|
declare type HookResult = Promise<void> | void;
|
|
39
65
|
interface DomRenderTagContext {
|
|
40
66
|
head: HeadClient;
|
|
41
67
|
tag: HeadTag;
|
|
42
|
-
$el: Element | null;
|
|
43
68
|
document: Document;
|
|
44
69
|
}
|
|
70
|
+
interface EntryResolveCtx<T> {
|
|
71
|
+
tags: HeadTag[];
|
|
72
|
+
entries: HeadEntry<T>[];
|
|
73
|
+
}
|
|
45
74
|
interface HeadHooks<T> {
|
|
46
|
-
'entries:resolve': (
|
|
75
|
+
'entries:resolve': (ctx: EntryResolveCtx<T>) => HookResult;
|
|
47
76
|
'tag:normalise': (ctx: {
|
|
48
77
|
tag: HeadTag;
|
|
49
78
|
entry: HeadEntry<T>;
|
|
50
79
|
}) => HookResult;
|
|
51
|
-
'tags:beforeResolve': (ctx: {
|
|
52
|
-
tags: HeadTag[];
|
|
53
|
-
}) => HookResult;
|
|
54
80
|
'tags:resolve': (ctx: {
|
|
55
81
|
tags: HeadTag[];
|
|
56
82
|
}) => HookResult;
|
|
57
|
-
'render': (ctx: any) => HookResult;
|
|
58
|
-
'dom:renderTag': (ctx: DomRenderTagContext) => HookResult;
|
|
59
83
|
'dom:beforeRender': (ctx: {
|
|
60
84
|
head: HeadClient;
|
|
61
85
|
tags: HeadTag[];
|
|
62
86
|
document: Document;
|
|
63
87
|
}) => HookResult;
|
|
88
|
+
'dom:renderTag': (ctx: DomRenderTagContext) => HookResult;
|
|
64
89
|
'ssr:beforeRender': (ctx: {
|
|
65
90
|
tags: HeadTag[];
|
|
66
91
|
}) => HookResult;
|
|
@@ -77,15 +102,30 @@ interface HeadEntryOptions {
|
|
|
77
102
|
mode?: RuntimeMode;
|
|
78
103
|
}
|
|
79
104
|
interface HeadClient<T = Head> {
|
|
80
|
-
|
|
81
|
-
|
|
105
|
+
/**
|
|
106
|
+
* The active head entries.
|
|
107
|
+
*/
|
|
82
108
|
headEntries: () => HeadEntry<T>[];
|
|
109
|
+
/**
|
|
110
|
+
* Create a new head entry.
|
|
111
|
+
*/
|
|
83
112
|
push: (entry: T, options?: HeadEntryOptions) => ActiveHeadEntry<T>;
|
|
113
|
+
/**
|
|
114
|
+
* Resolve tags from head entries.
|
|
115
|
+
*/
|
|
84
116
|
resolveTags: () => Promise<HeadTag[]>;
|
|
117
|
+
/**
|
|
118
|
+
* Exposed hooks for easier extension.
|
|
119
|
+
*/
|
|
120
|
+
hooks: Hookable<HeadHooks<T>>;
|
|
121
|
+
/**
|
|
122
|
+
* @internal
|
|
123
|
+
*/
|
|
124
|
+
_removeQueuedSideEffect: (key: string) => void;
|
|
85
125
|
/**
|
|
86
126
|
* @internal
|
|
87
127
|
*/
|
|
88
|
-
|
|
128
|
+
_flushQueuedSideEffects: () => void;
|
|
89
129
|
}
|
|
90
130
|
|
|
91
|
-
export { ActiveHeadEntry as A, CreateHeadOptions as C, DomRenderTagContext as D, HeadPlugin as H, RuntimeMode as R, SideEffectsRecord as S, HeadClient as a, HeadEntryOptions as b, HeadEntry as c, defineHeadPlugin as d,
|
|
131
|
+
export { ActiveHeadEntry as A, CreateHeadOptions as C, DomRenderTagContext as D, EntryResolveCtx as E, HeadPlugin as H, RuntimeMode as R, SideEffectsRecord as S, HeadClient as a, HeadEntryOptions as b, HeadEntry as c, defineHeadPlugin as d, HookResult as e, HeadHooks as f, SSRHeadPayload as g, renderSSRHead as r };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unhead",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.4",
|
|
5
5
|
"packageManager": "pnpm@7.14.0",
|
|
6
6
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -36,9 +36,8 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@unhead/schema": "0.0.
|
|
39
|
+
"@unhead/schema": "0.0.4",
|
|
40
40
|
"hookable": "^5.4.1",
|
|
41
|
-
"unctx": "^2.0.2",
|
|
42
41
|
"zhead": "1.0.0-beta.4"
|
|
43
42
|
},
|
|
44
43
|
"scripts": {
|