Frammenti di pagina

In questa pagina

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:

  1. 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,
    });
    ---
  2. 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:

kindCampi obbligatoriCampi facoltativiComportamento dell’output
external-scriptplacement, srcasync, defer, attributes, keyRenderizza un elemento <script src="…">.
inline-scriptplacement, codeattributes, keyRenderizza code dentro un elemento <script>.
htmlplacement, htmlkeyInserisce 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.

CampoTipo e significato
urlURL assoluto della pagina.
pathPathname dell’URL.
localeLocale attivo, o null.
kindcontent per una voce EmDash o custom per un’altra pagina.
pageTypeTipo definito dal tema, di solito article o website.
title, pageTitleTitolo completo del documento e titolo opzionale solo della pagina.
description, canonical, imageValori dei metadati di pagina, ciascuno nullable.
contentRiferimento opzionale { collection, id, slug } della voce renderizzata.
seoOverride opzionali di titolo, descrizione, immagine e robots Open Graph.
articleMetaOra di pubblicazione, ora di modifica e autore opzionali.
siteName, siteUrlIdentità pubblica opzionale del sito e origin.
breadcrumbsElementi 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, nlweb e site.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.