Markdown -> Docx 黑魔法实战: 大纲标号、图表注记、样式管理、参考文献、目录生成、多人协作...

390 阅读13分钟

这是什么?

整合+搓了一套基于 Markdown 的增强文档解决方案,以 Pandoc 为核心组件,整合并实现了一系列小扩展,实现了 多级标题自动化、图表注记、样式管理、分页控制、交叉引用、参考文献管理、LaTeX 数学公式、目录生成等 排版功能,支持简单的 编辑锁定、多人协作 等能力,目标在于最终转换为符合标准的 Word 文档,希望为技术文档、会议报告、申报材料、论文撰写等场景提供高效、可复用的工作流。

太长不看,我要开箱即用的东西

请先安装 Python 和 Pandoc,然后可以在 这里 获取。运行其中的 markdown_processor.py 即可。

为什么不丢到 GitHub?因为我懒得维护

为什么又造轮子?

简单的文档完全可以用纯文本,或者干脆直接使用 Word 来写;需要复杂排版的场景,干脆直接用 LaTeX 或者 Typst 这类已经成熟的排版工具。为什么还要造这个半成品轮子?

简单来说做这套东西的目的是:我们需要一个内容维护起来像 LaTeX 一样简单,同时希望对于不会使用 LaTex 的人,编辑、调整格式、审校像 Word 一样方便的方案

和其他方案对比一下,

LaTeX 能实现专业排版,主要问题是学习曲线陡峭,需大量时间掌握语法,定制模板。此方案通过扩展而非替代的方式提供近似 LaTeX 的排版能力,规避了 LaTeX 的学习复杂性。不会或无需使用 Markdown 特性的编写者甚至完全可以当做纯文本来写,也就有效降低了使用门槛。这也同时解决了某些场景下 需要提交的材料必须是 Word 文档而非 PDF,导致 LaTeX 等排版工具完全无法使用的问题。

Word 的所见即所得操作灵活,但手动调整格式效率低下,尤其在需要长期维护的长文档和多人协作等场景下,易出现样式混乱的问题,给审校工作带来了极大不便。此方案能够分离内容与样式,确保格式统一,同时兼顾批量处理的效率+最终产物的格式规范;考虑到目前 ChatGPT 等大语言模型也偏好使用 Markdown 给出输出,也 有利于在大模型辅助下编写格式化文档,省去了转换到 Word 时处理格式的麻烦。

一般 Markdown 缺乏对学术等场景下排版的关键支持(图表注记、分页控制、交叉引用、数学公式等)。本文方案集成了这些能力,在 Markdown 中添加简单标记就能直接获得对应的高级特性,希望能够省去内容变更后导出时,反复手动维护文档导出产物花费的大量无效时间。

核心组件与原理

Pandoc

Pandoc 是一款由 John MacFarlane 在 2006 年开始编写、用 Haskell 实现的开源通用文档转换器,被称为“文档转换瑞士军刀”。它能够在数十种标记语言与页面格式之间进行高质量、可高度定制的双向转换。

Pandoc 官网

Pandoc 的核心特性主要在于丰富的输入和输出格式。它支持多种输入格式,如 Markdown(支持多种 dialect)、LaTeX、HTML、Microsoft Word(docx)、ODT、EPUB 等,以及相应的输出格式,如 PDF、Beamer、PowerPoint (pptx)、Word (docx)、InDesign ICML、CommonMark 等。格式转换都依赖于 Pandoc 的统一抽象语法树(AST),在转换过程中,源文件首先被解析成 JSON-AST,然后基于 AST 生成目标格式。对于任何受支持的输入格式,都可以通过 AST 转换为任何输出格式。

Pandoc 提供功能完备的 Markdown 扩展,支持表格、脚注、数学公式 (TeX/LaTeX math)、跨文档引用、属性块等功能,并允许通过 +/- 语法进行自由开关。对于引用与文献管理,Pandoc 内置 citeproc 引擎,支持读取 CSL-JSON、BibTeX、BibLaTeX 等数据库,自动完成文内引用与参考文献排版。

