L’hook page:fragments fornisce script o HTML grezzo all’head o al body di una pagina pubblica renderizzata. Usalo per codice del browser che i metadati strutturati non possono esprimere, come un loader di analytics con un fallback <noscript>.
L’output dei frammenti viene eseguito come codice di prima parte della pagina. EmDash richiama questo hook solo per plugin attendibili in-process; i plugin sandboxed non contribuiscono mai con frammenti. Se la pagina necessita di meta tag, link canonical o alternate, o JSON-LD, usa invece l’hook page:metadata compatibile con sandbox.
Dichiarare la capability e l’hook
page:fragments richiede hooks.page-fragments:register nella definizione del runtime nativo. L’hook seguente aggiunge uno script esterno e un fallback HTML solo quando esiste un ID analytics configurato:
return definePlugin({
id: "plugin-analytics",
version: "0.1.0",
capabilities: ["hooks.page-fragments:register"],
hooks: {
"page:fragments": async (event, ctx) => {
const analyticsId = await ctx.settings.get<string>("analyticsId");
if (!analyticsId || event.page.path.startsWith("/_emdash/")) return null;
const encodedId = encodeURIComponent(analyticsId);
return [
{
kind: "external-script",
placement: "head",
src: `https://analytics.example.com/client.js?id=${encodedId}`,
async: true,
key: "analytics-client",
},
{
kind: "html",
placement: "body:end",
html: "<noscript>Analytics requires JavaScript.</noscript>",
key: "analytics-fallback",
},
];
},
},
});
I contributi HTML grezzo vengono inseriti così come sono. Mantieni il frammento statico quando possibile; altrimenti esegui l’escape di ogni valore che può provenire da impostazioni, contenuto, dati della richiesta o un servizio esterno.
Per i plugin nativi, dichiara la capability in definePlugin(). Il descrittore non necessita di una seconda copia perché createPlugin() fornisce l’elenco delle capability del runtime.
Se la capability manca, EmDash registra un avviso e non registra l’hook. Gli errori dell’hook vengono registrati e non impediscono il rendering della pagina.
Aggiungere i punti di inserimento del layout
Il tema host sceglie quali placement supporta. Deve passare lo stesso PublicPageContext ai componenti EmDash corrispondenti:
-
Costruisci il contesto della pagina una volta nel layout.
--- import { createPublicPageContext } from "emdash/page"; import { EmDashBodyEnd, EmDashBodyStart, EmDashHead, } from "emdash/ui"; interface Props { title: string; description?: string; content?: { collection: string; id: string; slug?: string | null }; } const { title, description, content } = Astro.props; const page = createPublicPageContext({ Astro, kind: content ? "content" : "custom", pageType: content ? "article" : "website", title, description, content, }); --- -
Renderizza ogni placement supportato nella parte corrispondente del documento.
<html lang="en"> <head> <title>{title}</title> <EmDashHead page={page} /> </head> <body> <EmDashBodyStart page={page} /> <slot /> <EmDashBodyEnd page={page} /> </body> </html>
EmDashHead renderizza i frammenti head nonché i metadati EmDash e dei plugin. EmDashBodyStart renderizza i frammenti body:start subito dopo il <body> di apertura, e EmDashBodyEnd renderizza i frammenti body:end dopo il contenuto della pagina. Un tema che omette un componente non renderizza frammenti per quel placement. Documenta qualsiasi punto di inserimento richiesto nel README del plugin.
Riferimento dei contributi
Un hook può restituire un contributo, un array o null. Le forme di contributo supportate sono:
kind | Campi obbligatori | Campi facoltativi | Comportamento dell’output |
|---|---|---|---|
external-script | placement, src | async, defer, attributes, key | Renderizza un elemento <script src="…">. |
inline-script | placement, code | attributes, key | Renderizza code dentro un elemento <script>. |
html | placement, html | key | Inserisce html senza sanitizzarlo. |
placement accetta head, body:start o body:end.
EmDash esegue l’escape HTML dei nomi e dei valori degli attributi e rimuove gli attributi i cui nomi iniziano con on. Per gli script inline, esegue l’escape di </ così un valore non può chiudere l’elemento script. Questi controlli del renderer non rendono sicuro HTML o JavaScript non attendibili; il plugin deve comunque codificare i dati interpolati per il linguaggio e il contesto in cui vengono inseriti.
L’hook seguente colloca in modo sicuro un valore JSON in uno script inline:
"page:fragments": async (event) => {
if (event.page.kind !== "content" || !event.page.content) return null;
return {
kind: "inline-script",
placement: "body:start",
code: `window.currentContent = ${JSON.stringify({
collection: event.page.content.collection,
id: event.page.content.id,
})};`,
key: "current-content",
};
},
All’interno di un placement, i contributi con la stessa key mantengono il primo valore. Gli script esterni senza chiave vengono anche deduplicati per src. Usa una chiave stabile quando due hook potrebbero descrivere lo stesso frammento logico.
Riferimento del contesto di pagina
L’hook riceve { page }. L’oggetto page proviene dal layout host, con valori opzionali del pannello SEO sovrapposti per una voce di contenuto caricata durante la richiesta.
| Campo | Tipo e significato |
|---|---|
url | URL assoluto della pagina. |
path | Pathname dell’URL. |
locale | Locale attivo, o null. |
kind | content per una voce EmDash o custom per un’altra pagina. |
pageType | Tipo definito dal tema, di solito article o website. |
title, pageTitle | Titolo completo del documento e titolo opzionale solo della pagina. |
description, canonical, image | Valori dei metadati di pagina, ciascuno nullable. |
content | Riferimento opzionale { collection, id, slug } della voce renderizzata. |
seo | Override opzionali di titolo, descrizione, immagine e robots Open Graph. |
articleMeta | Ora di pubblicazione, ora di modifica e autore opzionali. |
siteName, siteUrl | Identità pubblica opzionale del sito e origin. |
breadcrumbs | Elementi opzionali root-first { name, url }. Un array vuoto significa esplicitamente nessun breadcrumb. |
Usa kind, pageType, path, locale o content per limitare dove compare un frammento. Non recuperare di nuovo una voce quando il contesto della pagina porta già l’identità necessaria per la decisione.
Preferire i metadati strutturati quando possibile
Usa page:metadata per il seguente output:
- tag
<meta name="…">e<meta property="…"> - link canonical, alternate, author, license,
nlwebesite.standard.document - grafi JSON-LD
page:metadata convalida i suoi contributi strutturati, li deduplica con i metadati di base della pagina e funziona nei plugin nativi e sandboxed. Usa page:fragments quando il browser deve ricevere codice eseguibile o markup che l’hook strutturato non può rappresentare.