@adeu/core 1.28.0 → 1.29.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/dist/index.cjs +135 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +135 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/diff.test.ts +8 -1
- package/src/diff.ts +6 -0
- package/src/engine.bugs.test.ts +49 -0
- package/src/engine.tables.test.ts +31 -0
- package/src/engine.ts +122 -16
- package/src/ingest.ts +19 -2
- package/src/mapper.ts +20 -2
- package/src/repro_agy_bug.test.ts +108 -0
- package/src/sanitize/core.ts +1 -1
- package/src/sanitize/sanitize.test.ts +1 -0
package/dist/index.d.cts
CHANGED
|
@@ -308,7 +308,12 @@ declare class RedlineEngine {
|
|
|
308
308
|
private _build_edit_context_previews;
|
|
309
309
|
private _scan_existing_ids;
|
|
310
310
|
private _get_heading_path_and_page;
|
|
311
|
-
accept_all_revisions():
|
|
311
|
+
accept_all_revisions(): {
|
|
312
|
+
accepted_insertions: number;
|
|
313
|
+
accepted_deletions: number;
|
|
314
|
+
accepted_formatting: number;
|
|
315
|
+
removed_comments: number;
|
|
316
|
+
};
|
|
312
317
|
/**
|
|
313
318
|
* Revert every tracked change, returning the document to the state it had
|
|
314
319
|
* before any revision was proposed. The exact inverse of
|
|
@@ -449,7 +454,10 @@ declare class RedlineEngine {
|
|
|
449
454
|
* actions, so it can be stale mid-batch. Returns null if not found.
|
|
450
455
|
*/
|
|
451
456
|
private _get_comment_author;
|
|
457
|
+
/** Returns how many comment BODIES were actually deleted (see below: only
|
|
458
|
+
* our own are; foreign ones keep their body and lose only the anchor). */
|
|
452
459
|
private _clean_wrapping_comments;
|
|
460
|
+
/** Returns how many comment bodies were deleted. */
|
|
453
461
|
private _delete_comments_in_element;
|
|
454
462
|
validate_edits(edits: any[], index_offset?: number): string[];
|
|
455
463
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -308,7 +308,12 @@ declare class RedlineEngine {
|
|
|
308
308
|
private _build_edit_context_previews;
|
|
309
309
|
private _scan_existing_ids;
|
|
310
310
|
private _get_heading_path_and_page;
|
|
311
|
-
accept_all_revisions():
|
|
311
|
+
accept_all_revisions(): {
|
|
312
|
+
accepted_insertions: number;
|
|
313
|
+
accepted_deletions: number;
|
|
314
|
+
accepted_formatting: number;
|
|
315
|
+
removed_comments: number;
|
|
316
|
+
};
|
|
312
317
|
/**
|
|
313
318
|
* Revert every tracked change, returning the document to the state it had
|
|
314
319
|
* before any revision was proposed. The exact inverse of
|
|
@@ -449,7 +454,10 @@ declare class RedlineEngine {
|
|
|
449
454
|
* actions, so it can be stale mid-batch. Returns null if not found.
|
|
450
455
|
*/
|
|
451
456
|
private _get_comment_author;
|
|
457
|
+
/** Returns how many comment BODIES were actually deleted (see below: only
|
|
458
|
+
* our own are; foreign ones keep their body and lose only the anchor). */
|
|
452
459
|
private _clean_wrapping_comments;
|
|
460
|
+
/** Returns how many comment bodies were deleted. */
|
|
453
461
|
private _delete_comments_in_element;
|
|
454
462
|
validate_edits(edits: any[], index_offset?: number): string[];
|
|
455
463
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1696,8 +1696,26 @@ ${header}`;
|
|
|
1696
1696
|
const cell_start = current;
|
|
1697
1697
|
current = this._map_blocks(cell, current);
|
|
1698
1698
|
if (!this.clean_view && !this.original_view) {
|
|
1699
|
-
|
|
1700
|
-
|
|
1699
|
+
let firstP = cell._element.getElementsByTagName("w:p")[0];
|
|
1700
|
+
let paraId = firstP ? firstP.getAttribute("w14:paraId") : null;
|
|
1701
|
+
const is_empty = current === cell_start;
|
|
1702
|
+
if (!paraId && is_empty) {
|
|
1703
|
+
if (!firstP) {
|
|
1704
|
+
const xmlDoc = cell._element.ownerDocument;
|
|
1705
|
+
firstP = xmlDoc.createElement("w:p");
|
|
1706
|
+
cell._element.appendChild(firstP);
|
|
1707
|
+
}
|
|
1708
|
+
const allPs = Array.from(cell._element.ownerDocument.getElementsByTagName("w:p"));
|
|
1709
|
+
const index = allPs.indexOf(firstP);
|
|
1710
|
+
let hash = 2166136261;
|
|
1711
|
+
const str = `fallback-paraId-${index}`;
|
|
1712
|
+
for (let i = 0; i < str.length; i++) {
|
|
1713
|
+
hash ^= str.charCodeAt(i);
|
|
1714
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
1715
|
+
}
|
|
1716
|
+
paraId = (hash >>> 0).toString(16).toUpperCase().padStart(8, "0");
|
|
1717
|
+
firstP.setAttribute("w14:paraId", paraId);
|
|
1718
|
+
}
|
|
1701
1719
|
if (paraId && firstP) {
|
|
1702
1720
|
const cellPara = new Paragraph(firstP, cell);
|
|
1703
1721
|
this._add_virtual_text("", current, cellPara);
|
|
@@ -2870,6 +2888,10 @@ function _split_cross_paragraph_hunks(edits) {
|
|
|
2870
2888
|
return out;
|
|
2871
2889
|
}
|
|
2872
2890
|
function generate_edits_via_paragraph_alignment(original_text, modified_text) {
|
|
2891
|
+
const orig_stripped = original_text.trimEnd();
|
|
2892
|
+
const orig_ws = original_text.slice(orig_stripped.length);
|
|
2893
|
+
const mod_stripped = modified_text.trimEnd();
|
|
2894
|
+
modified_text = mod_stripped + orig_ws;
|
|
2873
2895
|
const orig_paragraphs = original_text.split("\n\n");
|
|
2874
2896
|
const mod_paragraphs = modified_text.split("\n\n");
|
|
2875
2897
|
const orig_offsets = [];
|
|
@@ -4655,10 +4677,21 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4655
4677
|
parts_to_process.push(part._element);
|
|
4656
4678
|
}
|
|
4657
4679
|
}
|
|
4680
|
+
let accepted_insertions = 0;
|
|
4681
|
+
let accepted_deletions = 0;
|
|
4682
|
+
let accepted_formatting = 0;
|
|
4683
|
+
for (const root_element of parts_to_process) {
|
|
4684
|
+
accepted_insertions += findAllDescendants(root_element, "w:ins").length;
|
|
4685
|
+
accepted_deletions += findAllDescendants(root_element, "w:del").length;
|
|
4686
|
+
for (const tag of ["w:rPrChange", "w:pPrChange", "w:sectPrChange"]) {
|
|
4687
|
+
accepted_formatting += findAllDescendants(root_element, tag).length;
|
|
4688
|
+
}
|
|
4689
|
+
}
|
|
4690
|
+
let removed_comments = 0;
|
|
4658
4691
|
for (const root_element of parts_to_process) {
|
|
4659
4692
|
const insNodes = findAllDescendants(root_element, "w:ins");
|
|
4660
4693
|
for (const ins of insNodes) {
|
|
4661
|
-
this._clean_wrapping_comments(ins);
|
|
4694
|
+
removed_comments += this._clean_wrapping_comments(ins);
|
|
4662
4695
|
const parent = ins.parentNode;
|
|
4663
4696
|
if (!parent) continue;
|
|
4664
4697
|
if (parent.tagName === "w:trPr") {
|
|
@@ -4702,8 +4735,8 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4702
4735
|
if (has_content) {
|
|
4703
4736
|
rPr.removeChild(delMark);
|
|
4704
4737
|
} else {
|
|
4705
|
-
this._clean_wrapping_comments(p);
|
|
4706
|
-
this._delete_comments_in_element(p);
|
|
4738
|
+
removed_comments += this._clean_wrapping_comments(p);
|
|
4739
|
+
removed_comments += this._delete_comments_in_element(p);
|
|
4707
4740
|
if (p.parentNode) {
|
|
4708
4741
|
p.parentNode.removeChild(p);
|
|
4709
4742
|
}
|
|
@@ -4713,8 +4746,8 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4713
4746
|
}
|
|
4714
4747
|
const delNodes = findAllDescendants(root_element, "w:del");
|
|
4715
4748
|
for (const d of delNodes) {
|
|
4716
|
-
this._clean_wrapping_comments(d);
|
|
4717
|
-
this._delete_comments_in_element(d);
|
|
4749
|
+
removed_comments += this._clean_wrapping_comments(d);
|
|
4750
|
+
removed_comments += this._delete_comments_in_element(d);
|
|
4718
4751
|
const parent = d.parentNode;
|
|
4719
4752
|
if (parent) {
|
|
4720
4753
|
if (parent.tagName === "w:trPr") {
|
|
@@ -4809,6 +4842,12 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4809
4842
|
}
|
|
4810
4843
|
}
|
|
4811
4844
|
}
|
|
4845
|
+
return {
|
|
4846
|
+
accepted_insertions,
|
|
4847
|
+
accepted_deletions,
|
|
4848
|
+
accepted_formatting,
|
|
4849
|
+
removed_comments
|
|
4850
|
+
};
|
|
4812
4851
|
}
|
|
4813
4852
|
/**
|
|
4814
4853
|
* Revert every tracked change, returning the document to the state it had
|
|
@@ -5465,7 +5504,10 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5465
5504
|
}
|
|
5466
5505
|
return null;
|
|
5467
5506
|
}
|
|
5507
|
+
/** Returns how many comment BODIES were actually deleted (see below: only
|
|
5508
|
+
* our own are; foreign ones keep their body and lose only the anchor). */
|
|
5468
5509
|
_clean_wrapping_comments(element) {
|
|
5510
|
+
let deleted = 0;
|
|
5469
5511
|
let first_node = element;
|
|
5470
5512
|
while (true) {
|
|
5471
5513
|
const prev2 = getPreviousElement(first_node);
|
|
@@ -5533,6 +5575,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5533
5575
|
const is_own = author !== null && author === this.author;
|
|
5534
5576
|
if (is_own) {
|
|
5535
5577
|
this.comments_manager.deleteComment(c_id);
|
|
5578
|
+
deleted++;
|
|
5536
5579
|
}
|
|
5537
5580
|
if (s.parentNode) s.parentNode.removeChild(s);
|
|
5538
5581
|
for (const e of ends_to_remove) {
|
|
@@ -5550,13 +5593,17 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5550
5593
|
}
|
|
5551
5594
|
}
|
|
5552
5595
|
}
|
|
5596
|
+
return deleted;
|
|
5553
5597
|
}
|
|
5598
|
+
/** Returns how many comment bodies were deleted. */
|
|
5554
5599
|
_delete_comments_in_element(element) {
|
|
5600
|
+
let deleted = 0;
|
|
5555
5601
|
const refs = findAllDescendants(element, "w:commentReference");
|
|
5556
5602
|
for (const ref of refs) {
|
|
5557
5603
|
const c_id = ref.getAttribute("w:id");
|
|
5558
5604
|
if (c_id) {
|
|
5559
5605
|
this.comments_manager.deleteComment(c_id);
|
|
5606
|
+
deleted++;
|
|
5560
5607
|
for (const tag of ["w:commentRangeStart", "w:commentRangeEnd"]) {
|
|
5561
5608
|
const nodes = findAllDescendants(this.doc.element, tag);
|
|
5562
5609
|
for (const node of nodes) {
|
|
@@ -5567,6 +5614,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5567
5614
|
}
|
|
5568
5615
|
}
|
|
5569
5616
|
}
|
|
5617
|
+
return deleted;
|
|
5570
5618
|
}
|
|
5571
5619
|
validate_edits(edits, index_offset = 0) {
|
|
5572
5620
|
const errors = [];
|
|
@@ -6083,6 +6131,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6083
6131
|
);
|
|
6084
6132
|
reports_by_input[i] = {
|
|
6085
6133
|
status: "failed",
|
|
6134
|
+
type: edit.type || "modify",
|
|
6086
6135
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6087
6136
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6088
6137
|
warning,
|
|
@@ -6098,6 +6147,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6098
6147
|
const previews = this._build_edit_context_previews(edit);
|
|
6099
6148
|
reports_by_input[i] = {
|
|
6100
6149
|
status: "applied",
|
|
6150
|
+
type: edit.type || "modify",
|
|
6101
6151
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6102
6152
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6103
6153
|
warning: null,
|
|
@@ -6119,6 +6169,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6119
6169
|
);
|
|
6120
6170
|
reports_by_input[i] = {
|
|
6121
6171
|
status: "failed",
|
|
6172
|
+
type: edit.type || "modify",
|
|
6122
6173
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6123
6174
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6124
6175
|
warning,
|
|
@@ -6137,6 +6188,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6137
6188
|
if (report.status === "applied") {
|
|
6138
6189
|
reports_by_input[i] = {
|
|
6139
6190
|
status: "failed",
|
|
6191
|
+
type: report.type || "modify",
|
|
6140
6192
|
target_text: report.target_text,
|
|
6141
6193
|
new_text: report.new_text,
|
|
6142
6194
|
warning: null,
|
|
@@ -6207,6 +6259,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6207
6259
|
}
|
|
6208
6260
|
edits_reports.push({
|
|
6209
6261
|
status: success ? "applied" : "failed",
|
|
6262
|
+
type: edit.type || "modify",
|
|
6210
6263
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6211
6264
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6212
6265
|
warning,
|
|
@@ -6284,9 +6337,52 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6284
6337
|
resolved_mapper = this.clean_mapper;
|
|
6285
6338
|
}
|
|
6286
6339
|
if (matches.length > 0) {
|
|
6287
|
-
edit.
|
|
6288
|
-
|
|
6289
|
-
|
|
6340
|
+
const match_mode = edit.match_mode || "strict";
|
|
6341
|
+
const unique_matches = [];
|
|
6342
|
+
const seen_trs = /* @__PURE__ */ new Set();
|
|
6343
|
+
for (const match of matches) {
|
|
6344
|
+
const start_idx = match[0];
|
|
6345
|
+
const [anchor_run, anchor_para] = resolved_mapper.get_insertion_anchor(start_idx, false);
|
|
6346
|
+
let target_element = null;
|
|
6347
|
+
if (anchor_run) target_element = anchor_run._element;
|
|
6348
|
+
else if (anchor_para) target_element = anchor_para._element;
|
|
6349
|
+
let tr = target_element;
|
|
6350
|
+
while (tr && tr.tagName !== "w:tr") tr = tr.parentNode;
|
|
6351
|
+
if (tr) {
|
|
6352
|
+
if (!seen_trs.has(tr)) {
|
|
6353
|
+
seen_trs.add(tr);
|
|
6354
|
+
unique_matches.push(match);
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
}
|
|
6358
|
+
if (unique_matches.length > 0) {
|
|
6359
|
+
let matches_to_apply = unique_matches;
|
|
6360
|
+
if (match_mode === "strict" || match_mode === "first") {
|
|
6361
|
+
matches_to_apply = unique_matches.slice(0, 1);
|
|
6362
|
+
}
|
|
6363
|
+
if (match_mode === "all" || matches_to_apply.length > 1) {
|
|
6364
|
+
for (const m of matches_to_apply) {
|
|
6365
|
+
const sub_edit = {
|
|
6366
|
+
...edit,
|
|
6367
|
+
_resolved_start_idx: m[0],
|
|
6368
|
+
_active_mapper_ref: resolved_mapper,
|
|
6369
|
+
_parent_edit_ref: edit
|
|
6370
|
+
};
|
|
6371
|
+
resolved_edits.push([sub_edit, null]);
|
|
6372
|
+
}
|
|
6373
|
+
} else {
|
|
6374
|
+
edit._resolved_start_idx = matches_to_apply[0][0];
|
|
6375
|
+
edit._active_mapper_ref = resolved_mapper;
|
|
6376
|
+
resolved_edits.push([edit, null]);
|
|
6377
|
+
}
|
|
6378
|
+
} else {
|
|
6379
|
+
skipped++;
|
|
6380
|
+
edit._applied_status = false;
|
|
6381
|
+
const target_snippet = (edit.target_text || "").trim().substring(0, 40);
|
|
6382
|
+
const msg = `- Failed to locate row target: '${target_snippet}...'`;
|
|
6383
|
+
this.skipped_details.push(msg);
|
|
6384
|
+
edit._error_msg = msg;
|
|
6385
|
+
}
|
|
6290
6386
|
} else {
|
|
6291
6387
|
skipped++;
|
|
6292
6388
|
edit._applied_status = false;
|
|
@@ -6592,8 +6688,15 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6592
6688
|
let skipped = 0;
|
|
6593
6689
|
let already_resolved = 0;
|
|
6594
6690
|
const resolved_history = /* @__PURE__ */ new Map();
|
|
6595
|
-
|
|
6596
|
-
const
|
|
6691
|
+
const sortedActions = actions.map((action, pos) => ({ action, pos })).sort((a, b) => {
|
|
6692
|
+
const aPri = a.action.type === "reply" ? 0 : 1;
|
|
6693
|
+
const bPri = b.action.type === "reply" ? 0 : 1;
|
|
6694
|
+
if (aPri !== bPri) {
|
|
6695
|
+
return aPri - bPri;
|
|
6696
|
+
}
|
|
6697
|
+
return a.pos - b.pos;
|
|
6698
|
+
});
|
|
6699
|
+
for (const { action, pos } of sortedActions) {
|
|
6597
6700
|
const type = action.type;
|
|
6598
6701
|
if (type === "reply") {
|
|
6599
6702
|
const cid = action.target_id.replace("Com:", "");
|
|
@@ -8741,8 +8844,25 @@ function extract_table(table, comments_map, cleanView, cursor, paragraph_offsets
|
|
|
8741
8844
|
paragraph_offsets
|
|
8742
8845
|
);
|
|
8743
8846
|
if (!cleanView) {
|
|
8744
|
-
|
|
8745
|
-
|
|
8847
|
+
let firstP = cell._element.getElementsByTagName("w:p")[0];
|
|
8848
|
+
let paraId = firstP ? firstP.getAttribute("w14:paraId") : null;
|
|
8849
|
+
if (!paraId && (!cell_content || cell_content.trim() === "")) {
|
|
8850
|
+
if (!firstP) {
|
|
8851
|
+
const xmlDoc = cell._element.ownerDocument;
|
|
8852
|
+
firstP = xmlDoc.createElement("w:p");
|
|
8853
|
+
cell._element.appendChild(firstP);
|
|
8854
|
+
}
|
|
8855
|
+
const allPs = Array.from(cell._element.ownerDocument.getElementsByTagName("w:p"));
|
|
8856
|
+
const index = allPs.indexOf(firstP);
|
|
8857
|
+
let hash = 2166136261;
|
|
8858
|
+
const str = `fallback-paraId-${index}`;
|
|
8859
|
+
for (let i = 0; i < str.length; i++) {
|
|
8860
|
+
hash ^= str.charCodeAt(i);
|
|
8861
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
8862
|
+
}
|
|
8863
|
+
paraId = (hash >>> 0).toString(16).toUpperCase().padStart(8, "0");
|
|
8864
|
+
firstP.setAttribute("w14:paraId", paraId);
|
|
8865
|
+
}
|
|
8746
8866
|
if (paraId) {
|
|
8747
8867
|
const space_pad = cell_content ? " " : "";
|
|
8748
8868
|
const anchor = `${space_pad}{#cell:${paraId}}`;
|
|
@@ -9701,7 +9821,7 @@ async function finalize_document(doc, options) {
|
|
|
9701
9821
|
report.tracked_changes_found = total;
|
|
9702
9822
|
if (total > 0 && !options.accept_all) {
|
|
9703
9823
|
report.status = "blocked";
|
|
9704
|
-
report.blocked_reason = `Document contains ${total} unresolved tracked changes (${counts[0]} insertions, ${counts[1]} deletions, ${counts[2]} formatting). Review in Word first, or set
|
|
9824
|
+
report.blocked_reason = `Document contains ${total} unresolved tracked changes (${counts[0]} insertions, ${counts[1]} deletions, ${counts[2]} formatting). Review in Word first, set accept_all=true, or set sanitize_mode='keep-markup'.`;
|
|
9705
9825
|
return { reportText: report.render() };
|
|
9706
9826
|
}
|
|
9707
9827
|
if (total > 0) {
|