Zum Inhalt springen
Docxcelerate

Nodes

Das Node-Modell

Was alle Nodes gemeinsam haben, worin sie sich unterscheiden und wo jeder von ihnen dokumentiert ist.

Ein Dokument ist ein Baum aus Nodes. Jeder Node ist drei Dinge: eine id, eine Art und eine Regel, die Inhalt erzeugt.

paragraph<MemberData>({
  id: "greeting",                                // the address
  render: (data) => `Dear ${data.memberName},`,  // the rule
});                                              // the helper is the kind

Gegen Ihre Daten aufgelöst, wird daraus reines JSON:

{ "id": "greeting", "kind": "paragraph", "mode": "static", "text": "Dear Adaeze Nkemelu," }

Kein Styling, kein Layout. Das gehört dem Renderer.

Der Katalog

Jeder Typ hat eine eigene Seite, mit jeder Option, die er annimmt, und einer Vorschau zu jeder Schreibweise.

Struktur

section Groups nodes under a titled heading.

The only construct that nests today. Its title carries into the document outline, so the structure you write is the structure the reader sees.

Helper: section, Section

export const Opening = section<SampleData>({ id: "opening", title: "Your renewal" }, [
  Greeting,
  PriceChange,
]);

Section-Referenz, mit Vorschauen →

tableOfContents A marker for a contents list, ahead of the renderers that build one. Noch kein Helper

The kind is part of the letter schema and both renderers accept it, but no authoring helper is exported yet. Writing the component by hand works — a node component is a function returning a definition, and the helpers are conveniences over exactly that shape.

export const Contents: NodeComponent<SampleData> = () => ({
  kind: "tableOfContents",
  id: "contents",
  title: "What is in this letter",
});

Table of contents-Referenz, mit Vorschauen →

Text

paragraph A block of prose, rendered from your data or from prompts.

The workhorse. A static paragraph returns a string from your typed data; a dynamic one carries prompts and a placeholder, and is filled at request time. Both land as the same node kind, differing only by `mode`.

export const Greeting = paragraph<SampleData>({
  id: "greeting",
  render: (data) => `Dear ${data.memberName},`,
});

Paragraph-Referenz, mit Vorschauen →

Medien

image A picture resolved from your data or described by a prompt.

A static image points at something you hold — a signature, a logo, a site photograph — with every field able to vary per recipient. A dynamic image describes what is wanted and leaves the endpoint to make it.

export const Signature = image<SampleData>({
  id: "signature",
  src: (data) => data.signatureUrl,
  alt: (data) => `Signed by ${data.managerName}`,
  width: 180,
  height: 60,
});

Image-Referenz, mit Vorschauen →

clipArt Named visual blocks — rules, marks, callouts — drawn by the renderer. Geplant

Not built yet. Nothing is fetched: the node names a shape and the renderer draws it, so it stays sharp in the DOCX and ships no asset.

Daten

graph A bar, line or pie chart declared as data.

Charts are declared, never drawn: `graphType` fixes the form, `data` returns the payload. Holding numbers rather than an image means one declaration serves every renderer and stays diffable in the artifact.

export const VisitsByMonth = graph<SampleData>({
  id: "visits-by-month",
  graphType: "bar",
  data: (data) => ({
    labels: data.visitsByMonth.map((entry) => entry.month),
    series: [{ name: "Visits", values: data.visitsByMonth.map((entry) => entry.visits) }],
  }),
  caption: (data) => `Your visits to ${data.centreName}, last six months`,
});

Graph-Referenz, mit Vorschauen →

table Rows and columns, with cells that are themselves nodes. Geplant

Not built yet. The intent is a node whose cells hold other nodes, so a table composes the way a section does rather than becoming a second content model beside it.

Ids sind Adressen

Über die id eines Nodes spricht ein Generierungs-Endpoint genau diesen Absatz an, und über sie liegen zwei Build-Artefakte in einem Diff nebeneinander. Eine Umbenennung bricht alles, was von außen darauf zeigt — genau wie das Umbenennen einer API-Route.

Halten Sie sie im Dokument eindeutig. Das kostet nichts und macht Logs lesbar.

Statisch und dynamisch

Ein statischer Node berechnet seinen Inhalt lokal aus Ihren Daten. Ein dynamischer Node trägt Prompts und einen Platzhalter und wird zur Anfragezeit ausgefüllt.

Sie deklarieren nie, was Sie wollen. Es gibt einen Helper je Art — paragraph, image, graph — und der Modus wird aus den Optionen abgeleitet, die Sie angeben: Geben Sie das Mitglied für die lokale Auflösung an (render, src, data), ist der Node statisch; geben Sie stattdessen Prompts an, ist er dynamisch. Beide lösen zur selben kind auf und unterscheiden sich im gebauten Dokument durch mode.

Beides anzugeben ist ein Compile-Fehler, mode hat also genau eine Wahrheitsquelle. Statisch und dynamisch behandelt, wo die Grenze verläuft und warum.

Verschachtelung

section ist heute der einzige Node, der Kinder aufnimmt, und er akzeptiert jede Art, auch weitere Abschnitte. Ein Tabellen-Node mit Nodes in seinen Zellen kommt als Nächstes, nach demselben Prinzip: Container nehmen die Komponenten auf, die Sie ohnehin schreiben, statt daneben ein zweites Inhaltsmodell zu stellen.

Zu diesen Vorschauen

Jede Vorschau hier ist ein echter Build. src/nodes/ im Repository dieser Site enthält eine Datei je Variante, geschrieben gegen das veröffentlichte Paket; ein Build-Schritt löst jede davon über buildDocument auf und rendert sie mit dem Renderer, den dxcl dev ausliefert. Der gezeigte Quelltext ist die Datei, die gelaufen ist, und das JSON ist das, was zurückkam — diese Seiten gehen also laut kaputt, statt still zu veralten.


Diese Seite auf GitHub bearbeiten ↗