leonardosalasd/doc-engine-cli

GitHub: leonardosalasd/doc-engine-cli

一款基于 Typst 引擎的零配置命令行工具,将 Markdown 转换为具有学术级排版质量的 PDF 文档。

Stars: 29 | Forks: 0

# doc-engine-cli **零配置 Markdown → PDF 文档引擎** [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Python 3.10+](https://img.shields.io/badge/python-3.10+-3776AB.svg?logo=python&logoColor=white)](https://www.python.org/downloads/) [![PyPI](https://img.shields.io/pypi/v/doc-engine-cli.svg?logo=pypi&logoColor=white&color=006DAD)](https://pypi.org/project/doc-engine-cli/) [![PyPI Downloads](https://static.pepy.tech/personalized-badge/doc-engine-cli?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/doc-engine-cli) [![Typst](https://img.shields.io/badge/Powered_by-Typst-239DAD.svg?logo=typst&logoColor=white)](https://typst.app/) [![Code style: black](https://img.shields.io/badge/code_style-black-000000.svg)](https://github.com/psf/black) 将任何 `README.md` 转换为优质的、可打印的 PDF 报告 —— 无需配置,无需模板,无需 LaTeX。
doc-engine-cli Generation Demo
``` pipx install doc-engine-cli ```
## 概述 **doc-engine-cli** 是一款开发者优先的 CLI 工具,它使用 [Typst](https://typst.app/) 作为渲染后端,将 Markdown 文件转换为具有专业排版的 PDF 文档。它专为需要高质量文档产物的团队和个人开发者设计,免去了 LaTeX 的复杂性或手动排版的工作。 该工具会自动检测你的 `README.md`,从 Git 提取元数据,并在单一命令中生成一份受 IEEE 启发的技术文档 —— 包含封面、目录和高级排版。 ``` doc-engine build ``` 就是这样。无需任何配置。 ## 功能 | 功能 | 描述 | |---|---| | **零配置** | 自动检测 `README.md`、Git 作者和文档标题。无需设置文件。 | | **五种模板** | 包含 academic、modern、minimal、technical 和 book 布局,每种都可配置强调色。通过 `--template` 指向你自己的 `.typ` 文件可进一步定制。 | | **Front Matter** | 可选的 `---` 元数据块可直接在文件中设置标题、副标题、作者、模板和强调色。 | | **Watch Mode** | 每次保存源文件时,`--watch` 都会重新构建 PDF。 | | **丰富的 Markdown** | 支持嵌入本地图片,将 GitHub 任务列表渲染为真实的复选框,并将 `[^1]` 脚注转换为原生的 Typst 脚注。 | | **错误检查** | 在编译前报告源文件中的问题及其行号和列号。`--dry-run` 模式可单独运行此检查。 | | **非破坏性** | 从不覆盖现有的 PDF —— 除非你传入 `--force`,否则会写入 `report (1).pdf`、`report (2).pdf` 等。 | | **高级排版** | 带有备选字体链的 Inter 字体家族,两端对齐文本以及优化的行间距。 | | **纯 Python** | 无需外部二进制文件(无需 Pandoc,无需 LaTeX)。通过单个 `pip install` 发布。 | | **跨平台** | 兼容 Windows、macOS 和 Linux,需 Python 3.10+。 | ## 🎓 学术功能 (v0.1.2+) `doc-engine-cli` 自带高级科学布局(使用 Linux Libertine 和 Inter 字体家族)以及**零配置参考文献**处理功能。 要为你的 PDF 添加 IEEE 风格的参考文献: 1. 在你的代码仓库中创建一个 `refs.bib`、`references.bib` 或 `bibliography.bib` 文件。 2. 在你的 `README.md` 中,使用标准语法引用:`[@citation-key]`。 当你运行 `doc-engine build` 时,CLI 会自动检测你的 `.bib` 文件,将其安全地绑定到沙盒中,并在文档末尾注入一个格式化的参考文献页面。 ## 快速开始 ### 安装 ``` pipx install doc-engine-cli ``` *(如果你没有 `pipx`,可以通过 `pip install pipx` 安装)* ### 生成你的第一个 PDF 导航到任何包含 `README.md` 的项目目录并运行: ``` doc-engine build ``` 该工具将会: 1. 自动检测当前目录下的 `README.md` 2. 从第一个 `# heading` 提取文档标题 3. 读取你的 Git `user.name` 作为作者字段 4. 生成一个包含封面、目录和格式化内容的 `README_doc.pdf` ### 显式选项 ``` doc-engine build path/to/file.md -o output.pdf -t "Custom Title" -a "Author Name" ``` ## 用法
doc-engine-cli configuration demo
Switching templates, recoloring the accent, and checking a file for errors.
### 命令 ``` doc-engine build [INPUT_FILE] Convert a Markdown file into a PDF doc-engine info Show version, repository, and templates doc-engine --version Print the version and exit doc-engine --help Show all commands and flags ``` ### `build` 标志 | 标志 | 默认值 | 描述 | |---|---|---| | `INPUT_FILE` | 自动检测 `README.md` | 要转换的 Markdown 文件的路径。 | | `-o, --output` | `_doc.pdf` | 输出的 PDF 路径。 | | `-t, --title` | 第一个 `# heading` | 覆盖文档标题。 | | `-s, --subtitle` | 无 | 封面上标题下方显示的副标题。 | | `-a, --author` | `git config user.name` | 覆盖作者名称。 | | `--date` | 今天 | 封面上显示的日期。 | | `--template` | `academic` | 内置布局(`academic`、`modern`、`minimal`、`technical`、`book`)或你自己的 `.typ` 文件路径。 | | `--accent` | 模板默认值 | 十六进制值(`#2563eb`)或名称(`blue`、`teal`、`rose` 等)表示的强调色。 | | `--bib` | 自动检测 `refs.bib` | 用于参考文献的自定义 `.bib` 文件的路径。 | | `--no-branding` | 关闭 | 在 PDF 中隐藏 `doc-engine` 的署名。 | | `--dry-run` | 关闭 | 检查 Markdown 错误并在不生成 PDF 的情况下退出。 | | `-w, --watch` | 关闭 | 每当源文件更改时自动重新构建。 | | `-f, --force` | 关闭 | 覆盖输出文件,而不是写入带有编号的副本。 | | `--open` | 关闭 | 在生成 PDF 后将其打开。 | 任何标志也都可以在 front matter 中设置(见下文);命令行上的标志始终具有最高优先级。 ### 示例 **基础 —— 零配置模式:** ``` cd my-project doc-engine build # → 生成 README_doc.pdf ``` **指定输入和输出:** ``` doc-engine build CONTRIBUTING.md -o contributing_guide.pdf ``` **覆盖元数据:** ``` doc-engine build -t "API Reference v2.0" -a "Engineering Team" ``` **选择模板和强调色:** ``` doc-engine build --template modern --accent teal doc-engine build --template technical --accent "#7c3aed" ``` **在构建前检查错误:** ``` doc-engine build --dry-run ``` **从 PDF 中移除引擎署名:** ``` doc-engine build --no-branding ``` **生成后立即打开:** ``` doc-engine build --open ``` **每次保存时重新构建:** ``` doc-engine build --watch ``` **作为 Python 模块使用:** ``` python -m doc_engine build README.md ``` ## Front Matter 任何 Markdown 文件都可以通过在开头添加一个 `---` 块来携带自身的设置,这样文档对每个人渲染出来的效果都是一样的 —— 无需记忆任何标志: ``` --- title: Payments API subtitle: Integration Guide author: Platform Team template: technical accent: teal --- # Payments API ... ``` 支持的键有:`title`、`subtitle`、`author`、`date`、`template`、`accent` 和 `bib`。命令行传入的标志会覆盖相应的 front matter 键,而后者又会覆盖自动检测到的值。 ## Watch Mode 传入 `--watch` 可保持 `doc-engine` 运行,并在你每次保存源文件时重新构建 PDF。这是微调模板或强调色并实时查看结果的最快方法:
doc-engine watch mode rebuilding on save
Metadata read from front matter, rebuilt live on every save.
``` doc-engine build --watch --template modern --accent teal ``` 输出路径在 watch 启动时选择一次,随后每次更改时都会原地重写。按 `Ctrl+C` 停止。 ## 模板 `doc-engine` 自带五种布局。通过 `--template ` 切换,并使用 `--accent` 为其中任何一种重新着色。 | 模板 | 外观 | |---|---| | `academic` | 衬线体 IEEE 风格报告,包含封面、目录和页眉。默认模板。 | | `modern` | 简洁的无衬线体布局,具有宽敞的间距和左对齐的封面。 | | `minimal` | 无封面或目录 —— 紧凑的标题块,然后直接进入正文。 | | `technical` | 粗体布局,带有填充的强调色横幅和章节标记。适用于工程文档。 | | `book` | 经典的居中标题页,带有章节式的分节符。 | ``` doc-engine build --template book doc-engine build --template modern --accent rose ``` 强调色接受十六进制值(`#0ea5e9`)或以下名称之一:`blue`、`sky`、`indigo`、`violet`、`purple`、`red`、`rose`、`orange`、`amber`、`green`、`emerald`、`teal`、`slate`、`black`。 ### 自带模板 `--template` 也接受一个 `.typ` 文件的路径,因此你无需派生该项目即可发布内部风格: ``` doc-engine build --template ./corporate.typ ``` 最快的上手方法是复制 [`doc_engine/templates/`](doc_engine/templates) 中的其中一个文件并进行编辑。模板会暴露一个单一的 `setup_doc` 入口点,编译器会将文档元数据传递给它: ``` #let setup_doc( title: "", subtitle: "", author: "Anonymous", date: datetime.today().display(), bibliography_file: none, accent: none, branding: true, version: "", body, ) = { ... } ``` ## 检查错误 在编译之前,`doc-engine` 会扫描 Markdown 中的问题,并报告准确的行号和列号,以便你可以直接跳转到需要修复的地方: ``` README.md:42:8: error: link URL must not be empty README.md:51:1: warning: image source is empty ``` 错误会终止构建;警告则不会。使用 `--dry-run` 可在不生成 PDF 的情况下单独运行检查 —— 这在 CI 中非常实用: ``` doc-engine build --dry-run ``` ## 架构 ``` ┌─────────────┐ │ README.md │ └──────┬──────┘ │ ┌──────▼──────┐ │ CLI Layer │ click + rich │ (cli.py) │ arg parsing, git detection └──────┬──────┘ │ ┌────────────┼────────────┐ │ │ ┌──────▼──────┐ ┌───────▼──────┐ │ Converter │ │ Compiler │ │(converter.py)│ │(compiler.py) │ │ │ │ │ │ Markdown AST │ │ Typst → PDF │ │ → Typst │ │ via typst-py│ └──────┬──────┘ └───────┬──────┘ │ │ │ ┌──────────────┐ │ └────► templates/ ◄─────┘ │ *.typ │ └──────┬──────┘ │ ┌──────▼──────┐ │ output.pdf │ └─────────────┘ ``` ### 流水线 | 阶段 | 模块 | 职责 | |---|---|---| | **1. 输入解析** | `cli.py` | 定位 Markdown 文件,检测 Git 元数据 | | **2. 源码检查** | `linter.py` | 报告空链接和未闭合的代码块,并附带行号/列号 | | **3. Markdown 解析** | `converter.py` | 通过 `mistune` 解析 Markdown AST,生成 Typst 标记 | | **4. 模板注入** | `compiler.py` | 将转换后的内容与所选模板合并 | | **5. PDF 编译** | `compiler.py` | 通过 `typst` Python 绑定进行编译 | ## 工作原理 ### Markdown → Typst 转换 转换器模块使用 [`mistune`](https://github.com/lepture/mistune) 解析 Markdown 并生成等效的 Typst 标记: | Markdown | Typst 输出 | |---|---| | `# Heading` | `= Heading` | | `**bold**` | `*bold*` | | `*italic*` | `_italic_` | | `` `code` `` | `` `code` `` | | `[text](url)` | `#link("url")[text]` | | `- item` | `- item` | | `1. item` | `+ item` | | `- [x] task` | 渲染的复选框 | | `text[^1]` | `#footnote[...]` | | `![alt](https://raw.githubusercontent.com/leonardosalasd/doc-engine-cli/main/local.png)` | `#image("local.png")` | | `> blockquote` | `#block(...)` | | `---` | `#line(...)` | 特殊字符(`#`、`$`、`@`、`*`、`_` 等)会被自动转义,以防止被 Typst 解释。 ### PDF 模板 每个模板都位于 `doc_engine/templates/` 中,并暴露相同的 `setup_doc` 入口点,因此编译器可以通过 `--template` 在它们之间进行切换。默认的 `academic` 模板提供: - **封面**包含标题、作者和日期 - **目录**提供深度为 3 的导航 - **页眉**包含文档标题和作者 - **页脚**包含页码和引擎署名 - **代码块**具有圆角和细微的边框 - **标题层级**具有强调色的 H2 章节 其他模板(`modern`、`minimal`、`technical`、`book`)保持相同的内容,但更改字体、布局和封面。强调色是在编译时注入的,因此 `--accent` 可以为其中任何一个重新着色。 ## 项目结构 ``` doc-engine-cli/ ├── doc_engine/ │ ├── __init__.py # Package version │ ├── __main__.py # python -m doc_engine entrypoint │ ├── cli.py # Click-based CLI + Git detection │ ├── converter.py # Markdown → Typst transpiler │ ├── compiler.py # Typst → PDF compilation engine │ ├── linter.py # Source checks (line/column reporting) │ └── templates/ │ ├── academic.typ # Default IEEE-style report │ ├── modern.typ # Clean sans-serif layout │ ├── minimal.typ # Compact, no cover page │ ├── technical.typ # Accent banner + section markers │ └── book.typ # Centered title page, chapter breaks ├── tests/ │ ├── __init__.py │ ├── test_converter.py # Unit tests for the converter │ ├── test_linter.py # Unit tests for the linter │ └── test_cli.py # CLI and template/accent tests ├── pyproject.toml # Package configuration + dependencies ├── LICENSE # MIT License ├── .gitignore └── README.md ``` ## 依赖 | 包 | 用途 | 许可证 | |---|---|---| | [`click`](https://click.palletsprojects.com/) | CLI 框架 | BSD-3 | | [`rich`](https://github.com/Textualize/rich) | 终端格式化和进度指示器 | MIT | | [`mistune`](https://github.com/lepture/mistune) | Markdown 解析器(纯 Python) | BSD-3 | | [`typst`](https://github.com/messense/typst-py) | Typst 编译器绑定 | Apache-2.0 | 所有依赖项都是纯 Python 的 —— 无需外部二进制文件(Pandoc、LaTeX 等)。 ## 开 ### 设置 ``` git clone https://github.com/leonardosalasd/doc-engine-cli.git cd doc-engine-cli pip install -e ".[dev]" ``` ### 运行测试 ``` python -m pytest tests/ -v ``` ### 项目命令 ``` # 从该项目的 README 生成 PDF python -m doc_engine build # 运行并输出详细的错误信息 python -m doc_engine build README.md -o docs_output.pdf ``` ## Docker 每次发布时都会将容器镜像发布到 GitHub Container Registry。将你的项目挂载到 `/workspace` 并像往常一样运行 `build`: ``` docker run --rm -v "$PWD:/workspace" ghcr.io/leonardosalasd/doc-engine-cli build ``` 入口点是 `doc-engine`,因此你可以传递任何命令或标志: ``` docker run --rm -v "$PWD:/workspace" ghcr.io/leonardosalasd/doc-engine-cli build --template modern --accent teal ``` ## 支持的 Markdown 元素 - [x] 标题 (H1–H6) - [x] 粗体、斜体、删除线 - [x] 行内代码和围栏代码块(带有语言提示) - [x] 链接 - [x] 有序列表和无序列表 - [x] 嵌套列表 - [x] 引用块 - [x] 表格 - [x] 水平分割线 - [x] 换行符 (`
`) - [x] 任务列表 (`- [x]` / `- [ ]`) - [x] 脚注 (`[^1]`) - [x] 本地图片(远程图片仍渲染为 alt 文本) - [ ] 数学块 ## 路线图 - [x] 通过 `--template` 标志选择模板 - [x] 通过 `--accent` 配置强调色 - [x] 带有行号/列号的源码错误检查和 `--dry-run` - [x] 用户提供模板文件(将 `--template` 指向某个路径) - [x] 用于覆盖元数据的 YAML front matter 支持 - [x] 本地图片嵌入 - [x] 用于持续重新构建的 Watch mode - [ ] 数学表达式 (LaTeX 风格的 `$...$`) - [ ] 多文件文档合并 - [ ] Mermaid 图表渲染 - [ ] 针对远程 URL 的图片下载和嵌入 - [ ] 用于存档的 PDF/A 合规性 ## 贡献 欢迎贡献。请遵循以下准则: 1. 派生该仓库 2. 创建功能分支 (`git checkout -b feature/your-feature`) 3. 为新功能编写测试 4. 确保所有测试通过 (`python -m pytest tests/ -v`) 5. 提交 pull request ## 许可证 该项目基于 [MIT License](LICENSE) 授权。
**使用 [Typst](https://typst.app/) 构建 · 使用 [mistune](https://github.com/lepture/mistune) 解析 · 使用 [Rich](https://github.com/Textualize/rich) 排版**
标签:Markdown, PDF生成, Typst, 文档自动化, 文档转换, 逆向工具