|
| 1 | +# Markdown ↔ docx 转换实现计划 |
| 2 | + |
| 3 | +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| 4 | +
|
| 5 | +**Goal:** 给 easydoc 增加 Markdown ↔ docx 快速转换:`EasyMarkdown.markdownToDocx(...)`(MD→HTML→现有 docx 管线)与 `EasyMarkdown.docxToMarkdown(...)`(docx→HTML→简化 MD)。 |
| 6 | + |
| 7 | +**Architecture:** 复用现有 HTML↔docx 管线,只新增 Markdown 转换层。MD→docx 用 flexmark(`com.vladsch.flexmark:flexmark-all:0.64.8`,Java 8 兼容)将 Markdown 渲染为 HTML,再走现有 `WordprocessingMLHtmlTemplate.process(html, ...)`(docx4j-ImportXHTML);docx→MD 用现有 `WordprocessingMLPackageWriter.writeToHtml` 输出 HTML,再以简化标签映射转回 Markdown(标题/段落/表格/列表/强调)。新门面 `EasyMarkdown`(对齐 EasyDocx 风格),薄封装不替代引擎。 |
| 8 | + |
| 9 | +**Tech Stack:** Java 21(3.0.x;代码保持 Java 8 兼容供 1.0.x/2.0.x 同步)、flexmark-all 0.64.8、JUnit 5、docx4j 17.0.3、Maven 4 + POM 4.1.0 + `${revision}`。 |
| 10 | + |
| 11 | +## Global Constraints |
| 12 | + |
| 13 | +- 新代码放 `easydoc-xhtml`(复用 HTML 管线),包 `io.github.easy4j.doc.xhtml.markdown` |
| 14 | +- **纯新增,零破坏**:不改现有 `WordprocessingMLHtmlTemplate`/`WordprocessingMLPackageWriter` 签名;现有测试全绿 |
| 15 | +- **Java 8 语法兼容**(禁 record/sealed/var/switch 表达式/instanceof pattern)——可同步 1.0.x/2.0.x |
| 16 | +- 每个 Task 末尾跑 `mvn -Denforcer.skip=true -pl easydoc-xhtml -am clean verify`(Maven 4:`~/tools/apache-maven-4.0.0-rc-6/bin/mvn`;1.0/2.0 同步时用各自 JDK/Maven)必须 BUILD SUCCESS |
| 17 | +- flexmark 依赖:`com.vladsch.flexmark:flexmark-all:0.64.8`(根 pom dependencyManagement 新增属性 `flexmark.version=0.64.8`;easydoc-xhtml 声明) |
| 18 | +- 测试用 JUnit 5,命名 `*Test.java` |
| 19 | +- 提交信息遵循现有风格(`feat(markdown): ...`) |
| 20 | + |
| 21 | +--- |
| 22 | + |
| 23 | +### Task 1: flexmark 依赖 + MarkdownConverter.mdToHtml |
| 24 | + |
| 25 | +**Files:** |
| 26 | +- Modify: `pom.xml`(根,加 `flexmark.version` 属性 + dependencyManagement 条目) |
| 27 | +- Modify: `easydoc-xhtml/pom.xml`(声明 flexmark-all 依赖) |
| 28 | +- Create: `easydoc-xhtml/src/main/java/io/github/easy4j/doc/xhtml/markdown/MarkdownConverter.java` |
| 29 | +- Test: `easydoc-xhtml/src/test/java/io/github/easy4j/doc/xhtml/markdown/MarkdownConverterTest.java` |
| 30 | + |
| 31 | +**Interfaces:** |
| 32 | +- Produces: `public static String mdToHtml(String markdown)` —— Markdown → HTML 字符串,供 Task 2 的 `markdownToDocx` 使用 |
| 33 | + |
| 34 | +- [ ] **Step 1: 写失败测试** |
| 35 | + |
| 36 | +`MarkdownConverterTest.java`: |
| 37 | +```java |
| 38 | +package io.github.easy4j.doc.xhtml.markdown; |
| 39 | + |
| 40 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
| 41 | + |
| 42 | +import org.junit.jupiter.api.Test; |
| 43 | + |
| 44 | +class MarkdownConverterTest { |
| 45 | + |
| 46 | + @Test |
| 47 | + void mdToHtmlConvertsHeadingsAndParagraphs() { |
| 48 | + String html = MarkdownConverter.mdToHtml("# Title\n\nHello **world**."); |
| 49 | + assertTrue(html.contains("<h1>"), "heading must render to <h1>"); |
| 50 | + assertTrue(html.contains("<strong>world</strong>"), "bold must render to <strong>"); |
| 51 | + assertTrue(html.contains("<p>"), "paragraph must render to <p>"); |
| 52 | + } |
| 53 | + |
| 54 | + @Test |
| 55 | + void mdToHtmlConvertsTable() { |
| 56 | + String html = MarkdownConverter.mdToHtml("| A | B |\n|---|---|\n| 1 | 2 |"); |
| 57 | + assertTrue(html.contains("<table>"), "GFM table must render to <table>"); |
| 58 | + assertTrue(html.contains("<td>1</td>"), "table cell must render"); |
| 59 | + } |
| 60 | + |
| 61 | + @Test |
| 62 | + void mdToHtmlConvertsCodeBlockAndList() { |
| 63 | + String html = MarkdownConverter.mdToHtml("```java\nint x=1;\n```\n\n- item1\n- item2"); |
| 64 | + assertTrue(html.contains("<pre>"), "code block must render to <pre>"); |
| 65 | + assertTrue(html.contains("<li>item1</li>"), "list item must render"); |
| 66 | + } |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +- [ ] **Step 2: 跑测试确认失败** |
| 71 | + |
| 72 | +Run: `~/tools/apache-maven-4.0.0-rc-6/bin/mvn -Denforcer.skip=true -pl easydoc-xhtml -am test -Dtest=MarkdownConverterTest` |
| 73 | +Expected: 编译失败(找不到 `MarkdownConverter`) |
| 74 | + |
| 75 | +- [ ] **Step 3: 加依赖 + 实现** |
| 76 | + |
| 77 | +根 `pom.xml` properties 加: |
| 78 | +```xml |
| 79 | +<!-- Markdown 解析(MD→HTML 渲染,Java 8 兼容) --> |
| 80 | +<flexmark.version>0.64.8</flexmark.version> |
| 81 | +``` |
| 82 | +根 `pom.xml` dependencyManagement 加: |
| 83 | +```xml |
| 84 | +<dependency> |
| 85 | + <groupId>com.vladsch.flexmark</groupId> |
| 86 | + <artifactId>flexmark-all</artifactId> |
| 87 | + <version>${flexmark.version}</version> |
| 88 | +</dependency> |
| 89 | +``` |
| 90 | +`easydoc-xhtml/pom.xml` dependencies 加: |
| 91 | +```xml |
| 92 | +<!-- flexmark:Markdown → HTML(GFM 表格/代码块扩展) --> |
| 93 | +<dependency> |
| 94 | + <groupId>com.vladsch.flexmark</groupId> |
| 95 | + <artifactId>flexmark-all</artifactId> |
| 96 | +</dependency> |
| 97 | +``` |
| 98 | + |
| 99 | +`markdown/MarkdownConverter.java`: |
| 100 | +```java |
| 101 | +package io.github.easy4j.doc.xhtml.markdown; |
| 102 | + |
| 103 | +import com.vladsch.flexmark.ast.Node; |
| 104 | +import com.vladsch.flexmark.html.HtmlRenderer; |
| 105 | +import com.vladsch.flexmark.parser.Parser; |
| 106 | +import com.vladsch.flexmark.util.data.MutableDataSet; |
| 107 | + |
| 108 | +/** |
| 109 | + * Markdown 文本 → HTML 字符串转换(flexmark 驱动,启用 GFM 表格/删除线扩展)。 |
| 110 | + * 输出 HTML 供 easydoc 现有 HTML→docx 管线消费。 |
| 111 | + */ |
| 112 | +public final class MarkdownConverter { |
| 113 | + |
| 114 | + private static final Parser PARSER; |
| 115 | + private static final HtmlRenderer RENDERER; |
| 116 | + |
| 117 | + static { |
| 118 | + MutableDataSet options = new MutableDataSet(); |
| 119 | + options.set(Parser.EXTENSIONS, java.util.Arrays.asList( |
| 120 | + com.vladsch.flexmark.ext.tables.TablesExtension.create(), |
| 121 | + com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension.create(), |
| 122 | + com.vladsch.flexmark.ext.autolink.AutolinkExtension.create())); |
| 123 | + PARSER = Parser.builder(options).build(); |
| 124 | + RENDERER = HtmlRenderer.builder(options).build(); |
| 125 | + } |
| 126 | + |
| 127 | + private MarkdownConverter() { |
| 128 | + } |
| 129 | + |
| 130 | + /** Markdown → HTML。null 输入返回空串。 */ |
| 131 | + public static String mdToHtml(String markdown) { |
| 132 | + if (markdown == null) { |
| 133 | + return ""; |
| 134 | + } |
| 135 | + Node document = PARSER.parse(markdown); |
| 136 | + return RENDERER.render(document); |
| 137 | + } |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +- [ ] **Step 4: 跑测试确认通过** |
| 142 | + |
| 143 | +Run: `~/tools/apache-maven-4.0.0-rc-6/bin/mvn -Denforcer.skip=true -pl easydoc-xhtml -am test -Dtest=MarkdownConverterTest` |
| 144 | +Expected: PASS |
| 145 | + |
| 146 | +- [ ] **Step 5: 提交** |
| 147 | + |
| 148 | +```bash |
| 149 | +git add pom.xml easydoc-xhtml/pom.xml easydoc-xhtml/src/main/java/io/github/easy4j/doc/xhtml/markdown/ easydoc-xhtml/src/test/java/io/github/easy4j/doc/xhtml/markdown/ |
| 150 | +git commit -m "feat(markdown): add flexmark dep + MarkdownConverter.mdToHtml" |
| 151 | +``` |
| 152 | + |
| 153 | +--- |
| 154 | + |
| 155 | +### Task 2: EasyMarkdown.markdownToDocx |
| 156 | + |
| 157 | +**Files:** |
| 158 | +- Create: `easydoc-xhtml/src/main/java/io/github/easy4j/doc/xhtml/markdown/EasyMarkdown.java` |
| 159 | +- Test: `easydoc-xhtml/src/test/java/io/github/easy4j/doc/xhtml/markdown/EasyMarkdownTest.java` |
| 160 | + |
| 161 | +**Interfaces:** |
| 162 | +- Consumes: `MarkdownConverter.mdToHtml`(Task 1)、现有 `WordprocessingMLHtmlTemplate` |
| 163 | +- Produces: `public static WordprocessingMLPackage markdownToDocx(String markdown)`、`public static WordprocessingMLPackage markdownToDocx(String markdown, Map<String,Object> vars)` |
| 164 | + |
| 165 | +- [ ] **Step 1: 写失败测试** |
| 166 | + |
| 167 | +`EasyMarkdownTest.java`: |
| 168 | +```java |
| 169 | +package io.github.easy4j.doc.xhtml.markdown; |
| 170 | + |
| 171 | +import static org.junit.jupiter.api.Assertions.assertNotNull; |
| 172 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
| 173 | + |
| 174 | +import org.docx4j.openpackaging.packages.WordprocessingMLPackage; |
| 175 | +import org.junit.jupiter.api.Test; |
| 176 | + |
| 177 | +class EasyMarkdownTest { |
| 178 | + |
| 179 | + @Test |
| 180 | + void markdownToDocxProducesPackage() throws Exception { |
| 181 | + WordprocessingMLPackage pkg = EasyMarkdown.markdownToDocx( |
| 182 | + "# 标题\n\n这是 **加粗** 内容。\n\n- 列表一\n- 列表二"); |
| 183 | + assertNotNull(pkg); |
| 184 | + String xml = pkg.getMainDocumentPart().getXML(); |
| 185 | + assertTrue(xml.contains("标题"), "heading text must appear in the docx"); |
| 186 | + assertTrue(xml.contains("加粗"), "bold text must appear in the docx"); |
| 187 | + } |
| 188 | + |
| 189 | + @Test |
| 190 | + void markdownToDocxHandlesNullAndEmpty() throws Exception { |
| 191 | + assertNotNull(EasyMarkdown.markdownToDocx(null), "null markdown yields a package"); |
| 192 | + assertNotNull(EasyMarkdown.markdownToDocx(""), "empty markdown yields a package"); |
| 193 | + } |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +- [ ] **Step 2: 跑测试确认失败** |
| 198 | + |
| 199 | +Run: `~/tools/apache-maven-4.0.0-rc-6/bin/mvn -Denforcer.skip=true -pl easydoc-xhtml -am test -Dtest=EasyMarkdownTest` |
| 200 | +Expected: 编译失败(找不到 `EasyMarkdown`) |
| 201 | + |
| 202 | +- [ ] **Step 3: 实现门面** |
| 203 | + |
| 204 | +`markdown/EasyMarkdown.java`: |
| 205 | +```java |
| 206 | +package io.github.easy4j.doc.xhtml.markdown; |
| 207 | + |
| 208 | +import java.util.Map; |
| 209 | + |
| 210 | +import org.docx4j.openpackaging.packages.WordprocessingMLPackage; |
| 211 | + |
| 212 | +import io.github.easy4j.doc.xhtml.WordprocessingMLHtmlTemplate; |
| 213 | + |
| 214 | +/** |
| 215 | + * Markdown ↔ docx 转换门面(对齐 EasyDocx 风格)。MD→docx 走 |
| 216 | + * MarkdownConverter.mdToHtml + 现有 WordprocessingMLHtmlTemplate(HTML→docx); |
| 217 | + * 薄封装,不替代引擎。 |
| 218 | + */ |
| 219 | +public final class EasyMarkdown { |
| 220 | + |
| 221 | + private EasyMarkdown() { |
| 222 | + } |
| 223 | + |
| 224 | + /** Markdown → docx(无变量替换)。 */ |
| 225 | + public static WordprocessingMLPackage markdownToDocx(String markdown) throws Exception { |
| 226 | + return markdownToDocx(markdown, null); |
| 227 | + } |
| 228 | + |
| 229 | + /** Markdown → docx(支持 ${var} 占位符替换——MD 内容渲染后由 HTML 管线处理)。 */ |
| 230 | + public static WordprocessingMLPackage markdownToDocx(String markdown, |
| 231 | + Map<String, Object> vars) throws Exception { |
| 232 | + String html = MarkdownConverter.mdToHtml(markdown); |
| 233 | + WordprocessingMLHtmlTemplate template = new WordprocessingMLHtmlTemplate(); |
| 234 | + return template.process(html, vars); |
| 235 | + } |
| 236 | +} |
| 237 | +``` |
| 238 | + |
| 239 | +- [ ] **Step 4: 跑测试确认通过** |
| 240 | + |
| 241 | +Run: `~/tools/apache-maven-4.0.0-rc-6/bin/mvn -Denforcer.skip=true -pl easydoc-xhtml -am test -Dtest=EasyMarkdownTest` |
| 242 | +Expected: PASS(若 docx4j-ImportXHTML 对 flexmark 输出(如 `<table>`/`<pre>`)解析有兼容问题,调整 flexmark 扩展或 HTML 预处理——报告具体失败) |
| 243 | + |
| 244 | +- [ ] **Step 5: 提交** |
| 245 | + |
| 246 | +```bash |
| 247 | +git add easydoc-xhtml/src/main/java/io/github/easy4j/doc/xhtml/markdown/EasyMarkdown.java easydoc-xhtml/src/test/java/io/github/easy4j/doc/xhtml/markdown/EasyMarkdownTest.java |
| 248 | +git commit -m "feat(markdown): add EasyMarkdown.markdownToDocx" |
| 249 | +``` |
| 250 | + |
| 251 | +--- |
| 252 | + |
| 253 | +### Task 3: EasyMarkdown.docxToMarkdown |
| 254 | + |
| 255 | +**Files:** |
| 256 | +- Modify: `easydoc-xhtml/src/main/java/io/github/easy4j/doc/xhtml/markdown/EasyMarkdown.java` |
| 257 | +- Modify: `easydoc-xhtml/src/main/java/io/github/easy4j/doc/xhtml/markdown/MarkdownConverter.java`(加 `docxToMarkdown` 辅助) |
| 258 | +- Test: `easydoc-xhtml/src/test/java/io/github/easy4j/doc/xhtml/markdown/EasyMarkdownTest.java`(追加) |
| 259 | + |
| 260 | +**Interfaces:** |
| 261 | +- Consumes: `WordprocessingMLPackageWriter.writeToHtml`(docx→HTML)、`MarkdownConverter.docxToMarkdown(String html)`(HTML→MD) |
| 262 | +- Produces: `public static String docxToMarkdown(WordprocessingMLPackage pkg)` |
| 263 | + |
| 264 | +- [ ] **Step 1: 追加失败测试** |
| 265 | + |
| 266 | +`EasyMarkdownTest.java` 追加: |
| 267 | +```java |
| 268 | + @Test |
| 269 | + void docxToMarkdownConvertsHeadingAndBold() throws Exception { |
| 270 | + WordprocessingMLPackage pkg = EasyMarkdown.markdownToDocx("# 标题\n\n**加粗** 内容"); |
| 271 | + String md = EasyMarkdown.docxToMarkdown(pkg); |
| 272 | + assertTrue(md.contains("标题"), "heading text must appear in markdown output"); |
| 273 | + assertTrue(md.contains("加粗"), "text must appear in markdown output"); |
| 274 | + } |
| 275 | +``` |
| 276 | + |
| 277 | +- [ ] **Step 2: 跑测试确认失败** |
| 278 | + |
| 279 | +Run: `~/tools/apache-maven-4.0.0-rc-6/bin/mvn -Denforcer.skip=true -pl easydoc-xhtml -am test -Dtest=EasyMarkdownTest` |
| 280 | +Expected: FAIL(`docxToMarkdown` 不存在) |
| 281 | + |
| 282 | +- [ ] **Step 3: 实现 docx→Markdown(docx→HTML→简化 MD)** |
| 283 | + |
| 284 | +`MarkdownConverter.java` 追加(HTML→MD 简化映射): |
| 285 | +```java |
| 286 | + /** HTML → Markdown(简化映射:标题/段落/粗斜体/列表/表格/代码块)。 */ |
| 287 | + public static String htmlToMarkdown(String html) { |
| 288 | + if (html == null) { |
| 289 | + return ""; |
| 290 | + } |
| 291 | + String out = html |
| 292 | + .replaceAll("(?i)<h1[^>]*>", "\n# ") |
| 293 | + .replaceAll("(?i)</h1>", "\n") |
| 294 | + .replaceAll("(?i)<h2[^>]*>", "\n## ") |
| 295 | + .replaceAll("(?i)</h2>", "\n") |
| 296 | + .replaceAll("(?i)<h3[^>]*>", "\n### ") |
| 297 | + .replaceAll("(?i)</h3>", "\n") |
| 298 | + .replaceAll("(?i)<strong>", "**").replaceAll("(?i)</strong>", "**") |
| 299 | + .replaceAll("(?i)<em>", "*").replaceAll("(?i)</em>", "*") |
| 300 | + .replaceAll("(?i)<li>", "- ").replaceAll("(?i)</li>", "\n") |
| 301 | + .replaceAll("(?i)<p[^>]*>", "\n").replaceAll("(?i)</p>", "\n") |
| 302 | + .replaceAll("(?i)<td[^>]*>", " | ").replaceAll("(?i)</td>", "") |
| 303 | + .replaceAll("(?i)</tr>", "\n") |
| 304 | + .replaceAll("(?i)<pre[^>]*>", "\n```\n").replaceAll("(?i)</pre>", "\n```\n") |
| 305 | + .replaceAll("(?i)</?table[^>]*>", "\n") |
| 306 | + .replaceAll("(?i)</?thead[^>]*>|</?tbody[^>]*>|</?tr[^>]*>", "\n") |
| 307 | + .replaceAll("(?i)<[^>]+>", ""); // 残余标签 |
| 308 | + return out.replaceAll("\\n{3,}", "\n\n").trim(); |
| 309 | + } |
| 310 | +``` |
| 311 | + |
| 312 | +`EasyMarkdown.java` 追加: |
| 313 | +```java |
| 314 | + /** docx → Markdown(经 docx4j HTML 导出 + 简化 HTML→MD 映射)。 */ |
| 315 | + public static String docxToMarkdown(org.docx4j.openpackaging.packages.WordprocessingMLPackage pkg) |
| 316 | + throws Exception { |
| 317 | + java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); |
| 318 | + new io.github.easy4j.doc.io.WordprocessingMLPackageWriter().writeToHtml(pkg, out); |
| 319 | + return MarkdownConverter.htmlToMarkdown(out.toString("UTF-8")); |
| 320 | + } |
| 321 | +``` |
| 322 | + |
| 323 | +- [ ] **Step 4: 跑测试确认通过** |
| 324 | + |
| 325 | +Run: `~/tools/apache-maven-4.0.0-rc-6/bin/mvn -Denforcer.skip=true -pl easydoc-xhtml -am test -Dtest=EasyMarkdownTest` |
| 326 | +Expected: PASS(docx4j HTML 导出的标签与映射匹配;若 `writeToHtml(OutputStream)` 签名/行为差异,按 easydoc-xhtml 实际 API 适配) |
| 327 | + |
| 328 | +- [ ] **Step 5: 提交** |
| 329 | + |
| 330 | +```bash |
| 331 | +git add easydoc-xhtml/src/main/java/io/github/easy4j/doc/xhtml/markdown/ easydoc-xhtml/src/test/java/io/github/easy4j/doc/xhtml/markdown/ |
| 332 | +git commit -m "feat(markdown): add EasyMarkdown.docxToMarkdown" |
| 333 | +``` |
| 334 | + |
| 335 | +--- |
| 336 | + |
| 337 | +### Task 4: 全量验证 + README/CHANGELOG + 推送 |
| 338 | + |
| 339 | +**Files:** |
| 340 | +- Modify: `README.md`(Markdown 转换快速上手段落) |
| 341 | +- Modify: `CHANGELOG.md` |
| 342 | + |
| 343 | +- [ ] **Step 1: README 增加 Markdown 转换** |
| 344 | + |
| 345 | +在 README.md 的 EasyDocx 段后追加: |
| 346 | +```markdown |
| 347 | +### Markdown ↔ docx |
| 348 | + |
| 349 | +```java |
| 350 | +// Markdown → docx(快速转换,复用 HTML 管线) |
| 351 | +org.docx4j.openpackaging.packages.WordprocessingMLPackage doc = |
| 352 | + EasyMarkdown.markdownToDocx("# 标题\n\n**加粗** 内容"); |
| 353 | + |
| 354 | +// docx → Markdown |
| 355 | +String md = EasyMarkdown.docxToMarkdown(doc); |
| 356 | +``` |
| 357 | +``` |
| 358 | + |
| 359 | +- [ ] **Step 2: 全量验证** |
| 360 | + |
| 361 | +Run: `~/tools/apache-maven-4.0.0-rc-6/bin/mvn clean verify`(Maven 4 无 skip) |
| 362 | +Expected: BUILD SUCCESS(13 模块 + JaCoCo 90%) |
| 363 | + |
| 364 | +- [ ] **Step 3: CHANGELOG 记录** |
| 365 | + |
| 366 | +`CHANGELOG.md` 3.0.x 段追加: |
| 367 | +```markdown |
| 368 | +- **Markdown ↔ docx**:`EasyMarkdown.markdownToDocx`(MD→HTML→docx,flexmark 驱动)、 |
| 369 | + `EasyMarkdown.docxToMarkdown`(docx→HTML→MD 简化映射) |
| 370 | +``` |
| 371 | + |
| 372 | +- [ ] **Step 4: 提交 + 推送** |
| 373 | + |
| 374 | +```bash |
| 375 | +git add README.md CHANGELOG.md |
| 376 | +git commit -m "docs(markdown): document Markdown conversion + changelog" |
| 377 | +git push origin feature/3.0.x |
| 378 | +git checkout main && git merge --ff-only feature/3.0.x && git push origin main |
| 379 | +``` |
| 380 | + |
| 381 | +--- |
| 382 | + |
| 383 | +## 执行后同步(1.0.x / 2.0.x) |
| 384 | + |
| 385 | +全部代码 Java 8 兼容 + flexmark 0.64.8 是 Java 8 库;依赖 API(`WordprocessingMLHtmlTemplate.process(html, vars)`、`WordprocessingMLPackageWriter.writeToHtml(pkg, OutputStream)`)在 1.0/2.0 存在(同步时核对签名:1.0/2.0 的 `writeToHtml` 是否接受 `OutputStream`——若无,用 `File` 重载 + 读回字符串适配)。 |
| 386 | + |
| 387 | +同步步骤(对应 worktree): |
| 388 | +1. 根 pom 加 `flexmark.version=0.64.8` + dependencyManagement;`easydoc-xhtml/pom.xml` 加 flexmark-all |
| 389 | +2. 复制 `xhtml/.../markdown/` 源码与测试到 1.0.x/2.0.x |
| 390 | +3. 适配 `docxToMarkdown` 的 `writeToHtml` 调用(核对 1.0/2.0 签名) |
| 391 | +4. 各分支 `mvn -Denforcer.skip=true -pl easydoc-xhtml -am clean verify` 绿 |
| 392 | +5. commit + push feature/1.0.x / feature/2.0.x |
0 commit comments