@cristianormazabal/triton-latex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@cristianormazabal/triton-latex",
3
+ "description": "LaTeX integration for Triton — render diagrams to vector PDF for \\includegraphics.",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "latex",
9
+ "pdf",
10
+ "triton",
11
+ "diagrams",
12
+ "svg-to-pdf",
13
+ "mermaid"
14
+ ],
15
+ "bin": {
16
+ "triton-latex": "./dist/cli.cjs"
17
+ },
18
+ "engines": {
19
+ "node": ">=20"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "triton.sty"
24
+ ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/ormasoftchile/triton.git",
28
+ "directory": "latex"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "homepage": "https://github.com/ormasoftchile/triton",
34
+ "bugs": "https://github.com/ormasoftchile/triton/issues",
35
+ "scripts": {
36
+ "build": "node esbuild.mjs",
37
+ "prepublishOnly": "npm run build",
38
+ "render": "node dist/cli.cjs render",
39
+ "render-dir": "node dist/cli.cjs render-dir",
40
+ "typecheck": "tsc -p tsconfig.json --noEmit"
41
+ },
42
+ "dependencies": {
43
+ "pdfkit": "^0.15.0",
44
+ "svg-to-pdfkit": "^0.1.8"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^22.0.0",
48
+ "@types/pdfkit": "^0.13.4",
49
+ "esbuild": "^0.24.0",
50
+ "typescript": "^5.8.3"
51
+ }
52
+ }
package/triton.sty ADDED
@@ -0,0 +1,198 @@
1
+ % triton.sty — author Triton diagrams directly in LaTeX (like TikZ), or include
2
+ % precompiled vector PDFs as an Overleaf fallback.
3
+ %
4
+ % ── HEADLINE: inline authoring ──────────────────────────────────────────────
5
+ % Put the diagram SOURCE straight in your .tex and it renders inline:
6
+ %
7
+ % \documentclass{article}
8
+ % \usepackage{triton}
9
+ % \begin{document}
10
+ % \begin{triton}
11
+ % flowchart LR
12
+ % A[Start] --> B{Choice}
13
+ % B --> C[End]
14
+ % \end{triton}
15
+ % \end{document}
16
+ %
17
+ % Compile WITH shell-escape (this is required for the inline environment):
18
+ % pdflatex -shell-escape file.tex
19
+ % lualatex -shell-escape file.tex
20
+ % tectonic -Z shell-escape -Z shell-escape-cwd=. file.tex
21
+ %
22
+ % How it works (the minted model): the `triton` environment captures its body
23
+ % VERBATIM, writes it to a temp file, content-hashes the source (so a diagram is
24
+ % only re-rendered when it changes), shells out via \write18 to the @triton/latex
25
+ % CLI to produce a vector PDF in a cache directory, then \includegraphics it.
26
+ %
27
+ % ── FALLBACK: precompiled include (Overleaf / no shell-escape) ──────────────
28
+ % Overleaf disallows arbitrary shell-escape. There, precompile the diagrams to
29
+ % PDF (see the @triton/latex CLI `render-dir`) and drop them in by NAME — this is
30
+ % engine-agnostic and needs no Node/Triton toolchain on the LaTeX side:
31
+ %
32
+ % \tritondir{figures} % where the *.pdf live (default: triton-figures)
33
+ % \triton{flowchart} % \includegraphics the precompiled figures/flowchart.pdf
34
+ % \triton[width=0.6\linewidth]{avl}
35
+ %
36
+ % \triton{<name>} is BOTH the precompiled-include command AND the name of the
37
+ % inline environment — LaTeX would normally forbid that, so the package dispatches
38
+ % on \@currenvir: inside \begin{triton}…\end{triton} it authors inline; used as a
39
+ % bare command \triton[opts]{name} it includes a precompiled PDF.
40
+ %
41
+ % ── Macro summary ───────────────────────────────────────────────────────────
42
+ % \begin{triton} … \end{triton} inline authoring (needs shell-escape)
43
+ % \tritonnext{opts} \includegraphics opts for the NEXT
44
+ % inline diagram only (per-diagram size)
45
+ % \tritoninline[opts]|… one line …| one-line inline source
46
+ % \triton[opts]{name} include precompiled <dir>/name.pdf
47
+ % \tritonfile[opts]{name} explicit alias of the include form
48
+ % \tritonfig[opts]{name}{caption} precompiled include in a figure
49
+ % \tritondir{path} precompiled-PDF directory
50
+ % \tritonsetup{opts} default \includegraphics options
51
+ % \tritoncli{cmd} CLI invocation (default: triton-latex)
52
+ % \tritontheme{name} theme preset for inline renders
53
+ % \tritonscale{n} scale passed to the CLI (default 1)
54
+ % \tritoncachedir{dir} render cache (default \jobname.triton-cache)
55
+ %
56
+ % NOTE on sizing: a verbatim environment cannot reliably take an inline optional
57
+ % argument (\begin{triton}[width=…] would swallow the diagram's first line), so
58
+ % per-diagram \includegraphics options are set just BEFORE the environment with
59
+ % \tritonnext{…}; \tritonsetup{…} sets the global default.
60
+
61
+ \NeedsTeXFormat{LaTeX2e}
62
+ \ProvidesPackage{triton}[2026/06/24 v0.2.0 Inline Triton diagram authoring in LaTeX]
63
+
64
+ \RequirePackage{graphicx}
65
+ \RequirePackage{fancyvrb} % verbatim body capture (VerbatimOut)
66
+ \RequirePackage{pdftexcmds} % \pdf@shellescape, \pdf@filemdfivesum (engine-agnostic)
67
+
68
+ % ── Shared default \includegraphics options ─────────────────────────────────
69
+ \def\triton@opts{width=\linewidth}
70
+ \newcommand{\tritonsetup}[1]{\def\triton@opts{#1}}
71
+
72
+ % ── Precompiled-PDF directory (fallback workflow) ───────────────────────────
73
+ \def\triton@dir{triton-figures}
74
+ \newcommand{\tritondir}[1]{\def\triton@dir{#1}}
75
+
76
+ % The precompiled-include behaviour, shared by \tritonfile and by the bare
77
+ % \triton[opts]{name} command form (dispatched below).
78
+ \newcommand{\triton@include}[2][\triton@opts]{%
79
+ \includegraphics[#1]{\triton@dir/#2.pdf}%
80
+ }
81
+ \let\tritonfile\triton@include
82
+
83
+ \newcommand{\tritonfig}[3][\triton@opts]{%
84
+ \begin{figure}[htbp]%
85
+ \centering
86
+ \triton@include[#1]{#2}%
87
+ \caption{#3}%
88
+ \end{figure}%
89
+ }
90
+
91
+ % ── Inline-render configuration ─────────────────────────────────────────────
92
+ \def\triton@cli{triton-latex}
93
+ \newcommand{\tritoncli}[1]{\def\triton@cli{#1}}
94
+ \def\triton@scale{1}
95
+ \newcommand{\tritonscale}[1]{\def\triton@scale{#1}}
96
+ \def\triton@themearg{}
97
+ \newcommand{\tritontheme}[1]{\def\triton@themearg{\space--theme #1}}
98
+ \def\triton@cachedir{\jobname.triton-cache}
99
+ \newcommand{\tritoncachedir}[1]{\def\triton@cachedir{#1}}
100
+ % Temp file the verbatim diagram source is written to before rendering. The
101
+ % input extension is irrelevant to the CLI's single-file `render' (the renderer
102
+ % auto-detects the diagram kind from the source header); only the .pdf OUTPUT
103
+ % extension matters.
104
+ \def\triton@tmpfile{\jobname.triton-src.triton}
105
+
106
+ % Per-diagram \includegraphics options for the NEXT inline render. Defaults to
107
+ % the global \triton@opts; \tritonnext{…} overrides it for the next diagram only.
108
+ % (A verbatim environment cannot reliably carry an inline optional argument like
109
+ % \begin{triton}[width=…] — peeking for the `[' tokenises the line break that
110
+ % fancyvrb needs to delimit the body — so per-diagram sizing is set just BEFORE
111
+ % the environment with \tritonnext instead.)
112
+ \newif\iftriton@nextset
113
+ \newcommand{\tritonnext}[1]{\def\triton@nextopts{#1}\triton@nextsettrue}
114
+
115
+ % Stream used by \tritoninline to write its verbatim argument to the temp file.
116
+ \newwrite\triton@inlinestream
117
+
118
+ % ── Core render step (shared by the environment and \tritoninline) ──────────
119
+ % Precondition: \triton@tmpfile holds the diagram source and \triton@curopts
120
+ % holds the \includegraphics options. Content-hash → cache → shell-out → include.
121
+ \newcommand{\triton@render}{%
122
+ \ifnum\pdf@shellescape=\@ne
123
+ \edef\triton@hash{\pdf@filemdfivesum{\triton@tmpfile}}%
124
+ \edef\triton@pdf{\triton@cachedir/\triton@hash.pdf}%
125
+ % Only render when this exact source has not been rendered before.
126
+ \IfFileExists{\triton@pdf}{}{%
127
+ \immediate\write18{\triton@cli\space render "\triton@tmpfile" -o
128
+ "\triton@pdf" --scale \triton@scale\triton@themearg}%
129
+ }%
130
+ \IfFileExists{\triton@pdf}{%
131
+ % \triton@curopts is a macro (e.g. width=\linewidth); graphicx mis-parses
132
+ % an unexpanded key-list macro in the optional argument ("Missing
133
+ % \endcsname" on the dimen), so expand it once into literal keys first.
134
+ \expandafter\includegraphics\expandafter[\triton@curopts]{\triton@pdf}%
135
+ }{%
136
+ \PackageError{triton}{Inline render produced no PDF}{%
137
+ The CLI did not create \triton@pdf.\MessageBreak
138
+ Check that Node and the triton-latex CLI are installed and that
139
+ \protect\tritoncli\space points at it (e.g.
140
+ \protect\tritoncli{node /path/to/latex/dist/cli.cjs}).}%
141
+ }%
142
+ \else
143
+ \PackageError{triton}{The inline `triton' environment needs shell-escape}{%
144
+ Recompile with -shell-escape (pdflatex/lualatex) or -Z shell-escape
145
+ (tectonic),\MessageBreak or use the precompiled \protect\triton{<name>}
146
+ workflow (render the diagrams to PDF first).}%
147
+ \fbox{\ttfamily[triton: shell-escape required for inline diagram]}%
148
+ \fi
149
+ }
150
+
151
+ % ── Inline environment + backward-compatible command, sharing the name `triton'
152
+ % LaTeX cannot have a command \triton AND an environment `triton' independently,
153
+ % because \begin{triton} simply calls \triton. We resolve this by dispatching on
154
+ % \@currenvir, which LaTeX sets to the environment name inside \begin{...}:
155
+ % • inside \begin{triton} … → start verbatim capture (inline author)
156
+ % • bare \triton[opts]{name} → include a precompiled PDF (fallback)
157
+ \def\triton@marker{triton}
158
+ \newcommand{\triton}{%
159
+ \ifx\@currenvir\triton@marker
160
+ \let\triton@dispatch\triton@beginenv
161
+ \else
162
+ \let\triton@dispatch\triton@include
163
+ \fi
164
+ \triton@dispatch
165
+ }
166
+
167
+ % Environment begin: capture the body verbatim to the temp file. NOTHING may be
168
+ % looked-ahead here (no optional argument), or the line break fancyvrb needs to
169
+ % find the end of the \begin{triton} line is consumed and the first body line is
170
+ % swallowed. \VerbatimEnvironment makes fancyvrb scan until \end{triton}.
171
+ \def\triton@beginenv{%
172
+ \iftriton@nextset
173
+ \let\triton@curopts\triton@nextopts
174
+ \else
175
+ \let\triton@curopts\triton@opts
176
+ \fi
177
+ \VerbatimEnvironment
178
+ \begin{VerbatimOut}{\triton@tmpfile}%
179
+ }
180
+ \def\endtriton{%
181
+ \end{VerbatimOut}%
182
+ \triton@render
183
+ \triton@nextsetfalse
184
+ }
185
+
186
+ % ── \tritoninline[opts]|one-line source| ────────────────────────────────────
187
+ % Convenience for short, single-line diagrams. The body is read verbatim (xparse
188
+ % `v' argument), written to the temp file, and rendered like the environment.
189
+ % Multi-statement diagrams should use the \begin{triton} environment instead.
190
+ \NewDocumentCommand{\tritoninline}{O{\triton@opts} v}{%
191
+ \def\triton@curopts{#1}%
192
+ \immediate\openout\triton@inlinestream=\triton@tmpfile\relax
193
+ \immediate\write\triton@inlinestream{#2}%
194
+ \immediate\closeout\triton@inlinestream
195
+ \triton@render
196
+ }
197
+
198
+ \endinput