Registry / RepositoryTypeScriptRustPython
Rollpie
ReadmeFiles
Versions
Info
Download
0.4.01085.8 KB2026-10-160.3.21087.6 KB2026-10-160.3.11087.5 KB2026-10-160.3.0117.8 KB2026-10-160.2.1106.1 KB2026-10-150.2.0105.5 KB2026-10-15
Version
0.4.0
Copyright
Rollpie, Irohabook
Publisher
math
Published
2026-10-16
Size
1085.8 KB
Downloads
18
Checksum
df10d3447b809454aba0a9fd252d07428b819520aff22324461ba2dcbf1e43fb
Dependencies
rust/[email protected]
rust/[email protected]

[email protected]

iroha get rust/[email protected]

hongo

A Rust library that typesets documents written in LaTeX into PDF.

It uses neither TeX nor LaTeX. Reading the source, breaking lines, laying out pages and writing the PDF are all done here. Math goes to suki, and chemical structures go to lina. Apart from these two, it depends on no crates.

It can set text that mixes Japanese and Latin script. It handles the spacing between Japanese characters, the space between Japanese and Latin text, and the characters that may not begin or end a line.

Usage

cargo build --release
./target/release/hongo doc.tex

The PDF is written next to the document, with the same name and .pdf. Change it with -o.

./target/release/hongo doc.tex -o out.pdf

Fonts go in font/. The math typeface is looked up under the name latinmodern-math.otf. For Japanese, the first file in font/ that is not the math typeface is used. To choose a font for each role, pass --font-roman, --font-japanese and so on. --help lists them.

It also works as a library.

use std::path::Path;

let library = hongo::font::open(
    Path::new("font/latinmodern-math.otf"),
    None, None, None, None, None,
    Some(Path::new("font/ipaexm.ttf")),
)?;
let source = std::fs::read_to_string("doc.tex")?;
let made = hongo::render(&source, &library, &hongo::Style::default(), Path::new("."))?;
std::fs::write("doc.pdf", made.data)?;

It also runs in a browser as wasm, as described under Typesetting as you type.

Trying it in a browser

A small server comes with it. Paste a source and press the button, and it becomes a PDF that shows on the page and can be saved.

cargo run --release --example serve

Open http://127.0.0.1:7830. It does not accept connections from other machines. If there is no Japanese typeface in font/, pass one with --font-japanese.

cargo run --release --example serve -- --font-japanese /path/to/mincho.otf

test/report.tex is loaded at the start. Edit it and press the button to typeset it again. If the source has a mistake, the page says on which line and what could not be read.

Typesetting as you type

web/index.html typesets in the browser while you type, with no server. Write LaTeX on the left, and the pages appear on the right. hongo runs inside the page as wasm.

The package comes with web/hongo.js and web/font.js, so web/index.html works as soon as it is opened by double clicking. web/font.js holds only Latin Modern Math, under the GUST Font License in web/GUST-FONT-LICENSE.txt, so Japanese text does not appear.

To make them again, build the wasm, then write what the page needs next to it.

rustup target add wasm32-unknown-unknown
cargo build --lib --release --target wasm32-unknown-unknown
cargo run --example web

The build makes target/wasm32-unknown-unknown/release/hongo.wasm, about 830 KB with Rust 1.98.1. A page opened by double clicking cannot read the files next to it, so examples/web.rs writes the wasm into web/hongo.js and the fonts into web/font.js as base64. Then open web/index.html. The directory can be copied anywhere, and --output ~/Desktop/hongo writes it there directly. When font/ has no Japanese typeface, pass one with --font-japanese.

If the cargo found first on the PATH is not rustup's (Homebrew's Rust, for example), it has no standard library for wasm32, and the build stops with "can't find crate for std". Run rustup's cargo and rustc directly. If rustup's rust-lld then cannot load libLLVM.dylib, add the toolchain's lib to the library path.

TOOL="$HOME/.rustup/toolchains/stable-aarch64-apple-darwin"
DYLD_FALLBACK_LIBRARY_PATH="$TOOL/lib:$HOME/lib:/usr/local/lib:/usr/lib" RUSTC="$TOOL/bin/rustc" "$TOOL/bin/cargo" build --lib --release --target wasm32-unknown-unknown

The right side shows the pages before they become a PDF, drawn as SVG with the glyph outlines from suki. Typesetting runs in a worker, so typing never waits for it, and a document that takes more than five seconds is stopped. The button writes the same pages as a PDF. Images and \input cannot be used there, because the page cannot read files.

Checking the page

The page was checked on macOS. The package was unpacked as it is downloaded, and its web/index.html was opened in Chrome from file://, as a double click opens it. The sample was typeset into one page in about 9 ms, with no character missing from the typeface. Typesetting again after an edit, the message for a mistake, and making the PDF were checked in a browser, with the page served from 127.0.0.1.

To check it by hand, open web/index.html and see that

  • the sample is typeset, and the bar at the top shows the number of pages and the milliseconds it took
  • an edit is typeset again as soon as typing stops
  • a mistake such as \nosuchthing shows its line and column, and the last pages stay
  • the button saves a PDF

Samples

