trans-doc-to-md

v2026.08.17

Convert PDFs, Lexiang document links, or prepared Markdown packages into faithful bilingual Markdown work packages. Preserves source paragraphs, local image paths and order, and rich document structure; uses a generic article profile or strict PDF-rich profile as appropriate. Outputs source.md, optional images/, meta.json, and a final Markdown file named from the original title. Publishing is delegated to upload-markdown-to-lexiang; this skill contains no upload implementation. 将 PDF、乐享文档链接或已准备好的 Markdown 工作包转换为保真的双语 Markdown 工作包。

GitHub
安装命令
npx skhub add ajaxhe/trans-doc-to-md
Markdown
SKILL.md

Trans Doc to Markdown(保真双语文档工作包)

处理三类输入:PDF、乐享文档链接、Prepared Markdown Package。输出保真的双语 Markdown 工作包;如需发布,统一复用 upload-markdown-to-lexiang,本 Skill 不实现上传。

开始前先读 references/lessons-learned.md 的 P0 教训。

适用边界

  • PDF:论文、报告、信息图的文字、图表、表格与卡片提取和双语化。
  • 乐享文档链接:解析正文、下载 assets 图片并双语化。
  • Prepared Markdown Package:消费已经准备好的 source.md、可选 images/、meta.json。
  • 不负责网页付费墙、视频、播客抓取。
  • 不负责乐享上传实现;发布只能调用公共 uploader Skill。

统一工作包契约

每个输入都先归一化为独立工作目录:

<work-dir>/
├── source.md          # 必需;不可变的原文完整性校验基准
├── images/            # 可选;source.md 引用的本地图片
├── meta.json          # 必需;标准元数据
└── <原文标题>.md      # 最终双语 Markdown

source.md 一旦形成即只读。清洗、重排、翻译必须写入草稿或最终文件,禁止覆盖 source.md;最终校验始终以它为基准。最终文件名取 meta.json.title 的原文标题,仅对 路径分隔符等文件系统非法字符做必要替换,不使用摘要标题或译名。

meta.json 标准字段:

{
  "title": "Original Document Title",
  "display_title": "Original Document Title / 中文标题",
  "source_url": "https://example.com/original",
  "source_title": "Original Document Title",
  "source_type": "pdf",
  "language": "en",
  "parent_id": "optional-lexiang-parent-entry-id"
}
  • title:最终 Markdown 文件名和默认发布标题的原文标题。
  • display_title:可选的发布展示标题。非中文双语文档必须使用 Original Title / 中文标题 单行格式;中文文档可与 title 相同。
  • source_url:原始来源 URL;纯本地文件可用 file:// URL 或空字符串。
  • source_title:来源显示标题,通常与 title 相同。
  • source_type:保留真实来源类型,支持 article、youtube、podcast、pdf、 lexiang 或通用的 prepared-markdown。
  • language:检测到的 BCP 47 语言标签,如 en、zh-CN。
  • parent_id:可选;发布到乐享时的父条目 ID。

提取器可以保留 entry_id、space_id、images.json、parsed_raw.md、paper.pdf 等扩展字段或旁路产物,但不能替代上述标准字段。

工作流总览

PDF ───────────┐
               ├─ 提取/归一化工作包 ─┐
乐享文档链接 ──┘                      ├─ 语言检测 → 通用清洗 → 翻译 → 校验
Prepared Markdown Package ────────────┘

PDF 使用 pdf-rich profile;乐享与 Prepared Markdown 默认使用 generic profile。
只有确认乐享来源本质是富 PDF 报告时,才显式切换为 pdf-rich。

任务清单:

- [ ] Step 0 读取 P0 教训并识别输入模式
- [ ] Step 1 提取或预检统一工作包
- [ ] Step 2 检测 source.md 语言
- [ ] Step 3 通用清洗(写新文件,不改 source.md)
- [ ] Step 4 仅 pdf-rich:图片、富元素、TOC 与标题层级处理
- [ ] Step 5 翻译并生成 <原文标题>.md
- [ ] Step 6 按 profile 校验
- [ ] Step 7 可选:调用公共 uploader

Step 1 — 按输入模式分流

A. 乐享文档链接

python3 scripts/lexiang_fetch.py "<乐享URL或entry_id>" --out-dir out/my-doc
# assets 失败时可补下原 PDF
python3 scripts/lexiang_fetch.py "<entry_id>" --out-dir out/my-doc --download-pdf

