# Markdown 原生导出 DOCX

`string.markdown.toDocx` 将 Markdown 转为可编辑的 DOCX。转换链为 **Markdown → HTML → Word 内容模型 → DOCX**：`string.html.toDocx` 仅解释 Markdown 所需的有限 HTML 子集，`fsys.openXml.docx.builder` 生成 WordprocessingML，公共 `fsys.openXml.writer` 负责 ZIP 和安全保存。生成时不调用 Word、MSXML、COM 或 .NET，不经过 RTF。

需要 `fsys.openXml` 0.13.0+、配套 zlib，以及支持 `string.html(html,true)` 的 HTML/XML 库。无需自行预编码空白；原有调用接口和默认选项保持。

## 快速使用

```aardio
import string.markdown.toDocx;

var md = "# 文档标题

Hello **bold** world。

- [x] 已完成
- [ ] 待处理
";

var path,err,report = string.markdown.toDocx.save("/output.docx",md);
if(!path){
    print(err);
    return;
}

for i,w in report.warnings print(w.message);
raw.explore(path,"/select");
```

默认不覆盖已有文件。确实需要替换时，给选项添加 `overwrite=true`。先生成临时文件，再在目标目录替换；失败不会先清空旧文件。

## 两个入口

- `string.markdown.toDocx(markdown,options)`：返回 `DOCX二进制字符串,err,report`。可用 `string.save` 保存。
- `string.markdown.toDocx.save(path,markdown,options)`：返回 `完整路径,err,report`，自动创建输出目录，要求 `.docx` 后缀。

成功时 `err` 为 null。失败时第一个返回值为 null；失败早期可能没有 report。`report.warnings` 是 `{code;message}` 数组；还包含 `paragraphCount/tableCount/listCount` 计数（列表计数对应生成的编号定义，不等于列表项数）。

两个输出入口都透传公共 writer 的写入限额。默认每部件 16 MiB、总写入 128 MiB；可用 maxPartBytes/maxWriteBytes 显式调整，超限返回错误。二进制入口会读取并删除一个临时 ZIP；save 直接在目标目录提交，不再创建临时 XML 部件目录。

## 常用选项

```aardio
import string.markdown.toDocx;

var options = {
    font="Microsoft YaHei";
    monoFont="Consolas";
    symbolFont="Segoe UI Symbol";
    fontSize=11;
    codeFontSize=10;
    lineSpacing=1.15;
    codeLineSpacing=1.15;
    pageWidth=11906;
    pageHeight=16838;
    landscape=false;
    margins={left=1440;right=1440;top=1440;bottom=1440};
    wideTable="stack";
    tableMinColumnWidth=720;
    checkboxStyle="unicode";
    overwrite=false;
    title="文档标题";
    author="作者";
    colors={inlineCodeBackground=0xEFF1F3};
};

var path,err,report=string.markdown.toDocx.save("/configured.docx","# 配置示例",options);
if(!path) print(err);
```

- 字号单位是磅；页面、边距和列宽单位是 twips（20 twips = 1 磅）。默认 A4。
- 行距为倍数，文字不使用固定精确行高。
- `landscape=true` 可将默认 A4 切换为横向。
- `colors` 以 `0xRRGGBB` 表示。支持 text、muted、link、border、codeBackground、codeText、inlineCode、inlineCodeBackground、tableHeaderBackground、mark。
- `inlineCodeBackground=false` 关闭行内代码底色；`0x000000` 是有效的黑色。
- `checkboxStyle="ascii"` 使用 `[x]` / `[ ]`，适合无法保证符号字体的阅读端。
- 字体仅指定名称，不安装、不嵌入；阅读端缺少字体时由阅读软件替换，不能保证完全一致的字形和分页。

## 第一版支持范围

- 一至六级真实标题样式及大纲级别。
- 正文、粗体、斜体、删除线、下划线、上下标、行内代码。
- 代码块的空格、制表符、空行及长内容；长代码按页面折行，不截掉行尾。
- 有序、无序及基础嵌套列表；真实编号定义。嵌套列表使用独立编号定义，不是可配置的多级章节编号模板。
- 任务列表的 Unicode 静态复选框，不依赖 FontAwesome；不是可点击的 Word 内容控件。
- 引用、分隔线、超链接、普通表格及单元格对齐。
- 中文、emoji 等 Unicode 内容；emoji 的彩色显示取决于字体和阅读软件。

### 保留内容的宽表策略

默认 `wideTable="stack"`：列数过多、页面放不下最小列宽，或遇到合并单元格时，按行/列展开为段落，并返回 `table-stacked` 警告。

`wideTable="wrap"`：优先保留表格并收窄列宽、允许单元格换行。若连基本的字符宽度和内边距都无法容纳，仍会展开；不会产生零宽/负宽单元格。可以配合横向页面。

### 尚未实现

- 图片嵌入：保留替代文字和地址，并返回 `image-alt` 警告。不会下载网络图片，也不会读取 HTML 指向的本地文件。
- 任意 HTML/CSS、复杂网页布局和合并单元格的高保真还原。
- 完整 LaTeX/KaTeX 转可编辑 Word 公式：上游能转成 Unicode 的简单符号可直接显示，其余公式保留为文本，不生成 OMML。
- 字体嵌入：显式 FontAwesome 图标仍要求阅读端安装字体，并返回 `fontawesome` 警告。

## 上游 Markdown 行为

本库使用现有 `string.markdown` 解析器，不改写其语法。当前解析器会将代码块 TAB 转为四空格；`3. item` 生成的 `<ol>` 未保留 `start`，因此输出编号从 1 开始。如必须指定起始编号，可调用 `string.html.toDocx` 并使用 `<ol start="3">` / `<li value="7">`。

## 范例与 HTML 入口

完整可运行范例：`~/examples/Text/Markdown/md2docx.aardio`。

HTML 子集入口详见 [string.html.toDocx](../../html.toDocx/index.html)。DOCX 库与现有 RTF 库独立，原来的调用不受影响。

实际兼容性验证覆盖本机 Windows 11 + Microsoft Word 16；不把它等同于所有版本 Word、WPS、LibreOffice 或 macOS 的测试结论。