They are in test/. cargo run --example check typesets all of them.

  • article.tex - an article with math, tables, footnotes and references (3 pages)
  • report.tex - a report with chapters, an appendix, floating figures, p{} columns and chemical structures (14 pages)
  • sample.tex - one of each command (3 pages)
  • figure.tex - images, floats and footnotes (2 pages)
  • feature.tex - chapters, the appendix, alignment and nested lists (3 pages)

What you need

Latin Modern Math (latinmodern-math.otf) is needed as the math typeface. It is the same file as in suki's font/. Without it, neither math nor Latin text can be set.

To set Japanese, put a Japanese typeface in font/. IPAex Mincho and Noto Serif JP may be embedded in PDF. Without one, Japanese characters do not appear, and hongo lists the missing characters at the end.

With the Latin Modern text faces (lmroman10-regular.otf and so on), body text is set in them. Otherwise the Latin glyphs of the math typeface are used, and bold and italic are replaced by the math alphanumeric characters (from U+1D400).

Where it runs

It is written with the standard library only, so it runs wherever Rust does. It makes no OS-specific calls. Sources with CRLF line endings are read too.

It has been checked on macOS only, not on Linux or Windows.

Only examples/check.rs looks for a macOS font when font/ has no Japanese typeface. It exists for local checks, and a font in font/ is used first.

Supported LaTeX

The document structure covers \documentclass, \title, \author, \date, \maketitle, \tableofcontents, headings from \part to \subparagraph, and \appendix. article has no chapters; report and book do. A chapter starts on a new page.

Font changes are \textbf, \textit, \emph, \texttt, \textsf and \underline, and declarations such as \bfseries. Sizes run from \small to \Huge.

Environments are itemize, enumerate, description, quote, quotation, center, flushleft, flushright, verbatim, abstract, tabular, table, figure and thebibliography. Tables take l, c, r and p{width} columns, | rules, \hline and \multicolumn.

Math is $…$, \(…\), $$…$$, \[…\], equation, align and gather, with their starred forms. suki sets the contents, including aligned, split and gathered inside a formula. Chemical structures are \chemfig and \chemname, set by lina.

References are \label, \ref, \pageref, \cite, \footnote and \caption. Images are \includegraphics, which reads width, height and scale. PNG and JPEG can be used.

You can define your own commands and environments. \newcommand{\name}[number of arguments][default]{body} and \newenvironment{name}[number of arguments]{begin}{end} are read and expanded into the tokens. plain TeX's \def\name#1{body} is read too. \input and \include are replaced by the contents of the file.

Furigana is added with \ruby{漢字}{かんじ}. The base text and the reading are centered on the wider of the two. The reading is drawn in the space between lines, so the line spacing does not change. The table of contents and the bookmarks show only the base text.

Some commands from common packages are read with a substitute. booktabs' \toprule and the like become horizontal rules, and \textcolor drops the color and keeps the content. \fbox, \mbox, \rule, \eqref, \footnotemark, \footnotetext, minipage, repeated columns such as *{3}{c}, and accented letters such as \'e are read as well.

How it works

Reading, layout and writing are kept apart.

token cuts the source into tokens, and parse builds a tree. The contents of math, chemical structures and verbatim are kept as written, to be passed to suki and lina unchanged.

number numbers headings, figures, tables, equations and references, and ties each \label to its number.

layout turns the tree into a vertical list. line breaks body text into lines. When both edges are justified, it chooses the breaks by looking at the whole paragraph; otherwise it fills each line as far as it goes. Zero-width spaces sit between Japanese characters, so lines of Japanese alone are justified the same way.

page lays the vertical list out on pages. A footnote is placed on the same page as the line that carries it, and the room for body text shrinks accordingly. Floats go to the top of the first page where they fit, and a float too large for that goes on a page by itself.

A page is broken where the penalty of the break and the space it leaves empty at the bottom cost least, so the first or last line of a paragraph is rarely left alone on a page.

pdf writes the file. Every character is set in a Type0 font with Identity-H, so glyph IDs can be written directly. Glyphs with no character assigned (such as stretched delimiters) and Japanese are handled the same way. ToUnicode is added so that text can be selected and copied.

The table of contents and \pageref cannot be written until page numbers are known, so layout runs twice.

Decisions

No outside crates. Fonts are read with suki's code, and the PDF writer is written here.

Content streams are not compressed, so that no compressor has to be written; the files are larger for it. Japanese typefaces are cut down to the glyphs used before they are embedded, so even a 20 MB typeface ends up as a few hundred kilobytes.

PNG and JPEG are passed to the PDF without being decoded. PNG's IDAT is zlib, and so is PDF's FlateDecode, so the data can go in as it is once the predictor parameters are copied over. PNGs with transparency are not read, because separating the transparency would mean decoding the image.

Not supported

There is no hyphenation for Latin text. Without hyphenation tables, a long word that does not fit simply runs past the end of the line.

Kerning and ligatures are not applied, because the font's kern and GPOS tables are not read.

Two-column layout, marginal notes, indexes and reading references from .bib files are not supported.

License

Dual licensed under MIT and Apache-2.0. Take whichever you prefer.