Pandoc 拥有丰富的扩展与插件生态,包括官方 Lua 过滤器库,同时支持第三方过滤器,例如 pandoc-crossref、panflute 等,以及官方 Docker 镜像等集成工具。

直接使用 Pandoc 需注意:并非所有格式转换都能 100% 无损,复杂排版可能需要手动调整,过滤器冲突可能影响最终结果等。本方案实践通过编写模板、一些拦截器及 Python 脚本解决相关问题。

OpenXML & MS Word

Open XML 是微软主导制定的开放文档标准(ECMA-376 / ISO/IEC 29500)。它把一份 Office 文件拆解成一组互相关联的 XML 文档和资源文件,再用 ZIP 容器整体打包。标准层面定义了三大标记语言:WordprocessingML(.docx)、SpreadsheetML(.xlsx)和 PresentationML(.pptx)。每个包内部都有一个 [Content_Types].xml 来声明内容类型、_rels 目录来维护各部件(Part)之间的 Relationship,以及若干主题、样式、媒体等独立部件。由于所有内容最终都是文本形式的 XML 和少量二进制资源,开发者可以不依赖 Office 本身就完成读取、修改、合并或生成文件的工作

Word 的 .docx 文件就是遵循 Open XML WordprocessingML 语法的压缩包。包里最核心的部件是 /word/document.xml,它用一系列 <w:p>(段落)、<w:r>(文字片段)、<w:tbl>(表格)等元素描述文档结构与排版属性;/word/styles.xml 负责定义样式集合,/word/numbering.xml 管理多级列表,/word/settings.xml 保存页面和兼容性设置;图片、嵌入对象等二进制数据则存放在 /word/media 下,并通过 .rels 文件与正文中的 <w:drawing> 元素建立引用。

Word 在打开 .docx 时,先解压 ZIP,按 _rels 链接图找到 document.xml 作为入口,解析各部件的 XML 树,构建内部对象模型(DOM);渲染引擎再根据样式层叠规则、段落/字符属性、页面设定和字体度量把内容排版到版面。保存时流程反向执行:把内存中的对象模型序列化为各自的 XML,更新关系、内容类型表后重新打包压缩,因而即便发生崩溃也只影响个别部件而不会损毁整个文件。

Open XML 文档结构与工作原理

与旧式二进制 .doc 不同,Open XML 的纯文本可读性与标准化协议使其更易版本控制、差异比较及跨平台处理;同时 ZIP 压缩又保证了体积小和随机访问性能。Open XML 已经成为现代 Office 自动化、批量生成报告、云端协作和合规性场景的事实标准。

Pandoc Lua 拦截器

Pandoc 2.x 以后内置了一整套 Lua 运行时,允许用户在文档转换的过程中“拦截”抽象语法树(AST)并对其做任意修改,这就是所谓的 Lua 过滤器(Lua interceptor/lua-filter)。它与早年的 JSON 过滤器相比无需外部解释器,速度更快、分发更简单,而且能够直接调用 Pandoc 提供的大量辅助函数(如 pandoc.utils、pandoc.system 等),是定制 Pandoc 行为的首选手段。

编写 Lua 过滤器的核心思想很简单:给 AST 中你关心的节点类型写同名的 Lua 函数。Pandoc 在遍历文档时发现匹配的节点就会把节点对象传给该函数,你可以返回:

  • 修改后的节点(单个或多个)
  • 原节点(原样放回)或
  • nil(删除该节点)

所有函数放在一个普通的 .lua 文件里即可;文件本身最后 return 一个表(或什么都不 return,Pandoc 会自动把全局函数收集成过滤器)。

例如以下代码,会把所有 斜体 文字改成 粗体

-- emph2strong.lua
function Emph(el)          -- el 为 pandoc.Emph 对象
  return pandoc.Strong(el.content)
end

使用时只需在命令行加上 --lua-filter 选项:

