@nextwebwg/htmlkit 1.0.0-alpha.40 → 1.0.0-alpha.42
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/README.md +21 -12
- package/components/breadcrumbs.html +9 -0
- package/components/{navigation.html → nav.html} +2 -2
- package/components/pager.html +13 -0
- package/dist/application.d.ts +10 -2
- package/dist/application.d.ts.map +1 -1
- package/dist/application.js +148 -45
- package/dist/application.js.map +1 -1
- package/dist/browser.d.ts +3 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +23 -22
- package/dist/browser.js.map +1 -1
- package/dist/build.d.ts +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +25 -10
- package/dist/build.js.map +1 -1
- package/dist/bundle-worker.js +2 -1
- package/dist/bundle-worker.js.map +1 -1
- package/dist/client.d.ts +32 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +322 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -1
- package/dist/config.js.map +1 -1
- package/dist/document.d.ts +30 -2
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +41 -6
- package/dist/document.js.map +1 -1
- package/dist/head.d.ts.map +1 -1
- package/dist/head.js +7 -5
- package/dist/head.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/resource.d.ts +11 -5
- package/dist/resource.d.ts.map +1 -1
- package/dist/resource.js +32 -12
- package/dist/resource.js.map +1 -1
- package/dist/routes.d.ts +12 -1
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +135 -41
- package/dist/routes.js.map +1 -1
- package/dist/serve.d.ts +2 -2
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +48 -30
- package/dist/serve.js.map +1 -1
- package/dist/types.d.ts +82 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/client.js
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
const definitions = new Map();
|
|
2
|
+
const controllers = {};
|
|
3
|
+
const styleStates = {};
|
|
4
|
+
const compiledStyles = (_css, definition) => ({ css: "", stateNames: styleStates[definition.contract.tag] ?? [] });
|
|
5
|
+
let started = false;
|
|
6
|
+
/** Each page module calls this once, when it is first imported. */
|
|
7
|
+
export function page(runtime, options, pageDefinitions, pageControllers, pageStyleStates) {
|
|
8
|
+
// A document keeps one definition and controller per tag (HTML Next's HR001). A page that
|
|
9
|
+
// redefines a tag fails here, before its DOM is inserted, and loads as a document instead.
|
|
10
|
+
for (const [tag, controller] of Object.entries(pageControllers)) {
|
|
11
|
+
if ((controllers[tag] ?? controller) !== controller)
|
|
12
|
+
throw new Error(`HTMLKit: <${tag}> already has another controller in this document.`);
|
|
13
|
+
}
|
|
14
|
+
Object.assign(styleStates, pageStyleStates);
|
|
15
|
+
runtime.registerComponentDefinitions(pageDefinitions, document, compiledStyles);
|
|
16
|
+
for (const definition of pageDefinitions)
|
|
17
|
+
definitions.set(definition.contract.tag, definition);
|
|
18
|
+
Object.assign(controllers, pageControllers);
|
|
19
|
+
if (started)
|
|
20
|
+
return;
|
|
21
|
+
started = true;
|
|
22
|
+
const initialized = new WeakSet();
|
|
23
|
+
runtime.observeDocument(document, { onConnect(element, definition) {
|
|
24
|
+
const controller = controllers[definition.contract.tag];
|
|
25
|
+
if (!controller)
|
|
26
|
+
return;
|
|
27
|
+
if (typeof controller.default !== "function")
|
|
28
|
+
throw new Error(`Controller for ${definition.contract.tag} must export a default function`);
|
|
29
|
+
const host = runtime.getComponentHost(element);
|
|
30
|
+
if (initialized.has(host))
|
|
31
|
+
return;
|
|
32
|
+
initialized.add(host);
|
|
33
|
+
return controller.default(host);
|
|
34
|
+
} });
|
|
35
|
+
// ponytail: links stay document navigations without NavigateEvent.sourceElement (Chrome 135, Firefox 147,
|
|
36
|
+
// Safari 26.2), which carries the per-link opt-outs; earlier Navigation API versions would skip them.
|
|
37
|
+
if ("navigation" in window && "sourceElement" in NavigateEvent.prototype)
|
|
38
|
+
navigate(runtime, options);
|
|
39
|
+
document.dispatchEvent(new Event("hk:ready"));
|
|
40
|
+
}
|
|
41
|
+
const layer = (root, index) => root.getElementById(`hk-layer-${index}`);
|
|
42
|
+
const fresh = (time) => performance.now() - time < 30_000;
|
|
43
|
+
const loaded = async (url, signal) => {
|
|
44
|
+
const response = await fetch(url, signal === undefined ? {} : { signal });
|
|
45
|
+
if (!response.ok || response.redirected)
|
|
46
|
+
throw new Error(`HTMLKit cannot load ${url} (${response.status}).`);
|
|
47
|
+
return response;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Renders a payload's layers as the server does (application.ts and HTML Next's server worker):
|
|
51
|
+
* the same invocations, lowered without connecting, with each loader's state, then serialized. The
|
|
52
|
+
* live document adopts the result as it adopts server HTML. Every layer renders, kept layouts
|
|
53
|
+
* included, so a page reads its layouts' context and kept layouts get their new props.
|
|
54
|
+
*/
|
|
55
|
+
async function render(runtime, payload, url) {
|
|
56
|
+
if (payload.version !== 1 || payload.layers.length === 0)
|
|
57
|
+
throw new Error("HTMLKit cannot read this page payload.");
|
|
58
|
+
const next = document.implementation.createHTMLDocument("");
|
|
59
|
+
const append = (parent, tag, attributes) => {
|
|
60
|
+
const element = parent.appendChild(next.createElement(tag));
|
|
61
|
+
for (const [name, value] of Object.entries(attributes))
|
|
62
|
+
element.setAttribute(name, value);
|
|
63
|
+
return element;
|
|
64
|
+
};
|
|
65
|
+
append(next.head, "base", { href: url.href });
|
|
66
|
+
for (const element of payload.head.elements)
|
|
67
|
+
append(next.head, element.tag, element.attributes);
|
|
68
|
+
if (payload.head.description !== undefined)
|
|
69
|
+
append(next.head, "meta", { name: "description", content: payload.head.description });
|
|
70
|
+
for (const href of payload.styles)
|
|
71
|
+
append(next.head, "link", { rel: "stylesheet", href });
|
|
72
|
+
for (const src of payload.modules)
|
|
73
|
+
append(next.head, "script", { type: "module", src });
|
|
74
|
+
runtime.registerComponentDefinitions([...definitions.values()], next, compiledStyles);
|
|
75
|
+
let parent = next.body;
|
|
76
|
+
payload.layers.forEach((layer, index) => {
|
|
77
|
+
parent = append(parent, layer.component, { id: `hk-layer-${index}`, ...index === 0 ? {} : { slot: "page" }, ...layer.attributes });
|
|
78
|
+
});
|
|
79
|
+
runtime.lowerDocument(next, { connect: false });
|
|
80
|
+
payload.layers.forEach(({ state }, index) => {
|
|
81
|
+
if (state === undefined)
|
|
82
|
+
return;
|
|
83
|
+
const root = layer(next, index);
|
|
84
|
+
const host = root === null ? undefined : runtime.getComponentHost(root);
|
|
85
|
+
if (host === undefined)
|
|
86
|
+
throw new Error(`HTMLKit cannot give layer ${index} its state.`);
|
|
87
|
+
Object.assign(host.state, state);
|
|
88
|
+
});
|
|
89
|
+
// As the server does: let structural updates settle, then lower what they added.
|
|
90
|
+
await new Promise(done => setTimeout(done));
|
|
91
|
+
runtime.lowerDocument(next, { connect: false });
|
|
92
|
+
next.body.innerHTML = runtime.serializeRenderedForm(next.body);
|
|
93
|
+
next.title = payload.head.title;
|
|
94
|
+
next.documentElement.lang = payload.head.lang;
|
|
95
|
+
return next;
|
|
96
|
+
}
|
|
97
|
+
function navigate(runtime, { base, prefetch: policy, manifest }) {
|
|
98
|
+
/** The pathname whose layers the document shows. A navigation's URL commits before its layers arrive. */
|
|
99
|
+
let rendered = location.pathname;
|
|
100
|
+
/** Head metadata from server documents. Elements that scripts add are never removed. */
|
|
101
|
+
let owned = [...document.head.querySelectorAll("meta, link")];
|
|
102
|
+
const announcer = document.createElement("div");
|
|
103
|
+
announcer.id = "hk-announcer";
|
|
104
|
+
announcer.setAttribute("aria-live", "polite");
|
|
105
|
+
announcer.setAttribute("aria-atomic", "true");
|
|
106
|
+
announcer.style.cssText = "position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap";
|
|
107
|
+
document.body.append(announcer);
|
|
108
|
+
/**
|
|
109
|
+
* Same-origin page URLs under base. Page URLs end in a slash; files and other sites load natively.
|
|
110
|
+
* Firefox 155 follows a download link's navigate event with a second one that has no downloadRequest.
|
|
111
|
+
*/
|
|
112
|
+
const local = (url, source) => url.origin === location.origin && url.pathname.startsWith(base) &&
|
|
113
|
+
url.pathname.endsWith("/") && !source?.closest("[data-hk-reload]") && !source?.hasAttribute("download");
|
|
114
|
+
const payloadURL = (url) => `${base}_htmlkit/pages/${url.pathname.slice(base.length)}payload.json`;
|
|
115
|
+
// Prefetching never runs anything: payloads are data, and modules and stylesheets are only hinted.
|
|
116
|
+
const hinted = new Set();
|
|
117
|
+
const hint = (rel, href) => {
|
|
118
|
+
if (hinted.has(href) || document.querySelector(`[src="${CSS.escape(href)}"], [href="${CSS.escape(href)}"]`) !== null)
|
|
119
|
+
return;
|
|
120
|
+
hinted.add(href);
|
|
121
|
+
const link = document.createElement("link");
|
|
122
|
+
link.rel = rel;
|
|
123
|
+
link.href = href;
|
|
124
|
+
document.head.append(link);
|
|
125
|
+
};
|
|
126
|
+
const prefetched = new Map();
|
|
127
|
+
const payloadOf = (url, signal) => loaded(payloadURL(url), signal).then(response => response.json());
|
|
128
|
+
/** The page an HTML link would visit in place, if any. An unparsable href is not a page. */
|
|
129
|
+
const target = (anchor) => {
|
|
130
|
+
const url = anchor instanceof HTMLAnchorElement ? URL.parse(anchor.href) : null;
|
|
131
|
+
return url !== null && local(url, anchor) && ["", "_self"].includes(anchor.target) && url.pathname !== rendered ? url : undefined;
|
|
132
|
+
};
|
|
133
|
+
const prefetchPage = (url) => {
|
|
134
|
+
const cached = prefetched.get(url.pathname);
|
|
135
|
+
if (cached !== undefined && fresh(cached.time))
|
|
136
|
+
return;
|
|
137
|
+
const payload = payloadOf(url);
|
|
138
|
+
prefetched.set(url.pathname, { time: performance.now(), payload });
|
|
139
|
+
payload.then(({ modules, styles }) => {
|
|
140
|
+
for (const src of modules)
|
|
141
|
+
hint("modulepreload", src);
|
|
142
|
+
for (const href of styles)
|
|
143
|
+
hint("prefetch", href);
|
|
144
|
+
}).catch(() => { prefetched.delete(url.pathname); });
|
|
145
|
+
};
|
|
146
|
+
// Links on screen prefetch only the shared chunks their page needs: a page's own module holds its
|
|
147
|
+
// content, so a long menu would otherwise download every page.
|
|
148
|
+
let chunks;
|
|
149
|
+
const prefetchShared = (url) => {
|
|
150
|
+
if (manifest === undefined)
|
|
151
|
+
return;
|
|
152
|
+
chunks ??= loaded(manifest).then(response => response.json())
|
|
153
|
+
.then((data) => new Map(data.pages.map(page => [page.pathname, page.chunks ?? []])))
|
|
154
|
+
.catch(() => new Map());
|
|
155
|
+
void chunks.then(map => { for (const src of map.get(url.pathname) ?? [])
|
|
156
|
+
hint("modulepreload", src); });
|
|
157
|
+
};
|
|
158
|
+
/** A link's policy: its own or an ancestor's data-hk-prefetch, else the site's. */
|
|
159
|
+
const mode = (anchor) => {
|
|
160
|
+
const value = anchor.closest("[data-hk-prefetch]")?.getAttribute("data-hk-prefetch");
|
|
161
|
+
return value === "interaction" || value === "visible" || value === "none" ? value : policy;
|
|
162
|
+
};
|
|
163
|
+
// Intent: touch at once; a link that keeps the pointer or focus briefly, so sweeping across a menu
|
|
164
|
+
// or tabbing through it fetches nothing.
|
|
165
|
+
let intended;
|
|
166
|
+
const intent = (event) => {
|
|
167
|
+
clearTimeout(intended);
|
|
168
|
+
const anchor = event.target instanceof Element ? event.target.closest("a[href]") : null;
|
|
169
|
+
const url = anchor !== null && mode(anchor) !== "none" ? target(anchor) : undefined;
|
|
170
|
+
if (url !== undefined)
|
|
171
|
+
intended = setTimeout(prefetchPage, event.type === "touchstart" ? 0 : 80, url);
|
|
172
|
+
};
|
|
173
|
+
document.addEventListener("pointerover", intent);
|
|
174
|
+
document.addEventListener("focusin", intent);
|
|
175
|
+
document.addEventListener("touchstart", intent, { passive: true });
|
|
176
|
+
// At idle, or within 2 s on a busy page; a timer where requestIdleCallback is missing.
|
|
177
|
+
const idle = (run) => "requestIdleCallback" in window ? requestIdleCallback(run, { timeout: 2000 }) : setTimeout(run, 1);
|
|
178
|
+
const visible = new IntersectionObserver(entries => {
|
|
179
|
+
for (const { isIntersecting, target: anchor } of entries) {
|
|
180
|
+
if (!isIntersecting)
|
|
181
|
+
continue;
|
|
182
|
+
visible.unobserve(anchor);
|
|
183
|
+
const url = target(anchor);
|
|
184
|
+
const policy = mode(anchor);
|
|
185
|
+
if (url !== undefined && policy !== "none")
|
|
186
|
+
idle(() => (policy === "visible" ? prefetchPage : prefetchShared)(url));
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
// ponytail: links that controllers add later are not watched; they still prefetch on interaction.
|
|
190
|
+
const watch = () => { for (const anchor of document.querySelectorAll("a[href]"))
|
|
191
|
+
visible.observe(anchor); };
|
|
192
|
+
watch();
|
|
193
|
+
const html = async (url, signal) => {
|
|
194
|
+
const response = await loaded(url.pathname + url.search, signal);
|
|
195
|
+
if (!response.headers.get("content-type")?.startsWith("text/html"))
|
|
196
|
+
throw new Error(`HTMLKit cannot render ${url.href} in place.`);
|
|
197
|
+
return new DOMParser().parseFromString(await response.text(), "text/html");
|
|
198
|
+
};
|
|
199
|
+
const payload = async (url, signal) => {
|
|
200
|
+
const cached = prefetched.get(url.pathname);
|
|
201
|
+
prefetched.delete(url.pathname);
|
|
202
|
+
const data = await (cached !== undefined && fresh(cached.time) ? cached.payload : payloadOf(url, signal));
|
|
203
|
+
// The page's module registers its definitions before anything renders. An absolute URL is the
|
|
204
|
+
// module's identity everywhere: Vite's development server adds ?import to a path, a second URL.
|
|
205
|
+
await Promise.all(data.modules.map(src => import(/* @vite-ignore */ new URL(src, location.href).href)));
|
|
206
|
+
signal.throwIfAborted();
|
|
207
|
+
return render(runtime, data, url);
|
|
208
|
+
};
|
|
209
|
+
const visit = async (url, event) => {
|
|
210
|
+
const { signal } = event;
|
|
211
|
+
const sheets = [];
|
|
212
|
+
let committed = false;
|
|
213
|
+
clearTimeout(intended);
|
|
214
|
+
try {
|
|
215
|
+
// The payload carries data, not markup; a page it cannot render loads from its HTML.
|
|
216
|
+
const next = await payload(url, signal).catch(error => {
|
|
217
|
+
if (signal.aborted)
|
|
218
|
+
throw error;
|
|
219
|
+
console.warn("HTMLKit renders this page from its HTML:", error);
|
|
220
|
+
return html(url, signal);
|
|
221
|
+
});
|
|
222
|
+
if (layer(next, 0) === null || layer(document, 0) === null)
|
|
223
|
+
throw new Error(`HTMLKit cannot render ${url.href} in place: it has no layers.`);
|
|
224
|
+
// Head metadata both documents share stays; the rest is removed or added at the swap.
|
|
225
|
+
const kept = new Set();
|
|
226
|
+
const added = [];
|
|
227
|
+
for (const element of next.head.querySelectorAll("meta, link")) {
|
|
228
|
+
const same = owned.find(candidate => !kept.has(candidate) && candidate.isEqualNode(element));
|
|
229
|
+
if (same === undefined)
|
|
230
|
+
added.push(element);
|
|
231
|
+
else
|
|
232
|
+
kept.add(same);
|
|
233
|
+
}
|
|
234
|
+
// New stylesheets load before the swap, so the next page never paints unstyled. Component styles
|
|
235
|
+
// are scoped, so only the next page's global rules apply to this one meanwhile.
|
|
236
|
+
for (const element of added)
|
|
237
|
+
if (element instanceof HTMLLinkElement && element.relList.contains("stylesheet"))
|
|
238
|
+
sheets.push(element);
|
|
239
|
+
const loading = sheets.map(sheet => new Promise(done => { sheet.addEventListener("load", done); sheet.addEventListener("error", done); }));
|
|
240
|
+
document.head.append(...sheets);
|
|
241
|
+
// The next page's components register before its DOM arrives; a conflicting one falls back below.
|
|
242
|
+
const modules = [...next.head.querySelectorAll('script[type="module"][src]')].map(script => import(/* @vite-ignore */ script.src));
|
|
243
|
+
await Promise.all([...loading, ...modules]);
|
|
244
|
+
const commit = () => {
|
|
245
|
+
signal.throwIfAborted();
|
|
246
|
+
committed = true;
|
|
247
|
+
for (const element of owned)
|
|
248
|
+
if (!kept.has(element))
|
|
249
|
+
element.remove();
|
|
250
|
+
document.head.append(...added.filter(element => !sheets.includes(element)));
|
|
251
|
+
owned = [...kept, ...added];
|
|
252
|
+
document.title = next.title;
|
|
253
|
+
document.documentElement.lang = next.documentElement.lang;
|
|
254
|
+
// Layouts persist while each depth renders the same component: they keep their DOM, state,
|
|
255
|
+
// and controllers, and take the new rendering's props. The page layer is always replaced.
|
|
256
|
+
let index = 0;
|
|
257
|
+
let incoming = layer(next, 0);
|
|
258
|
+
let deeper = layer(next, 1);
|
|
259
|
+
while (deeper !== null && layer(document, index)?.getAttribute("data-component") === incoming.getAttribute("data-component")) {
|
|
260
|
+
runtime.adoptRenderedProps(layer(document, index), incoming);
|
|
261
|
+
incoming = deeper;
|
|
262
|
+
deeper = layer(next, ++index + 1);
|
|
263
|
+
}
|
|
264
|
+
// A page sits in its layout's slot; the layout projects the new page as it did the old one.
|
|
265
|
+
runtime.replaceProjectedNode(layer(document, index), incoming);
|
|
266
|
+
rendered = url.pathname;
|
|
267
|
+
announcer.textContent = document.title;
|
|
268
|
+
watch();
|
|
269
|
+
};
|
|
270
|
+
signal.throwIfAborted();
|
|
271
|
+
if (typeof document.startViewTransition !== "function" || !transitions(document.styleSheets))
|
|
272
|
+
commit();
|
|
273
|
+
else
|
|
274
|
+
await document.startViewTransition(commit).updateCallbackDone;
|
|
275
|
+
const saved = event.navigationType === "traverse" ? positions.get(event.destination.key) : undefined;
|
|
276
|
+
if (saved === undefined)
|
|
277
|
+
event.scroll();
|
|
278
|
+
else
|
|
279
|
+
scrollTo(...saved);
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
if (!committed)
|
|
283
|
+
for (const sheet of sheets)
|
|
284
|
+
sheet.remove();
|
|
285
|
+
if (signal.aborted)
|
|
286
|
+
return;
|
|
287
|
+
// Anything this document cannot render in place loads as a document instead.
|
|
288
|
+
console.error(error);
|
|
289
|
+
location.reload();
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
// ponytail: WebKit 26.6 sometimes restores no position for an intercepted back or forward
|
|
293
|
+
// navigation, so HTMLKit records where each entry was left. Other scrolling stays native.
|
|
294
|
+
const positions = new Map();
|
|
295
|
+
navigation.addEventListener("navigate", event => {
|
|
296
|
+
if (navigation.currentEntry !== null)
|
|
297
|
+
positions.set(navigation.currentEntry.key, [scrollX, scrollY]);
|
|
298
|
+
const url = new URL(event.destination.url);
|
|
299
|
+
// Reloads, downloads, form posts, fragment and history.pushState changes, and other documents
|
|
300
|
+
// stay native. Modified clicks and link targets open other browsing contexts without this event.
|
|
301
|
+
if (!event.canIntercept || event.navigationType === "reload" || event.downloadRequest !== null || event.formData !== null ||
|
|
302
|
+
!local(url, event.sourceElement) || event.destination.sameDocument && (event.navigationType !== "traverse" || url.pathname === rendered))
|
|
303
|
+
return;
|
|
304
|
+
// After the swap, a new entry scrolls to its fragment or the top, back and forward return to
|
|
305
|
+
// where the entry was left, and focus resets as after a document load.
|
|
306
|
+
event.intercept({ scroll: "manual", handler: () => visit(url, event) });
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/** Authors animate navigation with @view-transition { navigation: auto }, as for document navigation. */
|
|
310
|
+
function transitions(rules) {
|
|
311
|
+
return Array.prototype.some.call(rules, (rule) => {
|
|
312
|
+
try {
|
|
313
|
+
return rule instanceof CSSStyleSheet ? transitions(rule.cssRules) :
|
|
314
|
+
typeof CSSViewTransitionRule === "function" && rule instanceof CSSViewTransitionRule ? rule.navigation === "auto" :
|
|
315
|
+
rule instanceof CSSGroupingRule && (!(rule instanceof CSSMediaRule) || matchMedia(rule.conditionText).matches) && transitions(rule.cssRules);
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
return false;
|
|
319
|
+
} // A cross-origin stylesheet hides its rules.
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -9,5 +9,15 @@ export declare function configure(options: ApplicationOptions): {
|
|
|
9
9
|
base: string;
|
|
10
10
|
origin: string;
|
|
11
11
|
outDir: string;
|
|
12
|
+
prefetch: import("./types.js").PrefetchPolicy;
|
|
12
13
|
};
|
|
14
|
+
/** Merge each plugin's config() once; options already merged pass through, so nested entry points don't repeat hooks. */
|
|
15
|
+
export declare function withPlugins(options: ApplicationOptions): Promise<ApplicationOptions>;
|
|
16
|
+
/** Vite's side of the import map's @/ entry, for loaders, controllers, and stylesheets. */
|
|
17
|
+
export declare function rootAlias(root: string): {
|
|
18
|
+
find: RegExp;
|
|
19
|
+
replacement: string;
|
|
20
|
+
}[];
|
|
21
|
+
/** The application's global stylesheets as absolute paths. */
|
|
22
|
+
export declare function globalStylesheets(options: ApplicationOptions, root: string): readonly string[];
|
|
13
23
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,qBAAa,YAAa,SAAQ,KAAK;IACR,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IAArD,YAAY,OAAO,EAAE,MAAM,EAAW,MAAM,CAAC,EAAE,MAAM,YAAA,EAGpD;CACF;AACD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG7D;AACD,wBAAgB,SAAS,CAAC,OAAO,EAAE,kBAAkB;;;;;;EAkBpD;AAGD,yHAAyH;AACzH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAc1F;AAED,2FAA2F;AAC3F,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM;;;IAErC;AAED,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAE9F"}
|
package/dist/config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
2
|
+
import { normalizePath } from "vite";
|
|
2
3
|
export class HtmlKitError extends Error {
|
|
3
4
|
source;
|
|
4
5
|
constructor(message, source) {
|
|
@@ -12,6 +13,9 @@ export function within(parent, child) {
|
|
|
12
13
|
return path === "" || (!isAbsolute(path) && path !== ".." && !path.startsWith(`..${sep}`));
|
|
13
14
|
}
|
|
14
15
|
export function configure(options) {
|
|
16
|
+
// Removed with the always-on 01. ordering; name that rather than quietly move pages to /01-guide/.
|
|
17
|
+
if ("routeOrdering" in options)
|
|
18
|
+
throw new HtmlKitError("The routeOrdering option was removed: a number and a dot (01.guide/) always orders pages.");
|
|
15
19
|
const root = resolve(options.root ?? process.cwd());
|
|
16
20
|
const base = options.base ?? "/";
|
|
17
21
|
if (!/^\/(?:[A-Za-z0-9_-]+\/)*$/.test(base))
|
|
@@ -25,6 +29,35 @@ export function configure(options) {
|
|
|
25
29
|
if (within(outDir, root) || ["app", "src", "public", "node_modules", ".git"].some(path => within(resolve(root, path), outDir))) {
|
|
26
30
|
throw new HtmlKitError("Unsafe output directory; choose dist or a separate deployment directory.", outDir);
|
|
27
31
|
}
|
|
28
|
-
|
|
32
|
+
const prefetch = options.prefetch ?? "interaction";
|
|
33
|
+
if (!["interaction", "visible", "none"].includes(prefetch))
|
|
34
|
+
throw new HtmlKitError('prefetch must be "interaction", "visible", or "none".');
|
|
35
|
+
return { root, base, origin: origin.origin, outDir, prefetch };
|
|
36
|
+
}
|
|
37
|
+
const pluginsApplied = new WeakSet();
|
|
38
|
+
/** Merge each plugin's config() once; options already merged pass through, so nested entry points don't repeat hooks. */
|
|
39
|
+
export async function withPlugins(options) {
|
|
40
|
+
if (pluginsApplied.has(options) || options.plugins === undefined)
|
|
41
|
+
return options;
|
|
42
|
+
let merged = options;
|
|
43
|
+
for (const plugin of options.plugins) {
|
|
44
|
+
const added = await plugin.config?.(merged) ?? {};
|
|
45
|
+
// Page folders, stylesheets, and routes add to the application's own; app/pages stays the default folder.
|
|
46
|
+
merged = { ...merged, ...added, plugins: options.plugins,
|
|
47
|
+
...(added.pages === undefined ? {} : { pages: [...merged.pages ?? [{ dir: "app/pages", optional: true }], ...added.pages] }),
|
|
48
|
+
...(added.css === undefined ? {} : { css: [...merged.css ?? [], ...added.css] }),
|
|
49
|
+
...(added.routes === undefined ? {} : { routes: [...merged.routes ?? [], ...added.routes] }) };
|
|
50
|
+
}
|
|
51
|
+
merged = { ...merged };
|
|
52
|
+
pluginsApplied.add(merged);
|
|
53
|
+
return merged;
|
|
54
|
+
}
|
|
55
|
+
/** Vite's side of the import map's @/ entry, for loaders, controllers, and stylesheets. */
|
|
56
|
+
export function rootAlias(root) {
|
|
57
|
+
return [{ find: /^@\//, replacement: normalizePath(root) + "/" }];
|
|
58
|
+
}
|
|
59
|
+
/** The application's global stylesheets as absolute paths. */
|
|
60
|
+
export function globalStylesheets(options, root) {
|
|
61
|
+
return (options.css ?? []).map(path => resolve(root, path.startsWith("@/") ? path.slice(2) : path));
|
|
29
62
|
}
|
|
30
63
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAGrC,MAAM,OAAO,YAAa,SAAQ,KAAK;IACC,MAAM;IAA5C,YAAY,OAAe,EAAW,MAAe;QACnD,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;sBAD5B,MAAM;QAE1C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AACD,MAAM,UAAU,MAAM,CAAC,MAAc,EAAE,KAAa;IAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;AAC7F,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,OAA2B;IACnD,mGAAmG;IACnG,IAAI,eAAe,IAAI,OAAO;QAAE,MAAM,IAAI,YAAY,CAAC,2FAA2F,CAAC,CAAC;IACpJ,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC;IACjC,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,YAAY,CAAC,0EAA0E,CAAC,CAAC;IAChJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,kBAAkB,CAAC,CAAC;IAC7D,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QACxI,MAAM,IAAI,YAAY,CAAC,mFAAmF,CAAC,CAAC;IAC9G,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;IACvD,gFAAgF;IAChF,IAAI,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;QAC/H,MAAM,IAAI,YAAY,CAAC,0EAA0E,EAAE,MAAM,CAAC,CAAC;IAC7G,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,aAAa,CAAC;IACnD,IAAI,CAAC,CAAC,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,YAAY,CAAC,uDAAuD,CAAC,CAAC;IAC5I,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,OAAO,EAAsB,CAAC;AACzD,yHAAyH;AACzH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACjF,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAClD,0GAA0G;QAC1G,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO;YACtD,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5H,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,EAAE,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YAChF,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IACnG,CAAC;IACD,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,iBAAiB,CAAC,OAA2B,EAAE,IAAY;IACzE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACtG,CAAC"}
|
package/dist/document.d.ts
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
|
-
import type { HeadElement, RenderedHead } from "./types.js";
|
|
1
|
+
import type { HeadElement, RenderedHead, RenderedPage } from "./types.js";
|
|
2
2
|
export declare const defaultHeadElements: readonly HeadElement[];
|
|
3
|
+
/** A page's browser delivery: stylesheet and module URLs, which the serving adapter supplies. */
|
|
4
|
+
export interface PageAssets {
|
|
5
|
+
readonly styles: readonly string[];
|
|
6
|
+
readonly modules: readonly string[];
|
|
7
|
+
}
|
|
3
8
|
export declare function escapeHTML(value: string): string;
|
|
4
|
-
export declare function documentHTML(body: string, head: RenderedHead, assets?:
|
|
9
|
+
export declare function documentHTML(body: string, head: RenderedHead, assets?: PageAssets): string;
|
|
10
|
+
/**
|
|
11
|
+
* A page's payload URL: its route path under the reserved _htmlkit/pages/ tree, which no route or
|
|
12
|
+
* public file may use, so it never collides with an application's own files.
|
|
13
|
+
*/
|
|
14
|
+
export declare function payloadPath(base: string, pathname: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* What the browser needs to render a page in place: the document's head, its delivery, and each
|
|
17
|
+
* layer's invocation and initial state, exactly as the server rendered them. The page's component
|
|
18
|
+
* definitions are in its module. Undefined when JSON cannot carry the state exactly; such a page
|
|
19
|
+
* navigates by its HTML instead.
|
|
20
|
+
*/
|
|
21
|
+
export declare function pagePayload(page: RenderedPage, assets: PageAssets): {
|
|
22
|
+
version: number;
|
|
23
|
+
head: {
|
|
24
|
+
lang: string;
|
|
25
|
+
title: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
elements: readonly HeadElement[];
|
|
28
|
+
};
|
|
29
|
+
styles: readonly string[];
|
|
30
|
+
modules: readonly string[];
|
|
31
|
+
layers: readonly import("./types.js").RenderedLayer[];
|
|
32
|
+
} | undefined;
|
|
5
33
|
//# sourceMappingURL=document.d.ts.map
|
package/dist/document.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1E,eAAO,MAAM,mBAAmB,EAAE,SAAS,WAAW,EAGrD,CAAC;AACF,iGAAiG;AACjG,MAAM,WAAW,UAAU;IAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AACvG,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AACD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,GAAE,UAAwC,GAAG,MAAM,CAavH;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElE;AAYD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU;;;;;;;;;;;cAKjE"}
|
package/dist/document.js
CHANGED
|
@@ -5,14 +5,49 @@ export const defaultHeadElements = [
|
|
|
5
5
|
export function escapeHTML(value) {
|
|
6
6
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
7
7
|
}
|
|
8
|
-
export function documentHTML(body, head, assets =
|
|
8
|
+
export function documentHTML(body, head, assets = { styles: [], modules: [] }) {
|
|
9
9
|
const elements = head.elements ?? defaultHeadElements;
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return `<!doctype html>\n<html lang="${escapeHTML(head.lang ?? "en")}"><head>${
|
|
10
|
+
const charset = elements.filter(element => element.tag === "meta" && element.attributes.charset !== undefined);
|
|
11
|
+
const html = (list) => list.map(element => `<${element.tag}${Object.entries(element.attributes).map(([name, value]) => ` ${name}="${escapeHTML(value)}"`).join("")}>`).join("");
|
|
12
|
+
// Head scripts precede stylesheets, which would otherwise delay it until they load.
|
|
13
|
+
return `<!doctype html>\n<html lang="${escapeHTML(head.lang ?? "en")}"><head>${html(charset)}` +
|
|
14
|
+
(head.scripts ?? []).map(script => `<script>${script}</script>`).join("") + html(elements.filter(element => !charset.includes(element))) +
|
|
14
15
|
`<title>${escapeHTML(head.title ?? "HTMLKit")}</title>` +
|
|
15
16
|
(head.description === undefined ? "" : `<meta name="description" content="${escapeHTML(head.description)}">`) +
|
|
16
|
-
|
|
17
|
+
assets.styles.map(href => `<link rel="stylesheet" href="${escapeHTML(href)}">`).join("") +
|
|
18
|
+
assets.modules.map(src => `<script type="module" src="${escapeHTML(src)}"></script>`).join("") +
|
|
19
|
+
`</head><body>${body}</body></html>`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A page's payload URL: its route path under the reserved _htmlkit/pages/ tree, which no route or
|
|
23
|
+
* public file may use, so it never collides with an application's own files.
|
|
24
|
+
*/
|
|
25
|
+
export function payloadPath(base, pathname) {
|
|
26
|
+
return `${base}_htmlkit/pages/${pathname.slice(base.length)}payload.json`;
|
|
27
|
+
}
|
|
28
|
+
/** Whether JSON carries a value exactly: no undefined, -0, non-finite numbers, or shared or opaque objects. */
|
|
29
|
+
function exact(value, seen) {
|
|
30
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
31
|
+
return true;
|
|
32
|
+
if (typeof value === "number")
|
|
33
|
+
return Number.isFinite(value) && !Object.is(value, -0);
|
|
34
|
+
if (typeof value !== "object" || seen.has(value) ||
|
|
35
|
+
!Array.isArray(value) && ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
|
|
36
|
+
return false;
|
|
37
|
+
seen.add(value);
|
|
38
|
+
return (Array.isArray(value) ? Array.from(value) : Object.values(value)).every(item => exact(item, seen));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* What the browser needs to render a page in place: the document's head, its delivery, and each
|
|
42
|
+
* layer's invocation and initial state, exactly as the server rendered them. The page's component
|
|
43
|
+
* definitions are in its module. Undefined when JSON cannot carry the state exactly; such a page
|
|
44
|
+
* navigates by its HTML instead.
|
|
45
|
+
*/
|
|
46
|
+
export function pagePayload(page, assets) {
|
|
47
|
+
if (page.status !== 200 || !page.layers.every(layer => layer.state === undefined || exact(layer.state, new Set())))
|
|
48
|
+
return undefined;
|
|
49
|
+
const { lang = "en", title = "HTMLKit", description, elements = defaultHeadElements } = page.head;
|
|
50
|
+
return { version: 1, head: { lang, title, ...(description === undefined ? {} : { description }), elements },
|
|
51
|
+
styles: assets.styles, modules: assets.modules, layers: page.layers };
|
|
17
52
|
}
|
|
18
53
|
//# sourceMappingURL=document.js.map
|
package/dist/document.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.js","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,mBAAmB,GAA2B;IACzD,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACjD,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,qCAAqC,EAAE,EAAE;CAClG,CAAC;
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,mBAAmB,GAA2B;IACzD,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACjD,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,qCAAqC,EAAE,EAAE;CAClG,CAAC;AAGF,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACjI,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,IAAkB,EAAE,MAAM,GAAe,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;IAC7G,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,mBAAmB,CAAC;IACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;IAC/G,MAAM,IAAI,GAAG,CAAC,IAA4B,EAAE,EAAE,CAC5C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,KAAK,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3J,oFAAoF;IACpF,OAAO,gCAAgC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5F,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACxI,UAAU,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,UAAU;QACvD,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qCAAqC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAC7G,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,gCAAgC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QACxF,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,8BAA8B,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9F,gBAAgB,IAAI,gBAAgB,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,QAAgB;IACxD,OAAO,GAAG,IAAI,kBAAkB,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;AAC5E,CAAC;AAED,+GAA+G;AAC/G,SAAS,KAAK,CAAC,KAAc,EAAE,IAAiB;IAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC3F,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IACtF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QAC9C,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1G,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAC5G,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAkB,EAAE,MAAkB;IAChE,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACrI,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,GAAG,SAAS,EAAE,WAAW,EAAE,QAAQ,GAAG,mBAAmB,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;IAClG,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE;QACzG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AAC1E,CAAC"}
|
package/dist/head.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../src/head.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAKhF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAe,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAiB1E,wBAAsB,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAChH,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EACzD,MAAM,EAAE,CAAC,UAAU,EAAE,mBAAmB,EAAE,MAAM,EAAE,YAAY,KAAK,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"head.d.ts","sourceRoot":"","sources":["../src/head.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAKhF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAe,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAiB1E,wBAAsB,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,EAAE,UAAU,EAAE,mBAAmB,EAChH,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EACzD,MAAM,EAAE,CAAC,UAAU,EAAE,mBAAmB,EAAE,MAAM,EAAE,YAAY,KAAK,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkDlG"}
|
package/dist/head.js
CHANGED
|
@@ -35,11 +35,11 @@ export async function renderHead(resource, definition, result, previous, url, in
|
|
|
35
35
|
for (const node of fragment.childNodes) {
|
|
36
36
|
if (!("tagName" in node))
|
|
37
37
|
continue;
|
|
38
|
-
node.attrs.push({ name: "data-
|
|
38
|
+
node.attrs.push({ name: "data-hk-head", value: node.tagName });
|
|
39
39
|
node.tagName = "span";
|
|
40
40
|
node.nodeName = "span";
|
|
41
41
|
}
|
|
42
|
-
const headDefinition = parseComponent(`<template component="
|
|
42
|
+
const headDefinition = parseComponent(`<template component="hk-head"><defs>${metadata.propDeclarations}</defs><div>${serialize(fragment)}</div></template>`, definition.source.file);
|
|
43
43
|
const rendered = await renderComponents(invoke(headDefinition, { props: result.props ?? {} }), { definitions: [headDefinition], url });
|
|
44
44
|
const root = parseFragment(rendered.html).childNodes.find(node => "tagName" in node);
|
|
45
45
|
if (root === undefined || !("childNodes" in root))
|
|
@@ -49,14 +49,14 @@ export async function renderHead(resource, definition, result, previous, url, in
|
|
|
49
49
|
for (const node of root.childNodes) {
|
|
50
50
|
if (!("tagName" in node))
|
|
51
51
|
continue;
|
|
52
|
-
const tag = node.attrs.find(attribute => attribute.name === "data-
|
|
52
|
+
const tag = node.attrs.find(attribute => attribute.name === "data-hk-head")?.value;
|
|
53
53
|
if (tag === "title") {
|
|
54
54
|
title = text(node);
|
|
55
55
|
continue;
|
|
56
56
|
}
|
|
57
57
|
if (tag !== "meta" && tag !== "link")
|
|
58
58
|
throw new HtmlKitError("Head content must render title, meta, or link elements.", definition.source.file);
|
|
59
|
-
const attributes = Object.fromEntries(node.attrs.filter(attribute => attribute.name !== "data-
|
|
59
|
+
const attributes = Object.fromEntries(node.attrs.filter(attribute => attribute.name !== "data-hk-head").map(attribute => [attribute.name, attribute.value]));
|
|
60
60
|
if (Object.keys(attributes).some(name => name.startsWith("on")) || (tag === "meta" && attributes["http-equiv"] !== undefined)) {
|
|
61
61
|
throw new HtmlKitError("Head metadata cannot activate event handlers or http-equiv policies.", definition.source.file);
|
|
62
62
|
}
|
|
@@ -82,7 +82,9 @@ export async function renderHead(resource, definition, result, previous, url, in
|
|
|
82
82
|
elements.splice(i, 1);
|
|
83
83
|
elements.push(...current);
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
// Only PageHead fields: an untyped loader's extra head keys must not reach the document assembler.
|
|
86
|
+
const loaded = Object.entries(result.head ?? {}).filter(([name]) => name === "title" || name === "description" || name === "lang");
|
|
87
|
+
return { ...previous, ...(title === undefined ? {} : { title }), ...(description === undefined ? {} : { description }), ...Object.fromEntries(loaded),
|
|
86
88
|
elements };
|
|
87
89
|
}
|
|
88
90
|
//# sourceMappingURL=head.js.map
|