From 2c95468cac571063b4874c226c0c3ac535fd263d Mon Sep 17 00:00:00 2001 From: Toshiki Iga Date: Fri, 24 Apr 2026 19:27:38 +0900 Subject: [PATCH] =?UTF-8?q?DOCX=E5=A4=89=E6=8F=9B=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=82=92=E3=83=A2=E3=82=B8=E3=83=A5=E3=83=BC=E3=83=AB=E5=88=86?= =?UTF-8?q?=E5=89=B2=E3=81=97=E7=94=BB=E5=83=8Fasset=E5=87=BA=E5=8A=9B?= =?UTF-8?q?=E4=BB=95=E6=A7=98=E3=82=92=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 DOCX変換処理の責務を複数モジュールへ分割し、画像asset出力、manifest生成、Markdownレンダリング、summary生成、ブラウザZIP生成などの処理を独立したモジュールへ整理しました。 あわせて、画像asset対応後の実装仕様・設計仕様・upstream参照方針のドキュメントを現状に合わせて更新しています。 ## 変更内容 - `core.ts` からDOCX package loading、画像asset収集、Markdownレンダリング、summary生成、asset manifest生成などの処理を分離 - `document-parser.ts` から文書ブロック解析、段落解析、inline解析、table解析、drawing解析、anchor処理、summary処理を分離 - `asset-manifest.ts`、`browser-zip.ts`、`docx-assets.ts`、`docx-package-loader.ts`、`image-trace.ts`、`markdown-renderer.ts`、`summary.ts` などの新規モジュールを追加 - browser UI 側の asset ZIP 生成処理を `browser-zip` モジュール利用へ整理 - `scripts/lib/docx2md-module-order.mjs` と `miku-docx2md-src.html` の読み込み順を、分割後のモジュール構成に合わせて更新 - `index-src.html` と `package.json` のバージョンを `0.8.1` に更新 - `docs/docx2md-impl-spec.md`、`docs/docx2md-spec.md`、`docs/upstream.md` を、解決可能な埋め込み画像の sidecar asset 出力に合わせて更新 - `TODO.md` のリファクタリング関連項目を完了状態へ更新し、リファクタリング再開メモを追加 - 生成済みの `src/js/*`、`index.html`、`miku-docx2md.html` を更新 ## 確認事項 - テスト実行結果: 未確認 - ビルド実行結果: 未確認 --- TODO.md | 29 +- docs/docx2md-impl-spec.md | 13 +- docs/docx2md-spec.md | 15 +- docs/upstream.md | 3 +- index-src.html | 2 +- index.html | 2 +- miku-docx2md-src.html | 15 + miku-docx2md.html | 1913 ++++++++++++++++---------- package-lock.json | 4 +- package.json | 2 +- scripts/lib/docx2md-module-order.mjs | 29 + scripts/lib/single-html.mjs | 2 +- src/js/asset-manifest.js | 28 + src/js/browser-zip.js | 115 ++ src/js/core.js | 357 +---- src/js/document-anchor-parser.js | 65 + src/js/document-block-parser.js | 121 ++ src/js/document-cell-parser.js | 29 + src/js/document-drawing-parser.js | 93 ++ src/js/document-inline-parser.js | 211 +++ src/js/document-paragraph-parser.js | 91 ++ src/js/document-parser.js | 548 +------- src/js/document-summary.js | 50 + src/js/document-table-parser.js | 76 + src/js/docx-assets.js | 127 ++ src/js/docx-package-loader.js | 29 + src/js/image-trace.js | 63 + src/js/main.js | 196 +-- src/js/markdown-renderer.js | 129 ++ src/js/numbering-parser.js | 12 +- src/js/rels-parser.js | 25 +- src/js/styles-parser.js | 12 +- src/js/summary.js | 34 + src/js/xml-utils.js | 14 +- src/js/zip-io.js | 56 +- src/ts/asset-manifest.ts | 43 + src/ts/browser-zip.ts | 138 ++ src/ts/core.ts | 550 +------- src/ts/document-anchor-parser.ts | 68 + src/ts/document-block-parser.ts | 253 ++++ src/ts/document-cell-parser.ts | 88 ++ src/ts/document-drawing-parser.ts | 108 ++ src/ts/document-inline-parser.ts | 279 ++++ src/ts/document-paragraph-parser.ts | 123 ++ src/ts/document-parser.ts | 791 +---------- src/ts/document-summary.ts | 57 + src/ts/document-table-parser.ts | 96 ++ src/ts/docx-assets.ts | 148 ++ src/ts/docx-package-loader.ts | 34 + src/ts/globals.d.ts | 146 ++ src/ts/image-trace.ts | 64 + src/ts/main.ts | 310 ++--- src/ts/markdown-renderer.ts | 169 +++ src/ts/module-registry.ts | 1 + src/ts/numbering-parser.ts | 35 +- src/ts/rels-parser.ts | 34 +- src/ts/styles-parser.ts | 40 +- src/ts/summary.ts | 41 + src/ts/xml-utils.ts | 22 +- src/ts/zip-io.ts | 61 +- 60 files changed, 4802 insertions(+), 3407 deletions(-) create mode 100644 src/js/asset-manifest.js create mode 100644 src/js/browser-zip.js create mode 100644 src/js/document-anchor-parser.js create mode 100644 src/js/document-block-parser.js create mode 100644 src/js/document-cell-parser.js create mode 100644 src/js/document-drawing-parser.js create mode 100644 src/js/document-inline-parser.js create mode 100644 src/js/document-paragraph-parser.js create mode 100644 src/js/document-summary.js create mode 100644 src/js/document-table-parser.js create mode 100644 src/js/docx-assets.js create mode 100644 src/js/docx-package-loader.js create mode 100644 src/js/image-trace.js create mode 100644 src/js/markdown-renderer.js create mode 100644 src/js/summary.js create mode 100644 src/ts/asset-manifest.ts create mode 100644 src/ts/browser-zip.ts create mode 100644 src/ts/document-anchor-parser.ts create mode 100644 src/ts/document-block-parser.ts create mode 100644 src/ts/document-cell-parser.ts create mode 100644 src/ts/document-drawing-parser.ts create mode 100644 src/ts/document-inline-parser.ts create mode 100644 src/ts/document-paragraph-parser.ts create mode 100644 src/ts/document-summary.ts create mode 100644 src/ts/document-table-parser.ts create mode 100644 src/ts/docx-assets.ts create mode 100644 src/ts/docx-package-loader.ts create mode 100644 src/ts/globals.d.ts create mode 100644 src/ts/image-trace.ts create mode 100644 src/ts/markdown-renderer.ts create mode 100644 src/ts/summary.ts diff --git a/TODO.md b/TODO.md index 8aab696..1831f8c 100644 --- a/TODO.md +++ b/TODO.md @@ -111,11 +111,24 @@ ## Phase 15: Refactoring -- [ ] Review `miku-xlsx2md` module boundaries before cutting files -- [ ] Split DOCX package loading and relationship/content-type resolution out of `core.ts` where useful -- [ ] Split document XML block parsing, inline run parsing, table parsing, and drawing/image extraction out of `document-parser.ts` -- [ ] Extract Markdown rendering/escaping helpers into focused modules instead of keeping rendering logic inside parser orchestration -- [ ] Extract asset manifest construction and browser ZIP packaging into focused modules -- [ ] Keep CLI and browser behavior unchanged while refactoring by adding or preserving focused regression tests -- [ ] Update `scripts/lib/docx2md-module-order.mjs` and generated `src/js/` order whenever TypeScript modules are split -- [ ] Re-run `npm run build` and `npm run test:unit` after each refactoring slice +- [x] Review `miku-xlsx2md` module boundaries before cutting files +- [x] Split DOCX package loading and relationship/content-type resolution out of `core.ts` where useful +- [x] Split document XML block parsing, inline run parsing, table parsing, and drawing/image extraction out of `document-parser.ts` +- [x] Extract bookmark anchor normalization and duplicate-claiming helpers into a focused module +- [x] Extract drawing/image unsupported trace description into a focused module +- [x] Extract table grid-span and vertical-merge row construction into a focused module +- [x] Extract Markdown rendering/escaping helpers into focused modules instead of keeping rendering logic inside parser orchestration +- [x] Extract asset manifest construction and browser ZIP packaging into focused modules +- [x] Keep CLI and browser behavior unchanged while refactoring by adding or preserving focused regression tests +- [x] Update `scripts/lib/docx2md-module-order.mjs` and generated `src/js/` order whenever TypeScript modules are split +- [x] Re-run `npm run build` and `npm run test:unit` after each refactoring slice + +## Phase 16: Refactoring Resume Notes + +- [x] Next safe slice: extract inline run parsing and hyperlink rendering from `document-parser.ts` into `document-inline-parser.ts` +- [x] Keep textbox text extraction close to inline parsing at first because it calls the same run/text/style logic +- [x] Keep `renderStructuredParagraphText` in `document-parser.ts` until inline/textbox extraction is stable +- [x] After inline/textbox extraction, consider splitting top-level block parsing from `parseDocumentXml` +- [x] Split table cell text extraction after inline/textbox callback boundary stabilized +- [x] After each slice, update `scripts/lib/docx2md-module-order.mjs`, `miku-docx2md-src.html`, and generated `src/js/` +- [x] After each slice, run `npm run build`, `npm run test:unit`, `npx tsc --noEmit`, and `git diff --check` diff --git a/docs/docx2md-impl-spec.md b/docs/docx2md-impl-spec.md index daab565..1c47bfe 100644 --- a/docs/docx2md-impl-spec.md +++ b/docs/docx2md-impl-spec.md @@ -28,6 +28,9 @@ The current first cut includes: - nested lists based on `numbering.xml` - structural table extraction - merge placeholders `←M←` and `↑M↑` +- resolved embedded image asset discovery and optional sidecar export +- lightweight image placeholders or Markdown image links when image metadata permits +- asset manifest output for CLI and browser image asset exports - summary counts - unsupported-element diagnostics - Node.js CLI @@ -35,8 +38,8 @@ The current first cut includes: The current first cut still excludes: -- image extraction -- drawing / shape extraction +- inline image layout reproduction +- drawing / shape layout extraction - exact layout reproduction - header / footer, footnotes, comments, tracked changes @@ -47,11 +50,11 @@ The current end-to-end flow is: 1. read a `.docx` file as bytes 2. expand ZIP entries in-house 3. load `word/document.xml` -4. optionally load `word/_rels/document.xml.rels`, `word/styles.xml`, and `word/numbering.xml` +4. optionally load `word/_rels/document.xml.rels`, `word/styles.xml`, `word/numbering.xml`, and `[Content_Types].xml` 5. parse document blocks in document order -6. build a lightweight parsed document with `blocks` and `summary` +6. build a lightweight parsed document with `blocks`, `summary`, and any resolved sidecar `assets` 7. render Markdown -8. optionally emit summary text and unsupported debug comments +8. optionally emit summary text, unsupported debug comments, and exported image assets ## 4. ZIP Handling diff --git a/docs/docx2md-spec.md b/docs/docx2md-spec.md index 9bb26c0..33e568a 100644 --- a/docs/docx2md-spec.md +++ b/docs/docx2md-spec.md @@ -46,12 +46,12 @@ The first cut should focus on textual and structural content that maps cleanly i - bullet lists - numbered lists - tables +- resolved embedded image references as lightweight placeholders or explicit sidecar assets ### 2.4 Out of Scope in First Cut -The first cut intentionally excludes visual and layout-heavy features. +The first cut intentionally excludes visual and layout-heavy reproduction. -- images - shapes - SmartArt - WordArt @@ -59,6 +59,7 @@ The first cut intentionally excludes visual and layout-heavy features. - floating objects - charts - drawing objects +- inline image layout and sizing fidelity - exact page layout reproduction - headers / footers - footnotes / endnotes @@ -66,7 +67,8 @@ The first cut intentionally excludes visual and layout-heavy features. - tracked changes - macros -These may be considered later, but should not complicate the first implementation. +Resolved embedded image files may be exposed as sidecar assets, but this does not imply Word-like layout reproduction. +Other visual features may be considered later, but should not complicate the first implementation. ## 3. Target Documents @@ -165,7 +167,8 @@ The primary output should be: - one combined Markdown file -Since images and shapes are out of scope in the first cut, ZIP export is not required initially. +When resolved embedded images are exported explicitly, a sidecar asset directory or archive may accompany the Markdown output. +The primary output remains the Markdown document; sidecar image export is optional and should not require layout reconstruction. ### 5.3 Naming @@ -504,7 +507,7 @@ When multiple XML spellings represent the same broad unsupported feature, the im An implementation may also choose a narrower compromise for text boxes: preserve plain textual paragraphs from `txbxContent` when they can be extracted safely, while still treating textbox layout and placement as unsupported. For image-like drawing content, an implementation may keep the image unsupported while still emitting a debug-oriented placeholder trace that includes the resolved relationship target and, when safely available, metadata such as alt text (`descr` / `title`) and drawing extent. -When meaningful alt text is available, the implementation may also emit a small non-debug placeholder such as `[Image: ...]` without attempting actual image extraction or layout reproduction. +When meaningful alt text is available, the implementation may also emit a small non-debug placeholder such as `[Image: ...]` without attempting inline layout reproduction. For Node-oriented workflows, an implementation may additionally expose resolved embedded image package entries as sidecar assets without attempting layout reconstruction or automatic Markdown image embedding. When such sidecar asset export is enabled explicitly, the implementation may choose to replace that placeholder with a relative Markdown image link such as `![alt](assets/word/media/example.png)`. When package content types are available, an implementation may prefer those declarations over file-extension inference when reporting exported asset media types. @@ -569,7 +572,7 @@ The intended direction is to follow the sibling app style where practical. - TypeScript as source of truth - testable core logic -CLI support may be added later, but it does not need to block the first cut. +Current implementations may include CLI support when it follows the same local-processing and testable-core direction. ## 12. Initial Development Priorities diff --git a/docs/upstream.md b/docs/upstream.md index a436258..3952a4a 100644 --- a/docs/upstream.md +++ b/docs/upstream.md @@ -24,4 +24,5 @@ When reviewing architecture, documentation style, file layout, build scripts, or ## Scope Note -For `miku-docx2md` first cut, images and shapes are out of scope even though the upstream sibling app handles richer asset extraction in the spreadsheet domain. +For `miku-docx2md`, Word-like visual layout reproduction remains out of scope. +Resolved embedded images may be exposed as sidecar assets, but shapes, charts, floating-object layout, and richer drawing reconstruction should still be treated as document-specific work rather than copied directly from the spreadsheet upstream. diff --git a/index-src.html b/index-src.html index 435c36f..7ee4559 100644 --- a/index-src.html +++ b/index-src.html @@ -168,7 +168,7 @@
Local Browser Tool

miku-docx2md

-

Version 0.8.0 / Updated 2026-04-24

+

Version 0.8.1 / Updated 2026-04-24

What is this?

diff --git a/index.html b/index.html index 435c36f..7ee4559 100644 --- a/index.html +++ b/index.html @@ -168,7 +168,7 @@
Local Browser Tool

miku-docx2md

-

Version 0.8.0 / Updated 2026-04-24

+

Version 0.8.1 / Updated 2026-04-24

What is this?

diff --git a/miku-docx2md-src.html b/miku-docx2md-src.html index 7ac31b4..5cae5fe 100644 --- a/miku-docx2md-src.html +++ b/miku-docx2md-src.html @@ -79,8 +79,23 @@

Markdown

+ + + + + + + + + + + + + + + diff --git a/miku-docx2md.html b/miku-docx2md.html index 3734ba0..8cc2f20 100644 --- a/miku-docx2md.html +++ b/miku-docx2md.html @@ -5,10 +5,10 @@ miku-docx2md - - - - + + + +