Skip to content
w32394045-dotcomPublic

About

离线单文件 Markdown → PDF 排版工具(LaTeX/MathML、内嵌 SVG、SVG/CSS/HTML 渲染型围栏)

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

41 Commits

Folders and files

Repository files navigation

md2pdf — a single-file, offline Markdown → PDF typesetter

License: MIT i18n

English · 简体中文

One HTML file. No build step, no dependencies, no network. Open index.html in Chrome or Edge and turn Markdown into a vector-text PDF — selectable, searchable, sharp at any zoom, not a screenshot.

Try it

Primary: https://md2pdf.xszx.cc.cd — this is the one to bookmark.

Entry URL When to use it
Primary https://md2pdf.xszx.cc.cd Default (custom domain, Cloudflare)
Mirror 1 https://md2pdf.w32394045.workers.dev Same Cloudflare Worker, native address — if DNS misbehaves
Mirror 2 https://w32394045-dotcom.github.io/md2pdf/ GitHub Pages — if Cloudflare is down entirely

All three serve the same index.html, byte for byte. Settings and history live in your browser, so they do not follow you between entries — pick one and stick with it.

Features

  • Markdown rendering — headings, lists, tables, quotes, footnotes, task lists, strikethrough, ==highlight==, code blocks with syntax highlighting, and CJK soft wrapping.
  • Print typesetting — A4 / Letter / A5, three margin presets. Print / Save PDF → system dialog → Save as PDF.
    • Nothing gets clipped — the preview page is exactly as wide as the real printed text area (178 mm on A4 with normal margins), so line breaks match the printout; when the window is too narrow the page is scaled down instead of scrolling sideways. Over-wide display formulas, tables and fixed-width custom HTML shrink to the page width, very tall formulas / images shrink to one page, tall tables may break across pages.
  • Print colours — your choice — three modes in Settings → Print & export: As seen (default) keeps exactly the colours you see on screen; Balanced keeps quote bars, table lines and fills as designed and only darkens text accents such as links (same hue) until they read on paper; Max readability switches the whole palette to ink (the old behaviour). Dark themes always print as black text on white paper, whichever mode you pick, and an exported HTML prints exactly like the app — the print-colour CSS is baked into it.
  • Math — the inlined Temml 0.14 engine (MIT) converts LaTeX to MathML:
    • covers most of amsmath / amssymb: \lesssim \geqslant \boxed \cancel \overrightarrow \operatorname \color \begin{aligned} …
    • renders through native browser MathML, so no font binaries are shipped; print and export stay vector
    • anything Temml rejects falls back to a small built-in parser (now covering \complement, \subsetneq, \Longrightarrow and friends); commands it still does not know are shown in red instead of a silent literal backslash — content is never dropped
  • Chemistry — \ce{…} and \pu{…} without mhchem: \ce{2H2 + O2 -> 2H2O}, \ce{N2(g) + 3H2(g) <=> 2NH3(g)}, \ce{2H2O2 ->[MnO2] 2H2O + O2}, \ce{CuSO4.5H2O}, \ce{SO4^2-}, \pu{1.0e-3 mol/L}.
  • Table of contents — optional, depth H1 … all levels.
  • Accent colour — seven presets, a wheel you can drag anywhere, a typed hex value or the brightness slider. It drives links, the quote bar and tint, table header tint, heading rules, table borders, ==highlight==, task boxes and the UI's own buttons / focus rings. What printing does with it is up to the Print colours setting: As seen leaves it untouched, Balanced darkens only text accents, Max readability converts everything to ink.
  • Page background — upload an image or pick one from the thumbnail history, then crop it in the built-in frosted-glass cropper: A4 / A5 / Letter / square / circle (A4 and A5 share the ratio; only the output resolution differs), drag to move, wheel or pinch to zoom, rendered at device pixel ratio, plus Keep original to skip cropping. Two sliders set the opacity of the image itself and of the tinted content surfaces on top of it (tables, code blocks, quotes, TOC). Printing paints the background as a fixed overlay (Chromium repeats fixed-position elements on each page) — tick Background graphics in the print dialog. The image never leaves the browser.
  • Colour from an image — sample an accent straight out of the current page background, or from any image chosen for the session: a crosshair and a 13×13 pixel magnifier follow the pointer, and on Chromium the system EyeDropper can pick from anywhere on screen (the button is greyed out elsewhere). The last 24 colours are kept in a swatch strip — click to reuse, ✕ to remove — and survive a reload.
  • Render fences — content inside a svg / css / html / render fence is rendered, not shown as code. Tag a fence text to show the code instead.
  • Inline SVG — an <svg> written straight into the Markdown stays vector in the PDF; scripts, event attributes and external URLs are stripped.
  • Author card and footer bar — an optional avatar plus one line of text, placed above or below the document, or repeated at the top / bottom of every printed page. The avatar can be uploaded or picked from the avatar history; the footer info bar with the tool name and repository link can be switched off, or shown once per page with its own switch (off = a single bar at the end). The styles live in the document stylesheet, so preview, print and export match. The avatar and the text each have their own opacity slider, and the strip behind the per-page decorations has a separate background opacity — 100 keeps the solid paper colour (the default, so body text at the page edge stays hidden); lower it and the page background image shows through, at the cost of page-edge body text becoming visible behind the strip.
  • Footnote placement — three modes: all notes at the end (default), each note right after the paragraph that cites it, or both at once.
  • Pictures embedded as base64, with an upload / manage dialog — the 🖼 Image button opens a card with two tabs. Upload compresses a picture to 1600 px on the long edge and writes it straight into the Markdown as ![name](data:image/jpeg;base64,…) (paste or drop into the editor works too), so the .md carries its own pictures: printing, exporting and moving the file never breaks them. Manage lists every image in the document as a thumbnail card — tick the ones to remove and delete; the matching base64 is removed too, no need to select a multi-megabyte string by hand. (Picking images together with the .md still works for older documents; local paths and remote links are no longer needed.)
  • Fill-in blanks — a run of two or more underscores (Answer: ____) is drawn as an even answer line whose width follows the underscore count (min 2.4 em, capped at 12 underscores). In Chinese text __text__ becomes a blank too, so use **text** for bold; a line containing only ___ stays a divider.
  • Spacing directives — put a marker on its own line to control vertical space exactly: [[gap:3]] leaves three blank lines (follows the font size), [[gap:20mm]] leaves a fixed 20 mm (printer-accurate), [[rules:3]] draws three answer rules for filling in by hand, and [[pagebreak]] starts a new page when printed. Several markers may share one line, e.g. [[gap:10]] [[rules:4]]; the whole line must contain nothing but markers. Works in preview, print and exported HTML; invalid markers stay as plain text, and the count is capped (200 lines / 500 mm per line) so a document cannot balloon into dozens of blank pages.
  • JSON extensions — one JSON file can rewrite the text before parsing (preProcess), add inline syntax and new fences (customSyntax), add toolbar buttons that insert a fixed snippet (uiInjection), and add CSS for the document only (cssInjection). The output passes the same sanitiser as render fences; a malformed file disables the whole extension with an error instead of half-applying it; the extension is stored locally and survives a reload.
  • Settings — five tabs: Appearance / Background & images / Smart extensions / Print & export / Data & fonts. Settings are saved to the browser database and restored on reload, with a one-click reset to defaults; the Data & fonts tab also holds font import and the font library. If the database is unavailable (private browsing), the UI says so instead of pretending to save.
  • Settings export / import — packs the settings and the extension JSON into one file for moving to another machine. Background, avatar, document images and fonts are deliberately left out.
  • Export — a self-contained HTML file (fonts, images and the page background embedded), or just the .md.
  • History — the 🗂 History button lists documents written here (title, last edit, word count, size). Open, delete one entry, or clear all. Autosaves ~2.6 s after you stop typing, keeps the newest 50. Everything sits in the browser's IndexedDB; nothing is uploaded.
  • Large documents fall back to IndexedDB — once embedded pictures push the Markdown past the localStorage quota, the text is kept in the local database instead, so reloading the page does not lose it.
  • Seven UI languages — 简体中文 · 繁體中文 · 日本語 · 한국어 · Deutsch · Français · English. Detected from your browser on first load, switchable from the 🌐 dropdown in the toolbar, and the built-in sample document follows the language as well (each language has its own hand-written sample, not machine output). Switching language reloads the page by default so every label, menu and sample is rebuilt cleanly, and swaps the sample to the new language; both behaviours can be switched off in Settings, and the seven accent-colour presets are translated too.