脚本生成 source.md、images/、images.json、parsed_raw.md 和 meta.json。 [IMAGE]...[/IMAGE] 与行内 ![](/assets/...)<image_ocr> 仅用于定位并下载图片; source.md 只保留 ![](images/...) 引用,不得附带 OCR 标签、图片描述或衍生表格。 检查并补齐标准 meta 字段,随后冻结 source.md。图片对账要求:

images.json 条目数 == downloaded=true 数 == source.md 本地图片引用数

B. 本地或 URL PDF

curl -L -o out/my-doc/paper.pdf "<PDF URL>"
python3 scripts/pdf_extract.py out/my-doc/paper.pdf --text --out-dir out/my-doc
python3 scripts/pdf_extract.py out/my-doc/paper.pdf --thumbs --out-dir out/my-doc

结合 paper.txt 与逐页图表裁剪装配出 source.md,写入标准 meta.json 后冻结 source.md。文字与图片分两条路径,详见 references/extraction.md。

C. Prepared Markdown Package

从语言检测和通用清洗直接开始,不运行提取器。预检:

  1. 工作目录内有非空 source.md 和合法 meta.json。
  2. meta.json 包含 title/source_url/source_title/source_type/language; parent_id 可选;source_type 保留真实来源类型,未知来源才使用 prepared-markdown。
  3. source.md 中每个本地图片路径都位于工作目录内且文件存在。
  4. images/ 可不存在;没有本地图片时这是合法状态。
  5. 不改写 source.md,不把已清洗稿反向覆盖为校验基准。

Step 2 — 语言检测

对所有模式统一读取 source.md 前 500 个正文字符,忽略 Markdown 标记、图片和 HTML 注释。中文字符占比 ≥30% 视为中文;否则按检测语言翻译为中英对照。把结果写入 meta.json.language。

Step 3 — 通用清洗

所有模式都执行,但结果写入临时草稿:

  • 保留每个源文正文段落,不摘要、不改写英文侧。
  • 保留本地 Markdown 图片的路径和先后顺序;alt 可翻译。
  • [IMAGE]...[/IMAGE] 及紧随图片的 <image_ocr>...</image_ocr> 是提取元数据, 只用于定位和下载图片;最终文档仅保留本地图片引用。禁止附带图片标题、图片描述、 OCR 原文、OCR 翻译或根据 OCR 另行重建的表格,除非这些内容本来就是图片块之外的 独立正文。
  • 保留链接、列表、表格、引用与代码。
  • 清除明确的解析噪音;任何可能属于正文的内容宁可保留。
  • 表示“约”的裸 ~ 改为 ≈;代码、行内代码和 URL 不改。
  • 普通货币金额直接写 $,不得转义成 \$;只有真实数学公式才按公式策略处理。
  • 标题使用单行双语格式;普通文章不要求 Contents/TOC。
  • 文档级标题用于 meta.json.display_title 和在线页面名称,不保留在最终 Markdown 正文中;章节标题继续保留。

翻译格式见 references/translation.md。

Step 4 — 仅 pdf-rich 的专项处理

Prepared Markdown 和普通乐享文章默认跳过本步骤。PDF 富文档执行:

  1. 逐页扫描并裁剪全部图表,处理一页多图;对账实际图表数与本地图片引用数。
  2. 重建统计卡、定义卡、多列信息图、样式化表格;见 references/rich-elements.md。
  3. 清理页眉页脚和 LaTeX 脚注残留。
  4. 严格重排标题层级。
  5. 源文存在 Contents/TOC 时逐项保持完整标题、真实类别和页码格式。

pdf-rich 校验 profile 要求严格 TOC/标题结构;若 PDF 确实没有 TOC,应使用 generic,不要伪造目录来满足校验。

Step 5 — 翻译与装配

默认由当前模型按 3000–5000 字符逐块翻译。备选仅在用户明确要求且配置 GEMINI_API_KEY 时使用本 Skill 唯一副本:

python3 scripts/translate_gemini.py draft.md "<原文标题>.md"

硬性要求:

  • 英文原文完整保留,后接中文译文。
  • 翻译后的清洗、重排和格式修复必须以完整双语稿为输入,禁止从 source.md 重新拼装并在 匹配失败时只保留英文。任何启发式合并若无法确认译文归属,必须失败退出,不得静默降级。
  • 标题单行双语:## English / 中文。
  • 将原文文档标题翻译为 Original Title / 中文标题,写入 meta.json.display_title;最终 Markdown 删除与该展示标题对应的首个文档级 H1, 避免在线页面名称与正文第一行重复。
  • 列表逐项单行双语:- English item / 中文条目;不受句末标点影响,禁止英文列表与中文列表分组堆叠。
  • Markdown/HTML 表格逐单元格双语:English<br>中文。表头和正文单元格都必须同格, 禁止先放一行英文、再另起一行中文;纯数字、百分比和代码标识可不翻译。
  • 本地图片 path 原样保留且顺序不变,alt 可翻译。
  • 图片块只输出图片引用,不输出 [IMAGE] 元数据、<image_ocr>、OCR 译文或衍生表格。
  • 非公式场景中的美元符号写为 $,禁止写成 \$。
  • 不在章节标题前添加 ---。
  • 最终文件必须命名为 <meta.title>.md。

