@ansonlai/docx-redline-js 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +13 -1
- package/CHANGELOG.md +35 -0
- package/README.md +12 -4
- package/dist/docx-redline-js.esm.js +358 -262
- package/dist/docx-redline-js.esm.js.map +4 -4
- package/dist/docx-redline-js.esm.min.js +92 -92
- package/dist/docx-redline-js.esm.min.js.map +4 -4
- package/dist/docx-redline.bundle.cjs +358 -262
- package/dist/docx-redline.bundle.cjs.map +4 -4
- package/dist/docx-redline.bundle.js +358 -262
- package/dist/docx-redline.bundle.js.map +4 -4
- package/docs/AGENT_KNOWLEDGE_BASE.md +35 -2
- package/docs/TESTING.md +6 -1
- package/engine/oxml-engine.js +2 -2
- package/engine/table-mode.js +7 -4
- package/index.d.ts +23 -1
- package/index.js +1 -0
- package/package.json +1 -1
- package/pipeline/content-analysis.js +2 -1
- package/pipeline/structured-content.js +2 -1
- package/services/comment-parts-merge.js +124 -0
- package/services/document-operation-mutations.js +6 -2
- package/services/operation-heuristics.js +1 -1
- package/services/standalone-docx-plumbing.js +38 -22
- package/services/table-reconciliation.js +11 -6
package/ARCHITECTURE.md
CHANGED
|
@@ -69,6 +69,7 @@ No Word add-in entrypoints or host-specific integration layers are part of this
|
|
|
69
69
|
│ ├── revision-comment-management.js
|
|
70
70
|
│ ├── document-inspection.js
|
|
71
71
|
│ ├── inspection-comparison.js
|
|
72
|
+
│ ├── comment-parts-merge.js
|
|
72
73
|
│ ├── document-operation-session.js
|
|
73
74
|
│ ├── document-operation-applier.js
|
|
74
75
|
│ ├── document-operation-mutations.js
|
|
@@ -187,9 +188,13 @@ No Word add-in entrypoints or host-specific integration layers are part of this
|
|
|
187
188
|
- `pipeline/structured-content.js`
|
|
188
189
|
- Strict decomposition and planning for atomic mixed heading/paragraph/list/
|
|
189
190
|
table replacements. It rejects ambiguous table-like pipe text rather than
|
|
190
|
-
allowing a fallback to literal paragraphs.
|
|
191
|
+
allowing a fallback to literal paragraphs. A one-column table needs a pipe on both sides of its separator
|
|
192
|
+
(`| --- |`); the same rule is in `pipeline/content-analysis.js` (`parseTable`).
|
|
191
193
|
- `pipeline/*`
|
|
192
194
|
- Ingestion, markdown preprocessing, diffing, patching, and serialization stages. Ingestion treats deleted and moved-from content as non-visible text and inserted/moved-to content as visible text.
|
|
195
|
+
- `services/table-reconciliation.js`
|
|
196
|
+
- Table generation (`generateTableOoxml`) and cell-level reconciliation against a virtual grid. A caller's
|
|
197
|
+
`structuredContent: false` reaches it as `plainTextContent`, so cell text is not parsed as inline Markdown.
|
|
193
198
|
- `services/comment-engine.js`
|
|
194
199
|
- Comment creation and package-level comment XML handling.
|
|
195
200
|
- `services/numbering-helpers.js`
|
|
@@ -320,6 +325,13 @@ No Word add-in entrypoints or host-specific integration layers are part of this
|
|
|
320
325
|
- `services/document-inspection.js`
|
|
321
326
|
- Read-only paragraphs/comments inventory with target identity, headings,
|
|
322
327
|
revision authors, table context, and advisory visible numbering.
|
|
328
|
+
- `services/comment-parts-merge.js`
|
|
329
|
+
- `mergeCommentParts`: the comment half of writing a batch result back into a package whose parts
|
|
330
|
+
are XML strings (no ZIP). Shares `mergeCommentsPartXml` with `ensureCommentsArtifactsInZip` and uses
|
|
331
|
+
`reconcileCommentSiblingParts`, so it merges exactly as `openDocx` does. Relationships and content
|
|
332
|
+
types stay with the host. Errors (`PARSE_ERROR`, `INVALID_COMMENT_PARTS`, `DUPLICATE_COMMENT_ID`,
|
|
333
|
+
`UNSUPPORTED_EXISTING_COMMENT_THREAD_METADATA`) are returned with `error.part`, never thrown, and the input
|
|
334
|
+
parts come back unchanged.
|
|
323
335
|
- `services/inspection-comparison.js`
|
|
324
336
|
- Pure comparison of two inspections by text, table position, list label,
|
|
325
337
|
merged review segments and comments, ignoring ids, dates and run boundaries.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`mergeCommentParts(parts, output)`:** merges a batch result's comment output (`commentsXml` / `commentsXmlMode`,
|
|
8
|
+
`commentsExtendedXml` / `commentsExtendedXmlMode`) into comment parts held as XML strings, for hosts that keep package
|
|
9
|
+
parts outside a ZIP (a Flat OPC package, a browser parts map). Appends or replaces comments.xml, brings existing
|
|
10
|
+
commentsIds.xml / commentsExtensible.xml in line, and replaces commentsExtended.xml. Returns
|
|
11
|
+
`{ status, hasChanges, parts, changedParts, addedParts }`. It never throws for document content: `PARSE_ERROR`,
|
|
12
|
+
`INVALID_COMMENT_PARTS` (a non-string input or a part with the wrong root element), `DUPLICATE_COMMENT_ID` (an id
|
|
13
|
+
already used, or repeated within the incoming part, in every mode) and `UNSUPPORTED_EXISTING_COMMENT_THREAD_METADATA` (a `'merge'` thread-metadata delta for
|
|
14
|
+
parts that already have it) come back as `error`, with `error.part` naming the part, and the input parts unchanged.
|
|
15
|
+
Existing commentsIds/commentsExtensible parts are validated before they are reconciled, and an incoming comments part
|
|
16
|
+
with no comments changes nothing. Relationships and content types stay with the
|
|
17
|
+
host; `addedParts` lists parts new to the input (presence only, so hosts should also repair a missing relationship for
|
|
18
|
+
any part in `changedParts`). Same merge as `openDocx` (shared helper).
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **`structuredContent: false` now also covers paragraphs a redline adds.** A plain-text redline whose `modified` adds
|
|
23
|
+
paragraphs before or after the target (`'Intro.
|
|
24
|
+
Use __literal__ text'`) kept the target literal but stripped inline
|
|
25
|
+
Markdown, and parsed `#` headings, in the new paragraphs. They now stay literal too, including list siblings, ranges,
|
|
26
|
+
`replace` and untracked edits. Inserting paragraphs this way still inherits the list of a list-item target.
|
|
27
|
+
- **One-column tables:** a one-column Markdown separator (`| --- |`) is now recognized. Before, a multi-line redline of a
|
|
28
|
+
cell in a one-column table (`'Cell text.
|
|
29
|
+
Second line'`) inserted a stray `---` row (`structuredContent: false`) or was
|
|
30
|
+
refused `TABLE_SEPARATOR_REQUIRED` (`true`), and a caller-written one-column table was refused the same way. A bare
|
|
31
|
+
`---` line is still not a table separator.
|
|
32
|
+
- **`structuredContent: false` on the table route:** text added to or rewritten in table cells by a plain-text redline
|
|
33
|
+
(including the multi-line cell edit that inserts rows) keeps inline Markdown literal.
|
|
34
|
+
- The `applyCommentReplyToParts` declaration now includes `documentXml`.
|
|
35
|
+
- `ensureCommentsArtifactsInZip` (and so `openDocx`), when merging into an existing comments.xml, also refuses an id
|
|
36
|
+
repeated within the incoming part, and leaves comments.xml untouched when the incoming part has no comments.
|
|
37
|
+
|
|
3
38
|
## 0.10.0
|
|
4
39
|
|
|
5
40
|
### Added
|
package/README.md
CHANGED
|
@@ -21,7 +21,14 @@ Converts AI-generated or programmatic text/markdown edits into valid Office Open
|
|
|
21
21
|
- Package plumbing helpers for numbering.xml, comments.xml, content types, and relationships
|
|
22
22
|
- Zero host dependencies: works in Node.js, browsers, Deno, and similar JS runtimes with DOM parsing support
|
|
23
23
|
|
|
24
|
-
## What's New in 0.10.0, 0.9.0 and 0.8.x
|
|
24
|
+
## What's New in 0.11.0, 0.10.0, 0.9.0 and 0.8.x
|
|
25
|
+
|
|
26
|
+
0.11.0 adds `mergeCommentParts(parts, output)`, which merges a batch result's comment output into comment parts held as
|
|
27
|
+
XML strings, for hosts that have no ZIP. It also fixes `structuredContent: false` so inline Markdown stays literal in
|
|
28
|
+
paragraphs a redline adds and in table cells, recognizes one-column Markdown table separators (`| --- |`), and makes
|
|
29
|
+
`ensureCommentsArtifactsInZip` refuse an incoming part that repeats a comment id while merging into an existing
|
|
30
|
+
`comments.xml`. See the
|
|
31
|
+
[0.11.0 release notes](./docs/releases/0.11.0.md).
|
|
25
32
|
|
|
26
33
|
0.10.0 adds `existingRevisions: 'auto'` (capability `existing-revisions-auto-v1`, contract version stays 9), which
|
|
27
34
|
merges a target's own-author history and slices around another reviewer's, per target. It also adds
|
|
@@ -382,7 +389,7 @@ See the [compact agent fast start](./docs/AGENT_FAST_START.md), the
|
|
|
382
389
|
| `generateRedlines` | `boolean` | `true` | When `true`, emit Word-native tracked changes (`w:ins`/`w:del`). When `false`, apply clean direct edits without revision markup. **Note: Redlines are not always the preferred method** — pass `generateRedlines: false` (or `--no-redlines` via CLI) when producing clean execution drafts, restructuring documents, or when revision clutter is unwanted. |
|
|
383
390
|
| `author` | `string` | `'AI Redliner'` | Reviewer/author name stamped on generated tracked changes and comments. Overridable via `DOCX_REDLINE_AUTHOR` env variable. |
|
|
384
391
|
| `atomic` | `boolean` | `false` | Batch transaction mode. By default (`false`), valid edits are applied and failing operations report errors. When `true`, any operation failure rolls back the entire batch to the original document state (`rolledBack: true`, `hasChanges: false`). Feature prominently in high-assurance workflows. |
|
|
385
|
-
| `structuredContent` | `boolean` | `true` | Auto-detects Markdown tables, headings (`#`), and lists in replacement text and renders them as native Word elements (`w:tbl`, `w:pStyle`, `w:numPr`). Pass `false` to treat replacement text strictly as plain text: inline Markdown markers (`**`, `__`, `_`, `~~`, `++`) are kept literally. With `true`, underscores follow CommonMark flanking rules, so signature lines (`_____`) and `snake_case` stay literal. |
|
|
392
|
+
| `structuredContent` | `boolean` | `true` | Auto-detects Markdown tables, headings (`#`), and lists in replacement text and renders them as native Word elements (`w:tbl`, `w:pStyle`, `w:numPr`). Pass `false` to treat replacement text strictly as plain text: inline Markdown markers (`**`, `__`, `_`, `~~`, `++`) are kept literally, including in paragraphs a redline adds and in table cells. With `true`, underscores follow CommonMark flanking rules, so signature lines (`_____`) and `snake_case` stay literal. |
|
|
386
393
|
| `pairReplacements` | `boolean` | `true` | Links adjacent `<w:del>` and `<w:ins>` revisions with matching timestamps so Word groups them as a single replacement in the Reviewing Pane. |
|
|
387
394
|
| `strictTargets` | `boolean` | `true` (CLI/facade) | Requires exact target descriptors (`exactText`, `paragraphId`, `index`, `occurrence`, `fingerprint`) and forbids ambiguous matching. Defaults to `false` in low-level runner for backwards compatibility. |
|
|
388
395
|
| `existingRevisions` | `string` | `'merge-same-author'` | How to handle paragraphs with existing tracked changes. `'merge-same-author'` merges revisions from the same author and protects other authors with `EXISTING_REVISIONS`. `'slice-cross-author'` keeps that same-author merge behavior while allowing Word-native edits inside another author's pending insertion. Pass `'accept-all-first'` to normalize prior revisions or `'reject-input'` to refuse editing revised paragraphs. `'auto'` chooses per target: `'merge-same-author'` when the target has no tracked changes or only the operation author's, otherwise `'slice-cross-author'` (preflight reports the resolved policy). |
|
|
@@ -558,7 +565,7 @@ const result = await document.applyOperations([plan.operation], {
|
|
|
558
565
|
});
|
|
559
566
|
```
|
|
560
567
|
|
|
561
|
-
Every Markdown table must include a separator row immediately below its header.
|
|
568
|
+
Every Markdown table must include a separator row immediately below its header (a one-column table uses `| --- |`).
|
|
562
569
|
Missing separators, missing data rows, and inconsistent column counts are
|
|
563
570
|
reported as structured errors instead of being inserted as visible pipe text.
|
|
564
571
|
Use `#` through `#########` to request Word heading paragraphs; blank lines
|
|
@@ -589,6 +596,7 @@ an earlier block has already replaced.
|
|
|
589
596
|
|----------|---------|
|
|
590
597
|
| `injectCommentsIntoOoxml(oxml, comments, options)` | Add comments anchored to text ranges. |
|
|
591
598
|
| `applyCommentReplyToParts(options)` | Build a threaded reply in `comments.xml` and `commentsExtended.xml` without adding a document-body anchor. Pass `documentXml` so the reply's `w14:paraId` also avoids body paragraph ids. |
|
|
599
|
+
| `mergeCommentParts(parts, output)` | Merge a batch result's comment output into comment parts held as XML strings (no ZIP): appends or replaces `comments.xml`, reconciles existing `commentsIds.xml` / `commentsExtensible.xml`, replaces `commentsExtended.xml`. Returns `{ status, hasChanges, parts, changedParts, addedParts, error? }`; never throws for document content. Error codes: `PARSE_ERROR`, `INVALID_COMMENT_PARTS`, `DUPLICATE_COMMENT_ID`, `UNSUPPORTED_EXISTING_COMMENT_THREAD_METADATA`, each with `error.part`. The host adds relationships and content types for `addedParts`; that list reflects part presence only, so also repair a missing relationship for any part in `changedParts`. |
|
|
592
600
|
| `compareDocumentInspections(expected, actual)` | Compare two `inspectDocumentParts` / `inspect()` results by text, table position, list label, review segments and comments, ignoring ids, dates and run boundaries. Returns `{ matches, differences }` (at most 10). See [Comparing inspections](#comparing-inspections). |
|
|
593
601
|
| `inspectionReviewShape(inspection)` | The normalized, host-independent shape `compareDocumentInspections` compares. |
|
|
594
602
|
| `acceptTrackedChangesInOoxml(oxml, { author?, allAuthors? })` | Accept `w:ins` / `w:del` / `w:moveFrom` / `w:moveTo` / `*PrChange` revisions for one author or all authors. |
|
|
@@ -597,7 +605,7 @@ an earlier block has already replaced.
|
|
|
597
605
|
| `generateTableOoxml(headers, rows, options)` | Generate a `w:tbl` from tabular data. |
|
|
598
606
|
| `createDynamicNumberingIdState(numberingXml)` | Allocate numbering IDs without collisions. |
|
|
599
607
|
| `ensureNumberingArtifactsInZip(zip, numberingXml, options)` | Add numbering artifacts to a `.docx` package. Always merges into an existing `word/numbering.xml` through the package's single numbering merge (`mergeNumberingParts`); an incoming id that already exists with different content fails with `NUMBERING_ID_CONFLICT`. The former `mergeNumberingXml` option is ignored. |
|
|
600
|
-
| `ensureCommentsArtifactsInZip(zip, commentsXml)` | Merge comments artifacts into a `.docx` package. |
|
|
608
|
+
| `ensureCommentsArtifactsInZip(zip, commentsXml)` | Merge comments artifacts into a `.docx` package. When merging into an existing `comments.xml`, refuses an id already in use, including one repeated within the incoming part (`DUPLICATE_COMMENT_ID`), and leaves `comments.xml` untouched when the incoming part has no comments. `replaceExisting` (or no existing part) writes the incoming part as is. |
|
|
601
609
|
| `ensureCommentsExtendedArtifactsInZip(zip, commentsExtendedXml)` | Add or replace modern Word comment-thread metadata in a `.docx` package. |
|
|
602
610
|
| `validateDocxPackage(zip)` | Validate `.docx` structural consistency. |
|
|
603
611
|
|