Schreibe dein eigenes lokales Plugin
Du musst nicht auf npm veröffentlichen, um Nera zu erweitern. Jedes Modul unter
src/plugins/<name>/index.js wird automatisch erkannt und angewendet. Bauen wir
ein echtes: ein Plugin, das jedes Tutorial in einer Liste für eine Indexseite
sammelt — genau das Plugin, das diese Seite antreibt.
Der Vertrag
Ein Plugin exportiert einen oder beide von zwei Hooks:
export function getAppData({ app, pagesData }) {
// must return a plain object — becomes the new `app`
}
export function getMetaData({ app, pagesData }) {
// must return an array — becomes the new `pagesData`
}
getAppData läuft zuerst; getMetaData sieht die app, die es zurückgegeben hat.
Halte sie synchron — ein asynchroner Hook kann app auf älteren
Generator-Versionen stillschweigend auslöschen.
Baue es
Erstelle src/plugins/tutorials-list/index.js:
export function getAppData({ app, pagesData }) {
if (!app || typeof app !== 'object') return app
if (!Array.isArray(pagesData)) return app
const tutorials = pagesData
.filter(({ meta }) => {
const href = meta?.href || ''
return href.startsWith('/tutorials/') && href !== '/tutorials/index.html'
})
.map(({ meta }) => ({
href: meta.href,
title: meta.title || meta.href,
description: meta.description || '',
createdAt: meta.createdAt,
}))
.sort((a, b) => {
const da = new Date(a.createdAt).getTime()
const db = new Date(b.createdAt).getTime()
if (!Number.isNaN(da) && !Number.isNaN(db) && da !== db) return db - da
return String(a.href).localeCompare(String(b.href))
})
return { ...app, tutorials }
}
Das ist das ganze Plugin. Es liest jede Seite, behält die unter /tutorials/ und
gibt eine neue app mit einem sortierten tutorials-Array zurück.
Verwende es in einem Layout
app.tutorials ist jetzt in jeder View verfügbar:
if app.tutorials && app.tutorials.length
ul.tutorials__list
each post in app.tutorials
li.tutorials__item
a.tutorials__link(href=post.href)
h2 #{ post.title }
p #{ post.description }
Warum ein neues Objekt zurückgeben
Nera reicht den Rückgabewert jedes Hooks in den nächsten weiter. { ...app, tutorials }
zurückzugeben (statt app zu mutieren) hält diesen Datenfluss vorhersehbar — aus
demselben Grund tun es die eingebauten Plugins. Von hier aus baut dasselbe Muster
Listen verwandter Beiträge, Autorenseiten, „kürzlich aktualisiert“-Widgets — alles,
was aus deinem Inhalt abgeleitet ist.