pandoc input.md -o output.pdf --lua-filter=emph2strong.lua

Lua 过滤器与模板、后端选项、宏等机制可以自由组合,因此只要掌握“写同名函数 → 返回想要的节点”这条黄金法则,就能简单地把 Pandoc 打造成一台可编程的文档工厂。

整合支持和实现的能力列表

  • 基本 Markdown 语法
  • 多级标题
  • 图注
  • 表注
  • 样式管理
  • 分页控制
  • 自动格式化(lint)
  • 参考文献引用
  • LaTeX 数学公式
  • TOC 目录生成
  • 锁定编辑权限
  • 多人协作

整体方案

整体的处理流程:

先将原始 Markdown 文件使用 Python 脚本处理成一个 Markdown,此过程通过脚本添加多级标题和图注表注。

随后调用 pandoc,将这个处理后的 Markdown 文档在一些 Lua 拦截器、提供的 bibtex、csl 样式、参考文档等资料下,转换为 Word 文档。

最后发布前,用户编辑 word 文档并导出发布。

处理流程

以下演示使用的文章是:如何在 Monaco Editor 中实现断点设置 的原始 Markdown 文本。

本方案在 WPS 上未全面测试,已知部分功能在 WPS 上支持欠佳。

基本 Markdown 语法

Markdown 的基本语法已经支持使用 # 表示标题(1 到 6 级),用 *_ 包围文本表示斜体,**__ 表示粗体,-*+ 表示无序列表,数字加点表示有序列表。代码块使用反引号 ` 包围,链接格式为 [文本](URL "文本"),图片格式为 ![替代文本](图片URL),引用使用 >,分割线使用 ---***,脚注使用 [^1] 等等。

Pandoc 原生的转换功能可以相当优秀地将这些标记转换到 Word 文档。直接使用这些标记来编写文章即可。

一些原生 MD 语法

摘要及多级标题

