Output functions¶
ProcessingModelFunctions is the abstract base every output format implements.
The generated transform module calls its methods (paragraph, heading,
block, inline, …) to emit output. Subclass it to add a new output format; see
the concrete implementations for HTML, Print, EPUB, Markdown, Typst, DOCX and JSON.
Base class and helpers¶
opm.runtime.output_functions ¶
Output format abstraction for TEI transformation.
Equivalent to html-functions.xql (and sibling format modules) in
tei-publisher-lib/content. Each concrete subclass of
ProcessingModelFunctions implements a specific serialisation
target (HTML, Markdown, …). The generated transformation module
calls methods on config.pmf and never imports a format-specific
module directly.
HTML and Markdown implementations live in opm.html_output_functions and
opm.markdown_output_functions; they are re-exported here for convenience.
TemplateOutput ¶
Bases: str
Preformatted or template text; skip prose normalisation that collapses line breaks.
ProcessingModelFunctions ¶
Bases: ABC
Abstract base for output format implementations.
Method names mirror the TEI Processing Model function vocabulary used by
html-functions.xql / markdown-functions.xql etc. The generated
transformation module calls these methods via config.pmf so that
only the config construction needs to change
when a different output format is required.
Every method receives config, a RenderContext,
as its first argument. Output functions delegate recursive processing
through it without importing the dispatch module:
config.apply – apply(config, nodes) → list
config.apply_children – apply_children(config, node, content,
parent) → None
A run creates its own instance, so per-run caches may live on self.
code ¶
Fallback code behaviour for output modes without dedicated formatting.
code_inline ¶
Inline code span — raw text, no markup escaping applied to the body.
unmatched ¶
Handle an element no model matched, i.e. the generated case _: arm.
Default: recurse into the children, which is what the generated dispatch
does inline for every other output mode. Only the JSON mode overrides
this — it is the sole way to see elements the ODD has no model for,
since they otherwise never reach a pmf method at all.
Source code in src/opm/runtime/output_functions.py
map_rend_to_class ¶
Map @rend attribute tokens directly to CSS class names, e.g. 'bold' → 'bold'.
classes ¶
add_lang_attrs ¶
Copy @xml:lang from source_node as HTML lang/dir attributes on el.
Source code in src/opm/runtime/output_functions.py
normalize ¶
Return content as a flat list of strings and lxml Elements.
Source code in src/opm/runtime/output_functions.py
param_str ¶
Coerce an ODD behaviour parameter (string or singleton sequence) to text.
A parameter whose XPath selected nothing arrives as an empty list, not as
None — <param name="label" value="…//note[@target=$t]/@n"/> with no
match, say. Returns '' for all of those, so a caller can treat "no
value" uniformly.
Source code in src/opm/runtime/output_functions.py
resolve_xml_id ¶
Resolve a bare or #-prefixed xml:id against node's document.
Source code in src/opm/runtime/output_functions.py
note_for_anchor ¶
The <note> whose @target points at anchor, if any.
Source code in src/opm/runtime/output_functions.py
is_lemma_range_note ¶
True when node is an inline note that closes a lemma range.
That is a <note target="…"> pointing at an <anchor> (usually
@type="note") which marks where the annotated passage begins.
Stand-off notes in listAnnotation are excluded — those are point
footnotes rendered at the anchor, not range ends.
Source code in src/opm/runtime/output_functions.py
lemma_range_markers ¶
Return (start, end, footnote) markers for a lemma-range label.
For label a that is ('a-', '-a', 'a-a').
Source code in src/opm/runtime/output_functions.py
note_element_id ¶
Stable id fragment for footnote links (xml:id, else fallback).
child_nodes ¶
All child content as a flat list of strings and elements.
Equivalent to the XPath node() axis: preserves interleaved text and
element children (including tail text of each child element).
Source code in src/opm/runtime/output_functions.py
should_preserve_whitespace ¶
Return True when dispatch classes indicate preformatted / code content.
Source code in src/opm/runtime/output_functions.py
apply_children_without_normalization ¶
Call config.apply_children with normalize_text off for this subtree.
Source code in src/opm/runtime/output_functions.py
serialize_element_content_literal ¶
Serialize the mixed content inside el as literal XML/text.
Source code in src/opm/runtime/output_functions.py
literal_code_body ¶
Build a code-block body without running child elements through the PM.
Source code in src/opm/runtime/output_functions.py
join_eol_hyphen ¶
Close up a word the source split across lines at a soft hyphen.
Where an encoder marks the split with U+00AD and indents the continuation
(Arra<lb/>gon), dropping the lb leaves that indentation behind,
and every renderer collapses it to a space: "Arra gon". The soft hyphen is
kept, so a reading system may still break the word there.
Source code in src/opm/runtime/output_functions.py
maybe_normalize_text ¶
Apply norm unless s is template output that must keep \n.
apply_pb_template ¶
Execute a pb:template: parse template_str as XML, substitute [[param]] placeholders, and return the resulting list of nodes (strings and lxml Elements).
config is accepted for API symmetry but not currently used; element-valued params that
appear in text positions are inserted directly into the result tree. The ODD compiler is
expected to pass already-rendered output nodes (see
apply_template_param_value, which expands a context node
to processed children instead of raw TEI).
Source code in src/opm/runtime/output_functions.py
HTML¶
opm.runtime.html_output_functions.HtmlOutputFunctions ¶
Bases: ProcessingModelFunctions
Serialise to HTML5 using lxml elements.
finish ¶
pass_through ¶
Render content without adding a wrapper element.
Source code in src/opm/runtime/html_output_functions.py
note ¶
Emit note - margin notes as inline spans, others as footnotes.
A footnote body is deferred to RunState
and placed by
inject_cached_footnotes
at the end of the run, which is where a
footnote_order
hook may reorder it. The label is also kept as data-n — as
PrintOutputFunctions.note
does — so CSS can tell a note carrying its own @n from one numbered
by the running counter without parsing the marker back out.
Lemma ranges (<anchor type="note"/> … <note target="…">) show
a- at the start, -a at the end, and a-a on the footnote.
Source code in src/opm/runtime/html_output_functions.py
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | |
code ¶
Emit a <pre><code> block so whitespace is preserved without JS.
data-language is omitted when web components are on: Prism in
pb-components would otherwise re-highlight already-rendered listings
(Pygments spans from tp:highlight, or the source itself).
Source code in src/opm/runtime/html_output_functions.py
Print (paged media)¶
opm.runtime.print_output_functions.PrintOutputFunctions ¶
Bases: HtmlOutputFunctions
Serialise to HTML tuned for paged-media CSS (Prince, Paged.js, print).
Equivalent to the pmf:* overrides in ext-printcss.xql.
note ¶
Emit note as an inline span for CSS float: footnote / margin notes.
Unlike HtmlOutputFunctions.note, does not build callout links or
append bodies to config.state.footnotes. A label (TEI @n) is kept
as data-n so print CSS can show a, b, … instead of the running number.
Lemma ranges: place="start" emits a plain a- marker; a note with
@target pointing at that anchor gets data-range so print CSS can
show -a as the call and a-a as the footnote marker.
Source code in src/opm/runtime/print_output_functions.py
alternate ¶
Emit the default reading plus the alternate as a print footnote.
Ignores webcomponents / popovers — print has no interactive UI.
Source code in src/opm/runtime/print_output_functions.py
EPUB¶
opm.runtime.epub_output_functions.EpubOutputFunctions ¶
Bases: HtmlOutputFunctions
Serialise to HTML with EPUB 3 structural semantics.
Equivalent to the pmf:* overrides in ext-epub.xql. Packaging into a
.epub ZIP is handled separately by opm.epub.
note ¶
Emit an EPUB noteref + footnote aside (in-flow; packager may hoist).
Labels and lemma ranges follow
HtmlOutputFunctions.note:
a note carrying its own @n shows that label and leaves the running
number alone, and a range reads a- … -a in the text and a-a
on the note. The label is kept as data-n so a stylesheet can set the
two series apart.
Source code in src/opm/runtime/epub_output_functions.py
alternate ¶
Default reading as noteref; alternate body as footnote aside.
An alternate that adds nothing — empty, or only the default reading again, as a register reference does when no register is configured — stays plain text: a popup repeating the word just tapped is noise.
Source code in src/opm/runtime/epub_output_functions.py
webcomponent ¶
Degrade custom elements: EPUB 3 XHTML has no place for them.
pb-link keeps its cross-reference as a fragment link (rewritten to
the target chapter file during packaging); everything else becomes a
transparent div / span wrapper.
Source code in src/opm/runtime/epub_output_functions.py
cells ¶
Wrap each content item as a <td> inside a <tr> (ext-epub).
Source code in src/opm/runtime/epub_output_functions.py
EPUB packaging (ZIP / OPF / nav) lives in opm.epub,
not in the PMF.
Markdown¶
opm.runtime.markdown_output_functions.MarkdownOutputFunctions ¶
Bases: ProcessingModelFunctions
Serialise to Markdown text fragments (CommonMark-style).
Mirrors pmf:* in tei-publisher-lib/content/markdown-functions.xql:
paragraph breaks, headings with #, list markers, pipe tables, links,
reference-style notes, and simple rend-based emphasis.
finish ¶
Run pmf:finish-style cleanup: collapse blank lines, tighten _ / ** spans.
note ¶
Emit a [^id] reference; the definition is placed when the run ends.
The marker a reader sees comes from the Markdown renderer, so label
is kept only on the
Footnote record, for a
footnote_order
hook to sort on. The hook decides the order of the definition block
this writes out.
Lemma ranges still write the a- / -a markers into the text;
the definition is prefixed with a-a so the label survives
rendering.
Source code in src/opm/runtime/markdown_output_functions.py
Typst¶
opm.runtime.typst_output_functions.TypstOutputFunctions ¶
DOCX¶
opm.runtime.docx_output_functions.DocxOutputFunctions ¶
Bases: ProcessingModelFunctions
DOCX output for TEI processing model.
Style resolution rules (matching tei-publisher-lib):
- For each ODD cssClass that does not start with tei-, look up the name
(case-insensitive) in the template's paragraph / character / table style
index. First match wins; unknown classes are silently skipped.
- Paragraph fallback: "Normal". Character fallback: no style (CSS properties
like bold/italic still apply). Table fallback: "TableGrid".
Source code in src/opm/runtime/docx_output_functions.py
metadata ¶
Collect a header value under key instead of emitting body content.
Mirrors TypstOutputFunctions.metadata: the ODD names the field,
the collected text lands in config.state.metadata and is
mapped onto the .docx core properties by finish.
Source code in src/opm/runtime/docx_output_functions.py
finish ¶
Assemble body elements into a .docx and return [bytes].
Source code in src/opm/runtime/docx_output_functions.py
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 | |
JSON¶
Records the processing model's own decisions rather than rendering the document.
It is the only implementation that overrides unmatched, which the generated
dispatch calls for elements no model matched.
opm.runtime.json_output_functions.JsonOutputFunctions ¶
Bases: ProcessingModelFunctions
Emit the processing model's decisions as JSON records.
template ¶
Record a pb:template and keep the content it wraps.
The generator hands templates their parameters already processed, so
params['content'] is a list of finished records. Dropping it would
lose every element a template-heavy ODD wraps — for DocBook that is
most of the document.
Source code in src/opm/runtime/json_output_functions.py
pass_through ¶
Recurse, but still record that a pass_through model won.
Emitting nothing here would hide a real decision: when the model you
expected did not fire because a pass_through one matched first,
the element simply would not appear. The same argument that puts inline
and suppressed behaviours in the tree applies to this one.
Source code in src/opm/runtime/json_output_functions.py
unmatched ¶
Record an element the ODD has no model for, then recurse into it.
The generated dispatch routes its case _: arm here for JSON output.
Without this the element would never reach a pmf method and its
text would surface in some ancestor with no provenance at all — which
is the one thing you most want to find when an ODD looks incomplete.