Template fragments¶
Fragments are small, pluggable LaTeX packages (.sty rendered from Jinja) that
TeXSmith can inject into any template at \VAR{extra_packages}. They keep
shared logic (callouts, code listings, …) out of individual templates
while staying configurable from front matter or your own extensions.
Built-in fragments¶
Most built-in fragments are contract fragments: they define the macros
the tmark writer emits for a construct (\tsmark, tscallout, tscode,
\tskeys, …), listed per fragment in tmark.fragments() and documented in
Contract macros. A contract fragment is activated by the writer:
a body that emits \begin{tscallout} names ts-callouts in its
Requires.fragments, and TeXSmith renders it — by construction, never by
sniffing the emitted LaTeX for a macro name. The remaining fragments are
configuration and render when their options say so.
ts-geometry- page size/orientation glue that mirrors
press.paper/press.geometryoptions. Configuration, not a contract. ts-typesetting- paragraph spacing, leading and line numbers (when configured), and the
contract macros
\tslead,\tsmark,\tsdivider,\tsrule,\tsepigraph,\tsaside,\tsprogress,\tsicon,\tslogoand thetsdivcontainer. ts-fonts- font selection driven by
fonts.family, script fallback fonts, and the\tsscript/\tsemojiswitches. ts-extra- aux packages: the writer's
Requires.packagesminus the packages the active contract fragments already load. ts-keystrokes\tskeys{Ctrl,Alt,Del}as styled TikZ boxes, one per key, joined by+.ts-callouts- the
tscalloutenvironment, generated from the callout definitions (built-in andpress.declare.admonitions) and thepress.callouts.*colours, icons and style. ts-code- the
tscodeenvironment and\tscodeinline, over pygments, minted, listings or fvextra according tocode.engine. ts-critic- critic markup:
\tsins,\tsdel,\tssubst,\tscomment. ts-index\tsindex, central imakeidx glue, one\makeindex[name=…]per registry ofRequires.index, texindy/makeindex selection.ts-glossary\tsgls/\tsacrand the glossary wiring: loadsglossaries, runs\makeglossarieswhen needed, and materializes acronym definitions from front matter with configurable styles.ts-bibliography\parencite/\textcitefallbacks when no.bibloadedbiblatex, plus the bibliography wiring. By default, raw URLs in entries are suppressed and the entry title becomes a clickable hyperlink to the entry'surlfield — this avoids the overfull/underfull\hboxwarnings that long URLs typically cause in justified bibliographies. Setbibliography_show_urls: truein the document front matter to print the full URL inline instead (same behaviour as biblatex's stock styles).ts-todolist- the
tstasklistenvironment and its\tsdone,\tstodoand\tspartialmarkers, for a Markdown task list. ts-frame- an optional page frame with an optional folded corner (
press.frame). Configuration, not a contract; the snippet previews in this documentation use it.
Templates default to the contract fragments plus the configuration ones they
need. Each is written into the build directory as ts-*.sty and loaded via
\usepackage{…} at \VAR{extra_packages}.
Using fragments in documents¶
Fragments are declared under the press.fragments key in front matter. Each
entry is either the name of a built-in fragment or a path to a custom Jinja
template (absolute or relative to the Markdown file).
Explicit list (replaces template defaults)¶
Provide a plain list to replace the template's default fragment set entirely:
---
press:
template: article
fragments:
- ts-callouts
- ts-code
- ts-glossary
- fragments/foo.jinja.sty # custom fragment located next to your doc
foo:
value: 42 # variables consumed by foo.jinja.sty
---
Modifier dict (extends template defaults)¶
When you only need to add or remove a few fragments without restating the full
list, use the dict form with any combination of append, prepend, and
disable:
---
press:
template: article
fragments:
append:
- ./fragments/heiglogo # add a custom fragment at the end
prepend:
- ./fragments/header # add a fragment at the start
disable:
- ts-geometry # remove a specific built-in fragment
---
All three keys are optional. Omitted keys leave the corresponding part of the
default list unchanged. disable is applied first (before prepend/append),
so the same fragment cannot appear in both disable and prepend/append.
--enable-fragment / -f and --disable-fragment / -F apply the same two
operations from the command line.
Disabling a contract fragment does not remove it: the writer still names it
in Requires.fragments, so the macros the body emits stay defined. To change
what a construct looks like, redefine its contract macro or replace the
fragment with one that provides the same list — see
Contract macros.
TeXSmith renders each fragment into the output directory and injects the
corresponding \usepackage{…} lines into \VAR{extra_packages}.
What a fragment looks like¶
Fragments are plain Jinja templates that output LaTeX. The package name is the stem of the file unless it is a built-in registered name.
% fragments/foo.jinja.sty
\ProvidesPackage{foo}[2025/01/01 Example fragment]
\newcommand{\FooValue}{\VAR{foo.value|default(0)}}
With the front matter above, the generated build will contain foo.sty and the
document preamble will include \usepackage{foo}.
Template authors: allowing fragments¶
To consume fragments, a template needs a placeholder where TeXSmith can inject
the \usepackage lines. Add \VAR{extra_packages} near the top of your
preamble—typically next to other package imports. No TOML manifest changes are
required; the core runtime resolves fragments before rendering.
Built-in templates already include this placeholder and declare their default
fragment set through the template runtime extras; a contract fragment renders
only when a body's Requires.fragments names it, so a document without code
carries no ts-code.sty. Third-party templates can declare their own defaults
in TemplateRuntime.extras["fragments"], or let users supply theirs through
press.fragments and -f / -F on the command line.
Passing variables to fragments¶
Any values under press (or other front matter keys) are merged into the
template rendering context. If your fragment expects a variable such as
foo.value, document it and read it directly in the Jinja template. Unknown
keys are ignored.
CLI and API integration¶
CLI usage is automatic once press.fragments is present. For API consumers:
from texsmith import Document, TemplateSession
from texsmith.core.templates import load_template_runtime
session = TemplateSession(load_template_runtime("article"))
session.add_document(Document.from_markdown(path_to_md))
result = session.render(output_dir)
# result.main_tex_path already includes the rendered fragments
Custom fragments may live anywhere; relative paths are resolved against the document’s directory. Built-in names are always available without shipping assets in your template package.