Pandoc 也提供了 pandoc-crossref 插件,可以用来处理章节编号和图注表注,不过存在一些问题:这个插件不是随 Pandoc 一并分发提供的,需要额外安装,有一些配置成本;设计上主要用于跨引用(用法例:![这是一个示例图](path/to/image.png){#fig:example},如图 {@fig:example} 所示...),且主要用于 LaTeX、HTML 或 PDF 输出,对 Docx 等其他格式的文档输出支持有限;对多语言本地化的支持有限,且灵活性不大。

我这里的场景没有太多需要跨引用的地方。如果对跨引用有需求,建议还是配置一下 pandoc-crossref 来用。

此方案使用编写的 Python 脚本添加多级标题。

关于摘要

一种摘要的声明方法:在 Markdown 文件的 YAML 头部区块中声明摘要内容。Pandoc 不能直接把摘要内容嵌入到 Word 文档的特定“摘要”或“摘要”位置,但可以在 YAML 头部中添加自定义变量,然后在转换后的 Word 文档中处理这些内容。

---
title: "文档标题"
author: "作者名字"
date: "2025-05-08"
abstract: |
  这是文档的摘要内容。可以是多行的文本。
---

# 你的文档内容

这是正文部分。

不过这个做法偏麻烦且必要性不大。既然我们已经决定使用自己写的 Python 脚本去处理章节编号,那么完全可以在脚本里定义对摘要章节的处理行为。

多级标题编号的添加实现

首先处理代码块。检查每一行是否以 ``` 开始或结束来检测代码块的边界。检测到代码块的开始或结束时,代码会翻转一个布尔标记 in_code_block 来跟踪是否在代码块中。如果在代码块中,当前行的内容直接添加到 processed_lines 列表中,而不作进一步处理。意义是确保在代码块中的所有文本都保持原样。

对于二级标题,检查它们是否是前两个二级标题,以下实现考虑到文本存在中英双语摘要,因而跳过,不添加章节号。跳过的二级标题直接添加到 processed_lines 中。如果不是摘要,代码会增加章节号 chapter_num,并重置三级及以下标题的计数 section_nums,以及图片和表格的计数 img_counttable_count。二级标题被重新格式化为 ## 第X章 标题内容,里面的 X 是当前章节号,使用 cn2an.an2cn 库将数字转换为中文数字。

三级标题会在确认不在被跳过的章节中时开始编号。三级标题的计数 section_nums[0] 增加,其余较低级别标题的计数重置。格式化后的三级标题为 ### X.Y 标题内容,其中 X 是当前的章节号,Y 是三级标题的当前计数。

    chapter_num = 0  # 二级标题章节号
    section_nums = [0] * 4  # 三级、四级、五级、六级标题的编号
    img_count = 0  # 当前章节图片计数
    table_count = 0  # 当前章节表格计数
    skipped_chapters = 0  # 已跳过的二级标题计数,用于跳过摘要
    processed_lines: List[str] = []
    in_code_block = False  # 标记是否在代码块中

    for line in lines:
        # 检测代码块开始或结束
        if line.strip().startswith('```'):
            in_code_block = not in_code_block
            processed_lines.append(line)
            continue

        # 如果在代码块中,直接添加行不处理
        if in_code_block:
            processed_lines.append(line)
            continue

        # 处理二级标题 (##)
        if line.startswith('## '):
            skipped_chapters += 1
            if skipped_chapters <= 2:
                # 跳过前两个二级标题,不做编号处理,因为这俩是摘要
                # 如果要改实现,记得改这里
                processed_lines.append(line)
                continue

            chapter_num += 1
            section_nums = [0] * 4
            img_count = 0
            table_count = 0
            processed_line = f'## 第{cn2an.an2cn(chapter_num)}{line[3:]}'
            processed_lines.append(processed_line)
            continue

        elif line.startswith('### '):
            if skipped_chapters <= 2:
                processed_lines.append(line)
                continue

            section_nums[0] += 1
            section_nums[1:] = [0] * 3
            processed_line = f'### {chapter_num}.{section_nums[0]} {line[4:]}'
            processed_lines.append(processed_line)
            continue
# 其他标题同理...

图注与表注

Markdown 中的图注和表注

除去在 Markdown 里写 HTML 的那种强烈不推荐的写法,Pandoc 支持识别以下写法的图片/图注:

  1. 一般的内联图片格式![alt](path),直接在 Markdown 文本中定义图片的路径和替代文字(alt text)。
  2. 引用图片格式![alt](path "alt"),使用一个引用标识符(id)来间接引用图片,通常与一个引用定义结合使用。
  3. 引用定义格式[id]: path {attrs},通常在 Markdown 文档的末尾定义,提供引用标识符与实际路径的关联。

使用以下写法的引用图片和引用定义,可以控制图片在得到的 Word 文档中的显示宽度,有些情况下可以美化排版:

![大语言模型演进趋势][llmrevo]

[llmrevo]: ./assets/figure.jpg {width=70%}

对于表注:

  1. 表格描述格式:以Table:开头,后面跟随表格的标题。注意使用这种写法作为表注的时候,上方必须紧跟着一个 Markdown 表格。

例如,以下写法是正确的:

| 搜索引擎/产品名 | 企业/开发团队 |
| --------------- | ------------- |
| 谷歌搜索        | Google        |
| 百度搜索        | Baidu         |
| 必应搜索        | Microsoft     |

Table: 各大厂商的搜索引擎

这样的表注在直接使用 Pandoc 转换为 Word 文档时,表注会生成在表格的底部。通常我们还需要控制表注的出现位置为表格的顶部。在 Markdown 文件的头部使用 YAML 声明如下内容即可。

---
...
tables:
  position: top
---

图注表注的添加实现

实现流程与章节号类似。不再赘述。

    img_inline_match = re.match(r'^!$$(.*?)$$$(.*?)$', line)  # 处理内联图片格式 ![alt](path)
    img_reference_match = re.match(r'^!$$(.*?)$$$$(.*?)$$', line)  # 处理引用格式 ![alt](path "alt")
    reference_def_match = re.match(r'^$$(.*?)$$:\s*(.*?)(?:\s+\{(.*?)\})?$', line)  # 处理引用定义 {attrs}

    if img_inline_match:
        if skipped_chapters <= 2:
            processed_lines.append(line)
            continue

        img_count += 1
        caption = img_inline_match.group(1)
        path = img_inline_match.group(2)
        new_caption = f'图{chapter_num}-{img_count} {caption}'
        processed_line = f'![{new_caption}]({path})\n'
        processed_lines.append(processed_line)
        continue
    elif img_reference_match:
        if skipped_chapters <= 2:
            processed_lines.append(line)
            continue

        img_count += 1
        caption = img_reference_match.group(1)
        ref_id = img_reference_match.group(2)
        new_caption = f'图{chapter_num}-{img_count} {caption}'
        processed_line = f'![{new_caption}][{ref_id}]\n'
        processed_lines.append(processed_line)
        continue
    elif reference_def_match:
        # 保留引用定义不变
        processed_lines.append(line)
        continue

    if line.startswith('Table: '):
        if skipped_chapters <= 2:
            processed_lines.append(line)
            continue

        table_count += 1
        caption = line[7:].strip()
        processed_line = f'Table: 表{chapter_num}-{table_count} {caption}\n'
        processed_lines.append(processed_line)
        continue

    processed_lines.append(line)
...

样式管理

我们希望能够定义转换后的 Markdown 样式在 Word 中的显示样式。Pandoc 允许在将 Markdown 转换到 Word 时提供参考文档。转换时,会应用提供的 Word 参考文档中的样式等等。

实际上,如果你不显式提供参考文档,Pandoc 就会使用自带的参考文档来完成转换。可以使用以下指令导出 Pandoc 自带的参考文档:

pandoc -o reference.docx --print-default-data-file reference.docx

打开这个参考文档,点击顶部“开始”选项卡,点击样式栏右下角的小箭头,就可以看到预定义的所有样式了。

Pandoc 在转换时,会自动把 Markdown 元素对应到这里定义的样式上去。你可以在这个列表中右键修改某个样式,这样,转换后的内容就会被自动应用你修改后的样式了。

例如,我修改二级标题为居中,使用某字号字体等等。

这样就完成了对该样式的更改。你可以按需对其他样式进行修改。

这里随文提供的资源包已经做了大量基本的修改,例如使用黑体作为标题字体,将图片表格图注表注居中,处理 TOC 样式,修改正文字体行距段落间距等。你也可以在我提供的模板上再作修改。

如果你已经编辑好了模板,使用以下指令就可以应用此参考文档来进行转换:

pandoc input.md -o output.docx --reference-doc=reference.docx

分页控制

定义两个过滤器函数来实现分页控制标记:RawBlockDivRawBlock 函数检查 Markdown 文档中的文本块是否匹配特定的分页模式:<!-- pagebreak -->\newpage\pagebreak。如果匹配,将这些标记转换为 DOCX 文档中相应的分页符,使用 Pandoc 的 pandoc.RawBlock 函数,以 OpenXML 格式注入 <w:p><w:r><w:br w:type="page"/></w:r></w:p> 这样的原始代码,表示 Word 中的分页符。Div 函数处理具有 pagebreak 类的 Div 元素,类似地,将其转化为 DOCX 分页符。

function RawBlock(el)
    if el.text == '<!-- pagebreak -->' then
        return pandoc.RawBlock('openxml', '<w:p><w:r><w:br w:type="page"/></w:r></w:p>')
    end

    if el.text == '\\newpage' or el.text == '\\pagebreak' then
        return pandoc.RawBlock('openxml', '<w:p><w:r><w:br w:type="page"/></w:r></w:p>')
    end
end

function Div(el)
    if el.attr and el.attr.classes:includes('pagebreak') then
        return pandoc.RawBlock('openxml', '<w:p><w:r><w:br w:type="page"/></w:r></w:p>')
    end

自动格式化

推荐使用 VSCode 作为 Markdown 编辑器。VSCode 扩展 AutoCorrectmarkdownLint 为 VSCode 添加了格式检查和自动格式化的功能。

AutoCorrect 用来自动修正常见文本错误和格式问题的插件,能够识别并自动更正常见的拼写错误,这样就无需手动修改。

markdownLint 主要用于格式检查和规范化,以确保文档的一致性和高质量。它检查 Markdown 文件中的常见问题,如标题格式、列表样式、链接格式和空行处理,确保文档符合最佳实践。可以根据项目需求自定义规则集,忽略某些检查或启用特定格式规则。

这两个扩展可以自动检测你的文档中不符合规范的地方并给出警告:

同时也能直接修复一些可以自动处理的问题。

如果你倾向于用 Obsidian 作为所见即所得的编辑器,也可以使用 Linter 插件来帮助你进行格式化。这个会在保存时直接自动运行格式化工具。

参考文献引用

Pandoc 提供了 citeproc 用于生成文内引用和参考文献列表。

准备 BibTeX 文件

处理引用需要准备一个 BibTeX 格式的参考文献文件,通常以.bib为后缀。在这个文件中,每一条文献记录都有一个唯一的引用键(key),在 Markdown 文档中可以用来进行引用。

如果你正在使用 Zotero 之类的文献管理软件,你可以使用这类软件直接导出 BibTeX 使用。

@book{doe2021,
  author    = {John Doe},
  title     = {Example Book},
  year      = {2021},
  publisher = {Fictional Publishing House}
}

在 Markdown 文档中添加引用

在你的 Markdown 文档中,你可以通过引用键进行文献引用。引用时需要在方括号中使用@符号加上 BibTeX 中定义的引用键。

这是一本书的引用示例 [@doe2021]。

控制参考文献列表的出现位置

默认参考文献列表会出现在文档尾。如果你需要控制出现的位置,使用以下标记:

## 参考文献

::: {#refs}
:::

使用 Pandoc 和 citeproc 转换文档

在命令行中执行以下命令:

pandoc yourfile.md -o output.docx --citeproc --bibliography=yourbibliography.bib

在这个命令中:

  • --citeproc选项启用 Pandoc 的引用处理功能。
  • --bibliography=yourbibliography.bib指定你的 BibTeX 文件。

如果你希望使用特定的引用格式(例如 APA、MLA),可以使用--csl选项来指定一个 CSL 样式文件。你可以从 [Citation Style Language (CSL)](github.com/citation-st… "Citation Style Language (CSL "Citation Style Language (CSL)")") 中下载所需格式的 CSL 文件:

pandoc yourfile.md -o output.docx --citeproc --bibliography=yourbibliography.bib --csl=apa.csl

效果

提供的整合包中,默认会使用 gb7714 引用格式。

LaTeX 公式

Pandoc 原生支持。

要写行内公式,可以使用单个美元符号包裹公式:

这是一个行内公式:$E=mc^2$。

要写块级公式,可以使用双美元符号包裹公式:

这是一个块级公式:

$$
E = mc^2
$$

效果如下:

TOC 目录

如果只是需要简单的在文档头部生成一个目录,可以直接在 Markdown 头部 YAML 声明以下内容:

---
...
toc: true
toc-depth: 3
..
---

控制目录生成位置

编写一个拦截器:

function Pandoc(doc)
    -- 查找文档中特定的标记位置
    local blocks = {}
    local toc_inserted = false
    local toc_marker = "{{TOC}}"

    for i, el in pairs(doc.blocks) do
        if el.t == "Para" then
        local content = stringify(el)
        if content == toc_marker then
            table.insert(blocks, pandoc.RawBlock('openxml',
            [[<w:sdt>
                <w:sdtPr>
                <w:docPartObj>
                    <w:docPartGallery w:val="Table of Contents"/>
                    <w:docPartUnique/>
                </w:docPartObj>
                </w:sdtPr>
                <w:sdtContent>
                <w:p>
                    <w:pPr>
                    <w:pStyle w:val="TOC"/>
                    </w:pPr>
                    <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="eastAsia"/>
                    </w:rPr>
                    <w:t xml:space="preserve">目录</w:t>
                    </w:r>
                </w:p>
                <w:p>
                    <w:r>
                    <w:fldChar w:fldCharType="begin" w:dirty="true"/>
                    <w:instrText xml:space="preserve">TOC \o "1-4" \h \z \u</w:instrText>
                    <w:fldChar w:fldCharType="separate"/>
                    <w:fldChar w:fldCharType="end"/>
                    </w:r>
                </w:p>
                </w:sdtContent>
            </w:sdt>]]))
            toc_inserted = true
        else
            table.insert(blocks, el)
        end
        else
        table.insert(blocks, el)
        end
    end

    return pandoc.Pandoc(blocks, doc.meta)
end

拦截器遍历文档中的所有块元素,当发现包含"{{TOC}}"标记的段落时,会将其替换为一段特定格式的 OpenXML 代码,这段代码定义了 Word 文档中目录的结构和样式。其他未匹配的内容则保持原样不变,最终返回处理后的完整文档。

插入的 OpenXML 代码是 Word 文档的原生标记语言,其中<w:sdt>标签创建了一个结构化文档标签容器,用于放置目录内容。内部包含了目录的样式定义(<w:pStyle>)、字体设置(<w:rFonts>)以及目录域代码(<w:instrText>)。"TOC \o "1-4" \h \z \u"这个指令定义了目录的层级范围(1-4 级)、超链接特性(\h)、制表符对齐(\z)和下划线样式(\u)。

使用:

<!-- 这里是目录 -->

{{TOC}}

效果:

(简单的)锁定编辑权限

实践上,除非这个文档马上要提交最终版,强烈建议所有内容编辑都应当在 Markdown 上修改,而非导出的 Word 文档内,以确保所有修改都能被最终同步。但是如果导出的文档被拿到此文档进行审阅的其他人直接进行了修改,就有点糟糕了。

为什么 LaTeX 没有出现这个问题?因为 LaTeX 导出的是 PDF,本身就基本无法修改...

在参考文档中选择审阅->限制编辑->不允许任何修改->是,启动强制保护。

设置一个密码:

保存。此后使用该模板导出的文档也会带有限制编辑。注意这个方法只建议用来当避免他人在文档上做误修改的手段,限制编辑的锁实际上是防君子不防小人的

多人协作

整套方案的内容维护都在使用 Markdown,那么无需多言,多人协作直接上 Git 就很完美了 😋。

配置图片粘贴存储位置

既然使用 Git,那么文档内的图片应当也是一并管理的。使用可视化编辑器的图片粘贴功能非常方便,但使用前,必须配置图片粘贴存储位置。否则图片可能会存储在本地用户目录等不受跟踪的文件夹内。

约定:图片资源统一存放在 md 文件同一相对目录下的 assets 文件夹。

MarkText 的配置方法

VSCode 的配置方法

需要修改设置文件。详见文章:如何设置 VS Code 中 Markdown 粘贴图片的位置

Typora 的配置方法

多人协作时推荐使用的文档结构约定

  • 每个需维护的文档应当在仓库根目录下新建一个文件夹,在该文件夹内新建文件 index.md 作为文档正文,/assets 文件夹用于存放图片等资源。
  • 如需插入 LaTex 公式,行内公式全部使用单美元符号$包裹,独立成行公式全部使用双美元符号$$包裹,请勿使用转义小括号、转义中括号包裹公式。
  • 参考文献一般应当使用 BibTeX 做交叉引用,文件应当存放在同一目录下的 reference.bib。引文格式与 chinese-gb7714-2005-numeric.csl 保持统一。