Zum Inhalt springen
Docxcelerate

Nodes

Section

Der einzige Node, der andere Nodes aufnimmt, und die Überschrift, zu der sein Titel wird.

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
Node-Art
section
Kategorie
Struktur
Wird aufgelöst
Locally
Kinder
Any node, including other sections. No depth limit.
Option Typ Was sie bewirkt
id string Stable address for the node. Engines target it and build artifacts diff on it, so treat a rename as a breaking change. Optional: a node without one takes an id from where it sits, which is what keeps branches and loops from forcing you to invent names. Two nodes claiming one id is an error rather than a race.
title erforderlich string The heading printed above the children, and the outline entry.
children Yield The children, as JSX children of <Section>. Components, elements, arrays and conditionals all count; anything falsy is skipped.
derivers DeriverInvocation[] Values the engine computes before the node resolves, written to derived.* and readable from a template token. Built with derive(). These survive publishing and run per document — use them for anything computed from request data. useDeriver runs one during the build instead.

Einen schreiben

Ein Abschnitt bekommt seine Optionen und seine Kinder — Node-Komponenten, dieselben Werte, die Sie auch auf der obersten Ebene eines Dokuments platzieren würden:

import { section } from "docxcelerate";

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

In TSX liest sich derselbe Aufruf wie Markup:

<Section id="opening" title="Your renewal">
  <Greeting />
  <PriceChange />
</Section>

Beides ergibt denselben Baum. Templates behandelt, wann welche Form sich lohnt.

Kinder können alles sein

Absätze, Bilder, Diagramme, eine Inhaltsverzeichnis-Markierung oder weitere Abschnitte. Kein anderer Node hat Kinder, also ist die Tiefe eines Dokuments die Tiefe seiner Abschnitte.

An einem Node ändert sich nichts dadurch, dass er in einen Abschnitt wandert: Er löst sich in jeder Tiefe gleich auf, und seine id bekommt kein Präfix.

Titel wandern in die Gliederung

title ist erforderlich und keine Verzierung — daraus wird die Überschrift über den Kindern und der Eintrag, aus dem ein Inhaltsverzeichnis entsteht. Eine Gruppe, die keine Überschrift will, will keinen Abschnitt; setzen Sie die Nodes dann direkt ins Dokument.

Varianten

A titled group

src/nodes/section/basic.node.tsx

Two paragraphs under one heading — the common case.

import { Section } from "docxcelerate/template";
import { PriceChange } from "../paragraph/conditional.node.tsx";
import { Greeting } from "../paragraph/static.node.tsx";

/**
 * A section takes an id, a title and its children. The children are the same
 * components you would place at the top level.
 */
export const Opening: Section = () => (
  <Section id="opening" title="Your renewal">
    <Greeting />
    <PriceChange />
  </Section>
);
section · a titled group Open ↗
Wozu es aufgelöst wird

Der Node, wie er im DocumentModel erscheint: das JSON, das ein Renderer bekommt. Kein Styling, kein Layout.

{
  "id": "opening",
  "kind": "section",
  "title": "Your renewal",
  "children": [
    {
      "id": "greeting",
      "kind": "paragraph",
      "mode": "static",
      "text": "Dear Adaeze Nkemelu,"
    },
    {
      "id": "price-change",
      "kind": "paragraph",
      "mode": "static",
      "text": "Your Peak Anytime membership is rising by 5.1%, from £468 to £492 a year. That is £41 a month from 1 October 2026."
    }
  ]
}

Mixed and nested children

src/nodes/section/nested.node.tsx

A graph, then a nested section holding a graph and a dynamic paragraph.

import { Section } from "docxcelerate/template";
import { ClassMix } from "../graph/pie.node.tsx";
import { VisitsByMonth } from "../graph/bar.node.tsx";
import { NextSteps } from "../paragraph/dynamic.node.tsx";

/**
 * Children can be of any kind, including another section — the one place a
 * document tree gains depth. The resolved document nests exactly as this reads.
 */
export const YourYear: Section = () => (
  <Section id="your-year" title="Your year here">
    <VisitsByMonth />
    <Section id="activity-mix" title="Where the time went">
      <ClassMix />
      <NextSteps />
    </Section>
  </Section>
);
section · mixed and nested children Open ↗
Wozu es aufgelöst wird

Der Node, wie er im DocumentModel erscheint: das JSON, das ein Renderer bekommt. Kein Styling, kein Layout.

{
  "id": "your-year",
  "kind": "section",
  "title": "Your year here",
  "children": [
    {
      "id": "visits-by-month",
      "kind": "graph",
      "mode": "static",
      "graphType": "bar",
      "title": "Visits to Riverside Leisure Centre",
      "valueAxisTitle": "Visits",
      "data": {
        "categories": [
          "Apr",
          "May",
          "Jun",
          "Jul",
          "Aug",
          "Sep"
        ],
        "series": [
          {
            "label": "Visits",
            "values": [
              11,
              14,
              9,
              16,
              18,
              12
            ]
          }
        ]
      },
      "caption": "Your visits to Riverside Leisure Centre, last six months"
    },
    {
      "id": "activity-mix",
      "kind": "section",
      "title": "Where the time went",
      "children": [
        {
          "id": "class-mix",
          "kind": "graph",
          "mode": "static",
          "graphType": "pie",
          "title": "Share of visits",
          "dataLabels": true,
          "data": {
            "categories": [
              "Swim",
              "Strength",
              "Classes"
            ],
            "series": [
              {
                "label": "Share of visits",
                "values": [
                  42,
                  33,
                  25
                ]
              }
            ]
          },
          "caption": "How you used the centre, by activity"
        },
        {
          "id": "next-steps",
          "kind": "paragraph",
          "mode": "dynamic",
          "text": "Your membership renews automatically on 1 October 2026. Nothing is needed from you unless you want to change plan."
        }
      ]
    }
  ]
}

Anmerkungen

  • Die Tiefe steckt im Baum, nicht in den Überschriften. Beide mitgelieferten Renderer drucken jeden Abschnittstitel auf einer Ebene — <h2> im Browser, Überschrift 1 im DOCX — wie tief er auch verschachtelt ist. Das JSON verschachtelt korrekt, das ist also eine Beschränkung der Renderer; ein drei Ebenen tiefes Dokument sieht aber noch nicht drei Ebenen tief aus.
  • Einen dynamischen Abschnitt gibt es nicht. Ein Endpoint füllt Nodes aus; er entscheidet nicht, was das Dokument enthält.
  • Ein leerer Abschnitt rendert als einzelne Überschrift. Kommen die Kinder aus einem Filter, der leer laufen kann, prüfen Sie das weiter oben.

Diese Seite auf GitHub bearbeiten ↗ Diese Seite als Markdown lesen