Naar de inhoud
Docxcelerate

Basis

Documenten en nodes

Een document is een boom van componenten, die elk hun data als state aannemen en de nodes teruggeven die ze willen.

Een document is een template plus een datatype. Het template is een boom van componenten; elk geeft nodes terug, en de boom oplossen tegen data levert een DocumentModel op — pure JSON, zonder dat daarmee iets over rendering gezegd is.

Een component neemt zijn data als state

import { Paragraph, useState } from "docxcelerate/template";
import type { DocumentData } from "../types.ts";

export const Greeting: Paragraph = () => {
  const [state] = useState((data: DocumentData) => ({
    name: data.residentName,
  }));

  return <Paragraph id="greeting">Dear {state.name},</Paragraph>;
};

useState is waar data een component binnenkomt, en de enige plek. Alles daarna leest state. Dat is een regel met een reden: doordat elke afhankelijkheid door één declaratie loopt, staat opgeschreven wat een component nodig heeft in plaats van verspreid door de code die het gebruikt.

De initializer is gewoon TypeScript. Er is geen templatetaal, dus condities, formattering en imports zijn simpelweg beschikbaar.

Paragraph benoemt zowel het element als het componenttype — een waarde en een type mogen een naam delen — dus const Greeting: Paragraph zegt wat dit oplevert, en er een <Section> uit teruggeven is een compileerfout.

Data kan ook als props binnenkomen

Een component die krijgt wat hij nodig heeft, hoeft er niet zelf naar te grijpen:

export const Arrears: Paragraph<{ amount: number }> = ({ amount }) => {
  const { currency } = useFormat();

  return <Paragraph id="arrears">You owe {currency(amount)}.</Paragraph>;
};

Iemand moet de data eerst lezen, dus een component met alleen props zit onder een ouder die ze als state heeft aangenomen. Gebruik props voor componenten die je tegen verschillende waarden wilt hergebruiken, en state voor componenten die weten bij welk document ze horen.

Beslissingen zijn een gewone if

export const Balance: Paragraph = () => {
  const [state] = useState((data: DocumentData) => ({
    settled: data.balanceDue === 0,
  }));

  if (state.settled) {
    return <Paragraph id="settled">Nothing outstanding.</Paragraph>;
  }

  return <Paragraph id="arrears">A balance remains.</Paragraph>;
};

Geef elke tak zijn eigen id. Het opgeloste document legt dan vast welke deze ontvanger kreeg, en dat is het verschil tussen een document dat je kunt controleren en een dat je alleen kunt bekijken.

Er is één ding om te weten over vertakken voordat je naar een engine publiceert: zie wat er verandert bij publiceren.

Ids

Een id is hoe een engine een node adresseert en hoe buildartefacten tussen runs diffbaar blijven, dus behandel een hernoeming als een breaking change.

Je mag hem weglaten. Een node zonder id krijgt er een van waar hij staat, en dat voorkomt dat takken en lussen je dwingen namen te verzinnen. Wat niet kan, is er een twee keer gebruiken: twee nodes die één id claimen is een fout, gemeld met beide posities, en geen race die de laatste wint.

Secties nesten, nodes niet

Section is de enige constructie die nest. De titel gaat mee in de documentstructuur:

<Section id="opening" title="Opening">
  <Greeting />
  <Offer />
</Section>

Zie Section voor wat een sectie mag bevatten en hoe diep.

Hooks

Hooks zijn hoe een component de build om zich heen bereikt:

HookWat het je geeft
useStateData, één keer aangenomen en bewaard
useSharedEen waarde achtergelaten voor de componenten die daarna renderen
useSetPromptsPrompts voor de node die dit oplevert — wat hem dynamisch maakt
useSetPlaceholdersWat previews tonen in plaats van gegenereerde inhoud
usePlaceholderDataVervangende namen, datums en cijfers voor previews
useFormatLandinstellingbewuste valuta, datums, lijsten en meervouden
useAvailableTokensHet tokenbudget dat deze build heeft toegewezen
useDeriverVoert nu een geregistreerde deriver uit

Ze lopen in aanroepvolgorde, dus elke hook moet bereikt zijn vóór de eerste await en vóór elke vertakking — dezelfde regel die React hanteert, om dezelfde reden. Er een aanroepen na een await is een fout die dat ook zegt, in plaats van zich stilletjes vast te haken aan de volgende component die rendert.

Het document bouwen

import { buildDocument } from "docxcelerate";

const doc = await buildDocument(documentTemplate, data);

Het resultaat is een DocumentModel: een schemaVersion, een id, een title en een nodes-array. Het bevat geen styling en geen lay-out — die worden later toegepast door de renderer die het verwerkt.

Voor een documentproject gedefinieerd met defineDocumentProject gebruik je liever buildProjectPreviewDocument, dat de stijl van het project toepast en dynamische nodes naar hun placeholders oplost:

import { buildProjectPreviewDocument } from "docxcelerate";

const doc = await buildProjectPreviewDocument(project);

Dat is precies wat de preview-app aanroept, dus wat je in code bouwt komt overeen met wat je in de browser zag.


Deze pagina bewerken op GitHub ↗ Deze pagina als Markdown lezen