Step 6 — 校验

普通文章、Prepared Markdown 和默认乐享模式:

python3 scripts/bilingual_validate.py source.md "<原文标题>.md" \
  --profile generic --json

PDF 富文档严格模式:

python3 scripts/bilingual_validate.py source.md "<原文标题>.md" \
  --profile pdf-rich --raw-source parsed_raw.md --json

兼容按章节校验:

python3 scripts/bilingual_validate.py source.md "<原文标题>.md" \
  --section "Mechanical Properties" --profile generic

generic 始终校验源文段落、中文译文覆盖率和本地图片路径/顺序;中文覆盖率低于 80% 直接失败,防止“英文完整但译文被后处理丢弃”的假通过。仅当源文存在 TOC 时运行 TOC 专项校验。pdf-rich 继续运行严格 TOC 和标题结构校验。成功/失败退出码分别为 0/1;--json 始终输出含 status/ok/profile/scope/error 的 JSON。

Step 7 — 可选发布(只调用公共 uploader)

先按公共 Skill 的定位规则获得 <uploader-root>,并检查 CLI 契约:

python3 "<uploader-root>/scripts/lexiang_upload.py" --version
# cli_api 必须为 "1"

使用统一工作包上传:

python3 "<uploader-root>/scripts/lexiang_upload.py" upload \
  --work-dir "out/my-doc" --md "<原文标题>.md" \
  --meta-file meta.json --parent-from-meta --source-from-meta \
  --name "<meta.display_title>" --pin --json

预览而不上传:

python3 "<uploader-root>/scripts/lexiang_upload.py" upload \
  --work-dir "out/my-doc" --md "<原文标题>.md" \
  --parent-id dry-run --dry-run --json

禁止在本 Skill 增加上传脚本、认证逻辑或逐块 MCP 上传代码。两个 Skill 仅通过 meta.json、images/ 和最终 .md 文件组合。

交付自检

  • source.md 未被修改,是最终校验的唯一原文基准。
  • meta.json 标准字段齐全,最终文件使用原文标题命名。
  • 非中文文档的 meta.json.display_title 为 Original Title / 中文标题,发布时 不使用“中英对照”等机械后缀。
  • 最终 Markdown 正文不含与 display_title 重复的文档级 H1;第一个标题应是正文 章节标题,或正文直接从副标题/元信息开始。
  • 所有源文段落完整保留,没有摘要替代。
  • 中文译文覆盖率校验通过;不得只凭英文原文完整和 uploader verified=true 判定双语完整。
  • 最终稿相对翻译原始输出的中文段落数不得异常下降;格式后处理必须保留全部译文。
  • 所有自然语言表格单元格同时包含英文与中文,译文没有被拆到下一行或另一张表。
  • 所有源文本地图片路径不变、顺序不变、文件存在。
  • 图片块仅保留图片引用,无图片元数据、OCR 文本、OCR 译文或衍生内容。
  • 全文无非必要的 \$;普通金额统一使用 $。
  • generic 对无 TOC 普通文章可通过;有 TOC 时标题保持完整。
  • pdf-rich 已完成图表、富元素、TOC 和标题层级专项检查。
  • 校验命令退出码为 0;JSON 中 ok=true。
  • 上传能力完全来自 upload-markdown-to-lexiang。

脚本职责

脚本职责
scripts/lexiang_fetch.py仅获取乐享正文与 assets;处理 [IMAGE] 与行内 asset,剔除 OCR 元数据
scripts/pdf_extract.py仅提取 PDF 文字、缩略图与裁剪图片
scripts/bilingual_validate.py按 generic/pdf-rich 校验双语产物
scripts/translate_gemini.py可选 Gemini 翻译,本 Skill 仅此一份

依赖

  • 乐享 fetch:标准库及现有读取凭证。
  • PDF:pymupdf、Pillow、numpy。
  • Gemini 备选:requests、GEMINI_API_KEY。
  • 发布:独立 Skill upload-markdown-to-lexiang,cli_api=1。
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.08.17

发布时间

Aug 17, 2026

分类

未分类

许可证

未指定

源路径

/

默认分支

main

最新提交

e79d1aa

Tree SHA

157b911