AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Library and CLI for converting DOCX files to PDF, matching Microsoft Word's output as closely as possible. Try the demo! 🫶 Accessible: Output PDFs should be just as accessible as Word's export, or better: tagged structure, reading order, language and metadata that pass the same PDF/UA checks. 🎯 Accurate: Given a .docx file, produce a .pdf that is visually identical to what Word would export. ⚡️ Fast: Typical conversions complete in under 100ms. 🤏 Small files: Output PDFs should be the same size or smaller than Word's export.查看完整 README ↗
Library and CLI for converting DOCX files to PDF, matching Microsoft Word's output as closely as possible.
🫶 Accessible: Output PDFs should be just as accessible as Word's export, or better: tagged structure, reading order, language and metadata that pass the same PDF/UA checks.
🎯 Accurate: Given a .docx file, produce a .pdf that is visually identical to what Word would export.
⚡️ Fast: Typical conversions complete in under 100ms.
🤏 Small files: Output PDFs should be the same size or smaller than Word's export.
Reference PDFs are generated using Microsoft Word for Mac (16.106.1 and later). Most (173 of 234) use the "Best for electronic distribution and accessibility (uses Microsoft online service)" export option; the other 61 were made with "Best for printing", macOS's untagged print path.
This crate might work for your production case, do give it a try! The API, output quality, and supported features are all actively changing.
Every fixture in the test corpus rendered side by side by Word (the reference) and
Each engine is scored against the Word reference with the same metrics the test suite uses: three for how the pages look, and one for how accessible the PDF is.
| Metric | What it measures |
|---|---|
| J (Jaccard) | Overlap of ink pixels at 150 DPI. Strict: a one-line vertical shift sends it toward zero. |
| SSIM | Structural similarity on 8×8 windows with ±8 px vertical tolerance, so small drift is forgiven. |
| TB (text boundary) | Share of lines whose first and last word match the reference. Measures line breaking and pagination, independent of fonts. |
| a11y | PDF/UA-1 rules failed (veraPDF), how many of those Word passes, and how closely the tag structure and screen-reader text order match Word's. |
If you have a .docx file that produces ugly, broken, or just plain wrong output, send it to me! Real-world documents with surprising formatting are the best way to improve. Open an issue or PR with the file included and I will try to make it work.
While the idea, architecture, testing strategy and validation of output are all human, the vast majority of the code as of now is written by various Claude models with access to the PDF specification (ISO-32000) and the Office Open XML File Formats specification (ECMA-376). This project was done as an exercise to get experience with the usage of coding agents.
w:position), small caps, all caps, character spacing, text expansion/compression (w:w), hidden text (w:vanish), kerning (legacy kern table + GPOS PairAdjustment), run borders with color/width/spacing, run shading (w:shd) and highlighting, legacy text-effect toggles (w:outline, w:shadow, w:emboss, w:imprint), Word 2010 text effects (w14:glow, w14:shadow, w14:textOutline, gradient w14:textFill), symbols (w:sym), positional tabs (w:ptab), non-breaking hyphens, UAX #14 line breaking, Word's per-character glyph fallback for symbols missing from the run's font (Segoe UI Symbol, Arial, Cambria Math)distribute), space before/after, line spacing (auto, exact, at-least), first-line and hanging indentation, left/right indentation, character-unit indents (*Chars), contextual spacing, keep-next, keep-lines, paragraph borders (top/bottom/left/right/between) with color, paragraph shading, vertical text alignment within the line (w:textAlignment), text frames (w:framePr)basedOn chains), document defaults from docDefaults (all run properties: bold, italic, caps, smallCaps, vanish, strikethrough, dstrike, underline, color, char_spacing), theme fonts and colorsdecimalEnclosedCircle, decimalFullWidth, aiueoFullWidth), list style inheritance, w:lvlRestart, w:lvlOverride/w:startOverride, w:isLgl, w:suff, w:pStyle level associationgridSpan and vertical vMerge), row heights (exact and minimum), per-cell borders with color/width, inline w:tblBorders, cell shading, pattern/hatch shading, vertical alignment, cell text direction (rotated cells, vertical CJK), cell margins, floating/positioned tables (tblpPr), nested tables, conditional formatting (/ — banded rows/columns, first/last row and column), repeated header rows (), , Word-compatible row splitting across pagesw:em), w:fitText, ruby, drop caps, vertical text outside table cellsmediumKashida/highKashida/lowKashida render as plain justify), GPOS mark positioning (harakat), joining across runs with different formatting, mirrored tab stops and bidiVisual tablestext/use/image, gradients, opacity, clip paths and filters (PNG fallback)w:restart (the counter never restarts per page or section)a:prstDash), 3D bevel/rotation (a:scene3d, a:sp3d), preset shadows (a:prstShdw), radial/path gradient fills (drawn as linear)dsp:drawing fallback (see roadmap)altChunk HTML (dropped)Every test case rendered as a Word reference and with docxide-pdf on the comparison page.
# Install the CLI
cargo install docxide-pdf
# Convert a DOCX file to PDF
docxide-pdf input.docx
# Specify output path (defaults to input.pdf)
docxide-pdf input.docx output.pdf
The CLI never overwrites: if the output exists it writes output(2).pdf, output(3).pdf and so on. RUST_LOG=info prints timings.
cargo add docxide-pdf --no-default-features
This avoids pulling in the CLI dependency (clap).
use docxide_pdf::convert_docx_to_pdf;
use std::path::Path;
convert_docx_to_pdf(
Path::new("input.docx"),
Path::new("output.pdf"),
)?;
To keep everything in memory, convert_docx_bytes_to_pdf_bytes takes the DOCX as bytes and returns the PDF as bytes:
let pdf: Vec<u8> = docxide_pdf::convert_docx_bytes_to_pdf_bytes(&docx_bytes)?;
docxide-templatedocxide-template is a sibling crate for type-safe MS Word templates. It scans a folder of .docx files at compile time and generates a Rust struct per template, with {Placeholder} patterns turned into snake_case fields. Pair it with docxide-pdf to go from template → filled DOCX → PDF in a single, fully in-memory pipeline:
use docxide_pdf::convert_docx_bytes_to_pdf;
use docxide_template::generate_templates;
use std::path::Path;
generate_templates!("templates");
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = HelloWorld {
first_name: "Alice".into(),
company: "Acme Corp".into(),
};
let docx_bytes = doc.to_bytes()?;
convert_docx_bytes_to_pdf(&docx_bytes, Path::new("output/greeting.pdf"))?;
Ok(())
}
100% Rust, end to end — no temporary files, and no Word or LibreOffice install required on the host. Fill the template in memory, hand the bytes to convert_docx_bytes_to_pdf, and write the PDF. Combined with docxide-template's embed feature, you get a single self-contained binary that turns structured data into a polished PDF.
| Variable | Description |
|---|---|
DOCXIDE_FONTS | Additional font directories to search, colon-separated (; on Windows). Highest priority: a face found there wins over the system's copy of the same family and style, and the first directory listed wins over the ones after it. System fonts still fill in the families and styles the directories lack. |
DOCXIDE_NO_FONT_CACHE | Set to any value to disable the font index disk cache. Forces a full font scan on every conversion. Useful for debugging font resolution issues. |
Font scanning results are cached to disk (per-directory, invalidated by mtime). The cache is stored at:
~/Library/Caches/docxide-pdf/font-index.tsv$XDG_CACHE_HOME/docxide-pdf/font-index.tsv (default ~/.cache/)%LOCALAPPDATA%\docxide-pdf\cache\font-index.tsvdocxide-pdf lays text out with the fonts it finds. The PDF can only match Word's if the font files match too.
DOCXIDE_FONTS (the first one listed wins), then the system font directories. Lookup is by family plus bold and italic, so a Regular you supply does not block the system's Bold.DOCXIDE_FONTS at it. Run with RUST_LOG=info to see which fonts were substituted.Tests require mutool on PATH for PDF-to-PNG rendering:
brew install mupdf # macOS
apt install mupdf-tools # Debian/Ubuntu
# Run all tests with a compact report of what changed
./tools/run-tests.sh
# Run only the visual comparison (Jaccard and SSIM)
./tools/run-tests.sh --test visual_comparison
.cargo/config.toml points DOCXIDE_FONTS at a fonts/ directory that isn't in the repository (the fixtures' fonts can't be redistributed). Without those fonts many fixtures fall back to substitutes and score lower. The accessibility test also needs veraPDF and Poppler (brew install verapdf poppler) and skips without them.
SCORING.md explains every score: the visual metrics, the accessibility metrics and what fails the suite.
Build the tools once:
cd tools && cargo build
Then run from the project root:
# Inspect XML inside a DOCX
./tools/target/debug/docx-inspect input.docx
# Print font information
./tools/target/debug/docx-fonts input.docx
# Compare two rendered pages
./tools/target/debug/jaccard a.png b.png
# Full fixture diff
./tools/target/debug/case-diff case1
# Browse reference vs generated pages per fixture, with notes
./tools/target/debug/case-browser
# Fixture features and scores, e.g. only the failing ones
./tools/target/debug/analyze-fixtures --failing
# Are our font files the builds Word embedded in these references? (needs mutool)
python3 tools/font_builds.py tests/fixtures/fonts/multi_font/reference.pdf -- fonts
Pull requests are welcome!
Apache-2.0
tblLooktblStylePrtblHeadercantSplitw:rFonts @eastAsia, Word's East Asian line height, compressPunctuation, autoSpaceDE/autoSpaceDN, mixed-script justificationw:bidi paragraphs, Unicode bidi reordering of mixed-direction lines, Arabic contextual joining forms and the lam-alef ligature, right-to-left list labelsa:srcRect), EMF/WMF vector translation to PDF form XObjects, SVG pictures (asvg:svgBlip) drawn as vectors (shapes, paths, solid paints, strokes, transforms, class stylesheets; everything else falls back to the embedded PNG), anchored/floating images with wrap modes (square, tight, through, topAndBottom), floating image positioning relative to page/margin/column, rotation, clipping to shape geometry, behind-document z-ordering, OLE objects (w:object) drawn from their preview picturea:outerShdw), inner shadow, glow, soft edges, reflection — rasterized blur masks via SMaskwps:txbx) and VML fallback (v:textbox), shape fills (solid color with theme color support including lumMod/lumOff, linear gradients with multiple color stops), textbox body marginsprstTxWarp presets — two-path envelope warping (wave, slant, inflate, etc.) and single-path text-on-a-path (arch, circle), text outlines, shadows, glow effects, bold/italic font variant selection, VML WordArt fallbacka:custGeom with moveTo, lineTo, cubicBezTo, arcTo), shape fills and strokes, drawing canvases (wpc:wpc) and shape groups (wpg:wgp/grpSp) flattened with nested transforms, connectorsm:oMathPara) with justification — fractions, radicals, n-ary operators with limits, delimiters, matrices, equation arrays, accents, bars, boxes and border boxes, functions, sub/superscripts and pre-scripts, group characters, phantoms, upper/lower limitsw:mirrorMargins), document grid (linePitch), page borders (w:pgBorders), vertical page alignment (w:vAlign), line numbering (w:lnNumType), explicit page breaks, pageBreakBefore, automatic page breaking with widow/orphan controlnextPage/continuous/oddPage/evenPage breaks, per-section page size and margins, blank page insertion for odd/even page alignmentword/comments.xml rendered in Word's right-hand review pane with callouts and body scalingw:fldChar fields, MACROBUTTON shows its display text or picture, cached results for every other field (and for w:fldSimple)dsp:drawing) with full geometry engine support — all 187 preset shapes, custom geometry, fills (solid, gradient, image), strokes, and textword/settings.xml parsing — even/odd headers, mirror margins, default tab stop interval, gutterAtTop, themeFontLang, characterSpacingControl, compatibilityMode, linkStyles, doNotExpandShiftReturnmc:AlternateContent fallback, structured document tag (w:sdt) content extraction, w:customXml transparent wrappers, altChunk HTML content parsing, smart tag handling, VML fallbacks for shapes, textboxes, WordArt and w:object embedsfontTable.xml altName, then Cambria or Calibri by family class)