@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.cjs
CHANGED
|
@@ -1755,8 +1755,26 @@ ${header}`;
|
|
|
1755
1755
|
const cell_start = current;
|
|
1756
1756
|
current = this._map_blocks(cell, current);
|
|
1757
1757
|
if (!this.clean_view && !this.original_view) {
|
|
1758
|
-
|
|
1759
|
-
|
|
1758
|
+
let firstP = cell._element.getElementsByTagName("w:p")[0];
|
|
1759
|
+
let paraId = firstP ? firstP.getAttribute("w14:paraId") : null;
|
|
1760
|
+
const is_empty = current === cell_start;
|
|
1761
|
+
if (!paraId && is_empty) {
|
|
1762
|
+
if (!firstP) {
|
|
1763
|
+
const xmlDoc = cell._element.ownerDocument;
|
|
1764
|
+
firstP = xmlDoc.createElement("w:p");
|
|
1765
|
+
cell._element.appendChild(firstP);
|
|
1766
|
+
}
|
|
1767
|
+
const allPs = Array.from(cell._element.ownerDocument.getElementsByTagName("w:p"));
|
|
1768
|
+
const index = allPs.indexOf(firstP);
|
|
1769
|
+
let hash = 2166136261;
|
|
1770
|
+
const str = `fallback-paraId-${index}`;
|
|
1771
|
+
for (let i = 0; i < str.length; i++) {
|
|
1772
|
+
hash ^= str.charCodeAt(i);
|
|
1773
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
1774
|
+
}
|
|
1775
|
+
paraId = (hash >>> 0).toString(16).toUpperCase().padStart(8, "0");
|
|
1776
|
+
firstP.setAttribute("w14:paraId", paraId);
|
|
1777
|
+
}
|
|
1760
1778
|
if (paraId && firstP) {
|
|
1761
1779
|
const cellPara = new Paragraph(firstP, cell);
|
|
1762
1780
|
this._add_virtual_text("", current, cellPara);
|
|
@@ -2929,6 +2947,10 @@ function _split_cross_paragraph_hunks(edits) {
|
|
|
2929
2947
|
return out;
|
|
2930
2948
|
}
|
|
2931
2949
|
function generate_edits_via_paragraph_alignment(original_text, modified_text) {
|
|
2950
|
+
const orig_stripped = original_text.trimEnd();
|
|
2951
|
+
const orig_ws = original_text.slice(orig_stripped.length);
|
|
2952
|
+
const mod_stripped = modified_text.trimEnd();
|
|
2953
|
+
modified_text = mod_stripped + orig_ws;
|
|
2932
2954
|
const orig_paragraphs = original_text.split("\n\n");
|
|
2933
2955
|
const mod_paragraphs = modified_text.split("\n\n");
|
|
2934
2956
|
const orig_offsets = [];
|
|
@@ -4714,10 +4736,21 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4714
4736
|
parts_to_process.push(part._element);
|
|
4715
4737
|
}
|
|
4716
4738
|
}
|
|
4739
|
+
let accepted_insertions = 0;
|
|
4740
|
+
let accepted_deletions = 0;
|
|
4741
|
+
let accepted_formatting = 0;
|
|
4742
|
+
for (const root_element of parts_to_process) {
|
|
4743
|
+
accepted_insertions += findAllDescendants(root_element, "w:ins").length;
|
|
4744
|
+
accepted_deletions += findAllDescendants(root_element, "w:del").length;
|
|
4745
|
+
for (const tag of ["w:rPrChange", "w:pPrChange", "w:sectPrChange"]) {
|
|
4746
|
+
accepted_formatting += findAllDescendants(root_element, tag).length;
|
|
4747
|
+
}
|
|
4748
|
+
}
|
|
4749
|
+
let removed_comments = 0;
|
|
4717
4750
|
for (const root_element of parts_to_process) {
|
|
4718
4751
|
const insNodes = findAllDescendants(root_element, "w:ins");
|
|
4719
4752
|
for (const ins of insNodes) {
|
|
4720
|
-
this._clean_wrapping_comments(ins);
|
|
4753
|
+
removed_comments += this._clean_wrapping_comments(ins);
|
|
4721
4754
|
const parent = ins.parentNode;
|
|
4722
4755
|
if (!parent) continue;
|
|
4723
4756
|
if (parent.tagName === "w:trPr") {
|
|
@@ -4761,8 +4794,8 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4761
4794
|
if (has_content) {
|
|
4762
4795
|
rPr.removeChild(delMark);
|
|
4763
4796
|
} else {
|
|
4764
|
-
this._clean_wrapping_comments(p);
|
|
4765
|
-
this._delete_comments_in_element(p);
|
|
4797
|
+
removed_comments += this._clean_wrapping_comments(p);
|
|
4798
|
+
removed_comments += this._delete_comments_in_element(p);
|
|
4766
4799
|
if (p.parentNode) {
|
|
4767
4800
|
p.parentNode.removeChild(p);
|
|
4768
4801
|
}
|
|
@@ -4772,8 +4805,8 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4772
4805
|
}
|
|
4773
4806
|
const delNodes = findAllDescendants(root_element, "w:del");
|
|
4774
4807
|
for (const d of delNodes) {
|
|
4775
|
-
this._clean_wrapping_comments(d);
|
|
4776
|
-
this._delete_comments_in_element(d);
|
|
4808
|
+
removed_comments += this._clean_wrapping_comments(d);
|
|
4809
|
+
removed_comments += this._delete_comments_in_element(d);
|
|
4777
4810
|
const parent = d.parentNode;
|
|
4778
4811
|
if (parent) {
|
|
4779
4812
|
if (parent.tagName === "w:trPr") {
|
|
@@ -4868,6 +4901,12 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
4868
4901
|
}
|
|
4869
4902
|
}
|
|
4870
4903
|
}
|
|
4904
|
+
return {
|
|
4905
|
+
accepted_insertions,
|
|
4906
|
+
accepted_deletions,
|
|
4907
|
+
accepted_formatting,
|
|
4908
|
+
removed_comments
|
|
4909
|
+
};
|
|
4871
4910
|
}
|
|
4872
4911
|
/**
|
|
4873
4912
|
* Revert every tracked change, returning the document to the state it had
|
|
@@ -5524,7 +5563,10 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5524
5563
|
}
|
|
5525
5564
|
return null;
|
|
5526
5565
|
}
|
|
5566
|
+
/** Returns how many comment BODIES were actually deleted (see below: only
|
|
5567
|
+
* our own are; foreign ones keep their body and lose only the anchor). */
|
|
5527
5568
|
_clean_wrapping_comments(element) {
|
|
5569
|
+
let deleted = 0;
|
|
5528
5570
|
let first_node = element;
|
|
5529
5571
|
while (true) {
|
|
5530
5572
|
const prev2 = getPreviousElement(first_node);
|
|
@@ -5592,6 +5634,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5592
5634
|
const is_own = author !== null && author === this.author;
|
|
5593
5635
|
if (is_own) {
|
|
5594
5636
|
this.comments_manager.deleteComment(c_id);
|
|
5637
|
+
deleted++;
|
|
5595
5638
|
}
|
|
5596
5639
|
if (s.parentNode) s.parentNode.removeChild(s);
|
|
5597
5640
|
for (const e of ends_to_remove) {
|
|
@@ -5609,13 +5652,17 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5609
5652
|
}
|
|
5610
5653
|
}
|
|
5611
5654
|
}
|
|
5655
|
+
return deleted;
|
|
5612
5656
|
}
|
|
5657
|
+
/** Returns how many comment bodies were deleted. */
|
|
5613
5658
|
_delete_comments_in_element(element) {
|
|
5659
|
+
let deleted = 0;
|
|
5614
5660
|
const refs = findAllDescendants(element, "w:commentReference");
|
|
5615
5661
|
for (const ref of refs) {
|
|
5616
5662
|
const c_id = ref.getAttribute("w:id");
|
|
5617
5663
|
if (c_id) {
|
|
5618
5664
|
this.comments_manager.deleteComment(c_id);
|
|
5665
|
+
deleted++;
|
|
5619
5666
|
for (const tag of ["w:commentRangeStart", "w:commentRangeEnd"]) {
|
|
5620
5667
|
const nodes = findAllDescendants(this.doc.element, tag);
|
|
5621
5668
|
for (const node of nodes) {
|
|
@@ -5626,6 +5673,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
5626
5673
|
}
|
|
5627
5674
|
}
|
|
5628
5675
|
}
|
|
5676
|
+
return deleted;
|
|
5629
5677
|
}
|
|
5630
5678
|
validate_edits(edits, index_offset = 0) {
|
|
5631
5679
|
const errors = [];
|
|
@@ -6142,6 +6190,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6142
6190
|
);
|
|
6143
6191
|
reports_by_input[i] = {
|
|
6144
6192
|
status: "failed",
|
|
6193
|
+
type: edit.type || "modify",
|
|
6145
6194
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6146
6195
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6147
6196
|
warning,
|
|
@@ -6157,6 +6206,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6157
6206
|
const previews = this._build_edit_context_previews(edit);
|
|
6158
6207
|
reports_by_input[i] = {
|
|
6159
6208
|
status: "applied",
|
|
6209
|
+
type: edit.type || "modify",
|
|
6160
6210
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6161
6211
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6162
6212
|
warning: null,
|
|
@@ -6178,6 +6228,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6178
6228
|
);
|
|
6179
6229
|
reports_by_input[i] = {
|
|
6180
6230
|
status: "failed",
|
|
6231
|
+
type: edit.type || "modify",
|
|
6181
6232
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6182
6233
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6183
6234
|
warning,
|
|
@@ -6196,6 +6247,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6196
6247
|
if (report.status === "applied") {
|
|
6197
6248
|
reports_by_input[i] = {
|
|
6198
6249
|
status: "failed",
|
|
6250
|
+
type: report.type || "modify",
|
|
6199
6251
|
target_text: report.target_text,
|
|
6200
6252
|
new_text: report.new_text,
|
|
6201
6253
|
warning: null,
|
|
@@ -6266,6 +6318,7 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6266
6318
|
}
|
|
6267
6319
|
edits_reports.push({
|
|
6268
6320
|
status: success ? "applied" : "failed",
|
|
6321
|
+
type: edit.type || "modify",
|
|
6269
6322
|
target_text: truncate_middle(edit.target_text || "", REPORT_ECHO_CAP),
|
|
6270
6323
|
new_text: truncate_middle(_RedlineEngine._report_new_text(edit), REPORT_ECHO_CAP),
|
|
6271
6324
|
warning,
|
|
@@ -6343,9 +6396,52 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6343
6396
|
resolved_mapper = this.clean_mapper;
|
|
6344
6397
|
}
|
|
6345
6398
|
if (matches.length > 0) {
|
|
6346
|
-
edit.
|
|
6347
|
-
|
|
6348
|
-
|
|
6399
|
+
const match_mode = edit.match_mode || "strict";
|
|
6400
|
+
const unique_matches = [];
|
|
6401
|
+
const seen_trs = /* @__PURE__ */ new Set();
|
|
6402
|
+
for (const match of matches) {
|
|
6403
|
+
const start_idx = match[0];
|
|
6404
|
+
const [anchor_run, anchor_para] = resolved_mapper.get_insertion_anchor(start_idx, false);
|
|
6405
|
+
let target_element = null;
|
|
6406
|
+
if (anchor_run) target_element = anchor_run._element;
|
|
6407
|
+
else if (anchor_para) target_element = anchor_para._element;
|
|
6408
|
+
let tr = target_element;
|
|
6409
|
+
while (tr && tr.tagName !== "w:tr") tr = tr.parentNode;
|
|
6410
|
+
if (tr) {
|
|
6411
|
+
if (!seen_trs.has(tr)) {
|
|
6412
|
+
seen_trs.add(tr);
|
|
6413
|
+
unique_matches.push(match);
|
|
6414
|
+
}
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
6417
|
+
if (unique_matches.length > 0) {
|
|
6418
|
+
let matches_to_apply = unique_matches;
|
|
6419
|
+
if (match_mode === "strict" || match_mode === "first") {
|
|
6420
|
+
matches_to_apply = unique_matches.slice(0, 1);
|
|
6421
|
+
}
|
|
6422
|
+
if (match_mode === "all" || matches_to_apply.length > 1) {
|
|
6423
|
+
for (const m of matches_to_apply) {
|
|
6424
|
+
const sub_edit = {
|
|
6425
|
+
...edit,
|
|
6426
|
+
_resolved_start_idx: m[0],
|
|
6427
|
+
_active_mapper_ref: resolved_mapper,
|
|
6428
|
+
_parent_edit_ref: edit
|
|
6429
|
+
};
|
|
6430
|
+
resolved_edits.push([sub_edit, null]);
|
|
6431
|
+
}
|
|
6432
|
+
} else {
|
|
6433
|
+
edit._resolved_start_idx = matches_to_apply[0][0];
|
|
6434
|
+
edit._active_mapper_ref = resolved_mapper;
|
|
6435
|
+
resolved_edits.push([edit, null]);
|
|
6436
|
+
}
|
|
6437
|
+
} else {
|
|
6438
|
+
skipped++;
|
|
6439
|
+
edit._applied_status = false;
|
|
6440
|
+
const target_snippet = (edit.target_text || "").trim().substring(0, 40);
|
|
6441
|
+
const msg = `- Failed to locate row target: '${target_snippet}...'`;
|
|
6442
|
+
this.skipped_details.push(msg);
|
|
6443
|
+
edit._error_msg = msg;
|
|
6444
|
+
}
|
|
6349
6445
|
} else {
|
|
6350
6446
|
skipped++;
|
|
6351
6447
|
edit._applied_status = false;
|
|
@@ -6651,8 +6747,15 @@ var RedlineEngine = class _RedlineEngine {
|
|
|
6651
6747
|
let skipped = 0;
|
|
6652
6748
|
let already_resolved = 0;
|
|
6653
6749
|
const resolved_history = /* @__PURE__ */ new Map();
|
|
6654
|
-
|
|
6655
|
-
const
|
|
6750
|
+
const sortedActions = actions.map((action, pos) => ({ action, pos })).sort((a, b) => {
|
|
6751
|
+
const aPri = a.action.type === "reply" ? 0 : 1;
|
|
6752
|
+
const bPri = b.action.type === "reply" ? 0 : 1;
|
|
6753
|
+
if (aPri !== bPri) {
|
|
6754
|
+
return aPri - bPri;
|
|
6755
|
+
}
|
|
6756
|
+
return a.pos - b.pos;
|
|
6757
|
+
});
|
|
6758
|
+
for (const { action, pos } of sortedActions) {
|
|
6656
6759
|
const type = action.type;
|
|
6657
6760
|
if (type === "reply") {
|
|
6658
6761
|
const cid = action.target_id.replace("Com:", "");
|
|
@@ -8800,8 +8903,25 @@ function extract_table(table, comments_map, cleanView, cursor, paragraph_offsets
|
|
|
8800
8903
|
paragraph_offsets
|
|
8801
8904
|
);
|
|
8802
8905
|
if (!cleanView) {
|
|
8803
|
-
|
|
8804
|
-
|
|
8906
|
+
let firstP = cell._element.getElementsByTagName("w:p")[0];
|
|
8907
|
+
let paraId = firstP ? firstP.getAttribute("w14:paraId") : null;
|
|
8908
|
+
if (!paraId && (!cell_content || cell_content.trim() === "")) {
|
|
8909
|
+
if (!firstP) {
|
|
8910
|
+
const xmlDoc = cell._element.ownerDocument;
|
|
8911
|
+
firstP = xmlDoc.createElement("w:p");
|
|
8912
|
+
cell._element.appendChild(firstP);
|
|
8913
|
+
}
|
|
8914
|
+
const allPs = Array.from(cell._element.ownerDocument.getElementsByTagName("w:p"));
|
|
8915
|
+
const index = allPs.indexOf(firstP);
|
|
8916
|
+
let hash = 2166136261;
|
|
8917
|
+
const str = `fallback-paraId-${index}`;
|
|
8918
|
+
for (let i = 0; i < str.length; i++) {
|
|
8919
|
+
hash ^= str.charCodeAt(i);
|
|
8920
|
+
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
8921
|
+
}
|
|
8922
|
+
paraId = (hash >>> 0).toString(16).toUpperCase().padStart(8, "0");
|
|
8923
|
+
firstP.setAttribute("w14:paraId", paraId);
|
|
8924
|
+
}
|
|
8805
8925
|
if (paraId) {
|
|
8806
8926
|
const space_pad = cell_content ? " " : "";
|
|
8807
8927
|
const anchor = `${space_pad}{#cell:${paraId}}`;
|
|
@@ -9760,7 +9880,7 @@ async function finalize_document(doc, options) {
|
|
|
9760
9880
|
report.tracked_changes_found = total;
|
|
9761
9881
|
if (total > 0 && !options.accept_all) {
|
|
9762
9882
|
report.status = "blocked";
|
|
9763
|
-
report.blocked_reason = `Document contains ${total} unresolved tracked changes (${counts[0]} insertions, ${counts[1]} deletions, ${counts[2]} formatting). Review in Word first, or set
|
|
9883
|
+
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'.`;
|
|
9764
9884
|
return { reportText: report.render() };
|
|
9765
9885
|
}
|
|
9766
9886
|
if (total > 0) {
|