Skip to Content

@stesura/docgen

Assembles markdown sources and a Stesura template into one document, ready to render to PDF or Word, with front matter and {{name}} variable substitution. Framework-free, so it runs in a server route or a CLI. The template is a doc JSON whose content_slot (inserted with insertContentSlot from @stesura/core/commands) marks where the sources go, and whose field nodes are the variables.

A typical render: read the first source’s front matter, resolve the variables against the template’s declarations, then assemble.

import { assemble, readFrontMatter, resolveVariableValues } from '@stesura/docgen' const { data } = readFrontMatter(sources[0].markdown) const resolved = resolveVariableValues(definitions, { ...data, ...requestVariables }) if (!resolved.ok) throw new Error(resolved.error.error) const { doc, warnings } = assemble({ schema, template, sources, assets, variables: resolved.values })

Assembly

assemble

Template + markdown sources + variables → one document.

  • Front matter is stripped from every source (the caller merges the first source’s into the variables before resolving them).
  • Sources are parsed with the template’s styles, joined by page breaks, and put where the content_slot (or a {{content}} paragraph) is, or at the end of the last section.
  • Relative image paths resolve against the source’s folder and are replaced by the matching assets entry. Remote images are not fetched.
  • Footnote bodies are created in the doc’s footnotes container; refs are namespaced per source so two files’ [^1] stay distinct.
  • Links between the files (other.md#heading, #heading) become in-document links; unresolvable relative links lose their link.
  • Common raw HTML (details, img, br, kbd) is rewritten to markdown first; code blocks get line numbers unless codeLineNumbers is false.
  • headingOffset shifts a file’s heading levels (and built-in heading styles). Chapter numbering itself comes from the template’s heading styles.
  • field nodes and typed {{name}} are filled everywhere, markdown included. A text watermark left empty after substitution is removed, so {{watermark}} toggles it.

Throws AssembleError only when the result is not a valid document.

Parameters:
NameTypeDefault
__0AssembleOptions
Returns:
AssembleResult

AssembleOptions

What assemble takes.

NameTypeDefault
schemaSchema<any, any>
templateJSONContent

The template, as stored: a doc JSON.

sourcesDocgenSource[]
assetsDocgenAssets
variablesRecord<string, string>

Text each {{name}} renders as, already resolved and type-checked.

separator"none" | "pageBreak"

What goes between two sources. Default: a page break.

codeLineNumbersboolean

Line numbers on code blocks. Default: on, as documentation usually wants.

AssembleResult

What assemble returns.

NameTypeDefault
docJSONContent

Valid against schema, with ids, as plain JSON.

warningsDocgenWarning[]

AssembleError

A template or doc that cannot be assembled at all (as opposed to a warning).

NameTypeDefault
namestring
messagestring
stackstring
causeunknown

DocgenSource

One markdown file of the request. path is repo-relative, /-separated.

NameTypeDefault
pathstring
markdownstring
headingOffsetnumber

Added to every heading level of this file (# → H2 with 1), clamped to H9.

DocgenAssets

export type DocgenAssets = Record<string, string>;

Files the sources refer to, keyed by repo-relative path; values are data: URIs.

DocgenWarning

A non-fatal degradation, safe to show in a CI log. Markdown parse warnings keep their code from @stesura/markdown; source names the file.

NameTypeDefault
codestring
messagestring
sourcestring

Front matter

readFrontMatter

Splits YAML front matter off a markdown file. Never throws: invalid YAML and nested values are reported and skipped, and the block is still removed so it never renders as a rule and a heading.

Parameters:
NameTypeDefault
markdownstring
sourcestring
Returns:
FrontMatter

FrontMatter

A markdown file split by readFrontMatter.

NameTypeDefault
dataRecord<string, string | number | boolean>

Scalar entries only: they are what can fill {{name}}.

bodystring

The markdown without its front matter block.

warningsDocgenWarning[]

Variables

A template declares its variables as VariableDefinitions. Request values are checked against them by resolveVariableValues; substituteVariables fills a doc with the result, which assemble already does for you.

resolveVariableValues

Turns request variables into the text each placeholder renders as.

Declared variables are type-checked and fall back to their default; a missing required one is an error unless lenient (editor previews). Undeclared request keys pass through as text, so hand-written templates without declarations still work.

Parameters:
NameTypeDefault
definitionsVariableDefinition[]
inputunknown
__2{ lenient?: boolean; builtins?: VariableValues; }
Returns:
{ ok: true; values: VariableValues; } | { ok: false; error: VariableError; }

substituteVariables

Fills a template with variable values, everywhere: body, headers, footers, notes and text watermarks.

  • A field node becomes text (keeping its marks): the value, else its applied value attr, else its fallback, else {{name}} with a warning.
  • Typed {{name}} text is replaced too, for templates written before fields and for markdown sources. Reserved and unknown names stay literal; unknown ones are reported. A placeholder split across two text runs is not seen. Code blocks and code spans are left alone: {{x}} there is a sample.

Text left empty is dropped (ProseMirror has no empty text nodes). Returns a new doc; the input is not mutated.

Parameters:
NameTypeDefault
docJSONContent
valuesVariableValues
Returns:
{ doc: JSONContent; warnings: string[]; }

defaultBuiltins

Values every template gets unless the request, front matter or a declared default sets them. date is the render day, ISO, so {{date}} works out of the box.

Parameters:
NameTypeDefault
nowDate
Returns:
VariableValues

validateVariableDefinitions

Checks definitions before they are saved. Returns the first problem, or null.

Parameters:
NameTypeDefault
definitionsVariableDefinition[]
Returns:
string | null

parseVariableDefinitions

Reads the templates.variables column. Malformed entries are dropped, never thrown on.

Parameters:
NameTypeDefault
valueunknown
Returns:
VariableDefinition[]

toVariableType

value as a VariableType, or null when it isn’t one.

Parameters:
NameTypeDefault
valueunknown
Returns:
"string" | "number" | "boolean" | "date" | null

VARIABLE_TYPES

export const VARIABLE_TYPES = ["string", "number", "boolean", "date"] as const;

The types a template variable can declare.

VARIABLE_NAME_PATTERN

What a declared variable name must match: a letter or _, then up to 63 of [A-Za-z0-9_.-].

NameTypeDefault
exec(string: string) => RegExpExecArray | null
test(string: string) => boolean
sourcestring
globalboolean
ignoreCaseboolean
multilineboolean
lastIndexnumber
compile(pattern: string, flags?: string | undefined) => RegExp
flagsstring
stickyboolean
unicodeboolean
dotAllboolean
hasIndicesboolean
__@match@41422(string: string) => RegExpMatchArray | null
__@replace@41420{ (string: string, replaceValue: string): string; (string: string, replacer: (substring: string, ...args: any[]) => string): string; }
__@search@41426(string: string) => number
__@split@41428(string: string, limit?: number | undefined) => string[]
__@matchAll@41430(str: string) => RegExpStringIterator<RegExpMatchArray>

RESERVED_VARIABLES

export const RESERVED_VARIABLES: readonly string[] = ["content", "page"];

Placeholders the substitution leaves alone: content is the assembler’s slot, page the page-number atom’s.

VariableDefinition

A variable a template declares.

NameTypeDefault
namestring
type"string" | "number" | "boolean" | "date"
requiredboolean
defaultstring

Used when the request omits the variable. Stored as the rendered text.

descriptionstring

VariableType

export type VariableType = (typeof VARIABLE_TYPES)[number];

One of VARIABLE_TYPES.

VariableValues

export type VariableValues = Record<string, string>;

Variable name → the text its placeholder renders as.

VariableError

Why resolveVariableValues refused a request’s variables.

NameTypeDefault
error"invalid_variables" | "missing_variable" | "invalid_variable"

API clients

For documenting a template’s render API: the shape of its variables object as JSON Schema or as a TypeScript type.

variablesJsonSchema

JSON Schema (draft 2020-12) of a template’s variables request object. Required means “must be sent”: a variable with a default is never required. Unknown keys are allowed, as the API passes them through as text.

Parameters:
NameTypeDefault
definitionsVariableDefinition[]
titlestring
Returns:
JsonSchema

variablesTypeScript

A TypeScript type for a template’s variables object, for generated client code.

Parameters:
NameTypeDefault
definitionsVariableDefinition[]
typeNamestring
Returns:
string
Last updated on