0.7.5-rc2
Pre-release
Pre-release
·
236 commits
to main
since this release
Installation
latexml-oxide ships as a single self-contained executable. It also calls a few external tools when they are on your PATH:
- a TeX distribution (TeX Live, MacTeX, or MiKTeX) — for the packages, classes, and fonts your documents load.
- graphics tools (ImageMagick, Ghostscript, MuPDF, Poppler, dvipng, dvisvgm) — to convert figures.
Per-platform install instructions are in the README Installation guide.
Download the asset for your platform (each has a matching .sha256 to verify file integrity):
- Linux (x86-64) —
latexml-oxide_0.7.5-rc2-1_amd64.deb, or the portablelatexml-oxide-0.7.5-rc2-x86_64-unknown-linux-gnu.tar.gz - Linux (aarch64 / arm64) —
latexml-oxide_0.7.5-rc2-1_arm64.deb, or the portablelatexml-oxide-0.7.5-rc2-aarch64-unknown-linux-gnu.tar.gz - macOS (Apple Silicon) —
latexml-oxide-0.7.5-rc2-aarch64-apple-darwin.tar.gz - macOS (Intel) —
latexml-oxide-0.7.5-rc2-x86_64-apple-darwin.tar.gz - Windows (x86-64) —
latexml-oxide-0.7.5-rc2-x86_64-pc-windows-msvc.zip(unzip;latexml_oxide.exeis self-contained, no installer)
Changelog
[0.7.5] (Rhai binding-API parity + default-CSS sync; ar5iv corpus fixes; file-resolution robustness)
- Runtime (Rhai) binding API brought to feature-parity with the compile-time
macros. A binding can now fetch an already-installed definition and push
before/after digest and construct hooks onto it (LookupDefinition), pass the
same flexary, unordered option bags toDefPrimitive/DefMath/DefConstructor
(beforeDigest/afterDigest/afterDigestBody), register new definitions from
inside a running body, shell out to external commands, read the engine version,
and use the full diagnostics surface (Info/Fatal/Note/progress).
List-valued state lookups no longer panic or leak their internal representation. - A
.rhaibinding can now parse and manipulate XML/(X)HTML.
document.insertXML(markup)splices a parsed subtree into the document at the
current point — the runtime half of BookML's\bmlRawHTML→<ltx:rawhtml>—
where previously only escaped text could be inserted.ParseXML(markup)exposes
the parser on its own, returning nodes a script can inspect, walk and edit
before inserting them; a chunk may be a fragment of several siblings. Parsed
nodes are safe to hold because each owns its document. Malformed markup is
rejected outright rather than quietly salvaged — libxml's recovery mode
silently deletes author content (<b>a</b> <i>b</i>became<b>a</b>,
a bbecameab). Inserted markup also keeps its own namespace:
namespaces resolve by URI through the registered prefix map
(RegisterNamespace) instead of being assumed to be LaTeXML's, and wildcard
schema entries such asxhtml:*are honoured, so attributes likeclass
survive onto the final page. A malformed chunk degrades only its own binding:
the rest of the document still converts, and the reported error names the
likely cause and quotes the offending snippet. .rhaibindings now reach the same document XML surface the compile-time
bindings do — XPath query (findnodes/findnode), element insertion
(insertElement), and structural editing (addClass,generateID,
removeNode,replaceNode,renameNode,wrapNodes,unwrapNodes,
appendClone,openElementAt/closeElementAt), each under its Perl name, so
the runtime and compile-time binding layers do not drift apart. Reading a
namespaced attribute such asxml:idback by its qualified name now works.- A failing
.rhaibinding no longer costs the whole document. An error
raised anywhere in a script body — athrow, a typo'd method name, an
operation-limit breach — used to abort the entire conversion; a single
throwing macro produced an empty document. Each binding kind now degrades to a
neutral result (an empty expansion, a skipped constructor, a false
conditional, …), reports a cleanError:, and the rest of the document
converts. A binding that fails repeatedly still ends the run at the usual
error ceiling, and a script that fails to compile still simply does not
install. - Default HTML styling re-synced to vanilla
LaTeXML.css— restores justified
text,\underline/\overline, and verbatim no-wrap that had drifted from
upstream; the.htmdestination extension now infers HTML5 like.html. - A stale or empty stylesheet already in the output directory is now overwritten
instead of being left in place — previously aLaTeXML.css/ltx-article.css
left by an earlier run could be truncated to empty, leaving the page unstyled. - Split output (
--splitat) now styles every page. Each auto-generated split
child (e.g.Ch1.html) again loads the default stylesheets and carries the
document date, matching Perl — a shared post-processing XPath defect had been
dropping resources, processing instructions, and other relative-path lookups
(also repairing split navigation and cross-reference/glossary resolution). - Split-page navigation links reach Perl parity. Each page now emits the full
<link rel=…>head set —prevback to the parent for a first child, the
relation-typedchapter/section/subsectionsibling and ancestor links, and
full-breadcrumbtitle=attributes on all of them (previously the relation-typed
links andprev-for-first-child were missing and the titles were empty). - Generator identifier now spells out the full product name ("LaTeXML oxide")
and stamps the version into the XSLT output to match Perl. - A
standalonedocument class's options are no longer mis-loaded as packages. - A package loaded in a subfile's preamble keeps its definitions. A
standaloneor\import-ed child used to end an otherwise complete conversion
with\ifpgf@external@grabshipoutundefined: the group around the child's
preamble discarded what the package defined, while the document hooks reading it
survived. The child's own definitions stay scoped to the child. - Named scopes are tracked correctly again. A scope that had been deactivated
still read as active, so it could never be re-activated — a counter- or
label-derived reference-number scope reused after a counter reset kept the
stale one — and a second deactivation popped the same bindings twice. \includefrom/\subincludefromno longer drop their file in silence — the
included content used to vanish with no error or warning at all.- The cortex worker builds without the
runtime-bindingsfeature — a
Rhai-free conversion binary for the fleet. - File resolution can no longer die silently. A conversion could run with
no kpathsea backend at all and say nothing about it: a failed
Kpaths::new()was discarded, so every lookup returnedNonewhile embedded
bindings and dumps kept the conversion working. The only symptom was
Can't find TeX file X— indistinguishable from a file that is genuinely
absent. The trigger was an unresolvablekpsewhich: missing from the
process'sPATH(as opposed to the user's interactive shell), a stale
KPSEWHICH, not executable, or akpsewhich.exebeside a Linux binary under
WSL. Fixed in kpathsea 0.3.4
(a linkedKpaths::new()degrades its program-name anchor instead of failing)
plus a subprocess fallback here. - Every conversion log now records the file-resolution backend —
in-process,subprocess kpsewhich, orunavailable. A dead or degraded
resolver used to be invisible and had to be inferred; it is now one line in an
ordinary log, with no special flags. A host TeX installation remains optional,
so an absent one warns rather than errors. - ar5iv corpus fixes (from the 2026-07 issue sprint):
xcolornow honors a
dvipsnamesglobal class option;\sidecaptionvposbound as a layout no-op;
\newtcblistingbodies close as verbatim;agujournal2019end-matter
(rotating + acronyms/notation);blkarraysupport, recovering papers that
previously hit OOM/timeout;scrartcl\titleheadfrontmatter capture; and
frontmatter bindings forfairmeta,selfevolagentandopenmossclasses. - A deferred package-load miss no longer poisons a later raw load.
- Perl
.ltxmlbindings are never read as TeX. When raw-loading a style
package that also ships a Perl LaTeXML binding (e.g. sTeX'sstex.sty.ltxml),
file resolution used to hand back the.ltxml— Perl source — and the loader
tokenized it as TeX, emitting spurious errors. latexml-oxide can't run Perl
bindings; binding availability is decided by its own dispatcher, so a missing
binding now falls through to the raw.sty, matching pdflatex. The
standalonebinding also regained standalone.sty's realxkeyval+
currfile → filehookdependencies, so the package-file hooks
(\AtEndOfPackageFile, …) and\define@keyexist — enough for raw sTeX 3.x
to load cleanly. \usepackage{X}now finds anX.sty.rhairuntime binding on$TEXINPUTS.
Previously only\input{file}resolved via TEXINPUTS while a Rhai package
binding placed in a texmf tree needed an explicit--path; the discovery now
consults kpsewhich too (covers.sty.rhaiand.cls.rhai). A.rhaibeside
your document keeps overriding a compiled binding; one that merely sits in a
texmf tree only fills a gap, so a stray copy there can no longer displace an
engine binding.cprotectis now supported —\cprotect\section{\verb|…\tensor…|}and
\cprotect\footnote{\begin{verbatim}…\end{verbatim}}produce the verbatim
title/footnote instead of\cprotect is not defined. The package works around
a TeX-only limitation (a braced argument is tokenized before\verbcan change
catcodes) by writing the argument to a scratch file and\inputting it back;
the binding does the same re-read through a mouth, with no file written.
\cMakeRobustand\cprotEnvcome with it. Perl LaTeXML has no binding for
this package.- The
.rhaibinding interface now has a reference. Every function a
runtime binding can call is listed, grouped by the handle it is called on,
each with a one-line explanation and a link to the Rust item implementing it.
It renders intocargo doc(and docs.rs) beside the Rust API. The list is
generated from the live engine rather than hand-maintained, so it cannot
drift from what is registered, and a test fails if a newly registered call
is left undocumented.
What's Changed
- chore(deps): Update syn requirement from 2 to 3 by @dependabot[bot] in #313
- fix #309: a standalone child's \documentclass options are not packages by @dginev in #310
- test: strict 0-error gate for hand-written conversion tests by @dginev in #322
- fix #314: LookupTokens on a VecDequeStored value no longer panics by @dginev in #324
- ar5iv mini-sprint: alignment + runaway fixes, parity triage by @dginev in #323
- fix #315: LookupString reverts option lists comma-separated (no Debug leak) by @dginev in #325
- Revert #325: rethink #315 reversion representation by @dginev in #327
- fix #315: structural list access (LookupString scalar-only, add LookupValue array) by @dginev in #328
- refs #312: re-sync bundled default CSS to vanilla; pin .htm→html5 inference by @dginev in #326
- fix #319: complete the Rhai diagnostics surface (Info/Fatal/Note*/Progress*) by @dginev in #329
- fix #317: RequireResource accepts an option map (type/media/content) by @dginev in #330
- fix #316: allow registration (DefPrimitive/DefMacro/…) from inside a body by @dginev in #331
- fix #318: external commands from Rhai bindings (std::process::Command mirror) by @dginev in #332
- harden: cortex_worker builds drop runtime-bindings (rhai-free untrusted worker) by @dginev in #334
- fix #321: LookupDefinition + before/after hook pushes for Rhai bindings by @dginev in #333
- fix #320: expose the latexml-oxide version to Rhai via LaTeXMLVersion() by @dginev in #335
- XSLT LATEXML_VERSION generator-stamp: restore Perl-parity + BookML utils.xsl by @dginev in #337
- Rhai Def* option-bag parity: digest hooks + afterDigestBody by @dginev in #336
- Generator identifier: spell out the full "LaTeXML oxide" by @dginev in #338
- fix #312: overwrite stale destination stylesheets instead of truncating them by @dginev in #339
- fix #333 (r3623947537): hook-push splices at same-level scope, not global by @dginev in #340
- fix #341: split HTML pages carry the default CSS links (and PIs/date) by @dginev in #342
- crossref: split-page navigation-link parity with Perl by @dginev in #343
- feat: raw-load Perl-bound style packages (sTeX) instead of misreading the .ltxml by @dginev in #344
- fix #345: find a .sty.rhai runtime binding on $TEXINPUTS by @dginev in #346
- Add TL2026 to the release dump window by @dginev in #349
- fix #311: hoist a package load past the enclosing group by @dginev in #348
- feat #350: expose an XML parser to .rhai bindings by @dginev in #351
- feat #347: bind cprotect.sty (verbatim in macro arguments) by @dginev in #353
- docs: generate the .rhai interface reference into cargo doc by @dginev in #352
- release: fix the RC release-body CHANGELOG slice; refresh verification numbers by @dginev in #355
Full Changelog: 0.7.5-rc1...0.7.5-rc2