@unhead/dom 1.0.21 → 1.0.22
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/index.cjs +38 -60
- package/dist/index.d.ts +12 -3
- package/dist/index.mjs +33 -56
- package/package.json +7 -9
package/dist/index.cjs
CHANGED
|
@@ -1,37 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const HasElementTags = [
|
|
5
|
-
"base",
|
|
6
|
-
"meta",
|
|
7
|
-
"link",
|
|
8
|
-
"style",
|
|
9
|
-
"script",
|
|
10
|
-
"noscript"
|
|
11
|
-
];
|
|
12
|
-
|
|
13
|
-
const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
|
|
14
|
-
function tagDedupeKey(tag, fn) {
|
|
15
|
-
const { props, tag: tagName } = tag;
|
|
16
|
-
if (UniqueTags.includes(tagName))
|
|
17
|
-
return tagName;
|
|
18
|
-
if (tagName === "link" && props.rel === "canonical")
|
|
19
|
-
return "canonical";
|
|
20
|
-
if (props.charset)
|
|
21
|
-
return "charset";
|
|
22
|
-
const name = ["id"];
|
|
23
|
-
if (tagName === "meta")
|
|
24
|
-
name.push(...["name", "property", "http-equiv"]);
|
|
25
|
-
for (const n of name) {
|
|
26
|
-
if (typeof props[n] !== "undefined") {
|
|
27
|
-
const val = String(props[n]);
|
|
28
|
-
if (fn && !fn(val))
|
|
29
|
-
return false;
|
|
30
|
-
return `${tagName}:${n}:${val}`;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
3
|
+
const shared = require('@unhead/shared');
|
|
35
4
|
|
|
36
5
|
const setAttrs = (ctx, markSideEffect) => {
|
|
37
6
|
const { tag, $el } = ctx;
|
|
@@ -57,17 +26,10 @@ const setAttrs = (ctx, markSideEffect) => {
|
|
|
57
26
|
if ($el.getAttribute(k) !== value)
|
|
58
27
|
$el.setAttribute(k, value);
|
|
59
28
|
});
|
|
60
|
-
if (TagsWithInnerContent.includes(tag.tag) && $el.innerHTML !== (tag.children || ""))
|
|
29
|
+
if (shared.TagsWithInnerContent.includes(tag.tag) && $el.innerHTML !== (tag.children || ""))
|
|
61
30
|
$el.innerHTML = tag.children || "";
|
|
62
31
|
};
|
|
63
32
|
|
|
64
|
-
function hashCode(s) {
|
|
65
|
-
let h = 9;
|
|
66
|
-
for (let i = 0; i < s.length; )
|
|
67
|
-
h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
|
|
68
|
-
return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
33
|
async function renderDOMHead(head, options = {}) {
|
|
72
34
|
const ctx = { shouldRender: true };
|
|
73
35
|
await head.hooks.callHook("dom:beforeRender", ctx);
|
|
@@ -80,10 +42,10 @@ async function renderDOMHead(head, options = {}) {
|
|
|
80
42
|
staleSideEffects[key] = fn;
|
|
81
43
|
});
|
|
82
44
|
});
|
|
83
|
-
const
|
|
45
|
+
const setupTagRenderCtx = async (tag) => {
|
|
84
46
|
const entry = head.headEntries().find((e) => e._i === tag._e);
|
|
85
47
|
const renderCtx = {
|
|
86
|
-
renderId: tag._d || hashCode(JSON.stringify({ ...tag, _e: void 0, _p: void 0 })),
|
|
48
|
+
renderId: tag._d || shared.hashCode(JSON.stringify({ ...tag, _e: void 0, _p: void 0 })),
|
|
87
49
|
$el: null,
|
|
88
50
|
shouldRender: true,
|
|
89
51
|
tag,
|
|
@@ -113,7 +75,7 @@ async function renderDOMHead(head, options = {}) {
|
|
|
113
75
|
});
|
|
114
76
|
};
|
|
115
77
|
for (const t of await head.resolveTags()) {
|
|
116
|
-
const ctx2 = await
|
|
78
|
+
const ctx2 = await setupTagRenderCtx(t);
|
|
117
79
|
if (!ctx2.shouldRender)
|
|
118
80
|
continue;
|
|
119
81
|
const { tag } = ctx2;
|
|
@@ -142,6 +104,11 @@ async function renderDOMHead(head, options = {}) {
|
|
|
142
104
|
setAttrs(ctx2);
|
|
143
105
|
pendingRenders[tag.tagPosition?.startsWith("body") ? "body" : "head"].push(ctx2);
|
|
144
106
|
}
|
|
107
|
+
const fragments = {
|
|
108
|
+
bodyClose: void 0,
|
|
109
|
+
bodyOpen: void 0,
|
|
110
|
+
head: void 0
|
|
111
|
+
};
|
|
145
112
|
Object.entries(pendingRenders).forEach(([pos, queue]) => {
|
|
146
113
|
if (!queue.length)
|
|
147
114
|
return;
|
|
@@ -150,9 +117,9 @@ async function renderDOMHead(head, options = {}) {
|
|
|
150
117
|
return;
|
|
151
118
|
for (const $el of [...children].reverse()) {
|
|
152
119
|
const elTag = $el.tagName.toLowerCase();
|
|
153
|
-
if (!HasElementTags.includes(elTag))
|
|
120
|
+
if (!shared.HasElementTags.includes(elTag))
|
|
154
121
|
continue;
|
|
155
|
-
const dedupeKey = tagDedupeKey({
|
|
122
|
+
const dedupeKey = shared.tagDedupeKey({
|
|
156
123
|
tag: elTag,
|
|
157
124
|
// convert attributes to object
|
|
158
125
|
props: $el.getAttributeNames().reduce((props, name) => ({ ...props, [name]: $el.getAttribute(name) }), {})
|
|
@@ -167,23 +134,18 @@ async function renderDOMHead(head, options = {}) {
|
|
|
167
134
|
}
|
|
168
135
|
}
|
|
169
136
|
queue.forEach((ctx2) => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
case "bodyClose":
|
|
174
|
-
dom.body.appendChild(ctx2.$el);
|
|
175
|
-
break;
|
|
176
|
-
case "bodyOpen":
|
|
177
|
-
dom.body.insertBefore(ctx2.$el, dom.body.firstChild);
|
|
178
|
-
break;
|
|
179
|
-
case "head":
|
|
180
|
-
default:
|
|
181
|
-
dom.head.appendChild(ctx2.$el);
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
137
|
+
const pos2 = ctx2.tag.tagPosition || "head";
|
|
138
|
+
fragments[pos2] = fragments[pos2] || dom.createDocumentFragment();
|
|
139
|
+
fragments[pos2].appendChild(ctx2.$el);
|
|
184
140
|
markEl(ctx2);
|
|
185
141
|
});
|
|
186
142
|
});
|
|
143
|
+
if (fragments.head)
|
|
144
|
+
dom.head.appendChild(fragments.head);
|
|
145
|
+
if (fragments.bodyOpen)
|
|
146
|
+
dom.body.insertBefore(fragments.bodyOpen, dom.body.firstChild);
|
|
147
|
+
if (fragments.bodyClose)
|
|
148
|
+
dom.body.appendChild(fragments.bodyClose);
|
|
187
149
|
for (const ctx2 of renders)
|
|
188
150
|
await head.hooks.callHook("dom:renderTag", ctx2);
|
|
189
151
|
Object.values(staleSideEffects).forEach((fn) => fn());
|
|
@@ -198,6 +160,22 @@ async function debouncedRenderDOMHead(head, options = {}) {
|
|
|
198
160
|
return exports.domUpdatePromise = exports.domUpdatePromise || new Promise((resolve) => delayFn(() => resolve(doDomUpdate())));
|
|
199
161
|
}
|
|
200
162
|
|
|
163
|
+
const PatchDomOnEntryUpdatesPlugin = (options) => {
|
|
164
|
+
return shared.defineHeadPlugin({
|
|
165
|
+
hooks: {
|
|
166
|
+
"entries:updated": function(head) {
|
|
167
|
+
if (typeof options?.document === "undefined" && typeof window === "undefined")
|
|
168
|
+
return;
|
|
169
|
+
let delayFn = options?.delayFn;
|
|
170
|
+
if (!delayFn && typeof requestAnimationFrame !== "undefined")
|
|
171
|
+
delayFn = requestAnimationFrame;
|
|
172
|
+
debouncedRenderDOMHead(head, { document: options?.document || window.document, delayFn });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
exports.PatchDomOnEntryUpdatesPlugin = PatchDomOnEntryUpdatesPlugin;
|
|
201
179
|
exports.debouncedRenderDOMHead = debouncedRenderDOMHead;
|
|
202
|
-
exports.hashCode = hashCode;
|
|
203
180
|
exports.renderDOMHead = renderDOMHead;
|
|
181
|
+
exports.setAttrs = setAttrs;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _unhead_schema from '@unhead/schema';
|
|
2
|
+
import { Unhead, DomRenderTagContext } from '@unhead/schema';
|
|
2
3
|
|
|
3
4
|
interface RenderDomHeadOptions {
|
|
4
5
|
/**
|
|
@@ -21,6 +22,14 @@ declare function debouncedRenderDOMHead<T extends Unhead<any>>(head: T, options?
|
|
|
21
22
|
delayFn?: (fn: () => void) => void;
|
|
22
23
|
}): Promise<void>;
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
interface TriggerDomPatchingOnUpdatesPluginOptions extends RenderDomHeadOptions {
|
|
26
|
+
delayFn?: (fn: () => void) => void;
|
|
27
|
+
}
|
|
28
|
+
declare const PatchDomOnEntryUpdatesPlugin: (options?: TriggerDomPatchingOnUpdatesPluginOptions) => _unhead_schema.HeadPlugin;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Set attributes on a DOM element, while adding entry side effects.
|
|
32
|
+
*/
|
|
33
|
+
declare const setAttrs: (ctx: DomRenderTagContext, markSideEffect?: ((ctx: DomRenderTagContext, k: string, fn: () => void) => void) | undefined) => void;
|
|
25
34
|
|
|
26
|
-
export { RenderDomHeadOptions, debouncedRenderDOMHead, domUpdatePromise,
|
|
35
|
+
export { PatchDomOnEntryUpdatesPlugin, RenderDomHeadOptions, TriggerDomPatchingOnUpdatesPluginOptions, debouncedRenderDOMHead, domUpdatePromise, renderDOMHead, setAttrs };
|
package/dist/index.mjs
CHANGED
|
@@ -1,35 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const HasElementTags = [
|
|
3
|
-
"base",
|
|
4
|
-
"meta",
|
|
5
|
-
"link",
|
|
6
|
-
"style",
|
|
7
|
-
"script",
|
|
8
|
-
"noscript"
|
|
9
|
-
];
|
|
10
|
-
|
|
11
|
-
const UniqueTags = ["base", "title", "titleTemplate", "bodyAttrs", "htmlAttrs"];
|
|
12
|
-
function tagDedupeKey(tag, fn) {
|
|
13
|
-
const { props, tag: tagName } = tag;
|
|
14
|
-
if (UniqueTags.includes(tagName))
|
|
15
|
-
return tagName;
|
|
16
|
-
if (tagName === "link" && props.rel === "canonical")
|
|
17
|
-
return "canonical";
|
|
18
|
-
if (props.charset)
|
|
19
|
-
return "charset";
|
|
20
|
-
const name = ["id"];
|
|
21
|
-
if (tagName === "meta")
|
|
22
|
-
name.push(...["name", "property", "http-equiv"]);
|
|
23
|
-
for (const n of name) {
|
|
24
|
-
if (typeof props[n] !== "undefined") {
|
|
25
|
-
const val = String(props[n]);
|
|
26
|
-
if (fn && !fn(val))
|
|
27
|
-
return false;
|
|
28
|
-
return `${tagName}:${n}:${val}`;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
1
|
+
import { TagsWithInnerContent, HasElementTags, tagDedupeKey, hashCode, defineHeadPlugin } from '@unhead/shared';
|
|
33
2
|
|
|
34
3
|
const setAttrs = (ctx, markSideEffect) => {
|
|
35
4
|
const { tag, $el } = ctx;
|
|
@@ -59,13 +28,6 @@ const setAttrs = (ctx, markSideEffect) => {
|
|
|
59
28
|
$el.innerHTML = tag.children || "";
|
|
60
29
|
};
|
|
61
30
|
|
|
62
|
-
function hashCode(s) {
|
|
63
|
-
let h = 9;
|
|
64
|
-
for (let i = 0; i < s.length; )
|
|
65
|
-
h = Math.imul(h ^ s.charCodeAt(i++), 9 ** 9);
|
|
66
|
-
return ((h ^ h >>> 9) + 65536).toString(16).substring(1, 8).toLowerCase();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
31
|
async function renderDOMHead(head, options = {}) {
|
|
70
32
|
const ctx = { shouldRender: true };
|
|
71
33
|
await head.hooks.callHook("dom:beforeRender", ctx);
|
|
@@ -78,7 +40,7 @@ async function renderDOMHead(head, options = {}) {
|
|
|
78
40
|
staleSideEffects[key] = fn;
|
|
79
41
|
});
|
|
80
42
|
});
|
|
81
|
-
const
|
|
43
|
+
const setupTagRenderCtx = async (tag) => {
|
|
82
44
|
const entry = head.headEntries().find((e) => e._i === tag._e);
|
|
83
45
|
const renderCtx = {
|
|
84
46
|
renderId: tag._d || hashCode(JSON.stringify({ ...tag, _e: void 0, _p: void 0 })),
|
|
@@ -111,7 +73,7 @@ async function renderDOMHead(head, options = {}) {
|
|
|
111
73
|
});
|
|
112
74
|
};
|
|
113
75
|
for (const t of await head.resolveTags()) {
|
|
114
|
-
const ctx2 = await
|
|
76
|
+
const ctx2 = await setupTagRenderCtx(t);
|
|
115
77
|
if (!ctx2.shouldRender)
|
|
116
78
|
continue;
|
|
117
79
|
const { tag } = ctx2;
|
|
@@ -140,6 +102,11 @@ async function renderDOMHead(head, options = {}) {
|
|
|
140
102
|
setAttrs(ctx2);
|
|
141
103
|
pendingRenders[tag.tagPosition?.startsWith("body") ? "body" : "head"].push(ctx2);
|
|
142
104
|
}
|
|
105
|
+
const fragments = {
|
|
106
|
+
bodyClose: void 0,
|
|
107
|
+
bodyOpen: void 0,
|
|
108
|
+
head: void 0
|
|
109
|
+
};
|
|
143
110
|
Object.entries(pendingRenders).forEach(([pos, queue]) => {
|
|
144
111
|
if (!queue.length)
|
|
145
112
|
return;
|
|
@@ -165,23 +132,18 @@ async function renderDOMHead(head, options = {}) {
|
|
|
165
132
|
}
|
|
166
133
|
}
|
|
167
134
|
queue.forEach((ctx2) => {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
case "bodyClose":
|
|
172
|
-
dom.body.appendChild(ctx2.$el);
|
|
173
|
-
break;
|
|
174
|
-
case "bodyOpen":
|
|
175
|
-
dom.body.insertBefore(ctx2.$el, dom.body.firstChild);
|
|
176
|
-
break;
|
|
177
|
-
case "head":
|
|
178
|
-
default:
|
|
179
|
-
dom.head.appendChild(ctx2.$el);
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
135
|
+
const pos2 = ctx2.tag.tagPosition || "head";
|
|
136
|
+
fragments[pos2] = fragments[pos2] || dom.createDocumentFragment();
|
|
137
|
+
fragments[pos2].appendChild(ctx2.$el);
|
|
182
138
|
markEl(ctx2);
|
|
183
139
|
});
|
|
184
140
|
});
|
|
141
|
+
if (fragments.head)
|
|
142
|
+
dom.head.appendChild(fragments.head);
|
|
143
|
+
if (fragments.bodyOpen)
|
|
144
|
+
dom.body.insertBefore(fragments.bodyOpen, dom.body.firstChild);
|
|
145
|
+
if (fragments.bodyClose)
|
|
146
|
+
dom.body.appendChild(fragments.bodyClose);
|
|
185
147
|
for (const ctx2 of renders)
|
|
186
148
|
await head.hooks.callHook("dom:renderTag", ctx2);
|
|
187
149
|
Object.values(staleSideEffects).forEach((fn) => fn());
|
|
@@ -196,4 +158,19 @@ async function debouncedRenderDOMHead(head, options = {}) {
|
|
|
196
158
|
return domUpdatePromise = domUpdatePromise || new Promise((resolve) => delayFn(() => resolve(doDomUpdate())));
|
|
197
159
|
}
|
|
198
160
|
|
|
199
|
-
|
|
161
|
+
const PatchDomOnEntryUpdatesPlugin = (options) => {
|
|
162
|
+
return defineHeadPlugin({
|
|
163
|
+
hooks: {
|
|
164
|
+
"entries:updated": function(head) {
|
|
165
|
+
if (typeof options?.document === "undefined" && typeof window === "undefined")
|
|
166
|
+
return;
|
|
167
|
+
let delayFn = options?.delayFn;
|
|
168
|
+
if (!delayFn && typeof requestAnimationFrame !== "undefined")
|
|
169
|
+
delayFn = requestAnimationFrame;
|
|
170
|
+
debouncedRenderDOMHead(head, { document: options?.document || window.document, delayFn });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export { PatchDomOnEntryUpdatesPlugin, debouncedRenderDOMHead, domUpdatePromise, renderDOMHead, setAttrs };
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unhead/dom",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
5
|
-
"packageManager": "pnpm@7.
|
|
4
|
+
"version": "1.0.22",
|
|
5
|
+
"packageManager": "pnpm@7.26.3",
|
|
6
6
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"funding": "https://github.com/sponsors/harlan-zw",
|
|
9
|
-
"homepage": "https://
|
|
9
|
+
"homepage": "https://unhead.harlanzw.com",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/
|
|
12
|
+
"url": "git+https://github.com/unjs/unhead.git",
|
|
13
13
|
"directory": "packages/dom"
|
|
14
14
|
},
|
|
15
15
|
"bugs": {
|
|
16
|
-
"url": "https://github.com/
|
|
16
|
+
"url": "https://github.com/unjs/unhead/issues"
|
|
17
17
|
},
|
|
18
18
|
"sideEffects": false,
|
|
19
19
|
"exports": {
|
|
@@ -30,10 +30,8 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@unhead/schema": "1.0.
|
|
34
|
-
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"zhead": "^1.1.0"
|
|
33
|
+
"@unhead/schema": "1.0.22",
|
|
34
|
+
"@unhead/shared": "1.0.22"
|
|
37
35
|
},
|
|
38
36
|
"scripts": {
|
|
39
37
|
"build": "unbuild .",
|