Usage

  1. Open index.html in Chrome or Edge (double-clicking the file works — no server needed).
  2. Click Open and pick a .md. To add pictures, click 🖼 Image (or paste / drop them into the editor) — they are compressed and embedded as base64, so the .md keeps them. Older documents that reference images by file name still work: select the .md and the images together when opening.
  3. Check the preview, then click Print / Save PDF and choose Save as PDF in the system dialog.
    • A web page cannot write a PDF file by itself; this route is the only one, and it is what yields vector text.
    • Want page numbers? Turn on Headers and footers in the print dialog.

Safety

Raw HTML and render fences are sanitised: <script>, event attributes (onclick …), javascript: / data:text/html protocols, external url() and @import are stripped. JSON extensions go through the same filters: generated HTML is sanitised, placeholders are inserted as data (escaped) rather than raw HTML, and extension CSS reaches the document stylesheet only, with @import, javascript: and external url() removed. The tool itself fetches nothing at runtime — the math engine is inlined, not pulled from a CDN — but a document that embeds remote images will still make the browser load them, so keep untrusted documents offline. Intended for documents you trust.

Third-party

  • Temml 0.14.0 — LaTeX → MathML, MIT, inlined together with its full licence text. See THIRD-PARTY.md for the notice, why KaTeX / MathJax / mhchem were not used, and what changed (only the @font-face rule was dropped, since the single-file build ships no font binaries).

Related projects

  • md2pdf-authoring — a companion AI skill (generic). It teaches an agent how to drive this tool and how to write Markdown whose maths, chemistry, figures and tables survive rendering and printing, and ships a check_md.py linter to run before delivery. Installing is one copy-paste: the skill repo's README has a ready-made prompt for Claude Code / Codex / DSH / Cursor, plus a file-drop route for chat-only assistants (ChatGPT, Kimi, Doubao …).

  • md2pdf-ext-rules — the second companion AI skill, for the JSON extension system (Settings → Smart extensions). It teaches an agent to write preProcess, customSyntax (inline + block), cssInjection and uiInjection correctly: $content only outside tags, namespaced fences and CSS, the $ traps in replacement strings, and what gets silently skipped. It ships a check_ext.py linter and sixteen counter-examples of mistakes that either disable the whole extension or fail quietly. Same install routes as above.

  • imgprint — imgprint.xszx.cc.cd · the single-file image printer for the same ecosystem: drop in several photos, choose paper size, margins and 1-2-4 images per page, print. It warns about effective DPI and non-sRGB colour spaces, runs fully offline in 7 languages, and carries the same switchable footer watermark. Use it when the thing to print is images rather than Markdown.

  • booklet — booklet.xszx.cc.cd · the standalone Booklet Printer (its own repository): load any PDF, fold-impose it two-up for saddle stitching (A4 → A5, A3 → A4), and print it in three passes straight from the browser — front sides, flip the whole stack, back sides, then the separate jacket sheet last. Adjustable centre gutter, auto-split, separate front/back cover images or PDFs printed on the jacket, a live sheet preview, and two print engines (vector PDF or rendered pages). The file never leaves the browser, printed output carries no watermark, and the UI has the same 7 languages.

  • pagepicker — pagerange.xszx.cc.cd · the print page-range builder for the same ecosystem: tell it the document's page count, light up the pages you want on the heat-map overview (or type 1-5, 8, 10-13), and copy the string straight into the print dialog's Pages / Page range field. Built for printers without a duplexer — it hands you the odd side and the even side as two separate strings, so you print one side, flip the stack, print the other. Runs fully offline in one HTML file, in 7 languages, and carries the same switchable footer.

Licence

MIT © 2026 w32394045-dotcom

Use it, change it, redistribute it — keep the copyright notice. No warranty.

About

离线单文件 Markdown → PDF 排版工具(LaTeX/MathML、内嵌 SVG、SVG/CSS/HTML 渲染型围栏)

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages